diff options
Diffstat (limited to 'sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java')
-rw-r--r-- | sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java new file mode 100644 index 0000000000..9ee1878625 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AbstractAggregateContext.java @@ -0,0 +1,652 @@ +package org.apache.tuscany.core.context.impl; + +import static org.apache.tuscany.core.context.EventContext.HTTP_SESSION; +import static org.apache.tuscany.core.context.EventContext.REQUEST_END; +import static org.apache.tuscany.core.context.EventContext.SESSION_NOTIFY; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.wsdl.Part; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.DuplicateNameException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.EventException; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeAwareContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.core.context.SimpleComponentContext; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.context.scope.DefaultScopeStrategy; +import org.apache.tuscany.core.invocation.InvocationConfiguration; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.invocation.spi.ProxyInitializationException; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.core.system.annotation.ParentContext; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Component; +import org.apache.tuscany.model.assembly.EntryPoint; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.assembly.ExternalService; +import org.apache.tuscany.model.assembly.Module; +import org.apache.tuscany.model.assembly.Scope; +import org.apache.tuscany.model.assembly.ComponentImplementation; +import org.apache.tuscany.model.assembly.impl.AssemblyFactoryImpl; + +/** + * The base implementation of an aggregate context + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractAggregateContext extends AbstractContext implements AutowireContext, ScopeAwareContext { + + public static final int DEFAULT_WAIT = 1000 * 60; + + // ---------------------------------- + // Fields + // ---------------------------------- + + // The parent context, if one exists + @ParentContext + protected AggregateContext parentContext; + + // The parent configuration context, if one exists + @Autowire(required = false) + protected ConfigurationContext configurationContext; + + // The system monitor factory + @Autowire(required = false) + protected MonitorFactory monitorFactory; + + // The logical model representing the module assembly + // protected ModuleComponent moduleComponent; + protected Module module; + + protected Map<String, RuntimeConfiguration<InstanceContext>> configurations = new HashMap(); + + // Factory for scope contexts + @Autowire(required = false) + protected ScopeStrategy scopeStrategy; + + // The event context for associating context events to threads + protected EventContext eventContext; + + // The scopes for this context + protected Map<Scope, ScopeContext> scopeContexts; + + protected Map<Scope, ScopeContext> immutableScopeContexts; + + // A component context name to scope context index + protected Map<String, ScopeContext> scopeIndex; + + // Listeners for context events + protected List<RuntimeEventListener> listeners = new CopyOnWriteArrayList(); + + // Blocking latch to ensure the module is initialized exactly once prior to servicing requests + protected CountDownLatch initializeLatch = new CountDownLatch(1); + + // Indicates whether the module context has been initialized + protected boolean initialized; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AbstractAggregateContext() { + scopeIndex = new ConcurrentHashMap(); + // FIXME the factory should be injected + module = new AssemblyFactoryImpl().createModule(); + } + + public AbstractAggregateContext(String name, AggregateContext parent, ScopeStrategy strategy, EventContext ctx, + ConfigurationContext configCtx, MonitorFactory factory) { + super(name); + this.scopeStrategy = strategy; + this.eventContext = ctx; + this.configurationContext = configCtx; + this.monitorFactory = factory; + scopeIndex = new ConcurrentHashMap(); + parentContext = parent; + // FIXME the factory should be injected + module = new AssemblyFactoryImpl().createModule(); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() { + synchronized (initializeLatch) { + try { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Context not in UNINITIALIZED state"); + } + lifecycleState = INITIALIZING; + initializeScopes(); + + Map<Scope, List<RuntimeConfiguration<SimpleComponentContext>>> configurationsByScope = new HashMap(); + if (configurations != null) { + for (RuntimeConfiguration source : configurations.values()) { + // FIXME scopes are defined at the interface level + Scope sourceScope = source.getScope(); + wireSource(source); + buildTarget(source); + scopeIndex.put(source.getName(), scopeContexts.get(sourceScope)); + List<RuntimeConfiguration<SimpleComponentContext>> list = configurationsByScope.get(sourceScope); + if (list == null) { + list = new ArrayList(); + configurationsByScope.put(sourceScope, list); + } + list.add(source); + } + } + for (EntryPoint ep : module.getEntryPoints()) { + registerAutowire(ep); + } + for (Component component : module.getComponents()) { + registerAutowire(component); + } + for (ExternalService es : module.getExternalServices()) { + registerAutowire(es); + } + for (Map.Entry entries : configurationsByScope.entrySet()) { + // register configurations with scope contexts + ScopeContext scope = scopeContexts.get(entries.getKey()); + scope.registerConfigurations((List<RuntimeConfiguration<InstanceContext>>) entries.getValue()); + } + initializeProxies(); + for (ScopeContext scope : scopeContexts.values()) { + // register scope contexts as a listeners for events in the aggregate context + registerListener(scope); + scope.start(); + } + lifecycleState = RUNNING; + } catch (ProxyInitializationException e) { + lifecycleState = ERROR; + ContextInitException cie = new ContextInitException(e); + cie.addContextName(getName()); + throw cie; + } catch (ConfigurationException e) { + lifecycleState = ERROR; + throw new ContextInitException(e); + } catch (CoreRuntimeException e) { + lifecycleState = ERROR; + e.addContextName(getName()); + throw e; + } finally { + initialized = true; + // release the latch and allow requests to be processed + initializeLatch.countDown(); + } + } + } + + public void stop() { + if (lifecycleState == STOPPED) { + return; + } + // need to block a start until reset is complete + initializeLatch = new CountDownLatch(2); + lifecycleState = STOPPING; + initialized = false; + if (scopeContexts != null) { + for (ScopeContext scope : scopeContexts.values()) { + try { + if (scope.getLifecycleState() == ScopeContext.RUNNING) { + scope.stop(); + } + } catch (ScopeRuntimeException e) { + // log.error("Error stopping scope container [" + scopeContainers[i].getName() + "]", e); + } + } + } + scopeContexts = null; + scopeIndex.clear(); + // allow initialized to be called + initializeLatch.countDown(); + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void setModule(Module module) { + assert (module != null) : "Module cannot be null"; + name = module.getName(); + this.module = module; + } + + public void setScopeStrategy(ScopeStrategy scopeStrategy) { + this.scopeStrategy = scopeStrategy; + } + + public void setEventContext(EventContext eventContext) { + this.eventContext = eventContext; + } + + public void setMonitorFactory(MonitorFactory factory) { + this.monitorFactory = factory; + } + + public AggregateContext getParent() { + return parentContext; + } + + public void registerModelObjects(List<Extensible> models) throws ConfigurationException { + assert (models != null) : "Model object collection was null"; + for (Extensible model : models) { + registerModelObject(model); + } + } + + public void registerModelObject(Extensible model) throws ConfigurationException { + assert (model != null) : "Model object was null"; + initializeScopes(); + if (configurationContext != null) { + try { + configurationContext.configure(model); + configurationContext.build(this, model); + } catch (ConfigurationException e) { + e.addContextName(getName()); + throw e; + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + RuntimeConfiguration<InstanceContext> configuration = null; + if (model instanceof Module) { + // merge new module definition with the existing one + Module oldModule = module; + Module newModule = (Module) model; + module = newModule; + for (Component component : newModule.getComponents()) { + ComponentImplementation componentImplementation = component.getComponentImplementation(); + if (componentImplementation == null) { + ConfigurationException e = new ConfigurationException("Component implementation not set"); + e.addContextName(component.getName()); + e.addContextName(getName()); + throw e; + } + configuration = (RuntimeConfiguration<InstanceContext>) componentImplementation.getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.addContextName(component.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(component); + } + for (EntryPoint ep : newModule.getEntryPoints()) { + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(ep.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(ep); + } + for (ExternalService service : newModule.getExternalServices()) { + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + e.setIdentifier(service.getName()); + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(service); + } + if (lifecycleState == RUNNING) { + for (Component component : newModule.getComponents()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) component + .getComponentImplementation().getRuntimeConfiguration(); + wireSource(config); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + for (EntryPoint ep : newModule.getEntryPoints()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) ep + .getConfiguredReference().getRuntimeConfiguration(); + wireSource(config); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + for (ExternalService es : newModule.getExternalServices()) { + RuntimeConfiguration<InstanceContext> config = (RuntimeConfiguration<InstanceContext>) es + .getConfiguredService().getRuntimeConfiguration(); + buildTarget(config); + try { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories() + .values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getTargetProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories() + .values()) { + targetProxyFactory.initialize(); + } + } + } catch (ProxyInitializationException e) { + throw new ConfigurationException(e); + } + + } + + } + // merge existing module component assets + module.getComponents().addAll(oldModule.getComponents()); + module.getEntryPoints().addAll(oldModule.getEntryPoints()); + module.getExternalServices().addAll(oldModule.getExternalServices()); + } else { + if (model instanceof Component) { + Component component = (Component) model; + module.getComponents().add(component); + configuration = (RuntimeConfiguration<InstanceContext>) component.getComponentImplementation() + .getRuntimeConfiguration(); + } else if (model instanceof EntryPoint) { + EntryPoint ep = (EntryPoint) model; + module.getEntryPoints().add(ep); + configuration = (RuntimeConfiguration<InstanceContext>) ep.getConfiguredReference().getRuntimeConfiguration(); + } else if (model instanceof ExternalService) { + ExternalService service = (ExternalService) model; + module.getExternalServices().add(service); + configuration = (RuntimeConfiguration<InstanceContext>) service.getConfiguredService().getRuntimeConfiguration(); + } else { + BuilderConfigException e = new BuilderConfigException("Unknown model type"); + e.setIdentifier(model.getClass().getName()); + e.addContextName(getName()); + throw e; + } + if (configuration == null) { + ConfigurationException e = new ConfigurationException("Runtime configuration not set"); + if (model instanceof Part) { + e.setIdentifier(((Part) model).getName()); + } + e.addContextName(getName()); + throw e; + } + registerConfiguration(configuration); + registerAutowire(model); + } + } + + protected void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) throws ConfigurationException { + if (lifecycleState == RUNNING) { + if (scopeIndex.get(configuration.getName()) != null) { + throw new DuplicateNameException(configuration.getName()); + } + ScopeContext scope = scopeContexts.get(configuration.getScope()); + if (scope == null) { + ConfigurationException e = new ConfigurationException("Component has an unknown scope"); + e.addContextName(configuration.getName()); + e.addContextName(getName()); + throw e; + } + scope.registerConfiguration(configuration); + scopeIndex.put(configuration.getName(), scope); + configurations.put(configuration.getName(), configuration); // xcv + } else { + if (configurations.get(configuration.getName()) != null) { + throw new DuplicateNameException(configuration.getName()); + } + configurations.put(configuration.getName(), configuration); + } + + } + + public void registerListener(RuntimeEventListener listener) { + assert (listener != null) : "Listener cannot be null"; + listeners.add(listener); + } + + public void fireEvent(int eventType, Object message) throws EventException { + checkInit(); + if (eventType == SESSION_NOTIFY) { + // update context + eventContext.setIdentifier(HTTP_SESSION, message); + } else if (eventType == REQUEST_END) { + // be very careful with pooled threads, ensuring threadlocals are cleaned up + eventContext.clearIdentifier(HTTP_SESSION); + } + for (RuntimeEventListener listener : listeners) { + listener.onEvent(eventType, message); + } + } + + public InstanceContext getContext(String componentName) { + checkInit(); + assert (componentName != null) : "Name was null"; + ScopeContext scope = scopeIndex.get(componentName); + if (scope == null) { + return null; + } + return scope.getContext(componentName); + + } + + public Object getInstance(QualifiedName qName) throws TargetException { + return getInstance(qName, true); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + assert (qName != null) : "Name was null "; + // use the port name to get the context since entry points ports + ScopeContext scope = scopeIndex.get(qName.getPortName()); + if (scope == null) { + return null; + } + InstanceContext ctx = scope.getContext(qName.getPortName()); + if (!(ctx instanceof EntryPointContext)) { + TargetException e = new TargetException("Target not an entry point"); + e.setIdentifier(qName.getQualifiedName()); + e.addContextName(name); + throw e; + } + return ctx.getInstance(null, notify); + } + + public Object locateInstance(String qualifiedName) throws TargetException { + checkInit(); + QualifiedName qName = new QualifiedName(qualifiedName); + ScopeContext scope = scopeIndex.get(qName.getPartName()); + if (scope == null) { + TargetException e = new TargetException("Component not found"); + e.setIdentifier(qualifiedName); + e.addContextName(getName()); + throw e; + } + InstanceContext ctx = scope.getContext(qName.getPartName()); + try { + return ctx.getInstance(qName, true); + } catch (TargetException e) { + e.addContextName(getName()); + throw e; + } + } + + public Map<Scope, ScopeContext> getScopeContexts() { + initializeScopes(); + return immutableScopeContexts; + } + + // ---------------------------------- + // Abstract methods + // ---------------------------------- + + /** + * Registers a model object as autowirable + * + * @throws ContextInitException + */ + protected abstract void registerAutowire(Extensible model) throws ConfigurationException; + + // ---------------------------------- + // Protected methods + // ---------------------------------- + + /** + * Blocks until the module context has been initialized + */ + protected void checkInit() { + if (!initialized) { + try { + /* block until the module has initialized */ + boolean success = initializeLatch.await(DEFAULT_WAIT, TimeUnit.MILLISECONDS); + if (!success) { + throw new ContextInitException("Timeout waiting for module context to initialize"); + } + } catch (InterruptedException e) { // should not happen + } + } + + } + + protected void initializeScopes() { + if (scopeContexts == null) { + if (scopeStrategy == null) { + scopeStrategy = new DefaultScopeStrategy(); + } + scopeContexts = scopeStrategy.createScopes(eventContext); + immutableScopeContexts = Collections.unmodifiableMap(scopeContexts); + } + } + + /** + * Iterates through references and delegates to the configuration context to wire them to their targets + */ + protected void wireSource(RuntimeConfiguration source) { + Scope sourceScope = source.getScope(); + if (source.getSourceProxyFactories() != null) { + for (ProxyFactory sourceFactory : ((Map<String, ProxyFactory>) source.getSourceProxyFactories()).values()) { + QualifiedName targetName = sourceFactory.getProxyConfiguration().getTargetName(); + RuntimeConfiguration target = configurations.get(targetName.getPartName()); + if (target == null) { + ContextInitException e = new ContextInitException("Target not found"); + e.setIdentifier(targetName.getPartName()); + e.addContextName(source.getName()); + e.addContextName(name); + throw e; + } + // get the proxy chain for the target + ProxyFactory targetFactory = target.getTargetProxyFactory(sourceFactory.getProxyConfiguration().getTargetName() + .getPortName()); + if (targetFactory == null) { + ContextInitException e = new ContextInitException("No proxy factory found for service"); + e.setIdentifier(sourceFactory.getProxyConfiguration().getTargetName().getPortName()); + e.addContextName(target.getName()); + e.addContextName(source.getName()); + e.addContextName(name); + throw e; + } + boolean downScope = scopeStrategy.downScopeReference(sourceScope, target.getScope()); + configurationContext.wire(sourceFactory, targetFactory, target.getClass(), downScope, scopeContexts.get(target + .getScope())); + } + } + // wire invokers when the proxy only contains the target chain + if (source.getTargetProxyFactories() != null) { + for (ProxyFactory targetFactory : ((Map<String, ProxyFactory>) source.getTargetProxyFactories()).values()) { + configurationContext.wire(targetFactory, source.getClass(), scopeContexts.get(sourceScope)); + } + } + source.prepare(); + } + + /** + * Signals to target side of reference configurations to initialize + */ + protected void buildTarget(RuntimeConfiguration target) { + if (target.getTargetProxyFactories() != null) { + for (ProxyFactory targetFactory : ((Map<String, ProxyFactory>) target.getTargetProxyFactories()).values()) { + for (InvocationConfiguration iConfig : (Collection<InvocationConfiguration>) targetFactory + .getProxyConfiguration().getInvocationConfigurations().values()) { + iConfig.build(); + } + } + } + } + + protected void initializeProxies() throws ProxyInitializationException { + for (RuntimeConfiguration config : configurations.values()) { + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory sourceProxyFactory : (Collection<ProxyFactory>) config.getSourceProxyFactories().values()) { + sourceProxyFactory.initialize(); + } + } + if (config.getSourceProxyFactories() != null) { + for (ProxyFactory targetProxyFactory : (Collection<ProxyFactory>) config.getTargetProxyFactories().values()) { + targetProxyFactory.initialize(); + } + } + } + } + + /** + * @see org.apache.tuscany.core.context.AggregateContext#getAggregate() + */ + public Aggregate getAggregate() { + return module; + } +}
\ No newline at end of file |