diff options
Diffstat (limited to 'sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context')
46 files changed, 4153 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java new file mode 100644 index 0000000000..c1abcb3c03 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AbstractContext.java @@ -0,0 +1,89 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Functionality common to all <code>Context<code> implementations + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractContext implements Context { + + public AbstractContext() { + } + + public AbstractContext(String name) { + this.name = name; + } + + protected String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + protected int lifecycleState = UNINITIALIZED; + + public int getLifecycleState() { + return lifecycleState; + } + + public void setLifecycleState(int state) { + lifecycleState = state; + } + + protected List<LifecycleEventListener> contextListener = new CopyOnWriteArrayList(); + + public void addContextListener(LifecycleEventListener listener) { + contextListener.add(listener); + } + + public void removeContextListener(LifecycleEventListener listener) { + contextListener.remove(listener); + } + + public String toString() { + switch (lifecycleState) { + case (CONFIG_ERROR): + return "Context [" + name + "] in state [CONFIG_ERROR]"; + case (ERROR): + return "Context [" + name + "] in state [ERROR]"; + case (INITIALIZING): + return "Context [" + name + "] in state [INITIALIZING]"; + case (INITIALIZED): + return "Context [" + name + "] in state [INITIALIZED]"; + case (RUNNING): + return "Context [" + name + "] in state [RUNNING]"; + case (STOPPING): + return "Context [" + name + "] in state [STOPPING]"; + case (STOPPED): + return "Context [" + name + "] in state [STOPPED]"; + case (UNINITIALIZED): + return "Context [" + name + "] in state [UNINITIALIZED]"; + default: + return "Context [" + name + "] in state [UNKNOWN]"; + } + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java new file mode 100644 index 0000000000..0fab87358f --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AggregateContext.java @@ -0,0 +1,85 @@ +package org.apache.tuscany.core.context; + +import java.util.List; + +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.model.assembly.Aggregate; +import org.apache.tuscany.model.assembly.Extensible; +import org.apache.tuscany.model.assembly.AggregatePart; + +/** + * A context which contains child component contexts. + * + * @version $Rev$ $Date$ + */ +public interface AggregateContext extends InstanceContext { + + /** + * Propagates an event to registered listeners. All lifecycle events will be propagated to children in the order + * that they were registered. Listeners are expected to be well-behaved and if an exception is thrown the + * notification process will be aborted. + * + * @param pEventType the type of event. Basic types are defined in {@link EventContext} + * @param pMessage the message associated with the event or null + * @throws EventException if an error occurs while sending the event + */ + public void fireEvent(int pEventType, Object pMessage) throws EventException; + + /** + * Registers a listener to receive notifications for the context + * + * @throws ContextRuntimeException if an error occurs during registration + */ + public void registerListener(RuntimeEventListener listener) throws ContextRuntimeException; + + /** + * Adds runtime artifacts represented by the set of model objects to the aggregate context by merging them with + * existing artifacts. Implementing classes may support only a subset of {@link AggregatePart} types. + * + * @see org.apache.tuscany.model.assembly.Component + * @see org.apache.tuscany.model.assembly.ModuleComponent + * @see org.apache.tuscany.model.assembly.SimpleComponent + * @see org.apache.tuscany.model.assembly.EntryPoint + * @see org.apache.tuscany.model.assembly.ExternalService + */ + public void registerModelObjects(List<Extensible> models) throws ConfigurationException; + + /** + * Adds a runtime artifact represented by the model object to the aggregate context by merging it with existing + * artifacts. Implementing classes may support only a subset of {@link AggregatePart} types. + * + * @see org.apache.tuscany.model.assembly.Component + * @see org.apache.tuscany.model.assembly.ModuleComponent + * @see org.apache.tuscany.model.assembly.SimpleComponent + * @see org.apache.tuscany.model.assembly.EntryPoint + * @see org.apache.tuscany.model.assembly.ExternalService + */ + public void registerModelObject(Extensible model) throws ConfigurationException; + + /** + * Returns the child context associated with a given name + */ + public InstanceContext getContext(String name); + + /** + * Returns the parent context, or null if the context does not have one + */ + public AggregateContext getParent(); + + /** + * Intended for internal use by the runtime, returns an implementation instance for the given context name, which + * may be a compound component/service form. Unlike {@link InstanceContext#getInstance(QualifiedName)}, which for aggregate contexts only returns + * entry point proxies, this method will return any type of contained implementation instance. + * + * @throws TargetException if there was an error returning the instance + */ + public Object locateInstance(String name) throws TargetException; + + /** + * Returns the aggregate managed by this aggregate context + * @return + */ + @Deprecated + public Aggregate getAggregate(); + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java new file mode 100644 index 0000000000..5f3973f358 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireContext.java @@ -0,0 +1,35 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * A specialization of an AggregateContext that is able to automatically resolve references + * for its children using EntryPoint or Service interfaces exposed by it or, recursively, any + * of it parents. + * + * @version $Rev$ $Date$ + */ +public interface AutowireContext extends AggregateContext { + + /** + * Returns an reference to the requested service. + * + * @param instanceInterface the type of service being requested + * @return a reference to the requested service or null if none can be found + * @throws AutowireResolutionException if an error occurs attempting to resolve an autowire + */ + <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException; + + // todo add additional methods that allow other qualifications to be supplied +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java new file mode 100644 index 0000000000..4da4206a94 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/AutowireResolutionException.java @@ -0,0 +1,40 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an exception while resolving an automatic wire + * + * @version $Rev$ $Date$ + */ +public class AutowireResolutionException extends TargetException { + + public AutowireResolutionException() { + super(); + } + + public AutowireResolutionException(String message) { + super(message); + } + + public AutowireResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public AutowireResolutionException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java new file mode 100644 index 0000000000..a57ed03ffd --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ConfigurationContext.java @@ -0,0 +1,66 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.model.assembly.Extensible; + +/** + * Offers configuration services in the runtime. A ConfigurationContext is able to configure a model and then build the + * runtime representation corresponding to that model in the live system. <p/> Configuration contexts will typically be + * hierarchical, delegating to their parent <b>after</b> performing an operation. The parent ConfigurationContext will + * typically be injected into an implementation of this interface during registration. + * + * @version $Rev$ $Date$ + */ +public interface ConfigurationContext { + + /** + * Adds additional configuration information to a model object. + * + * @param model the model object to be configured + * @throws ConfigurationException + */ + public void configure(Extensible model) throws ConfigurationException; + + /** + * Decorates the supplied model object with a {@link org.apache.tuscany.core.builder.RuntimeConfiguration} that can + * be used to create the runtime context corresponding to the model. + * + * @param parent an AggregrateContext that will ultimately become the parent of the runtime context + * @param model the model object that defines the configuration to be built + * @throws BuilderConfigException + * @see org.apache.tuscany.core.builder.RuntimeConfiguration + */ + public void build(AggregateContext parent, Extensible model) throws BuilderConfigException; + + /** + * Constructs a wire from a source proxy factory to a corresponding target, potentially performing optimizations + * + * @param sourceFactory the proxy factory that will be used to create the injected proxy for a reference + * @param targetFactory the proxy factory that contains the invocation chains for the target side of the wire + * @param targetType the {@link org.apache.tuscany.core.builder.RuntimeConfiguration} implementation type for the + * wire target + * @param downScope whether the source is a shorter lived scope than the target. Used in optimization. + * @param targetScopeContext the scope context of the target service + * @throws BuilderConfigException + */ + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException; + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException; + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java new file mode 100644 index 0000000000..2eb70e8711 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/Context.java @@ -0,0 +1,106 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An entity that provides an execution context for a runtime artifact + * + * @version $Rev$ $Date$ + */ +public interface Context { + + /* A configuration error state */ + public static final int CONFIG_ERROR = -1; + + /* Has not been initialized */ + public static final int UNINITIALIZED = 0; + + /* In the process of being configured and initialized */ + public static final int INITIALIZING = 1; + + /* Instantiated and configured */ + public static final int INITIALIZED = 2; + + /* Configured and initialized */ + public static final int RUNNING = 4; + + /* In the process of being shutdown */ + public static final int STOPPING = 5; + + /* Has been shutdown and removed from the module */ + public static final int STOPPED = 6; + + /* In an error state */ + public static final int ERROR = 7; + + /** + * Returns the name of the context + */ + public String getName(); + + /** + * Sets the name of the context + */ + public void setName(String name); + + /** + * Returns the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + public int getLifecycleState(); + + /** + * Sets the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + public void setLifecycleState(int state); + + /** + * Starts the container + * + * @throws CoreRuntimeException + */ + public void start() throws CoreRuntimeException; + + /** + * Stops the container + * + * @throws CoreRuntimeException + */ + public void stop() throws CoreRuntimeException; + + /** + * Registers a listener for context events + */ + public void addContextListener(LifecycleEventListener listener); + + /** + * Deregisters a context event listener + */ + public void removeContextListener(LifecycleEventListener listener); + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java new file mode 100644 index 0000000000..e024a98b0e --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextInitException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error encountered while initializing an instance context + * + * @version $Rev$ $Date$ + */ +public class ContextInitException extends ContextRuntimeException { + + public ContextInitException() { + super(); + } + + public ContextInitException(String message) { + super(message); + } + + public ContextInitException(String message, Throwable cause) { + super(message, cause); + } + + public ContextInitException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java new file mode 100644 index 0000000000..0d35f145dc --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ContextRuntimeException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An unchecked exception encountered by an {@link org.apache.tuscany.core.context.Context} + * + * @version $Rev$ $Date$ + */ +public class ContextRuntimeException extends CoreRuntimeException { + + public ContextRuntimeException() { + super(); + } + + public ContextRuntimeException(String message) { + super(message); + } + + public ContextRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ContextRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java new file mode 100644 index 0000000000..a46d35c22c --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/CoreRuntimeException.java @@ -0,0 +1,27 @@ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.common.TuscanyRuntimeException; + +/** + * The root exception for the runtime package. Exceptions occurring in the runtime are generally non-recoverable + * + * @version $Rev$ $Date$ + */ +public abstract class CoreRuntimeException extends TuscanyRuntimeException { + + public CoreRuntimeException() { + super(); + } + + public CoreRuntimeException(String message) { + super(message); + } + + public CoreRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public CoreRuntimeException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java new file mode 100644 index 0000000000..81a334d3c8 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/DuplicateNameException.java @@ -0,0 +1,39 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an attempt to add a context with a name equal to an existing context + * + * @version $Rev$ $Date$ + */ +public class DuplicateNameException extends ContextRuntimeException { + + public DuplicateNameException() { + super(); + } + + public DuplicateNameException(String message) { + super(message); + } + + public DuplicateNameException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateNameException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java new file mode 100644 index 0000000000..aef2840f9a --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EntryPointContext.java @@ -0,0 +1,57 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * The runtime artifact representing an entry point, <code>EntryPointContext</code> manages invocation handler + * instances that expose service operations offered by a component in the parent aggregate. The invocation handler + * instance is responsible for dispatching the request down an invocation chain to the target instance. The invocation + * chain may contain {@link org.apache.tuscany.core.invocation.Interceptor}s and + * {@link org.apache.tuscany.core.invocation.MessageHandler}s that implement policies or perform mediations on the + * invocation. + * <p> + * Entry point contexts are used by transport binding artifacts to invoke an operation on a service. The transport + * binding uses an {@link java.lang.reflect.InvocationHandler} instance obtained from the <code>EntryPointContext</code> + * to perform the invocation as in: + * + * <pre> + * AggregateContext aggregateContext = ... + * EntryPointContext ctx = (EntryPointContext) aggregateContext.getContext("source"); + * Assert.assertNotNull(ctx); + * InvocationHandler handler = (InvocationHandler) ctx.getImplementationInstance(); + * Object response = handler.invoke(null, operation, new Object[] { param }); + * </pre> + * + * The <code>Proxy</code> instance passed to <code>InvocationHandler</code> may be null as the client is invoking + * directly on the handler. + * <p> + * Alternatively, the following will return a proxy implementing the service interface exposed by the entry point: + * + * <pre> + * AggregateContext aggregateContext = ... + * EntryPointContext ctx = (EntryPointContext) aggregateContext.getContext("source"); + * Assert.assertNotNull(ctx); + * HelloWorld proxy = (Helloworld) ctx.getInstance(null); // service name not necessary + * </pre> + * + * The proxy returned will be backed by the entry point invocation chain. + * + * @version $Rev$ $Date$ + */ +public interface EntryPointContext extends InstanceContext { + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java new file mode 100644 index 0000000000..9f7c98200a --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventContext.java @@ -0,0 +1,66 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Implementations are responsible for tracking scope keys associated with the current request. + * + * @version $Rev$ $Date$ + */ +public interface EventContext { + + /* An event type fired when a request is first serviced in the runtime */ + public static final int REQUEST_START = 1; + + /* An event type fired when the runtime finishes servicing a request */ + public static final int REQUEST_END = 2; + + /* An event type fired when a session is set for the current context */ + public static final int SESSION_NOTIFY = 3; + + /* An event type fired when a session is invalidated in the runtime */ + public static final int SESSION_END = 4; + + /* An event type fired when the current deployment unit is initialized */ + public static final int MODULE_START = 5; + + /* An event type fired when the current deployment unit is quiesced */ + public static final int MODULE_STOP = 6; + + public static final int SYSTEM_START = 7; + + public static final int SYSTEM_STOP = 8; + + /* An identifier type associated with an HTTP session */ + public static final Object HTTP_SESSION = new Object(); + + /** + * Returns the unique key for the given identifier, e.g a session + */ + public Object getIdentifier(Object type); + + /** + * Sets the unique key for the given identifier, e.g a session + */ + public void setIdentifier(Object type, Object identifier); + + /** + * Clears the unique key for the given identifier, e.g a session + */ + public void clearIdentifier(Object type); + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java new file mode 100644 index 0000000000..aaf26aee69 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/EventException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error encountered while firing a module event + * + * @version $Rev$ $Date$ + */ +public class EventException extends CoreRuntimeException { + + public EventException(String message, Throwable cause) { + super(message, cause); + } + + public EventException(String message) { + super(message); + } + + public EventException(Throwable cause) { + super(cause); + } + + public EventException() { + super(); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java new file mode 100644 index 0000000000..298246dc81 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ExternalServiceContext.java @@ -0,0 +1,24 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Manages an external service + * + * @version $Rev$ $Date$ + */ +public interface ExternalServiceContext extends InstanceContext { + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java new file mode 100644 index 0000000000..473762b6b0 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InstanceContext.java @@ -0,0 +1,75 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Manages instances of a runtime artifact. An <code>InstanceContext</code> may contain child contexts which + * themselves manage implementation instances or it may be a leaf context. + * + * @see org.apache.tuscany.core.context.SimpleComponentContext + * @see org.apache.tuscany.core.context.AggregateContext + * @see org.apache.tuscany.core.context.EntryPointContext + * @see org.apache.tuscany.core.context.ExternalServiceContext + * + * @version $Rev$ $Date$ + */ +public interface InstanceContext extends Context { + + /** + * Returns the instance associated with the requested name, which may be in a simple or compound form. Simple (i.e. + * leaf) contexts will return an instance associated with the service name part of the compound name, which may be + * null. + * <p> + * Aggregate contexts will return an instance (likely a proxy) of a contained entry point context. In this case, the + * port name on the qualified name will correspond to the aggregate context name and the part name will be used to + * retrieve the contained entry point context. The latter may be null. If the contained context is not an entry + * point context, an exception will be thrown. + * + * @param qName a qualified name of the requested instance + * @return the implementation instance or a proxy to it + * @throws TargetException if an error occurs retrieving the instance or the requested component is not an entry + * point. + * + * @see AggregateContext + * @see org.apache.tuscany.model.assembly.EntryPoint + */ + public Object getInstance(QualifiedName qName) throws TargetException; + + /** + * Returns an instance associated with the requested name without notifying <code>ContextEventListener</code>s + * that may be registered with this context on instance creation. Note that {@link #getInstance(QualifiedName)} + * should generally be called and this method is only provided as an optimization for particular circumstances. + * + * @param qName a qualified name of the requested instance + * @param notify whether to notify <code>ContextEventListener</code>s + * @return the instance or a proxy to it + * @throws TargetException if an error occurs retrieving the instance or proxy + * @see LifecycleEventListener + */ + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException; + + /** + * Returns the implementation instance associated witht he component. An implementation instance does not + * have a proxy invocation chainXXX + * @return + * @throws TargetException + */ + public Object getImplementationInstance() throws TargetException; + + public Object getImplementationInstance(boolean notify) throws TargetException; + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java new file mode 100644 index 0000000000..65c709e569 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/InvalidNameException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an invalid name + * + * @version $Rev$ $Date$ + */ +public class InvalidNameException extends ContextRuntimeException { + + public InvalidNameException() { + super(); + } + + public InvalidNameException(String message) { + super(message); + } + + public InvalidNameException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidNameException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java new file mode 100644 index 0000000000..78962b53b4 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/LifecycleEventListener.java @@ -0,0 +1,32 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.EventListener; + +/** + * Callback interface for receiving instance context lifecycle events + * + * @version $Rev$ $Date$ + */ +public interface LifecycleEventListener extends EventListener { + + /** + * Notifies the listener that a new component context was created + */ + public void onInstanceCreate(Context component); +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java new file mode 100644 index 0000000000..ad71721b75 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/QualifiedName.java @@ -0,0 +1,83 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * An evaluated name consisting of a part/port pair. In the runtime, a part generally 'contains' or 'provides' ports + * such as a module component/entry point or a component/service pair. + * + * @version $Rev$ $Date$ + */ +public class QualifiedName { + + private String qName; + + private String partName; + + private String portName; + + public static final String NAME_SEPARATOR = "/"; + + /** + * Constructs a new qualified name + * + * @throws InvalidNameException if the name is in an invalid format + */ + public QualifiedName(String qualifiedName) throws InvalidNameException { + assert (qualifiedName != null) : "Name was null"; + int pos = qualifiedName.indexOf(QualifiedName.NAME_SEPARATOR); + switch (pos) { + case -1: + partName = qualifiedName; + break; + case 0: + throw new InvalidNameException(qualifiedName); + default: + partName = qualifiedName.substring(0, pos); + portName = qualifiedName.substring(pos + 1); + break; + } + qName = qualifiedName; + } + + /** + * Returns the parsed part name + */ + public String getPartName() { + return partName; + } + + /** + * Returns the parsed port name if the original is of the compound for part/port + */ + public String getPortName() { + return portName; + } + + /** + * Returns the full part/port name pair + * + * @return + */ + public String getQualifiedName() { + return qName; + } + + public String toString() { + return qName; + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java new file mode 100644 index 0000000000..e90f30b9cc --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/RuntimeEventListener.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.EventListener; + +/** + * Listeners observe events fired in the SCA runtime. + * + * @version $Rev$ $Date$ + */ +public interface RuntimeEventListener extends EventListener { + + /** + * A method called when an event for which the <tt>Listener</tt> class is registered to observe is fired in the runtime + * + * @param type the event type identifier + * @param message the event message + * @throws EventException if an error occurs processing the event + */ + public void onEvent(int type, Object message) throws EventException; +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java new file mode 100644 index 0000000000..565d7b49a6 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeAwareContext.java @@ -0,0 +1,31 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.Map; + +import org.apache.tuscany.model.assembly.Scope; + +/** + * Denotes an aggregate context that supports scopes + * + * @version $Rev$ $Date$ + */ +public interface ScopeAwareContext extends AggregateContext { + + /** + * Returns an immutable collection of scopes keyed by type for the aggregate context + */ + public Map<Scope, ScopeContext> getScopeContexts(); +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java new file mode 100644 index 0000000000..abda942c88 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeContext.java @@ -0,0 +1,72 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.List; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; + +/** + * Manages the lifecycle and visibility of <code>InstanceContext</code>s. + * + * @see org.apache.tuscany.core.context.InstanceContext + * + * @version $Rev$ $Date$ + */ +public interface ScopeContext extends InstanceContext, RuntimeEventListener { + + /** + * Returns whether implementation instances may be held for the duration of an invocation + */ + public boolean isCacheable(); + + /** + * Registers the runtime configurations used to construct instance contexts for the scope + */ + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations); + + /** + * Adds a runtime configuration to the scope + */ + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration); + + /** + * Returns a context bound to the given name or null if the component does not exist. The returned context is bound + * to a key determined from the thread context. + */ + public InstanceContext getContext(String name); + + /** + * Returns a context bound to the given name and scoped to the given key or null if the context does not exist + */ + public InstanceContext getContextByKey(String name, Object key); + + /** + * Removes a context with the given name, determining the scope key from the thread context + * + * @throws ScopeRuntimeException + */ + public void removeContext(String name) throws ScopeRuntimeException; + + /** + * Removes a context bound to the given name and scope key + * + * @throws ScopeRuntimeException + */ + public void removeContextByKey(String name, Object key) throws ScopeRuntimeException; + +}
\ No newline at end of file diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java new file mode 100644 index 0000000000..38a847295c --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeIdentifier.java @@ -0,0 +1,33 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Implementations enable lazy retrieval of a scope id associated with a request, i.e. an id (and presumably a context) do not + * have to be generated if the scope is never accessed. Identifiers are associated with the current request thread and keyed on + * scope type. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.container.module.EventContext + */ +public interface ScopeIdentifier { + + /** + * Returns the scope id for the request. + */ + public Object getIdentifier(); +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java new file mode 100644 index 0000000000..6ef5bfe9dd --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeInitializationException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an initialization exception thrown by a scope container + * + * @version $Rev$ $Date$ + */ +public class ScopeInitializationException extends ScopeRuntimeException { + + public ScopeInitializationException() { + super(); + } + + public ScopeInitializationException(String message) { + super(message); + } + + public ScopeInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public ScopeInitializationException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java new file mode 100644 index 0000000000..5022f7589d --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeRuntimeException.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes a general runtime exception encountered by a scope container + * + * @version $Rev$ $Date$ + */ +public class ScopeRuntimeException extends CoreRuntimeException { + + public ScopeRuntimeException() { + super(); + } + + public ScopeRuntimeException(String message) { + super(message); + } + + public ScopeRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ScopeRuntimeException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java new file mode 100644 index 0000000000..b648fc2dcc --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ScopeStrategy.java @@ -0,0 +1,43 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +import java.util.Map; + +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implementations provide scope container creation facilities and scope semantics to the runtime + * + * @version $Rev$ $Date$ + */ +public interface ScopeStrategy { + + /* Denotes an undefined scope */ + public static final int SCOPE_NOT_FOUND = -3; + + /** + * Creates and returns new instances of configured scope containers + */ + public Map<Scope, ScopeContext> createScopes(EventContext eventContext); + + /** + * Determines whether a wire proceeds from a source of higher scope to a target of lesser scope + */ + public boolean downScopeReference(Scope sourceScope, Scope targetScope); + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java new file mode 100644 index 0000000000..253909d7fa --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/ServiceNotFoundException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.osoa.sca.ServiceUnavailableException; + +/** + * Denotes the specific case where a service was not found at runtime + * + * @version $Rev$ $Date$ + */ +public class ServiceNotFoundException extends ServiceUnavailableException { + + public ServiceNotFoundException() { + super(); + } + + public ServiceNotFoundException(String message) { + super(message); + } + + public ServiceNotFoundException(Throwable cause) { + super(cause); + } + + public ServiceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java new file mode 100644 index 0000000000..d35a3712a0 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SimpleComponentContext.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * A runtime entity that manages a non-aggregate (i.e. leaf-type) instance. + * + * @version $Rev$ $Date$ + */ +public interface SimpleComponentContext extends InstanceContext { + + /** + * Returns whether a the context should be eagerly initialized + */ + public boolean isEagerInit(); + + /** + * Returns whether a the context should be called back when its scope ends + */ + public boolean isDestroyable(); + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java new file mode 100644 index 0000000000..afb8499104 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/SystemAggregateContext.java @@ -0,0 +1,36 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context; + +import org.apache.tuscany.core.config.ConfigurationException; + +/** + * Marker type for system aggregate contexts + * + * @version $Rev$ $Date$ + */ +public interface SystemAggregateContext extends AutowireContext, ScopeAwareContext, ConfigurationContext { + + /** + * Register a simple Java Object as a system component. + * This is primarily intended for use by bootstrap code to create the initial + * configuration components. + * + * @param name the name of the resulting component + * @param instance the Object that will become the component's implementation + * @throws ConfigurationException + */ + void registerJavaObject(String name, Object instance) throws ConfigurationException; +} + diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java new file mode 100644 index 0000000000..dd39d06aa1 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/TargetException.java @@ -0,0 +1,42 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context; + +/** + * Denotes an error while performing an operation on a target component implementation instance or proxy + * + * @version $Rev$ $Date$ + */ +public class TargetException extends CoreRuntimeException { + + public TargetException() { + super(); + } + + public TargetException(String message) { + super(message); + } + + public TargetException(String message, Throwable cause) { + super(message, cause); + } + + public TargetException(Throwable cause) { + super(cause); + } + +} 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 diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java new file mode 100644 index 0000000000..69e0b8edfc --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/AggregateContextImpl.java @@ -0,0 +1,222 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import org.apache.tuscany.common.monitor.MonitorFactory; +import org.apache.tuscany.core.builder.BuilderConfigException; +import org.apache.tuscany.core.config.ConfigurationException; +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.AutowireContext; +import org.apache.tuscany.core.context.AutowireResolutionException; +import org.apache.tuscany.core.context.ConfigurationContext; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.core.context.ServiceNotFoundException; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.system.annotation.Autowire; +import org.apache.tuscany.model.assembly.Extensible; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceUnavailableException; + +/** + * The standard implementation of an aggregate context. Autowiring is performed by delegating to the parent context. + * + * @version $Rev$ $Date$ + */ +public class AggregateContextImpl extends AbstractAggregateContext implements ConfigurationContext, ModuleContext { + + // ---------------------------------- + // Fields + // ---------------------------------- + + @Autowire(required = false) + private AutowireContext autowireContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AggregateContextImpl() { + super(); + eventContext = new EventContextImpl(); + } + + public AggregateContextImpl(String name, AggregateContext parent, ScopeStrategy strategy, EventContext ctx, + ConfigurationContext configCtx, MonitorFactory factory) { + super(name, parent, strategy, ctx, configCtx, factory); + } + + public AggregateContextImpl(String name, AggregateContext parent, AutowireContext autowireContext, ScopeStrategy strategy, + EventContext ctx, ConfigurationContext configCtx, MonitorFactory factory) { + super(name, parent, strategy, ctx, configCtx, factory); + this.autowireContext = autowireContext; + } + + // ---------------------------------- + // ModuleContext methods + // ---------------------------------- + + private String uri; + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public Object locateService(String qualifiedName) throws ServiceUnavailableException { + checkInit(); + QualifiedName qName = new QualifiedName(qualifiedName); + ScopeContext scope = scopeIndex.get(qName.getPartName()); + if (scope == null) { + throw new ServiceNotFoundException(qualifiedName); + } + InstanceContext ctx = scope.getContext(qName.getPartName()); + try { + Object o = ctx.getInstance(qName, true); + if (o == null) { + throw new ServiceUnavailableException(qualifiedName); + } + return o; + } catch (TargetException e) { + e.addContextName(getName()); + throw new ServiceUnavailableException(e); + } + } + + public ServiceReference createServiceReference(String serviceName) { + throw new UnsupportedOperationException(); + } + + public RequestContext getRequestContext() { + throw new UnsupportedOperationException(); + } + + public ServiceReference createServiceReferenceForSession(Object self) { + throw new UnsupportedOperationException(); + } + + public ServiceReference createServiceReferenceForSession(Object self, String serviceName) { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String serviceName) { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String serviceName, Object sessionId) { + throw new UnsupportedOperationException(); + } + + // ---------------------------------- + // AutowireContext methods + // ---------------------------------- + + public <T> T resolveInstance(Class<T> instanceInterface) throws AutowireResolutionException { + if (MonitorFactory.class.equals(instanceInterface)) { + return instanceInterface.cast(monitorFactory); + } else if (ConfigurationContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } else if (AutowireContext.class.equals(instanceInterface)) { + return instanceInterface.cast(this); + } + if (autowireContext != null) { + try { + return autowireContext.resolveInstance(instanceInterface); + } catch (AutowireResolutionException e) { + e.addContextName(getName()); + throw e; + } + } + return null; + } + + @Override + protected void registerAutowire(Extensible model) { + // this context only delegates autowiring + } + + // ---------------------------------- + // ConfigurationContext methods + // ---------------------------------- + + public void configure(Extensible model) throws ConfigurationException { + if (configurationContext != null) { + try { + configurationContext.configure(model); + } catch (ConfigurationException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void build(AggregateContext parent, Extensible model) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.build(parent, model); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void wire(ProxyFactory sourceFactory, ProxyFactory targetFactory, Class targetType, boolean downScope, + ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(sourceFactory, targetFactory, targetType, downScope, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + public void wire(ProxyFactory targetFactory, Class targetType, ScopeContext targetScopeContext) throws BuilderConfigException { + if (configurationContext != null) { + try { + configurationContext.wire(targetFactory, targetType, targetScopeContext); + } catch (BuilderConfigException e) { + e.addContextName(getName()); + throw e; + } + } + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return this; + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java new file mode 100644 index 0000000000..791ce6b8a5 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EntryPointContextImpl.java @@ -0,0 +1,112 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import java.lang.reflect.InvocationHandler; + +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.ContextInitException; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EntryPointContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.jdk.JDKInvocationHandler; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; +import org.apache.tuscany.core.message.MessageFactory; + +/** + * The default implementation of an entry point context + * + * @version $Rev$ $Date$ + */ +public class EntryPointContextImpl extends AbstractContext implements EntryPointContext { + + private MessageFactory messageFactory; + + private ProxyFactory proxyFactory; + + private Object target; + + private InvocationHandler invocationHandler; + + // a proxy implementing the service exposed by the entry point backed by the invocation handler + private Object proxy; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates a new entry point + * + * @param name the entry point name + * @param proxyFactory the proxy factory containing the invocation chains for the entry point + * @param parentContext the containing aggregate of the entry point + * @param messageFactory a factory for generating invocation messages + * @throws ContextInitException if an error occurs creating the entry point + */ + public EntryPointContextImpl(String name, ProxyFactory proxyFactory, MessageFactory messageFactory) + throws ContextInitException { + super(name); + assert (proxyFactory != null) : "Proxy factory was null"; + assert (messageFactory != null) : "Message factory was null"; + this.proxyFactory = proxyFactory; + this.messageFactory = messageFactory; + invocationHandler = new JDKInvocationHandler(messageFactory, proxyFactory.getProxyConfiguration() + .getInvocationConfigurations()); + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + if (proxy == null) { + try { + proxy = proxyFactory.createProxy(); + } catch (ProxyCreationException e) { + TargetException te = new TargetException(e); + te.addContextName(getName()); + throw te; + } + } + return proxy; + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public void start() throws ContextInitException { + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + lifecycleState = STOPPED; + } + + // ---------------------------------- + // InstanceContext methods + // ---------------------------------- + + public Object getImplementationInstance() throws TargetException { + return invocationHandler; + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return getImplementationInstance(); + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java new file mode 100644 index 0000000000..accf6b3030 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/EventContextImpl.java @@ -0,0 +1,77 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeIdentifier; + +/** + * An implementation of an {@link org.apache.tuscany.core.context.EventContext} that handles event-to-thread associations using an + * <code>InheritableThreadLocal</code> + * + * @version $Rev$ $Date$ + */ +public class EventContextImpl implements EventContext { + + // @TODO design a proper propagation strategy for creating new threads + /* + * a map ( associated with the current thread) of scope identifiers keyed on the event context id type. the scope identifier + * may be a {@link ScopeIdentifier} or an opaque id + */ + private ThreadLocal<Map> eventContext = new InheritableThreadLocal(); + + public Object getIdentifier(Object type) { + Map map = eventContext.get(); + if (map == null) { + return null; + } + Object currentId = map.get(type); + if (currentId instanceof ScopeIdentifier) { + currentId = ((ScopeIdentifier) currentId).getIdentifier(); + // once we have accessed the id, replace the lazy wrapper + map.put(type, currentId); + } + return currentId; + } + + public void setIdentifier(Object type, Object identifier) { + Map map = eventContext.get(); + if (map == null) { + map = new HashMap(); + eventContext.set(map); + } + map.put(type, identifier); + } + + public void clearIdentifier(Object type) { + if (type == null) { + return; + } + Map map = eventContext.get(); + if (map != null) { + map.remove(type); + } + } + + public EventContextImpl() { + super(); + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java new file mode 100644 index 0000000000..a73081ef66 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/impl/ExternalServiceContextImpl.java @@ -0,0 +1,92 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.impl; + +import org.apache.tuscany.core.builder.ObjectFactory; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.ExternalServiceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.TargetException; +import org.apache.tuscany.core.invocation.spi.ProxyCreationException; +import org.apache.tuscany.core.invocation.spi.ProxyFactory; + +/** + * The default implementation of an external service context + * + * @version $Rev$ $Date$ + */ +public class ExternalServiceContextImpl extends AbstractContext implements ExternalServiceContext { + + private ProxyFactory targetProxyFactory; + + private ObjectFactory targetInstanceFactory; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + /** + * Creates an external service context + * + * @param name the name of the external service + * @param targetProxyFactory the factory which creates proxies implementing the configured service interface for the + * external service. There is always only one proxy factory as an external service is configured with one + * service + * @param targetInstanceFactory the object factory that creates an artifact capabile of communicating over the + * binding transport configured on the external service. The object factory may implement a caching strategy. + */ + public ExternalServiceContextImpl(String name, ProxyFactory targetProxyFactory, ObjectFactory targetInstanceFactory) { + super(name); + assert (targetProxyFactory != null) : "Target proxy factory was null"; + assert (targetInstanceFactory != null) : "Target instance factory was null"; + this.targetProxyFactory = targetProxyFactory; + this.targetInstanceFactory = targetInstanceFactory; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public Object getInstance(QualifiedName qName) throws TargetException { + try { + return targetProxyFactory.createProxy(); + // TODO do we cache the proxy, (assumes stateful capabilities will be provided in an interceptor) + } catch (ProxyCreationException e) { + TargetException te = new TargetException(e); + te.addContextName(getName()); + throw te; + } + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public void start() throws CoreRuntimeException { + lifecycleState = RUNNING; + } + + public void stop() throws CoreRuntimeException { + lifecycleState = STOPPED; + } + + public Object getImplementationInstance() throws TargetException { + return targetInstanceFactory.getInstance(); + } + + public Object getImplementationInstance(boolean notify) throws TargetException { + return getImplementationInstance(); + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java new file mode 100644 index 0000000000..449af4bdf8 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeContext.java @@ -0,0 +1,158 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.QualifiedName; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.core.context.TargetException; + +/** + * Implements functionality common to scope contexts. + * <p> + * <b>NB: </b>Minimal synchronization is performed, particularly for initializing and destroying scopes, and it is + * assumed the scope container will block requests until these operations have completed. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContext extends AbstractContext implements ScopeContext{ + // ---------------------------------- + // Fields + // ---------------------------------- + + // The collection of runtime configurations for the scope + protected Map<String, RuntimeConfiguration<InstanceContext>> runtimeConfigurations = new ConcurrentHashMap(); + + // The event context the scope container is associated with + protected EventContext eventContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AbstractScopeContext(EventContext eventContext) { + assert (eventContext != null) : "Event context was null"; + this.eventContext = eventContext; + } + + // ---------------------------------- + // Lifecycle methods + // --------------------------_-------- + + public synchronized void start() { + } + + public synchronized void stop() { + } + + + // ---------------------------------- + // Scope methods + // ---------------------------------- + + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations) { + for (RuntimeConfiguration<InstanceContext> configuration : configurations) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + } + + public Object getInstance(QualifiedName qName) throws TargetException { + Object instance = null; + InstanceContext context = getContext(qName.getPartName()); + if (context == null) { + TargetException e = new TargetException("Target not found"); + e.setIdentifier(qName.getQualifiedName()); + throw e; + } + return context.getInstance(qName); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + //---------------------------------- + // InstanceContext methods + //---------------------------------- + + public Object getImplementationInstance() throws TargetException{ + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException{ + return this; + } + + // ---------------------------------- + // Protected methods + // ---------------------------------- + + protected EventContext getEventContext() { + return eventContext; + } + + /** + * Notfies instances that are associated with a context and configured to receive callbacks that the context is + * being destroyed in reverse order + * + * @param key the context key + */ + protected void notifyInstanceShutdown(Object key) { + InstanceContext[] contexts = getShutdownContexts(key); + if ((contexts == null) || (contexts.length < 1)) { + return; + } + // shutdown destroyable instances in reverse instantiation order + for (int i = contexts.length - 1; i >= 0; i--) { + InstanceContext context = contexts[i]; + + if (context.getLifecycleState() == Context.RUNNING) { + synchronized (context) { + context.setLifecycleState(Context.STOPPING); + removeContextByKey(context.getName(), key); + try { + context.stop(); + } catch (TargetException e) { + // TODO send a monitoring event + // log.error("Error releasing instance [" + context.getName() + "]",e); + } + } + } + } + } + + protected void checkInit() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not running [" + lifecycleState + "]"); + } + } + + /** + * Returns an array of contexts that need to be notified of scope shutdown. The array must be in the order in which + * component contexts were created + */ + protected abstract InstanceContext[] getShutdownContexts(Object key); + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java new file mode 100644 index 0000000000..f89d09196d --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AbstractScopeStrategy.java @@ -0,0 +1,67 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import org.apache.tuscany.core.context.ScopeStrategy; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements basic scope strategy functionality + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeStrategy implements ScopeStrategy { + + public AbstractScopeStrategy() { + } + + /** + * Determines legal scope references according to standard SCA scope rules + * + * @param pReferrer the scope of the component making the reference + * @param pReferee the scope of the component being referred to + */ + public boolean downScopeReference(Scope pReferrer, Scope pReferee) { + if (pReferrer == Scope.UNDEFINED || pReferee == Scope.UNDEFINED) { + return false; + } + if (pReferee == pReferrer){ + return false; + }else if(pReferrer == Scope.INSTANCE){ + return false; + }else if(pReferee == Scope.INSTANCE){ + return true; + }else if (pReferrer == Scope.REQUEST && pReferee == Scope.SESSION){ + return false; + }else if (pReferrer == Scope.REQUEST && pReferee == Scope.MODULE){ + return false; +// }else if (pReferrer == Scope.SESSION && pReferee == Scope.REQUEST){ +// return true; + }else if (pReferrer == Scope.SESSION && pReferee == Scope.MODULE){ + return false; +// }else if (pReferrer == Scope.MODULE){ +// return true; + }else{ + return true; + } + //FIXME Jim this does not work with enumerations, what does it mean to have a scope <0? +// } else if ((pReferrer < 0) || (pReferee < 0)) { +// return false; +// } +// +// return (pReferrer > pReferee); +// return pReferrer != pReferee; + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java new file mode 100644 index 0000000000..19f554a625 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/AggregateScopeContext.java @@ -0,0 +1,184 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.AbstractContext; +import org.apache.tuscany.core.context.AggregateContext; +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.ScopeContext; +import org.apache.tuscany.core.context.ScopeInitializationException; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.TargetException; + +/** + * Manages the lifecycle of aggregate component contexts, i.e. contexts which contain child contexts + * + * @see org.apache.tuscany.core.context.AggregateContext + * @version $Rev$ $Date$ + */ +public class AggregateScopeContext extends AbstractContext implements ScopeContext { + + // ---------------------------------- + // Fields + // ---------------------------------- + + private EventContext eventContext; + + private List<RuntimeConfiguration<InstanceContext>> configs = new ArrayList(); + + // Aggregate component contexts in this scope keyed by name + private Map<String, AggregateContext> contexts = new ConcurrentHashMap(); + + // indicates if a module start event has been previously propagated so child contexts added after can be notified + private boolean moduleScopeStarted; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public AggregateScopeContext(EventContext eventContext) { + assert (eventContext != null) : "Event context was null"; + this.eventContext = eventContext; + name = "Aggregate Scope"; + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public void start() throws ScopeInitializationException { + for (RuntimeConfiguration<InstanceContext> configuration : configs) { + InstanceContext context = configuration.createInstanceContext(); + if (!(context instanceof AggregateContext)) { + ScopeInitializationException e = new ScopeInitializationException("Context not an aggregate type"); + e.addContextName(context.getName()); + throw e; + } + AggregateContext aggregateCtx = (AggregateContext) context; + aggregateCtx.start(); + contexts.put(aggregateCtx.getName(), aggregateCtx); + } + lifecycleState = RUNNING; + } + + public void stop() throws ScopeRuntimeException { + for (AggregateContext context : contexts.values()) { + context.stop(); + } + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void registerConfigurations(List<RuntimeConfiguration<InstanceContext>> configurations) { + this.configs = configurations; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + assert (configuration != null) : "Configuration was null"; + configs.add(configuration); + if (lifecycleState == RUNNING) { + InstanceContext context = configuration.createInstanceContext(); + if (!(context instanceof AggregateContext)) { + ScopeInitializationException e = new ScopeInitializationException("Context not an aggregate type"); + e.setIdentifier(context.getName()); + throw e; + } + AggregateContext aggregateCtx = (AggregateContext) context; + aggregateCtx.start(); + if (moduleScopeStarted) { + aggregateCtx.fireEvent(EventContext.MODULE_START, null); + } + contexts.put(aggregateCtx.getName(), aggregateCtx); + } + } + + public boolean isCacheable() { + return false; + } + + public Object getInstance(QualifiedName qName) throws TargetException { + Object instance = null; + InstanceContext context = getContext(qName.getPartName()); + if (context == null) { + TargetException e = new TargetException("Component not found"); + e.setIdentifier(qName.getQualifiedName()); + throw e; + } + return context.getInstance(qName); + } + + public Object getInstance(QualifiedName qName, boolean notify) throws TargetException { + return getInstance(qName); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + return contexts.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + return getContext(ctxName); + } + + public void removeContext(String ctxName) throws ScopeRuntimeException { + InstanceContext context = contexts.remove(ctxName); + if (context != null) { + context.stop(); + } + } + + public void removeContextByKey(String ctxName, Object key) throws ScopeRuntimeException { + } + + public void onEvent(int type, Object message) throws EventException { + if (type == EventContext.MODULE_START) { + // track module starting so that aggregate contexts registered after the event are notified properly + moduleScopeStarted = true; + } else if (type == EventContext.MODULE_STOP) { + moduleScopeStarted = false; + } + // propagate events to child contexts + for (AggregateContext context : contexts.values()) { + context.fireEvent(type, message); + } + } + + public Object getImplementationInstance() throws TargetException{ + return this; + } + + public Object getImplementationInstance(boolean notify) throws TargetException{ + return this; + } + + private void checkInit() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not running [" + lifecycleState + "]"); + } + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java new file mode 100644 index 0000000000..509eb7941f --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/DefaultScopeStrategy.java @@ -0,0 +1,52 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.ScopeContext; +import org.apache.tuscany.model.assembly.Scope; + +/** + * Implements a {@link org.apache.tuscany.core.context.ScopeStrategy} for the default module scopes: stateless, request, session, + * and module. + * + * @version $Rev$ $Date$ + */ +public class DefaultScopeStrategy extends AbstractScopeStrategy { + + public DefaultScopeStrategy() { + } + + public Map<Scope,ScopeContext> createScopes(EventContext eventContext) { + ScopeContext moduleScope = new ModuleScopeContext(eventContext); + ScopeContext sessionScope = new HttpSessionScopeContext(eventContext); + ScopeContext requestScope = new RequestScopeContext(eventContext); + ScopeContext statelessScope = new StatelessScopeContext(eventContext); + ScopeContext aggregrateScope = new AggregateScopeContext(eventContext); + Map<Scope,ScopeContext> scopes = new HashMap(); + scopes.put(Scope.MODULE,moduleScope); + scopes.put(Scope.SESSION,sessionScope); + scopes.put(Scope.REQUEST,requestScope); + scopes.put(Scope.INSTANCE,statelessScope); + scopes.put(Scope.AGGREGATE,aggregrateScope); + return scopes; + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java new file mode 100644 index 0000000000..e1fcc4ab70 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/HttpSessionScopeContext.java @@ -0,0 +1,254 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.ScopeRuntimeException; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * An implementation of an HTTP session-scoped component container where each HTTP session is mapped to a context in the scope + * + * @version $Rev$ $Date$ + */ +public class HttpSessionScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // The collection of service component contexts keyed by session + private Map<Object, Map<String, InstanceContext>> contexts; + + // Stores ordered lists of contexts to shutdown keyed by session + private Map<Object, Queue<InstanceContext>> destroyableContexts; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public HttpSessionScopeContext(EventContext eventContext) { + super(eventContext); + setName("Http Session Scope"); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope container must be in UNINITIALIZED state"); + } + super.start(); + contexts = new ConcurrentHashMap(); + destroyableContexts = new ConcurrentHashMap(); + lifecycleState = RUNNING; + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope container in wrong state"); + } + super.stop(); + contexts = null; + contexts = null; + destroyableContexts = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + checkInit(); + if (key == null) { + return; + } + if (type == EventContext.SESSION_END) { + notifyInstanceShutdown(key); + destroyComponentContext(key); + } + } + + // ---------------------------------- + // Scope methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + if (ctxName == null) { + return null; + } + // try{ + Map<String, InstanceContext> ctxs = getSessionContext(); + if (ctxs == null) { + return null; + } + InstanceContext ctx = ctxs.get(ctxName); + if (ctx == null) { + // the configuration was added after the session had started, so create a context now and start it + RuntimeConfiguration<InstanceContext> configuration = runtimeConfigurations.get(ctxName); + if (configuration != null) { + ctx = configuration.createInstanceContext(); + ctx.addContextListener(this); + ctx.start(); + ctxs.put(ctx.getName(), ctx); + } + } + return ctx; + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null && ctxName == null) { + return null; + } + Map components = (Map) contexts.get(key); + if (components == null) { + return null; + } + return (InstanceContext) components.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + removeContextByKey(ctxName, key); + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null || ctxName == null) { + return; + } + Map components = (Map) contexts.get(key); + if (components == null) { + return; + } + components.remove(ctxName); + Map definitions = contexts.get(key); + InstanceContext meta = (InstanceContext) definitions.get(ctxName); + destroyableContexts.get(key).remove(meta); + definitions.remove(ctxName); + } + + public void onInstanceCreate(Context context) throws ScopeRuntimeException { + checkInit(); + if (context instanceof SimpleComponentContext) { + // if destroyable, queue the context to have its component implementation instance released + if (((SimpleComponentContext) context).isDestroyable()) { + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + Queue comps = destroyableContexts.get(key); + if (comps == null) { + ScopeRuntimeException e = new ScopeRuntimeException("Shutdown queue not found for key"); + e.setIdentifier(key.toString()); + throw e; + } + comps.add(context); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown or + * null if none found. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + /* + * This method will be called from the Listener which is associated with a different thread than the request. So, just + * grab the key directly + */ + Queue queue = destroyableContexts.get(key); + if (queue != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) queue.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + /** + * Returns and, if necessary, creates a context for the current sesion + */ + private Map<String, InstanceContext> getSessionContext() throws CoreRuntimeException { + Object key = getEventContext().getIdentifier(EventContext.HTTP_SESSION); + if (key == null) { + throw new ScopeRuntimeException("Session key not set in request context"); + } + Map m = contexts.get(key); + if (m != null) { + return m; // already created, return + } + Map<String, InstanceContext> sessionContext = new ConcurrentHashMap(runtimeConfigurations.size()); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + sessionContext.put(context.getName(), context); + } + + Queue shutdownQueue = new ConcurrentLinkedQueue(); + contexts.put(key, sessionContext); + destroyableContexts.put(key, shutdownQueue); + // initialize eager components. Note this cannot be done when we initially create each context since a component may + // contain a forward reference to a component which has not been instantiated + for (InstanceContext context : sessionContext.values()) { + if (context instanceof SimpleComponentContext) { + SimpleComponentContext simpleCtx = (SimpleComponentContext) context; + if (simpleCtx.isEagerInit()) { + // Get the instance and perform manual shutdown registration to avoid a map lookup + context.getInstance(null, false); + if (simpleCtx.isDestroyable()) { + shutdownQueue.add(context); + } + } + } + } + return sessionContext; + } + + /** + * Removes the components associated with an expiring context + */ + private void destroyComponentContext(Object key) { + contexts.remove(key); + destroyableContexts.remove(key); + } + +}
\ No newline at end of file diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java new file mode 100644 index 0000000000..00f2747fae --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/ModuleScopeContext.java @@ -0,0 +1,182 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * Manages component contexts whose implementations are module scoped + * + * @version $Rev$ $Date$ + */ +public class ModuleScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // Component contexts in this scope keyed by name + private Map<String, InstanceContext> componentContexts; + + private Queue<SimpleComponentContext> destroyableContexts; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public ModuleScopeContext(EventContext eventContext) { + super(eventContext); + setName("Module Scope"); + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + if (type == EventContext.MODULE_START) { + lifecycleState = RUNNING; + initComponentContexts(); + } else if (type == EventContext.MODULE_STOP) { + notifyInstanceShutdown(key); + } + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + componentContexts = null; + destroyableContexts = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + if (lifecycleState == RUNNING) { + componentContexts.put(configuration.getName(), configuration.createInstanceContext()); + } + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + return componentContexts.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + return componentContexts.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + Object component = componentContexts.remove(ctxName); + if (component != null) { + destroyableContexts.remove(component); + } + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + removeContext(ctxName); + } + + public void onInstanceCreate(Context context) { + checkInit(); + if (context instanceof SimpleComponentContext) { + SimpleComponentContext serviceContext = (SimpleComponentContext) context; + // Queue the context to have its implementation instance released if destroyable + if (serviceContext.isDestroyable()) { + destroyableContexts.add(serviceContext); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + if (destroyableContexts != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) destroyableContexts.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + private synchronized void initComponentContexts() throws CoreRuntimeException { + if (componentContexts == null) { + componentContexts = new ConcurrentHashMap(); + destroyableContexts = new ConcurrentLinkedQueue(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + componentContexts.put(context.getName(), context); + } + // Initialize eager contexts. Note this cannot be done when we initially create each context since a component may + // contain a forward reference to a component which has not been instantiated + for (InstanceContext context : componentContexts.values()) { + if (context instanceof SimpleComponentContext) { + SimpleComponentContext simpleCtx = (SimpleComponentContext) context; + if (simpleCtx.isEagerInit()) { + // perform silent creation and manual shutdown registration + simpleCtx.getInstance(null, false); + if (simpleCtx.isDestroyable()) { + destroyableContexts.add(simpleCtx); + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java new file mode 100644 index 0000000000..deed3e2dee --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/RequestScopeContext.java @@ -0,0 +1,224 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.RuntimeEventListener; +import org.apache.tuscany.core.context.SimpleComponentContext; + +/** + * An implementation of a request-scoped component container. + * + * @version $Rev$ $Date$ + */ +public class RequestScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // A collection of service component contexts keyed by thread. Note this could have been implemented with a ThreadLocal but + // using a Map allows finer-grained concurrency. + private Map<Object, Map<String, InstanceContext>> contextMap; + + // stores ordered lists of contexts to shutdown for each thread. + private Map<Object, Queue> destroyComponents; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public RequestScopeContext(EventContext eventContext) { + super(eventContext); + setName("Request Scope"); + } + + // ---------------------------------- + // Listener methods + // ---------------------------------- + + public void onEvent(int type, Object key) { + checkInit(); + /* clean up current context for pooled threads */ + if (type == EventContext.REQUEST_END) { + getEventContext().clearIdentifier(EventContext.HTTP_SESSION); + notifyInstanceShutdown(Thread.currentThread()); + destroyContext(); + } + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + super.start(); + contextMap = new ConcurrentHashMap(); + destroyComponents = new ConcurrentHashMap(); + lifecycleState = RUNNING; + + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + contextMap = null; + destroyComponents = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public boolean isCacheable() { + return true; + } + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + } + + public InstanceContext getContext(String ctxName) { + checkInit(); + Map<String, InstanceContext> contexts = getComponentContexts(); + InstanceContext ctx = contexts.get(ctxName); + if (ctx == null){ + // check to see if the configuration was added after the request was started + RuntimeConfiguration<InstanceContext> configuration = runtimeConfigurations.get(ctxName); + if (configuration != null) { + ctx = configuration.createInstanceContext(); + ctx.addContextListener(this); + ctx.start(); + contexts.put(ctx.getName(), ctx); + } + } + return ctx; + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null) { + return null; + } + Map<String, InstanceContext> components = (Map) contextMap.get(key); + if (components == null) { + return null; + } + return components.get(ctxName); + } + + public void removeContext(String ctxName) { + checkInit(); + removeContextByKey(ctxName, Thread.currentThread()); + } + + public void removeContextByKey(String ctxName, Object key) { + checkInit(); + if (key == null || ctxName == null) { + return; + } + Map components = (Map) contextMap.get(key); + if (components == null) { + return; + } + components.remove(ctxName); + Map<String, InstanceContext> contexts = (Map) contextMap.get(key); + // no synchronization for the following two operations since the request + // context will not be shutdown before the second call is processed + InstanceContext context = contexts.get(ctxName); + destroyComponents.get(key).remove(context); + } + + public void onInstanceCreate(Context context) { + checkInit(); + if (context instanceof SimpleComponentContext) { + // Queue the context to have its implementation instance released if destroyable + if (((SimpleComponentContext) context).isDestroyable()) { + Queue collection = destroyComponents.get(Thread.currentThread()); + collection.add(context); + } + } + } + + /** + * Returns an array of {@link SimpleComponentContext}s representing components that need to be notified of scope shutdown. + */ + protected InstanceContext[] getShutdownContexts(Object key) { + checkInit(); + Queue queue = destroyComponents.get(Thread.currentThread()); + if (queue != null) { + // create 0-length array since Queue.size() has O(n) traversal + return (InstanceContext[]) queue.toArray(new InstanceContext[0]); + } else { + return null; + } + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + private void destroyContext() { + // TODO uninitialize all request-scoped components + contextMap.remove(Thread.currentThread()); + destroyComponents.remove(Thread.currentThread()); + } + + /** + * Initializes ServiceComponentContexts for the current request. + * <p> + * TODO This eagerly creates all component contexts, even if the component is never accessed during the request. This method + * should be profiled to determine if lazy initialization is more performant + * <p> + * TODO Eager initialization is not performed for request-scoped components + */ + + private Map<String, InstanceContext> getComponentContexts() throws CoreRuntimeException { + Map contexts = (Map) contextMap.get(Thread.currentThread()); + if (contexts == null) { + contexts = new ConcurrentHashMap(); + Queue shutdownQueue = new ConcurrentLinkedQueue(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + contexts.put(context.getName(), context); + } + contextMap.put(Thread.currentThread(), contexts); + destroyComponents.put(Thread.currentThread(), shutdownQueue); + } + return contexts; + } + +}
\ No newline at end of file diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java new file mode 100644 index 0000000000..8b12f8b183 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/scope/StatelessScopeContext.java @@ -0,0 +1,145 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.core.builder.RuntimeConfiguration; +import org.apache.tuscany.core.context.InstanceContext; +import org.apache.tuscany.core.context.Context; +import org.apache.tuscany.core.context.LifecycleEventListener; +import org.apache.tuscany.core.context.CoreRuntimeException; +import org.apache.tuscany.core.context.EventContext; +import org.apache.tuscany.core.context.RuntimeEventListener; + +/** + * A container that manages stateless components. + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContext extends AbstractScopeContext implements RuntimeEventListener, LifecycleEventListener { + + // ---------------------------------- + // Fields + // ---------------------------------- + + // Component contexts keyed by name + private Map<String, InstanceContext> contextMap; + + // ---------------------------------- + // Constructor + // ---------------------------------- + + public StatelessScopeContext(EventContext eventContext) { + super(eventContext); + setName("Stateless Scope"); + } + + // ---------------------------------- + // Lifecycle methods + // ---------------------------------- + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED state [" + lifecycleState + "]"); + } + super.start(); + lifecycleState = RUNNING; + prepare(); + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + super.stop(); + contextMap = null; + lifecycleState = STOPPED; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void registerConfiguration(RuntimeConfiguration<InstanceContext> configuration) { + runtimeConfigurations.put(configuration.getName(), configuration); + if (lifecycleState == RUNNING) { + contextMap.put(configuration.getName(), configuration.createInstanceContext()); + } + + } + + public void onEvent(int type, Object key) { + // do nothing + } + + public boolean isCacheable() { + return true; + } + + public InstanceContext getContext(String ctxName) { + return contextMap.get(ctxName); + } + + public InstanceContext getContextByKey(String ctxName, Object key) { + return getContext(ctxName); + } + + public void removeContext(String ctxName) { + removeContextByKey(ctxName, null); + } + + public void removeContextByKey(String ctxName, Object key) { + contextMap.remove(ctxName); + } + + /** + * Always returns null since stateless components cannot be shutdown + */ + protected InstanceContext[] getShutdownContexts(Object key) { + return null; + } + + // ---------------------------------- + // Private methods + // ---------------------------------- + + public void onInstanceCreate(Context component) { + // do nothing + } + + private void prepare() throws CoreRuntimeException { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope not in INITIALIZED state [" + lifecycleState + "]"); + } + if (contextMap == null) { + contextMap = new ConcurrentHashMap(); + for (RuntimeConfiguration<InstanceContext> config : runtimeConfigurations.values()) { + for (int i = 0; i < runtimeConfigurations.size(); i++) { + InstanceContext context = null; + context = config.createInstanceContext(); + context.addContextListener(this); + context.start(); + contextMap.put(context.getName(), context); + } + + } + } + } + +}
\ No newline at end of file diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java new file mode 100644 index 0000000000..923b9fb941 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/HTTPSessionExpirationListener.java @@ -0,0 +1,62 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; + +/** + * Cleans up resources used by expired sessions + * + * @version $Rev$ $Date$ + */ +public class HTTPSessionExpirationListener implements HttpSessionListener { + // ---------------------------------- + // Constructors + // ---------------------------------- + + public HTTPSessionExpirationListener() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void sessionCreated(HttpSessionEvent event) { + // do nothing since sessions are lazily created in {@link + // org.apache.tuscany.tomcat.webapp.listener.RequestFilter} + } + + public void sessionDestroyed(HttpSessionEvent event) { + TuscanyWebAppRuntime tuscanyRuntime = null; + try { + tuscanyRuntime = (TuscanyWebAppRuntime) event.getSession().getServletContext().getAttribute( + TuscanyWebAppRuntime.class.getName()); + tuscanyRuntime.start(); + + // End the session + AggregateContext context = tuscanyRuntime.getModuleComponentContext(); + context.fireEvent(EventContext.SESSION_END, event.getSession()); + } finally { + if (tuscanyRuntime != null) + tuscanyRuntime.stop(); + } + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java new file mode 100644 index 0000000000..186f35df14 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/LazyHTTPSessionId.java @@ -0,0 +1,56 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.tuscany.core.context.ScopeIdentifier; + +/** + * Implements a <code>ScopeIdentifier</code> for a Servlet-based transport. + * Wraps an <code>HttpServletRequest</code> so that the session id associated + * with the current request may be lazily retrieved by the module context - i.e. + * if a session context or session-scoped component is not accessed, no session + * is created. + * + * @version $Rev$ $Date$ + */ +public class LazyHTTPSessionId implements ScopeIdentifier { + + private HttpServletRequest request; + + //---------------------------------- + // Constructors + //---------------------------------- + + public LazyHTTPSessionId(HttpServletRequest request) { + this.request = request; + } + + //---------------------------------- + // Methods + //---------------------------------- + + /** + * Returns the session identifier + * + * @see org.apache.tuscany.core.context.ScopeIdentifier#getIdentifier() + */ + public Object getIdentifier() { + return request.getSession(true); + } +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java new file mode 100644 index 0000000000..8e92c9ebd4 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyRequestFilter.java @@ -0,0 +1,107 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.tuscany.core.context.AggregateContext; +import org.apache.tuscany.core.context.EventContext; + +/** + * Notifies the {@link org.apache.tuscany.core.context.AggregateContext} of web request start and end events as well as setting up the + * current session context. The latter is done using lazy Servlet-based session retrieval. The filter fires a session + * start event, passing a <tt>LazyServletSessionId</tt> as the session id. The <tt>LazyServletSessionId</tt> is a + * wrapper for the servlet request which may be called by the <tt>ModuleContext</tt> to retrieve the session id + * lazily. + * + * @version $Rev$ $Date$ + */ +public class TuscanyRequestFilter implements Filter { + private TuscanyWebAppRuntime tuscanyRuntime; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public TuscanyRequestFilter() { + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + public void init(FilterConfig filterConfig) throws ServletException { + + // Get the Tuscany runtime from the servlet context + tuscanyRuntime = (TuscanyWebAppRuntime) filterConfig.getServletContext().getAttribute( + TuscanyWebAppRuntime.class.getName()); + } + + public void destroy() { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, + IOException { + // Get the module component context from the tuscany runtime + AggregateContext context = tuscanyRuntime.getModuleComponentContext(); + try { + + // Start the SCA implementation + tuscanyRuntime.start(); + + // Handle a request + if (request instanceof HttpServletRequest) { + if (((HttpServletRequest) request).getSession(false) != null) { + + // A session is already active + context.fireEvent(EventContext.SESSION_NOTIFY, ((HttpServletRequest) request).getSession(true)); + } else { + // Create a lazy wrapper since a session is not yet active + context.fireEvent(EventContext.SESSION_NOTIFY, new LazyHTTPSessionId((HttpServletRequest) request)); + } + } else { + context.fireEvent(EventContext.SESSION_NOTIFY, request); + } + // Start processing the request + context.fireEvent(EventContext.REQUEST_START, request); + // Dispatch to the next filter + filterChain.doFilter(request, response); + } catch (Exception e) { + throw new ServletException(e); + + } finally { + try { + // End processing the request + context.fireEvent(EventContext.REQUEST_END, request); + // Stop the SCA implementation + tuscanyRuntime.stop(); + } catch (Exception e) { + throw new ServletException(e); + } + } + + } + +} diff --git a/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java new file mode 100644 index 0000000000..3b9801a811 --- /dev/null +++ b/sca-java-1.x/tags/java-stable-20060304/sca/core/src/main/java/org/apache/tuscany/core/context/webapp/TuscanyWebAppRuntime.java @@ -0,0 +1,59 @@ +/** + * + * Copyright 2005 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tuscany.core.context.webapp; + +import org.apache.tuscany.core.context.AggregateContext; +import org.osoa.sca.ModuleContext; +import org.osoa.sca.SCA; + +/** + * An implementation of the SCA runtime for use in a Web app + * + * @version $Rev$ $Date$ + */ +public class TuscanyWebAppRuntime extends SCA { + private AggregateContext moduleComponentContext; + + // ---------------------------------- + // Constructors + // ---------------------------------- + + public TuscanyWebAppRuntime(AggregateContext moduleComponentContext) { + this.moduleComponentContext = moduleComponentContext; + } + + // ---------------------------------- + // Methods + // ---------------------------------- + + /** + * Returns the module component context associated with this runtime + */ + public AggregateContext getModuleComponentContext() { + return moduleComponentContext; + } + + public void start() { + // Associate it with the current thread + setModuleContext((ModuleContext) moduleComponentContext); + } + + public void stop() { + setModuleContext(null); + } + +} |