summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-2.0-M2/modules/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-2.0-M2/modules/core/src')
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java37
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java137
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java80
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl2.java874
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointReferenceImpl.java186
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java101
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java139
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java111
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java144
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java163
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl2.java507
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceExt.java68
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextExt.java31
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CompositeContext.java225
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java42
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java29
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallableReferenceImpl.java609
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java479
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CompositeContextImpl.java355
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java117
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java135
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationExt.java66
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java71
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java29
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ConversationManagerImpl.java218
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ExtendedConversationImpl.java267
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java48
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java47
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java35
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CachedProxy.java70
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java63
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java57
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java49
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java47
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java152
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java75
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java114
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java194
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java48
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java88
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java53
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java264
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java73
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java55
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/CallbackReferenceImpl.java301
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java191
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java110
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java519
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java105
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java36
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java104
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java45
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java298
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java236
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java196
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java46
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java66
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java158
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java32
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java43
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java65
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java82
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainer.java293
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainerFactory.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainer.java74
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainerFactory.java44
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainer.java79
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainerFactory.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java68
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java59
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java40
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java191
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java229
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java65
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java80
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java167
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java32
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory17
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory17
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor19
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.assembly.CompositeActivator18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.conversation.ConversationManager18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler18
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/CallbackInterfaceInterceptorTestCase.java.fixme62
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java95
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/NonBlockingInterceptorTestCase.java.fixme74
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java50
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java67
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java54
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java43
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java71
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java154
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java240
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java153
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java243
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java86
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java66
-rw-r--r--branches/sca-java-2.0-M2/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest24
110 files changed, 12913 insertions, 0 deletions
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java
new file mode 100644
index 0000000000..c86c876075
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly;
+
+
+/**
+ * Denotes an error starting the runtime
+ *
+ * @version $Rev$ $Date$
+ */
+public class ActivationException extends Exception {
+ private static final long serialVersionUID = 8612661660934426123L;
+
+ public ActivationException(String message) {
+ super(message);
+ }
+
+ public ActivationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java
new file mode 100644
index 0000000000..939afa40a8
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * Start/stop a composite
+ *
+ * @version $Rev$ $Date$
+ */
+public interface CompositeActivator {
+ /**
+ * Activate a composite
+ * @param composite
+ */
+ void activate(Composite composite) throws ActivationException;
+
+ /**
+ * Activate a component reference
+ * @param component
+ * @param ref
+ */
+ void start(RuntimeComponent component, RuntimeComponentReference ref);
+
+ /**
+ * Activate a component reference
+ * @param component
+ * @param ref
+ */
+ void activate(RuntimeComponent component, RuntimeComponentReference ref);
+
+ /**
+ * Activate a component reference
+ * @param component
+ * @param ref
+ */
+ void activate(RuntimeComponent component, RuntimeComponentService service);
+
+ /**
+ * De-activate a component reference
+ * @param component
+ * @param ref
+ */
+ void deactivate(RuntimeComponent component, RuntimeComponentReference ref);
+
+ /**
+ * De-activate a component reference
+ * @param component
+ * @param ref
+ */
+ void deactivate(RuntimeComponent component, RuntimeComponentService service);
+
+ /**
+ * Stop a composite
+ * @param composite
+ */
+ void deactivate(Composite composite) throws ActivationException;
+
+ /**
+ * Start a component
+ * @param component
+ */
+ void start(Component component) throws ActivationException;
+
+ /**
+ * Stop a component
+ * @param component
+ */
+ void stop(Component component) throws ActivationException;
+
+ /**
+ * Start components in a composite
+ * @param composite
+ */
+ void start(Composite composite) throws ActivationException;
+
+ /**
+ * Stop components in a composite
+ * @param composite
+ */
+ void stop(Composite composite) throws ActivationException;
+
+ /**
+ * Get the component context helper
+ * @return
+ */
+ CompositeContext getCompositeContext();
+
+ /**
+ * Configure the runtime component with component context
+ * @param component
+ */
+ void configureComponentContext(RuntimeComponent component);
+
+ /**
+ * Resolve a component by URI in the domain
+ * @param componentURI
+ * @return
+ */
+ Component resolve(String componentURI);
+
+ /**
+ * Set the domain composite
+ * @param domainComposite
+ */
+ void setDomainComposite(Composite domainComposite);
+
+ /**
+ * Get the domain composite
+ * @return
+ */
+ Composite getDomainComposite();
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java
new file mode 100644
index 0000000000..8d8c9d10e8
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.assembly.impl.ReferenceParametersImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentReferenceImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentServiceImpl;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * The runtime version of assembly factory
+ * @version $Rev$ $Date$
+ */
+public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory {
+
+ public RuntimeAssemblyFactory() {
+ super();
+ }
+
+ @Override
+ public Component createComponent() {
+ return new RuntimeComponentImpl();
+ }
+
+ @Override
+ public ComponentReference createComponentReference() {
+ return new RuntimeComponentReferenceImpl();
+ }
+
+ @Override
+ public ComponentService createComponentService() {
+ return new RuntimeComponentServiceImpl();
+ }
+
+ // FIXME: [rfeng] We need to find a more consistent story to deal with EPR, EP and CallableReference
+ public EndpointReference createEndpointReference(String uri) {
+ return new EndpointReferenceImpl(uri);
+ }
+
+ public EndpointReference createEndpointReference(RuntimeComponent component,
+ Contract contract,
+ Binding binding,
+ InterfaceContract interfaceContract) {
+ return new EndpointReferenceImpl(component, contract, binding, interfaceContract);
+ }
+
+ public ReferenceParameters createReferenceParameters() {
+ return new ReferenceParametersImpl();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl2.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl2.java
new file mode 100644
index 0000000000..de304ac3b5
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl2.java
@@ -0,0 +1,874 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Endpoint2;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.context.ComponentContextFactory;
+import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint;
+import org.apache.tuscany.sca.context.PropertyValueFactory;
+import org.apache.tuscany.sca.context.RequestContextFactory;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.assembly.ActivationException;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.core.context.impl.CompositeContextImpl;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeRegistry;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+import org.apache.tuscany.sca.core.scope.impl.ConversationalScopeContainer;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.provider.ImplementationProviderFactory;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.provider.PolicyProviderFactory;
+import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint;
+import org.apache.tuscany.sca.work.WorkScheduler;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CompositeActivatorImpl2 implements CompositeActivator {
+ private static final Logger logger = Logger.getLogger(CompositeActivatorImpl2.class.getName());
+
+ private final AssemblyFactory assemblyFactory;
+ private final MessageFactory messageFactory;
+ private final InterfaceContractMapper interfaceContractMapper;
+ private final ScopeRegistry scopeRegistry;
+ private final WorkScheduler workScheduler;
+ private final RuntimeWireProcessor wireProcessor;
+ private final ProviderFactoryExtensionPoint providerFactories;
+
+ private final ComponentContextFactory componentContextFactory;
+ private final RequestContextFactory requestContextFactory;
+ private final ProxyFactory proxyFactory;
+ private final JavaInterfaceFactory javaInterfaceFactory;
+ private final PropertyValueFactory propertyValueFactory;
+
+ private final ConversationManager conversationManager;
+
+ private final CompositeContext compositeContext;
+
+ private Composite domainComposite;
+
+ public CompositeActivatorImpl2(ExtensionPointRegistry extensionPoints) {
+ this.compositeContext = new CompositeContextImpl(extensionPoints);
+ FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.messageFactory = factories.getFactory(MessageFactory.class);
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+ this.scopeRegistry = utilities.getUtility(ScopeRegistry.class);
+ this.workScheduler = utilities.getUtility(WorkScheduler.class);
+ this.wireProcessor = new ExtensibleWireProcessor(extensionPoints.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class));
+ this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class);
+ this.javaInterfaceFactory = compositeContext.getJavaInterfaceFactory();
+ this.propertyValueFactory = factories.getFactory(PropertyValueFactory.class);
+ ContextFactoryExtensionPoint contextFactories = extensionPoints.getExtensionPoint(ContextFactoryExtensionPoint.class);
+ this.componentContextFactory = contextFactories.getFactory(ComponentContextFactory.class);
+ this.requestContextFactory = contextFactories.getFactory(RequestContextFactory.class);
+ proxyFactory = compositeContext.getProxyFactory();
+ this.conversationManager = compositeContext.getConversationManager();
+ }
+
+ //=========================================================================
+ // Activation
+ //=========================================================================
+
+ // Composite activation/deactivation
+
+ public void activate(Composite composite) throws ActivationException {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating composite: " + composite.getName());
+ }
+ for (Component component : composite.getComponents()) {
+ activateComponent(component);
+ }
+ } catch (Exception e) {
+ throw new ActivationException(e);
+ }
+ }
+
+ public void deactivate(Composite composite) throws ActivationException {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating composite: " + composite.getName());
+ }
+ for (Component component : composite.getComponents()) {
+ deactivateComponent(component);
+ }
+ } catch (Exception e) {
+ throw new ActivationException(e);
+ }
+ }
+
+ // Component activation/deactivation
+
+ public void activateComponent(Component component)
+ throws ActivationException {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating component: " + component.getURI());
+ }
+
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ activate((Composite) implementation);
+ } else if (implementation != null) {
+ addImplementationProvider((RuntimeComponent) component,
+ implementation);
+ addScopeContainer(component);
+ }
+
+ for (ComponentService service : component.getServices()) {
+ activate((RuntimeComponent) component,
+ (RuntimeComponentService) service);
+ }
+
+ for (ComponentReference reference : component.getReferences()) {
+ activate((RuntimeComponent) component,
+ (RuntimeComponentReference) reference);
+ }
+ } catch (Exception e) {
+ throw new ActivationException(e);
+ }
+ }
+
+ public void deactivateComponent(Component component)
+ throws ActivationException {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating component: " + component.getURI());
+ }
+ for (ComponentService service : component.getServices()) {
+ deactivate((RuntimeComponent) component,
+ (RuntimeComponentService) service);
+ }
+
+ for (ComponentReference reference : component.getReferences()) {
+ deactivate((RuntimeComponent) component,
+ (RuntimeComponentReference) reference);
+ }
+
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ deactivate((Composite) implementation);
+ } else if (implementation != null) {
+ removeImplementationProvider((RuntimeComponent) component);
+ removeScopeContainer(component);
+ }
+ } catch (Exception e) {
+ throw new ActivationException(e);
+ }
+ }
+
+ // add/remove artifacts required to get the implementation going
+
+ private void addImplementationProvider(RuntimeComponent component, Implementation implementation) {
+ ImplementationProviderFactory providerFactory =
+ (ImplementationProviderFactory)providerFactories.getProviderFactory(implementation.getClass());
+ if (providerFactory != null) {
+ @SuppressWarnings("unchecked")
+ ImplementationProvider implementationProvider =
+ providerFactory.createImplementationProvider(component, implementation);
+ if (implementationProvider != null) {
+ component.setImplementationProvider(implementationProvider);
+ }
+ } else {
+ throw new IllegalStateException("Provider factory not found for class: " + implementation.getClass()
+ .getName());
+ }
+ for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) {
+ PolicyProvider policyProvider = f.createImplementationPolicyProvider(component, implementation);
+ if (policyProvider != null) {
+ component.addPolicyProvider(policyProvider);
+ }
+ }
+
+ }
+
+ private void removeImplementationProvider(RuntimeComponent component) {
+ component.setImplementationProvider(null);
+ component.getPolicyProviders().clear();
+ }
+
+ private void addScopeContainer(Component component) {
+ if (!(component instanceof ScopedRuntimeComponent)) {
+ return;
+ }
+ ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component;
+ ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent);
+ if (scopeContainer != null && scopeContainer.getScope() == Scope.CONVERSATION) {
+ conversationManager.addListener((ConversationalScopeContainer)scopeContainer);
+ }
+ runtimeComponent.setScopeContainer(scopeContainer);
+ }
+
+ private void removeScopeContainer(Component component) {
+ if (!(component instanceof ScopedRuntimeComponent)) {
+ return;
+ }
+ ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component;
+ ScopeContainer scopeContainer = runtimeComponent.getScopeContainer();
+ if(scopeContainer != null && scopeContainer.getScope() == Scope.CONVERSATION) {
+ conversationManager.removeListener((ConversationalScopeContainer) scopeContainer);
+ }
+ runtimeComponent.setScopeContainer(null);
+ }
+
+
+ // Service activation/deactivation
+
+ public void activate(RuntimeComponent component, RuntimeComponentService service) {
+ if (service.getService() == null) {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("Skipping component service not defined in the component type: " + component.getURI()
+ + "#"
+ + service.getName());
+ }
+ return;
+ }
+
+ /* TODO - EPR - activate services at all levels as promoted endpoin references are maintained
+ * on the higher level services
+ if (service.getService() instanceof CompositeService) {
+ return;
+ }
+ */
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating component service: " + component.getURI() + "#" + service.getName());
+ }
+
+ for (Endpoint2 endpoint : service.getEndpoints()) {
+ addServiceBindingProvider(component, service, endpoint.getBinding());
+ }
+ addServiceWires(component, service);
+ }
+
+ public void deactivate(RuntimeComponent component, RuntimeComponentService service) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating component service: " + component.getURI() + "#" + service.getName());
+ }
+ removeServiceWires(service);
+ for (Binding binding : service.getBindings()) {
+ removeServiceBindingProvider(component, service, binding);
+ }
+ }
+
+ private ServiceBindingProvider addServiceBindingProvider(
+ RuntimeComponent component, RuntimeComponentService service,
+ Binding binding) {
+ BindingProviderFactory providerFactory = (BindingProviderFactory) providerFactories
+ .getProviderFactory(binding.getClass());
+ if (providerFactory != null) {
+ @SuppressWarnings("unchecked")
+ ServiceBindingProvider bindingProvider = providerFactory
+ .createServiceBindingProvider((RuntimeComponent) component,
+ (RuntimeComponentService) service, binding);
+ if (bindingProvider != null) {
+ ((RuntimeComponentService) service).setBindingProvider(binding,
+ bindingProvider);
+ }
+ for (PolicyProviderFactory f : providerFactories
+ .getPolicyProviderFactories()) {
+ PolicyProvider policyProvider = f.createServicePolicyProvider(
+ component, service, binding);
+ if (policyProvider != null) {
+ service.addPolicyProvider(binding, policyProvider);
+ }
+ }
+ return bindingProvider;
+ } else {
+ throw new IllegalStateException(
+ "Provider factory not found for class: "
+ + binding.getClass().getName());
+ }
+ }
+
+ private void removeServiceBindingProvider(RuntimeComponent component,
+ RuntimeComponentService service, Binding binding) {
+ service.setBindingProvider(binding, null);
+ for (Binding b : service.getBindings()) {
+ List<PolicyProvider> pps = service.getPolicyProviders(b);
+ if (pps != null) {
+ pps.clear();
+ }
+ }
+ }
+
+ private void addServiceWires(Component serviceComponent, ComponentService service) {
+ if (!(service instanceof RuntimeComponentService)) {
+ return;
+ }
+
+ RuntimeComponentService runtimeService = (RuntimeComponentService)service;
+
+ // Add a wire for each service Endpoint
+ for ( Endpoint2 endpoint : runtimeService.getEndpoints()){
+
+ // fluff up a fake endpoint reference as we are on the service side
+ // so we need to represent the reference that will call us
+ EndpointReference2 endpointReference = assemblyFactory.createEndpointReference();
+ endpointReference.setBinding(endpoint.getBinding());
+ endpointReference.setTargetEndpoint(endpoint);
+
+ // create the interface contract for the binding and service ends of the wire
+ // that are created as forward only contracts
+ // FIXME: [rfeng] We might need a better way to get the impl interface contract
+ Service targetService = service.getService();
+ if (targetService == null) {
+ targetService = service;
+ }
+ endpoint.setInterfaceContract(targetService.getInterfaceContract().makeUnidirectional(false));
+ endpointReference.setInterfaceContract(getServiceBindingInterfaceContract(service, endpoint.getBinding()));
+
+ // create the wire
+ RuntimeWire wire = new RuntimeWireImpl2(false,
+ endpointReference,
+ endpoint,
+ interfaceContractMapper,
+ workScheduler,
+ wireProcessor,
+ messageFactory,
+ conversationManager);
+
+ runtimeService.getRuntimeWires().add(wire);
+ }
+ }
+
+ private void removeServiceWires(ComponentService service) {
+ if (!(service instanceof RuntimeComponentService)) {
+ return;
+ }
+ RuntimeComponentService runtimeService = (RuntimeComponentService)service;
+ runtimeService.getRuntimeWires().clear();
+ }
+
+ private InterfaceContract getServiceBindingInterfaceContract(ComponentService service, Binding binding) {
+ InterfaceContract interfaceContract = service.getInterfaceContract();
+
+ ServiceBindingProvider provider = ((RuntimeComponentService)service).getBindingProvider(binding);
+ if (provider != null) {
+ InterfaceContract bindingContract = provider.getBindingInterfaceContract();
+ if (bindingContract != null) {
+ interfaceContract = bindingContract;
+ }
+ }
+ return interfaceContract.makeUnidirectional(false);
+ }
+
+ // Reference activation/deactivation
+
+ public void activate(RuntimeComponent component, RuntimeComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating component reference: " + component.getURI() + "#" + reference.getName());
+ }
+
+ // TODO this may need to move into the code where we check that an endpoint is resolved
+ for (EndpointReference2 endpointReference : reference.getEndpointReferences()) {
+ if (endpointReference.getBinding() != null){
+ addReferenceBindingProvider(component, reference, endpointReference.getBinding());
+ }
+ }
+
+ // set the parent component onto the reference. It's used at start time when the
+ // reference is asked to return it's runtime wires. If there are none the reference
+ // asks the component context to start the reference which creates the wires
+ reference.setComponent(component);
+
+ // TODO reference wires are added at component start for some reason
+ }
+
+ public void deactivate(RuntimeComponent component, RuntimeComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating component reference: " + component.getURI() + "#" + reference.getName());
+ }
+ removeReferenceWires(reference);
+ for (EndpointReference2 endpointReference : reference.getEndpointReferences()) {
+ if (endpointReference.getBinding() != null){
+ removeReferenceBindingProvider(component, reference, endpointReference.getBinding());
+ }
+ }
+ }
+
+ private ReferenceBindingProvider addReferenceBindingProvider(
+ RuntimeComponent component, RuntimeComponentReference reference,
+ Binding binding) {
+ BindingProviderFactory providerFactory = (BindingProviderFactory) providerFactories
+ .getProviderFactory(binding.getClass());
+ if (providerFactory != null) {
+ @SuppressWarnings("unchecked")
+ ReferenceBindingProvider bindingProvider = providerFactory
+ .createReferenceBindingProvider(
+ (RuntimeComponent) component,
+ (RuntimeComponentReference) reference, binding);
+ if (bindingProvider != null) {
+ ((RuntimeComponentReference) reference).setBindingProvider(
+ binding, bindingProvider);
+ }
+ for (PolicyProviderFactory f : providerFactories
+ .getPolicyProviderFactories()) {
+ PolicyProvider policyProvider = f
+ .createReferencePolicyProvider(component, reference,
+ binding);
+ if (policyProvider != null) {
+ reference.addPolicyProvider(binding, policyProvider);
+ }
+ }
+
+ return bindingProvider;
+ } else {
+ throw new IllegalStateException(
+ "Provider factory not found for class: "
+ + binding.getClass().getName());
+ }
+ }
+
+ private void removeReferenceBindingProvider(RuntimeComponent component,
+ RuntimeComponentReference reference, Binding binding) {
+ reference.setBindingProvider(binding, null);
+ for (Binding b : reference.getBindings()) {
+ List<PolicyProvider> pps = reference.getPolicyProviders(b);
+ if (pps != null) {
+ pps.clear();
+ }
+ }
+ }
+
+ private void removeReferenceWires(ComponentReference reference) {
+ if (!(reference instanceof RuntimeComponentReference)) {
+ return;
+ }
+
+ // TODO - EPR what is this all about?
+ // [rfeng] Comment out the following statements to avoid the on-demand activation
+ // RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference;
+ // runtimeRef.getRuntimeWires().clear();
+ }
+
+ //=========================================================================
+ // Start
+ //=========================================================================
+
+ // Composite start/stop
+
+ public void start(Composite composite) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting composite: " + composite.getName());
+ }
+ for (Component component : composite.getComponents()) {
+ start(component);
+ }
+ }
+
+ public void stop(Composite composite) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping composite: " + composite.getName());
+ }
+ for (final Component component : composite.getComponents()) {
+ stop(component);
+ }
+ }
+
+ // Component start/stop
+
+ public void start(Component component) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component: " + component.getURI());
+ }
+ RuntimeComponent runtimeComponent = ((RuntimeComponent)component);
+ if(runtimeComponent.isStarted()) {
+ return;
+ }
+
+ configureComponentContext(runtimeComponent);
+
+/* TODO - EPR won't start until reference is actually started later
+ for (ComponentReference reference : component.getReferences()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName());
+ }
+ RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference);
+ runtimeRef.setComponent(runtimeComponent);
+
+ for (Binding binding : reference.getBindings()) {
+ final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(binding);
+ if (bindingProvider != null) {
+ // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.start();
+ return null;
+ }
+ });
+ }
+ }
+ }
+*/
+
+ for (ComponentService service : component.getServices()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component service: " + component.getURI() + "#" + service.getName());
+ }
+ RuntimeComponentService runtimeService = (RuntimeComponentService)service;
+ for (Endpoint2 endpoint : service.getEndpoints()) {
+ final ServiceBindingProvider bindingProvider = runtimeService.getBindingProvider(endpoint.getBinding());
+ if (bindingProvider != null) {
+ // bindingProvider.start();
+ // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.start();
+ return null;
+ }
+ });
+ }
+ }
+ }
+
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ start((Composite)implementation);
+ } else {
+ ImplementationProvider implementationProvider = runtimeComponent.getImplementationProvider();
+ if (implementationProvider != null) {
+ implementationProvider.start();
+ }
+ }
+
+ if (component instanceof ScopedRuntimeComponent) {
+ ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)component;
+ if (scopedRuntimeComponent.getScopeContainer() != null) {
+ scopedRuntimeComponent.getScopeContainer().start();
+ }
+ }
+
+ runtimeComponent.setStarted(true);
+ }
+
+ public void stop(Component component) {
+ if (!((RuntimeComponent)component).isStarted()) {
+ return;
+ }
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping component: " + component.getURI());
+ }
+ for (ComponentService service : component.getServices()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping component service: " + component.getURI() + "#" + service.getName());
+ }
+ for (Endpoint2 endpoint : service.getEndpoints()) {
+ final ServiceBindingProvider bindingProvider = ((RuntimeComponentService)service).getBindingProvider(endpoint.getBinding());
+ if (bindingProvider != null) {
+ // Allow bindings to read properties. Requires PropertyPermission read in security policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.stop();
+ return null;
+ }
+ });
+ }
+ }
+ }
+ for (ComponentReference reference : component.getReferences()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName());
+ }
+ RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference);
+
+ for (EndpointReference2 endpointReference : reference.getEndpointReferences()) {
+ final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding());
+ if (bindingProvider != null) {
+ // Allow bindings to read properties. Requires PropertyPermission read in security policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.stop();
+ return null;
+ }
+ });
+ }
+ }
+ }
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ stop((Composite)implementation);
+ } else {
+ final ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider();
+ if (implementationProvider != null) {
+ // Allow bindings to read properties. Requires PropertyPermission read in security policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ implementationProvider.stop();
+ return null;
+ }
+ });
+ }
+ }
+
+ if (component instanceof ScopedRuntimeComponent) {
+ ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component;
+ if (runtimeComponent.getScopeContainer() != null &&
+ runtimeComponent.getScopeContainer().getLifecycleState() != ScopeContainer.STOPPED) {
+ runtimeComponent.getScopeContainer().stop();
+ }
+ }
+
+ ((RuntimeComponent)component).setStarted(false);
+ }
+
+ public void configureComponentContext(RuntimeComponent runtimeComponent) {
+ RuntimeComponentContext componentContext = (RuntimeComponentContext) componentContextFactory.createComponentContext(runtimeComponent);
+ runtimeComponent.setComponentContext(componentContext);
+ }
+
+ // Service start/stop
+
+ // TODO - EPR done as part of the component start above
+
+ // Reference start/stop
+ // Used by component context start
+ // TODO - EPR I don't know why reference wires don't get added until component start
+
+ public void start(RuntimeComponent component, RuntimeComponentReference componentReference) {
+ synchronized (componentReference) {
+
+ if (!(componentReference instanceof RuntimeComponentReference)) {
+ return;
+ }
+
+ // create a wire for each endpoint reference. An endpoint reference says that a
+ // target has been specified and hence the reference has been wired in some way.
+ // The service may not have been found yet, depending on the way the composite
+ // is deployed, but it is expected to be found. In the case where the reference
+ // is unwired (a target has not been specified) there will be no endpoint
+ // reference and this will lead to null being injected
+ for (EndpointReference2 endpointReference : componentReference.getEndpointReferences()){
+
+ // if there is a binding an endpoint has been found for the endpoint reference
+ if (endpointReference.getBinding() != null){
+
+ // add the binding provider. This is apparently a repeat
+ // of previous configuration as self references are created
+ // on the fly and miss the previous point where providers are added
+ RuntimeComponentReference runtimeRef = (RuntimeComponentReference)componentReference;
+
+ if (runtimeRef.getBindingProvider(endpointReference.getBinding()) == null) {
+ addReferenceBindingProvider(component, componentReference, endpointReference.getBinding());
+ }
+
+ // start the binding provider
+ final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding());
+
+ if (bindingProvider != null) {
+ // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.start();
+ return null;
+ }
+ });
+ }
+
+ // add the wire
+ addReferenceWire(component, componentReference, endpointReference);
+ }
+ }
+ }
+ }
+
+ public void stop(Component component, ComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName());
+ }
+ RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference);
+ for ( EndpointReference2 endpointReference : runtimeRef.getEndpointReferences()){
+ ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding());
+ if (bindingProvider != null) {
+ bindingProvider.stop();
+ }
+ }
+ }
+
+ private void addReferenceWire(Component component, ComponentReference reference, EndpointReference2 endpointReference) {
+ RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference;
+
+ // Use the interface contract of the reference on the component type and if there
+ // isn't one then use the one from the reference itself
+ Reference componentTypeRef = reference.getReference();
+
+ InterfaceContract sourceContract;
+ if (componentTypeRef == null || componentTypeRef.getInterfaceContract() == null) {
+ sourceContract = reference.getInterfaceContract();
+ } else {
+ sourceContract = componentTypeRef.getInterfaceContract();
+ }
+
+ // TODO - EPR - interface contract seems to be null in the implementation.web
+ // case. Not introspecting the CT properly?
+ if (sourceContract == null){
+ // take the contract from the service to which the reference is connected
+ sourceContract = endpointReference.getTargetEndpoint().getInterfaceContract();
+ reference.setInterfaceContract(sourceContract);
+ }
+
+ endpointReference.setInterfaceContract(sourceContract.makeUnidirectional(false));
+
+/* TODO - EPR should have been done previously during matching
+ ComponentService callbackService = reference.getCallbackService();
+ if (callbackService != null) {
+ // select a reference callback binding to pass with invocations on this wire
+ Binding callbackBinding = null;
+ for (Binding binding : callbackService.getBindings()) {
+ // first look for a callback binding whose name matches the reference binding name
+ if (refBinding.getName().startsWith(binding.getName())) {
+ callbackBinding = binding;
+ break;
+ }
+ }
+ // if no callback binding found, try again based on reference binding type
+ if (callbackBinding == null) {
+ callbackBinding = callbackService.getBinding(refBinding.getClass());
+ }
+ InterfaceContract callbackContract = callbackService.getInterfaceContract();
+ EndpointReference callbackEndpoint =
+ new EndpointReferenceImpl((RuntimeComponent)refComponent, callbackService, callbackBinding,
+ callbackContract);
+ wireSource.setCallbackEndpoint(callbackEndpoint);
+ }
+*/
+
+ InterfaceContract bindingContract = getInterfaceContract(reference, endpointReference.getBinding());
+ Endpoint2 endpoint = endpointReference.getTargetEndpoint();
+ endpoint.setInterfaceContract(bindingContract);
+
+/* TODO - EPR review in the light of new matching code
+ // TUSCANY-2029 - We should use the URI of the serviceBinding because the target may be a Component in a
+ // nested composite.
+ if (serviceBinding != null) {
+ wireTarget.setURI(serviceBinding.getURI());
+ }
+*/
+
+ // create the wire
+ RuntimeWire wire = new RuntimeWireImpl2(true,
+ endpointReference,
+ endpoint,
+ interfaceContractMapper,
+ workScheduler,
+ wireProcessor,
+ messageFactory,
+ conversationManager);
+ runtimeRef.getRuntimeWires().add(wire);
+
+ }
+
+ private InterfaceContract getInterfaceContract(ComponentReference reference, Binding binding) {
+ InterfaceContract interfaceContract = reference.getInterfaceContract();
+ ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding);
+ if (provider != null) {
+ InterfaceContract bindingContract = provider.getBindingInterfaceContract();
+ if (bindingContract != null) {
+ interfaceContract = bindingContract;
+ }
+ }
+ return interfaceContract.makeUnidirectional(false);
+ }
+
+
+
+ // Utility functions
+ // TODO - can we get rid of these?
+
+ public CompositeContext getCompositeContext() {
+ return compositeContext;
+ }
+
+ public Composite getDomainComposite() {
+ return domainComposite;
+ }
+
+ public void setDomainComposite(Composite domainComposite) {
+ this.domainComposite = domainComposite;
+ }
+
+ public Component resolve(String componentURI) {
+ for (Composite composite : domainComposite.getIncludes()) {
+ Component component = resolve(composite, componentURI);
+ if (component != null) {
+ return component;
+ }
+ }
+ return null;
+ }
+
+ public Component resolve(Composite composite, String componentURI) {
+ for (Component component : composite.getComponents()) {
+ String uri = component.getURI();
+ if (uri.equals(componentURI)) {
+ return component;
+ }
+ if (componentURI.startsWith(uri)) {
+ Implementation implementation = component.getImplementation();
+ if (!(implementation instanceof Composite)) {
+ return null;
+ }
+ return resolve((Composite)implementation, componentURI);
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointReferenceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointReferenceImpl.java
new file mode 100644
index 0000000000..022cac398a
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointReferenceImpl.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class EndpointReferenceImpl implements EndpointReference {
+ private RuntimeComponent component;
+ private Contract contract;
+ private Binding binding;
+ private InterfaceContract interfaceContract;
+ private String uri;
+ private EndpointReference callbackEndpoint;
+ private ReferenceParameters parameters = new ReferenceParametersImpl();
+
+ /**
+ * @param component
+ * @param contract
+ * @param binding
+ * @param interfaceContract
+ */
+ public EndpointReferenceImpl(RuntimeComponent component,
+ Contract contract,
+ Binding binding,
+ InterfaceContract interfaceContract) {
+ super();
+ this.component = component;
+ this.contract = contract;
+ this.binding = binding;
+ this.interfaceContract = interfaceContract;
+ this.uri = (component != null ? component.getURI() : "") + '/' +
+ (contract != null ? contract.getName() : "");
+ }
+
+ /**
+ * @param uri
+ */
+ public EndpointReferenceImpl(String uri) {
+ super();
+ this.uri = uri;
+ }
+
+ public Binding getBinding() {
+ return binding;
+ }
+
+ public void setBinding(Binding binding) {
+ this.binding = binding;
+ }
+
+ public RuntimeComponent getComponent() {
+ return component;
+ }
+
+ public void setComponent(RuntimeComponent component) {
+ this.component = component;
+ }
+
+ public Contract getContract() {
+ return contract;
+ }
+
+ public void setContract(Contract contract) {
+ this.contract = contract;
+ }
+
+ public InterfaceContract getInterfaceContract() {
+ return interfaceContract;
+ }
+
+ public void setInterfaceContract(InterfaceContract interfaceContract) {
+ this.interfaceContract = interfaceContract;
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public EndpointReference getCallbackEndpoint() {
+ return callbackEndpoint;
+ }
+
+ public void setCallbackEndpoint(EndpointReference callbackEndpoint) {
+ this.callbackEndpoint = callbackEndpoint;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = PRIME * result + ((uri == null) ? 0 : uri.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final EndpointReferenceImpl other = (EndpointReferenceImpl)obj;
+ if (uri == null) {
+ if (other.uri != null) {
+ return false;
+ }
+ } else if (!uri.equals(other.uri)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ EndpointReferenceImpl copy = (EndpointReferenceImpl)super.clone();
+ /* [nash] no need to copy callback endpoint
+ if (callbackEndpoint != null) {
+ copy.callbackEndpoint = (EndpointReference)callbackEndpoint.clone();
+ }
+ */
+ if (parameters != null) {
+ copy.parameters = (ReferenceParameters)parameters.clone();
+ }
+ return copy;
+ }
+
+ /**
+ * @return the parameters
+ */
+ public ReferenceParameters getReferenceParameters() {
+ return parameters;
+ }
+
+ /**
+ * @param parameters the parameters to set
+ */
+ public void setReferenceParameters(ReferenceParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ public void mergeEndpoint(EndpointReference epr) {
+ this.component = epr.getComponent();
+ this.contract = epr.getContract();
+ this.binding = epr.getBinding();
+ this.interfaceContract = epr.getInterfaceContract();
+ this.uri = epr.getURI();
+ this.callbackEndpoint = epr.getCallbackEndpoint();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java
new file mode 100644
index 0000000000..2c833a885e
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+
+/**
+ * Artifact processor for reference parameters.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceParameterProcessor implements StAXArtifactProcessor<ReferenceParameters> {
+ private static final QName REFERENCE_PARAMETERS =
+ new QName("http://tuscany.apache.org/xmlns/sca/1.1", "referenceParameters", "tuscany");
+
+ /**
+ * Constructs a new processor.
+ *
+ * @param modelFactories
+ */
+ public ReferenceParameterProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#getArtifactType()
+ */
+ public QName getArtifactType() {
+ return REFERENCE_PARAMETERS;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#read(javax.xml.stream.XMLStreamReader)
+ */
+ public ReferenceParameters read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ ReferenceParameters parameters = new ReferenceParametersImpl();
+ parameters.setConversationID(reader.getAttributeValue(null, "conversationID"));
+ parameters.setCallbackID(reader.getAttributeValue(null, "callbackID"));
+ return parameters;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter)
+ */
+ public void write(ReferenceParameters model, XMLStreamWriter writer) throws ContributionWriteException,
+ XMLStreamException {
+ writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(),
+ REFERENCE_PARAMETERS.getLocalPart(),
+ REFERENCE_PARAMETERS.getNamespaceURI());
+ writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI());
+ if (model.getConversationID() != null) {
+ writer.writeAttribute("conversationID", model.getConversationID().toString());
+ }
+ if (model.getCallbackID() != null) {
+ writer.writeAttribute("callbackID", model.getCallbackID().toString());
+ }
+ writer.writeEndElement();
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#getModelType()
+ */
+ public Class<ReferenceParameters> getModelType() {
+ return ReferenceParameters.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#resolve(java.lang.Object, org.apache.tuscany.sca.contribution.resolver.ModelResolver)
+ */
+ public void resolve(ReferenceParameters model, ModelResolver resolver) throws ContributionResolveException {
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java
new file mode 100644
index 0000000000..0170af54fc
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ReferenceParametersImpl implements ReferenceParameters {
+ private Object callbackID;
+ private Object conversationID;
+ private EndpointReference callbackReference;
+ private Object callbackObjectID;
+
+ /**
+ * @return the callbackID
+ */
+ public Object getCallbackID() {
+ return callbackID;
+ }
+ /**
+ * @param callbackID the callbackID to set
+ */
+ public void setCallbackID(Object callbackID) {
+ this.callbackID = callbackID;
+ }
+ /**
+ * @return the conversationID
+ */
+ public Object getConversationID() {
+ return conversationID;
+ }
+ /**
+ * @param conversationID the conversationID to set
+ */
+ public void setConversationID(Object conversationID) {
+ this.conversationID = conversationID;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.runtime.ReferenceParameters#getCallbackReference()
+ */
+ public EndpointReference getCallbackReference() {
+ return callbackReference;
+ }
+ /**
+ * @see org.apache.tuscany.sca.runtime.ReferenceParameters#setCallback(java.lang.Object)
+ */
+ public void setCallbackReference(EndpointReference callback) {
+ this.callbackReference = callback;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ /**
+ * @return the callbackObjectID
+ */
+ public Object getCallbackObjectID() {
+ return callbackObjectID;
+ }
+ /**
+ * @param callbackObjectID the callbackObjectID to set
+ */
+ public void setCallbackObjectID(Object callbackObjectID) {
+ this.callbackObjectID = callbackObjectID;
+ }
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((callbackID == null) ? 0 : callbackID.hashCode());
+ result = prime * result + ((callbackObjectID == null) ? 0 : callbackObjectID.hashCode());
+ result = prime * result + ((callbackReference == null) ? 0 : callbackReference.hashCode());
+ result = prime * result + ((conversationID == null) ? 0 : conversationID.hashCode());
+ return result;
+ }
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof ReferenceParametersImpl))
+ return false;
+ final ReferenceParametersImpl other = (ReferenceParametersImpl)obj;
+ if (callbackID == null) {
+ if (other.callbackID != null)
+ return false;
+ } else if (!callbackID.equals(other.callbackID))
+ return false;
+ if (callbackObjectID == null) {
+ if (other.callbackObjectID != null)
+ return false;
+ } else if (!callbackObjectID.equals(other.callbackObjectID))
+ return false;
+ if (callbackReference == null) {
+ if (other.callbackReference != null)
+ return false;
+ } else if (!callbackReference.equals(other.callbackReference))
+ return false;
+ if (conversationID == null) {
+ if (other.conversationID != null)
+ return false;
+ } else if (!conversationID.equals(other.conversationID))
+ return false;
+ return true;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java
new file mode 100644
index 0000000000..6032005b9a
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.impl.ComponentImpl;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ResolverExtension;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RuntimeComponentImpl extends ComponentImpl implements RuntimeComponent,
+ ScopedRuntimeComponent, ResolverExtension {
+ protected RuntimeComponentContext componentContext;
+ protected ImplementationProvider implementationProvider;
+ protected List<PolicyProvider> policyProviders = new ArrayList<PolicyProvider>();
+ protected ScopeContainer scopeContainer;
+ protected boolean started;
+ protected ModelResolver modelResolver;
+
+ /**
+ */
+ public RuntimeComponentImpl() {
+ super();
+ }
+
+ public ImplementationProvider getImplementationProvider() {
+ return implementationProvider;
+ }
+
+ public void setImplementationProvider(ImplementationProvider provider) {
+ this.implementationProvider = provider;
+ }
+
+ public ScopeContainer getScopeContainer() {
+ return scopeContainer;
+ }
+
+ public void setScopeContainer(ScopeContainer scopeContainer) {
+ this.scopeContainer = scopeContainer;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void setStarted(boolean started) {
+ this.started = started;
+ }
+
+ /**
+ * @return the componentContext
+ */
+ public RuntimeComponentContext getComponentContext() {
+ return componentContext;
+ }
+
+ /**
+ * @param componentContext the componentContext to set
+ */
+ public void setComponentContext(RuntimeComponentContext componentContext) {
+ this.componentContext = componentContext;
+ }
+
+ public void addPolicyProvider(PolicyProvider policyProvider) {
+ policyProviders.add(policyProvider);
+ }
+
+ public List<PolicyProvider> getPolicyProviders() {
+ return policyProviders;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java
new file mode 100644
index 0000000000..dbdba54dc0
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+
+/**
+ * Implementation of a Component Reference.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RuntimeComponentReferenceImpl extends ComponentReferenceImpl implements RuntimeComponentReference {
+ private ArrayList<RuntimeWire> wires;
+ private HashMap<Binding, ReferenceBindingProvider> bindingProviders =
+ new HashMap<Binding, ReferenceBindingProvider>();
+ private HashMap<Binding, List<PolicyProvider>> policyProviders = new HashMap<Binding, List<PolicyProvider>>();
+
+ private RuntimeComponent component;
+
+ public RuntimeComponentReferenceImpl() {
+ super();
+ }
+
+ public synchronized List<RuntimeWire> getRuntimeWires() {
+ if (wires == null) {
+ wires = new ArrayList<RuntimeWire>();
+ component.getComponentContext().start(this);
+ }
+ return wires;
+ }
+
+ // TODO - EPR - shouldn't rely on this anymore
+ public RuntimeWire getRuntimeWire(Binding binding) {
+ for (RuntimeWire wire : getRuntimeWires()) {
+ if (wire.getSource().getBinding() == binding) {
+ return wire;
+ }
+ }
+
+ return null;
+ }
+
+ public RuntimeWire getRuntimeWire(EndpointReference2 endpointReference) {
+ for (RuntimeWire wire : getRuntimeWires()) {
+ if (wire.getEndpointReference() == endpointReference) {
+ return wire;
+ }
+ }
+
+ return null;
+ }
+
+ public ReferenceBindingProvider getBindingProvider(Binding binding) {
+ return bindingProviders.get(binding);
+ }
+
+ public void setBindingProvider(Binding binding, ReferenceBindingProvider bindingProvider) {
+ bindingProviders.put(binding, bindingProvider);
+ }
+
+ public Invoker getInvoker(Binding binding, Operation operation) {
+ RuntimeWire wire = getRuntimeWire(binding);
+ if (wire == null) {
+ return null;
+ }
+ InvocationChain chain = wire.getInvocationChain(operation);
+ return chain == null ? null : chain.getHeadInvoker();
+ }
+
+ /**
+ * @return the component
+ */
+ public RuntimeComponent getComponent() {
+ return component;
+ }
+
+ /**
+ * @param component the component to set
+ */
+ public void setComponent(RuntimeComponent component) {
+ this.component = component;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeComponentReferenceImpl ref = (RuntimeComponentReferenceImpl)super.clone();
+ ref.wires = null;
+ ref.bindingProviders = new HashMap<Binding, ReferenceBindingProvider>();
+ ref.policyProviders = new HashMap<Binding, List<PolicyProvider>>();
+ return ref;
+ }
+
+ public void addPolicyProvider(Binding binding, PolicyProvider policyProvider) {
+ List<PolicyProvider> providers = policyProviders.get(binding);
+ if (providers == null) {
+ providers = new ArrayList<PolicyProvider>();
+ policyProviders.put(binding, providers);
+ }
+ providers.add(policyProvider);
+ }
+
+ public List<PolicyProvider> getPolicyProviders(Binding binding) {
+ return policyProviders.get(binding);
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java
new file mode 100644
index 0000000000..2cbd72f218
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Implementation of a Component Service.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RuntimeComponentServiceImpl extends ComponentServiceImpl implements RuntimeComponentService {
+ private ArrayList<RuntimeWire> wires = new ArrayList<RuntimeWire>();
+ private ArrayList<RuntimeWire> callbackWires = new ArrayList<RuntimeWire>();
+ private HashMap<Binding, ServiceBindingProvider> bindingProviders = new HashMap<Binding, ServiceBindingProvider>();
+ private HashMap<Binding, List<PolicyProvider>> policyProviders = new HashMap<Binding, List<PolicyProvider>>();
+
+ public RuntimeComponentServiceImpl() {
+ super();
+ }
+
+ public List<RuntimeWire> getRuntimeWires() {
+ return wires;
+ }
+
+ public RuntimeWire getRuntimeWire(Binding binding) {
+ for (RuntimeWire wire : wires) {
+ if (wire.getTarget().getBinding() == binding) {
+ return wire;
+ }
+ }
+ return null;
+ }
+
+ public RuntimeWire getRuntimeWire(Binding binding, InterfaceContract interfaceContract) {
+ RuntimeWire wire = getRuntimeWire(binding);
+ if (wire == null) {
+ return null;
+ }
+ if (interfaceContract != null && interfaceContract != wire.getSource().getInterfaceContract()) {
+ try {
+ // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts
+ wire = (RuntimeWire)wire.clone();
+ wire.getSource().setInterfaceContract(interfaceContract);
+ wire.rebuild();
+ } catch (CloneNotSupportedException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ return wire;
+ }
+
+ public List<RuntimeWire> getCallbackWires() {
+ return callbackWires;
+ }
+
+ public ServiceBindingProvider getBindingProvider(Binding binding) {
+ return bindingProviders.get(binding);
+ }
+
+ public void setBindingProvider(Binding binding, ServiceBindingProvider bindingProvider) {
+ bindingProviders.put(binding, bindingProvider);
+ }
+
+ public Invoker getInvoker(Binding binding, Operation operation) {
+ return getInvoker(binding, null, operation);
+ }
+
+ public Invoker getInvoker(Binding binding, InterfaceContract interfaceContract, Operation operation) {
+ InvocationChain chain = getInvocationChain(binding, interfaceContract, operation);
+ if (chain != null) {
+ return chain.getHeadInvoker();
+ } else {
+ return null;
+ }
+ }
+
+ public InvocationChain getInvocationChain(Binding binding, InterfaceContract interfaceContract, Operation operation) {
+ RuntimeWire wire = getRuntimeWire(binding);
+ if (wire == null) {
+ return null;
+ }
+ if (interfaceContract != null && interfaceContract != wire.getSource().getInterfaceContract()) {
+ try {
+ // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts
+ wire = (RuntimeWire)wire.clone();
+ wire.getSource().setInterfaceContract(interfaceContract);
+ wire.rebuild();
+ } catch (CloneNotSupportedException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+ return wire.getInvocationChain(operation);
+ }
+
+ public InvocationChain getInvocationChain(Binding binding, Operation operation) {
+ return getInvocationChain(binding, null, operation);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl#clone()
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeComponentServiceImpl clone = (RuntimeComponentServiceImpl)super.clone();
+ clone.bindingProviders = (HashMap<Binding, ServiceBindingProvider>)bindingProviders.clone();
+ clone.wires = (ArrayList<RuntimeWire>)wires.clone();
+ clone.callbackWires = (ArrayList<RuntimeWire>)callbackWires.clone();
+ clone.policyProviders = (HashMap<Binding, List<PolicyProvider>>)policyProviders.clone();
+ return clone;
+ }
+
+ public void addPolicyProvider(Binding binding, PolicyProvider policyProvider) {
+ List<PolicyProvider> providers = policyProviders.get(binding);
+ if (providers == null) {
+ providers = new ArrayList<PolicyProvider>();
+ policyProviders.put(binding, providers);
+ }
+ providers.add(policyProvider);
+ }
+
+ public List<PolicyProvider> getPolicyProviders(Binding binding) {
+ return policyProviders.get(binding);
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl2.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl2.java
new file mode 100644
index 0000000000..754f6063cb
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl2.java
@@ -0,0 +1,507 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.assembly.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Endpoint2;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
+import org.apache.tuscany.sca.core.invocation.RuntimeWireInvoker;
+import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.provider.PolicyProviderRRB;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ReferenceBindingProviderRRB;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProviderRRB;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RuntimeWireImpl2 implements RuntimeWire {
+ private Boolean isReferenceWire = false;
+ private EndpointReference2 endpointReference;
+ private Endpoint2 endpoint;
+
+ private transient RuntimeWireProcessor wireProcessor;
+ private transient InterfaceContractMapper interfaceContractMapper;
+ private transient WorkScheduler workScheduler;
+ private transient MessageFactory messageFactory;
+ private transient ConversationManager conversationManager;
+ private transient RuntimeWireInvoker invoker;
+
+ // the following is a very simple cache that avoids re-cloning a wire
+ // when consecutive callbacks to the same endpoint are made
+ private EndpointReference lastCallback;
+ private RuntimeWire cachedWire;
+ private boolean wireReserved;
+ private RuntimeWireImpl2 clonedFrom;
+
+ private List<InvocationChain> chains;
+ private InvocationChain bindingInvocationChain;
+
+ /**
+ * @param source
+ * @param target
+ * @param interfaceContractMapper
+ * @param workScheduler
+ * @param wireProcessor
+ * @param messageFactory
+ * @param conversationManager
+ */
+ public RuntimeWireImpl2(boolean isReferenceWire,
+ EndpointReference2 endpointReference,
+ Endpoint2 endpoint,
+ InterfaceContractMapper interfaceContractMapper,
+ WorkScheduler workScheduler,
+ RuntimeWireProcessor wireProcessor,
+ MessageFactory messageFactory,
+ ConversationManager conversationManager) {
+ super();
+ this.isReferenceWire = isReferenceWire;
+ this.endpointReference = endpointReference;
+ this.endpoint = endpoint;
+ this.interfaceContractMapper = interfaceContractMapper;
+ this.workScheduler = workScheduler;
+ this.wireProcessor = wireProcessor;
+ this.messageFactory = messageFactory;
+ this.conversationManager = conversationManager;
+ this.invoker = new RuntimeWireInvoker(this.messageFactory, this.conversationManager, this);
+ }
+
+ public synchronized List<InvocationChain> getInvocationChains() {
+ if (chains == null) {
+ initInvocationChains();
+ }
+ return chains;
+ }
+
+ public synchronized InvocationChain getBindingInvocationChain() {
+ if (bindingInvocationChain == null) {
+ bindingInvocationChain = new InvocationChainImpl(null, null, isReferenceWire);
+ if (isReferenceWire) {
+ initReferenceBindingInvocationChains();
+ } else {
+ initServiceBindingInvocationChains();
+ }
+ }
+ return bindingInvocationChain;
+ }
+
+ public InvocationChain getInvocationChain(Operation operation) {
+ for (InvocationChain chain : getInvocationChains()) {
+ Operation op = null;
+ if (isReferenceWire) {
+ op = chain.getSourceOperation();
+ } else {
+ op = chain.getTargetOperation();
+ }
+ if (interfaceContractMapper.isCompatible(operation, op, op.getInterface().isRemotable())) {
+ return chain;
+ }
+ }
+ return null;
+ }
+
+ public Object invoke(Message msg) throws InvocationTargetException {
+ return getBindingInvocationChain().getHeadInvoker().invoke(msg);
+ }
+
+ public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
+ Message msg = messageFactory.createMessage();
+ msg.setBody(args);
+ return invoker.invoke(operation, msg);
+ }
+
+ public Object invoke(Operation operation, Message msg) throws InvocationTargetException {
+ return invoker.invoke(operation, msg);
+ }
+
+ /**
+ * Initialize the invocation chains
+ */
+ private void initInvocationChains() {
+ chains = new ArrayList<InvocationChain>();
+ InterfaceContract sourceContract = endpointReference.getInterfaceContract();
+ InterfaceContract targetContract = endpoint.getInterfaceContract();
+
+ if (isReferenceWire) {
+ // It's the reference wire
+ RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
+ Binding refBinding = endpointReference.getBinding();
+ for (Operation operation : sourceContract.getInterface().getOperations()) {
+ Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation);
+ if (targetOperation == null) {
+ throw new ServiceRuntimeException("No matching operation for " + operation.getName()
+ + " is found in reference "
+ + endpointReference.getComponent().getURI()
+ + "#"
+ + reference.getName());
+ }
+ InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true);
+ if (operation.isNonBlocking()) {
+ addNonBlockingInterceptor(reference, refBinding, chain);
+ }
+ addReferenceBindingInterceptor(reference, refBinding, chain, operation);
+ chains.add(chain);
+ }
+
+ } else {
+ // It's the service wire
+ RuntimeComponentService service = (RuntimeComponentService)endpoint.getService();
+ RuntimeComponent serviceComponent = (RuntimeComponent)endpoint.getComponent();
+ Binding serviceBinding = endpoint.getBinding();
+ for (Operation operation : sourceContract.getInterface().getOperations()) {
+ Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation);
+ if (targetOperation == null) {
+ throw new ServiceRuntimeException("No matching operation for " + operation.getName()
+ + " is found in service "
+ + serviceComponent.getURI()
+ + "#"
+ + service.getName());
+ }
+ InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false);
+ if (operation.isNonBlocking()) {
+ addNonBlockingInterceptor(service, serviceBinding, chain);
+ }
+ addServiceBindingInterceptor(service, serviceBinding, chain, operation);
+ addImplementationInterceptor(serviceComponent, service, chain, targetOperation);
+ chains.add(chain);
+ }
+
+ }
+ wireProcessor.process(this);
+ }
+
+ private void initReferenceBindingInvocationChains() {
+ RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
+ Binding referenceBinding = endpointReference.getBinding();
+
+ // add the binding interceptors to the reference binding wire
+ ReferenceBindingProvider provider = reference.getBindingProvider(referenceBinding);
+ if ((provider != null) &&
+ (provider instanceof ReferenceBindingProviderRRB)){
+ ((ReferenceBindingProviderRRB)provider).configureBindingChain(this);
+ }
+
+ // add the policy interceptors to the service binding wire
+ // find out which policies are active
+ List<PolicyProvider> pps = ((RuntimeComponentReference)reference).getPolicyProviders(referenceBinding);
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ if (p instanceof PolicyProviderRRB) {
+ Interceptor interceptor = ((PolicyProviderRRB)p).createBindingInterceptor();
+ if (interceptor != null) {
+ bindingInvocationChain.addInterceptor(p.getPhase(), interceptor);
+ }
+ }
+ }
+ }
+ }
+
+ private void initServiceBindingInvocationChains() {
+ RuntimeComponentService service = (RuntimeComponentService)endpoint.getService();
+ Binding serviceBinding = endpoint.getBinding();
+
+ // add the binding interceptors to the service binding wire
+ ServiceBindingProvider provider = service.getBindingProvider(serviceBinding);
+ if ((provider != null) &&
+ (provider instanceof ServiceBindingProviderRRB)){
+ ((ServiceBindingProviderRRB)provider).configureBindingChain(this);
+ }
+
+ // add the policy interceptors to the service binding wire
+ List<PolicyProvider> pps = ((RuntimeComponentService)service).getPolicyProviders(serviceBinding);
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ if (p instanceof PolicyProviderRRB) {
+ Interceptor interceptor = ((PolicyProviderRRB)p).createBindingInterceptor();
+ if (interceptor != null) {
+ bindingInvocationChain.addInterceptor(p.getPhase(), interceptor);
+ }
+ }
+ }
+ }
+
+
+ // TODO - add something on the end of the wire to invoke the
+ // invocation chain. Need to split out the runtime
+ // wire invoker into conversation, callback interceptors etc
+ bindingInvocationChain.addInvoker(invoker);
+
+ }
+
+ // ===============================================================
+ // TODO - EPR remove when we convert fully over to EndpointReference2
+
+ // TODO - remove. Just here during development
+ static EndpointReference epr;
+
+ public EndpointReference getSource() {
+ // TODO - EPR convert this into method that returns EndpointReference2
+
+ // convert the source info into old endpoint reference format
+ epr = new EndpointReferenceImpl((RuntimeComponent)endpointReference.getComponent(),
+ endpointReference.getReference(),
+ endpointReference.getBinding(),
+ endpointReference.getInterfaceContract());
+
+ if (endpointReference.getCallbackEndpoint() != null){
+ // convert the source callback endpoint into old endpoint reference format
+ EndpointReference cepr;
+ cepr = new EndpointReferenceImpl((RuntimeComponent)endpointReference.getComponent(),
+ endpointReference.getCallbackEndpoint().getService(),
+ endpointReference.getCallbackEndpoint().getBinding(),
+ endpointReference.getCallbackEndpoint().getInterfaceContract());
+ epr.setCallbackEndpoint(cepr);
+ }
+
+
+ // TODO - somtimes used to reset the interface contract so we
+ // copy it back in in the rebuild method below
+ return epr;
+ }
+
+
+
+ public EndpointReference getTarget() {
+ // TODO - EPR convert this into method that returns Endpoint2
+
+ // convert the target info into old endpoint reference format
+ EndpointReference epr = new EndpointReferenceImpl((RuntimeComponent)endpoint.getComponent(),
+ endpoint.getService(),
+ endpoint.getBinding(),
+ endpoint.getInterfaceContract());
+ return epr;
+ }
+
+ public void setTarget(EndpointReference target) {
+ // TODO - can we use the idea of setTarget to rebuild the wire?
+
+ }
+
+ // ===================================================================
+
+ public void rebuild() {
+ // TODO - can we use the idea of setTarget to rebuild the wire?
+ // used at the moment by binding.sca when it resets the
+ // source interface contract for local wires
+ this.chains = null;
+
+ // TODO - cheating here as I fixed the RuntimeComponentService code
+ // to call this when it resets the interface contract
+ endpointReference.setInterfaceContract(epr.getInterfaceContract());
+ }
+
+ public EndpointReference2 getEndpointReference(){
+ return endpointReference;
+ }
+
+ /**
+ * Add the interceptor for a reference binding
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ * @param operation
+ */
+ private void addReferenceBindingInterceptor(ComponentReference reference,
+ Binding binding,
+ InvocationChain chain,
+ Operation operation) {
+ ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding);
+ if (provider != null) {
+ Invoker invoker = provider.createInvoker(operation);
+ if (invoker != null) {
+ chain.addInvoker(invoker);
+ }
+ }
+ List<PolicyProvider> pps = ((RuntimeComponentReference)reference).getPolicyProviders(binding);
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createInterceptor(operation);
+ if (interceptor != null) {
+ chain.addInterceptor(p.getPhase(), p.createInterceptor(operation));
+ }
+ }
+ }
+ }
+
+ /**
+ * Add the interceptor for a binding
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ * @param operation
+ */
+ private void addServiceBindingInterceptor(ComponentService service,
+ Binding binding,
+ InvocationChain chain,
+ Operation operation) {
+ List<PolicyProvider> pps = ((RuntimeComponentService)service).getPolicyProviders(binding);
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createInterceptor(operation);
+ if (interceptor != null) {
+ chain.addInterceptor(p.getPhase(), p.createInterceptor(operation));
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a non-blocking interceptor if the reference binding needs it
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ */
+ private void addNonBlockingInterceptor(ComponentReference reference, Binding binding, InvocationChain chain) {
+ ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding);
+ if (provider != null) {
+ boolean supportsOneWayInvocation = provider.supportsOneWayInvocation();
+ if (!supportsOneWayInvocation) {
+ chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler));
+ }
+ }
+ }
+
+ /**
+ * Add a non-blocking interceptor if the service binding needs it
+ *
+ * @param service
+ * @param binding
+ * @param chain
+ */
+ private void addNonBlockingInterceptor(ComponentService service, Binding binding, InvocationChain chain) {
+ ServiceBindingProvider provider = ((RuntimeComponentService)service).getBindingProvider(binding);
+ if (provider != null) {
+ if (!provider.supportsOneWayInvocation()) {
+ chain.addInterceptor(Phase.SERVICE, new NonBlockingInterceptor(workScheduler));
+ }
+ }
+ }
+
+ /**
+ * Add the interceptor for a component implementation
+ *
+ * @param component
+ * @param service
+ * @param chain
+ * @param operation
+ */
+ private void addImplementationInterceptor(Component component,
+ ComponentService service,
+ InvocationChain chain,
+ Operation operation) {
+ ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider();
+ if (provider != null) {
+ Invoker invoker = null;
+ invoker = provider.createInvoker((RuntimeComponentService)service, operation);
+ chain.addInvoker(invoker);
+ }
+ List<PolicyProvider> pps = ((RuntimeComponent)component).getPolicyProviders();
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createInterceptor(operation);
+ if (interceptor != null) {
+ chain.addInterceptor(p.getPhase(), p.createInterceptor(operation));
+ }
+ }
+ }
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeWireImpl2 copy = (RuntimeWireImpl2)super.clone();
+ copy.endpointReference = (EndpointReference2)endpointReference.clone();
+ copy.endpoint = copy.endpointReference.getTargetEndpoint();
+ copy.invoker = new RuntimeWireInvoker(copy.messageFactory, copy.conversationManager, copy);
+ copy.cachedWire = null; // TUSCANY-2630
+ return copy;
+ }
+
+ /**
+ * @return the conversationManager
+ */
+ public ConversationManager getConversationManager() {
+ return conversationManager;
+ }
+
+ public synchronized RuntimeWire lookupCache(EndpointReference callback) {
+ if (lastCallback != null && callback.getURI().equals(lastCallback.getURI()) && !wireReserved) {
+ wireReserved = true;
+ return cachedWire;
+ } else {
+ return null;
+ }
+ }
+
+ public synchronized void addToCache(EndpointReference callback, RuntimeWire clonedWire) {
+ ((RuntimeWireImpl2)clonedWire).setClonedFrom(this);
+ lastCallback = callback;
+ cachedWire = clonedWire;
+ wireReserved = true;
+ }
+
+ public synchronized void releaseClonedWire(RuntimeWire wire) {
+ if (cachedWire == wire) {
+ wireReserved = false;
+ }
+ }
+
+ public synchronized void releaseWire() {
+ clonedFrom.releaseClonedWire(this);
+ }
+
+ private void setClonedFrom(RuntimeWireImpl2 wire) {
+ clonedFrom = wire;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceExt.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceExt.java
new file mode 100644
index 0000000000..c0217e7336
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceExt.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import java.io.Externalizable;
+import java.io.IOException;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+
+/**
+ * Extended version of CallableReference
+ */
+public interface CallableReferenceExt<B> extends CallableReference<B>, Externalizable {
+ /**
+ * @return
+ */
+ RuntimeWire getRuntimeWire();
+
+ /**
+ * @return
+ * @throws IOException
+ */
+ String toXMLString() throws IOException;
+
+ /**
+ * @param callbackID
+ */
+ void attachCallbackID(Object callbackID);
+
+ void attachConversationID(Object conversationID);
+
+ void attachConversation(ConversationExt conversation);
+
+ void attachConversation(Object conversationID);
+
+ /**
+ * @return
+ */
+ EndpointReference getEndpointReference();
+
+ /**
+ * @return
+ */
+ XMLStreamReader getXMLReader();
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextExt.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextExt.java
new file mode 100644
index 0000000000..6db3af213d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextExt.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
+
+/**
+ * Extended ComponentContext
+ */
+public interface ComponentContextExt extends RuntimeComponentContext {
+ CompositeActivator getCompositeActivator();
+ CompositeContext getCompositeContext();
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CompositeContext.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CompositeContext.java
new file mode 100644
index 0000000000..29c4dfd362
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/CompositeContext.java
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class CompositeContext {
+ /**
+ * Create a self-reference for a component service
+ * @param component
+ * @param service
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public abstract ComponentReference createSelfReference(Component component,
+ ComponentService service,
+ Class<?> businessInterface)
+ throws CloneNotSupportedException, InvalidInterfaceException;
+
+ /**
+ * Bind a component reference to a component service
+ * @param <B>
+ * @param businessInterface
+ * @param reference
+ * @param service
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public abstract RuntimeComponentReference bindComponentReference(Class<?> businessInterface,
+ RuntimeComponentReference reference,
+ RuntimeComponent component,
+ RuntimeComponentService service)
+ throws CloneNotSupportedException, InvalidInterfaceException;
+
+ /**
+ * @param component
+ * @param reference
+ * @param writer
+ * @throws IOException
+ */
+ public abstract void write(Component component, ComponentReference reference, Writer writer) throws IOException;
+
+ /**
+ * @param component
+ * @param reference
+ * @param service
+ * @param writer
+ * @throws IOException
+ */
+ public abstract void write(Component component,
+ ComponentReference reference,
+ ComponentService service,
+ Writer writer) throws IOException;
+
+ /**
+ * @param component
+ * @param reference
+ * @return
+ * @throws IOException
+ */
+ public abstract String toXML(Component component, ComponentReference reference) throws IOException;
+
+ /**
+ * @param component
+ * @param service
+ * @return
+ * @throws IOException
+ */
+ public abstract String toXML(Component component, ComponentService service) throws IOException;
+
+ /**
+ * @param reader
+ * @return
+ * @throws IOException
+ */
+ public abstract RuntimeComponent read(Reader reader) throws IOException;
+
+ /**
+ * @param streamReader
+ * @return
+ * @throws IOException
+ */
+ public abstract RuntimeComponent read(XMLStreamReader streamReader) throws IOException;
+
+ /**
+ * @param xml
+ * @return
+ * @throws IOException
+ */
+ public abstract Component fromXML(String xml) throws IOException;
+
+ /**
+ * @param streamReader
+ * @return
+ * @throws IOException
+ */
+ public abstract Component fromXML(XMLStreamReader streamReader) throws IOException;
+
+ /**
+ * @return
+ */
+ public static RuntimeComponent getCurrentComponent() {
+ Message message = ThreadMessageContext.getMessageContext();
+ if (message != null) {
+ EndpointReference to = message.getTo();
+ if (to == null) {
+ return null;
+ }
+ RuntimeComponent component = message.getTo().getComponent();
+ return component;
+ }
+ return null;
+ }
+
+ /**
+ * @return
+ */
+ public static CompositeActivator getCurrentCompositeActivator() {
+ RuntimeComponent component = getCurrentComponent();
+ if (component != null) {
+ ComponentContextExt context = (ComponentContextExt)component.getComponentContext();
+ return context.getCompositeActivator();
+ }
+ return null;
+ }
+
+ /**
+ * @return
+ */
+ public static CompositeContext getCurrentCompositeContext() {
+ CompositeActivator activator = getCurrentCompositeActivator();
+ if (activator != null) {
+ return activator.getCompositeContext();
+ }
+ return null;
+ }
+
+ /**
+ * @param component
+ */
+ public static ComponentService getSingleService(Component component) {
+ ComponentService targetService;
+ List<ComponentService> services = component.getServices();
+ List<ComponentService> regularServices = new ArrayList<ComponentService>();
+ for (ComponentService service : services) {
+ if (service.isCallback()) {
+ continue;
+ }
+ String name = service.getName();
+ if (!name.startsWith("$") || name.startsWith("$dynamic$")) {
+ regularServices.add(service);
+ }
+ }
+ if (regularServices.size() == 0) {
+ throw new ServiceRuntimeException("No service is declared on component " + component.getURI());
+ }
+ if (regularServices.size() != 1) {
+ throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI()
+ + ". Service name is required to get the service.");
+ }
+ targetService = regularServices.get(0);
+ return targetService;
+ }
+
+ public abstract ExtensionPointRegistry getExtensionPointRegistry();
+
+ public abstract ConversationManager getConversationManager();
+
+ /**
+ * Get the java interface factory
+ * @return
+ */
+ public abstract JavaInterfaceFactory getJavaInterfaceFactory();
+
+ /**
+ * Get the proxy factory
+ * @return
+ */
+ public abstract ProxyFactory getProxyFactory();
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java
new file mode 100644
index 0000000000..4e43518738
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import org.apache.tuscany.sca.context.ComponentContextFactory;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.context.impl.ComponentContextImpl;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.oasisopen.sca.ComponentContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DefaultComponentContextFactory implements ComponentContextFactory {
+ private final ExtensionPointRegistry registry;
+
+ public DefaultComponentContextFactory(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ }
+
+ public ComponentContext createComponentContext(RuntimeComponent component) {
+ return new ComponentContextImpl(registry, component);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java
new file mode 100644
index 0000000000..ace4dc48e1
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import org.apache.tuscany.sca.context.RequestContextFactory;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.context.impl.RequestContextImpl;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.oasisopen.sca.RequestContext;
+
+/**
+ * Default implementation of RequestContextFactory
+ */
+public class DefaultRequestContextFactory implements RequestContextFactory {
+
+ public DefaultRequestContextFactory(ExtensionPointRegistry registry) {
+ }
+
+ public RequestContext createRequestContext(RuntimeComponent component) {
+ return new RequestContextImpl(component);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java
new file mode 100644
index 0000000000..aa1e1de0f6
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context;
+
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * Extended ServiceReference
+ */
+public interface ServiceReferenceExt<B> extends CallableReferenceExt<B>, ServiceReference<B> {
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallableReferenceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallableReferenceImpl.java
new file mode 100644
index 0000000000..205ad6a62c
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallableReferenceImpl.java
@@ -0,0 +1,609 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context.impl;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.UUID;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.assembly.OptimizableBinding;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.SCABinding;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilderExtension;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.assembly.impl.CompositeActivatorImpl2;
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.assembly.impl.ReferenceParametersImpl;
+import org.apache.tuscany.sca.core.context.CallableReferenceExt;
+import org.apache.tuscany.sca.core.context.ComponentContextExt;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.Conversation;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Base class for implementations of service and callback references.
+ *
+ * @version $Rev$ $Date$
+ * @param <B> the type of the business interface
+ */
+public class CallableReferenceImpl<B> implements CallableReferenceExt<B> {
+ static final long serialVersionUID = -521548304761848325L;
+ protected transient CompositeActivator compositeActivator;
+ protected transient ProxyFactory proxyFactory;
+ protected transient Class<B> businessInterface;
+ protected transient Object proxy;
+
+ // if the wire targets a conversational service this holds the conversation state
+ protected transient ConversationManager conversationManager;
+ protected transient ConversationExt conversation;
+ protected transient Object conversationID;
+ protected Object callbackID; // The callbackID should be serializable
+
+ protected transient RuntimeComponent component;
+ protected transient RuntimeComponentReference reference;
+ // TODO - EPR - remove wire indexing on bindings as enpoint references
+ // can share reference bindings
+ protected transient Binding binding;
+ protected transient EndpointReference2 endpointReference;
+
+ protected String scdl;
+
+ private transient RuntimeComponentReference clonedRef;
+ private transient ReferenceParameters refParams;
+ private transient XMLStreamReader xmlReader;
+
+ /*
+ * Public constructor for Externalizable serialization/deserialization
+ */
+ public CallableReferenceImpl() {
+ super();
+ }
+
+ /*
+ * Public constructor for use by XMLStreamReader2CallableReference
+ */
+ public CallableReferenceImpl(XMLStreamReader xmlReader) throws Exception {
+ this.xmlReader = xmlReader;
+ resolve();
+ }
+
+ protected CallableReferenceImpl(Class<B> businessInterface,
+ RuntimeComponent component,
+ RuntimeComponentReference reference,
+ Binding binding,
+ ProxyFactory proxyFactory,
+ CompositeActivator compositeActivator) {
+ this.proxyFactory = proxyFactory;
+ this.businessInterface = businessInterface;
+ this.component = component;
+ this.reference = reference;
+ this.binding = binding;
+
+ // FIXME: The SCA Specification is not clear how we should handle multiplicity
+ // for CallableReference
+ if (this.binding == null) {
+ this.binding = this.reference.getBinding(SCABinding.class);
+ if (this.binding == null) {
+
+ // TODO: TUSCANY-2580: if the refernece doesn't have a binding yet then instead of NPE use a candidate one if its avaialable
+ if (reference.getBindings() != null && reference.getBindings().size() > 0) {
+ this.binding = this.reference.getBindings().get(0);
+ }
+ }
+
+ // TODO - EPR - If no binding specified assume default binding and find the endpoint reference
+ // related to it
+ for (EndpointReference2 endpointReference : this.reference.getEndpointReferences()){
+ if ((endpointReference.getBinding() != null) &&
+ (endpointReference.getBinding() instanceof SCABinding)){
+ this.endpointReference = endpointReference;
+ break;
+ }
+ }
+ }
+
+ // FIXME: Should we normalize the componentName/serviceName URI into an absolute SCA URI in the SCA binding?
+ // sca:component1/component11/component112/service1?
+ this.compositeActivator = compositeActivator;
+ this.conversationManager = this.compositeActivator.getCompositeContext().getConversationManager();
+ initCallbackID();
+ }
+
+ public CallableReferenceImpl(Class<B> businessInterface, RuntimeWire wire, ProxyFactory proxyFactory) {
+ this.proxyFactory = proxyFactory;
+ this.businessInterface = businessInterface;
+ bind(wire);
+ }
+
+ public RuntimeWire getRuntimeWire() {
+ try {
+ resolve();
+ if (endpointReference != null){
+ return reference.getRuntimeWire(endpointReference);
+ } else if (reference != null) {
+ return reference.getRuntimeWire(binding);
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ protected void bind(RuntimeWire wire) {
+ if (wire != null) {
+ this.component = wire.getSource().getComponent();
+ this.reference = (RuntimeComponentReference)wire.getSource().getContract();
+ this.binding = wire.getSource().getBinding();
+ this.endpointReference = wire.getEndpointReference();
+ this.compositeActivator = ((ComponentContextExt)component.getComponentContext()).getCompositeActivator();
+ this.conversationManager = this.compositeActivator.getCompositeContext().getConversationManager();
+ initCallbackID();
+ }
+ }
+
+ protected void initCallbackID() {
+ if (reference.getInterfaceContract() != null) {
+ if (reference.getInterfaceContract().getCallbackInterface() != null) {
+ this.callbackID = createCallbackID();
+ }
+ }
+ }
+
+ public B getProxy() throws ObjectCreationException {
+ try {
+ if (proxy == null) {
+ proxy = createProxy();
+ }
+ return businessInterface.cast(proxy);
+ } catch (Exception e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+
+ public void setProxy(Object proxy) {
+ this.proxy = proxy;
+ }
+
+ protected Object createProxy() throws Exception {
+ return proxyFactory.createProxy(this);
+ }
+
+ public B getService() {
+ try {
+ resolve();
+ return getProxy();
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public Class<B> getBusinessInterface() {
+ try {
+ resolve();
+ return businessInterface;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public boolean isConversational() {
+ try {
+ resolve();
+ return reference == null ? false : reference.getInterfaceContract().getInterface().isConversational();
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public Conversation getConversation() {
+ try {
+ // resolve from XML just in case this CallableReference is the result of
+ // passing a CallableReference as a parameter
+ resolve();
+
+ if (conversation == null || conversation.getState() == ConversationState.ENDED) {
+ conversation = null;
+ }
+ return conversation;
+
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public Object getCallbackID() {
+ try {
+ resolve();
+ return callbackID;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
+ */
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ final boolean hasSCDL = in.readBoolean();
+ if (hasSCDL) {
+ this.scdl = in.readUTF();
+ } else {
+ this.scdl = null;
+ }
+ }
+
+ /**
+ * @throws IOException
+ */
+ private synchronized void resolve() throws Exception {
+ if ((scdl != null || xmlReader != null) && component == null && reference == null) {
+ CompositeContext componentContextHelper = CompositeContext.getCurrentCompositeContext();
+ if (componentContextHelper != null) {
+ this.compositeActivator = CompositeContext.getCurrentCompositeActivator();
+ this.conversationManager = componentContextHelper.getConversationManager();
+ Component c;
+ if (xmlReader != null) {
+ c = componentContextHelper.fromXML(xmlReader);
+ xmlReader = null; // OK to GC this now
+ } else {
+ c = componentContextHelper.fromXML(scdl);
+ scdl = null; // OK to GC this now
+ }
+ this.component = (RuntimeComponent)c;
+ compositeActivator.configureComponentContext(this.component);
+ this.reference = (RuntimeComponentReference)c.getReferences().get(0);
+ this.reference.setComponent(this.component);
+ clonedRef = reference;
+ ReferenceParameters parameters = null;
+ for (Object ext : reference.getExtensions()) {
+ if (ext instanceof ReferenceParameters) {
+ parameters = (ReferenceParameters)ext;
+ break;
+ }
+ }
+ if (parameters != null) {
+ refParams = parameters;
+ this.callbackID = parameters.getCallbackID();
+ attachConversation(parameters.getConversationID());
+ }
+
+ for (Binding binding : reference.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ // Resolve the Component
+ final String bindingURI = binding.getURI();
+ final Component targetComponent = resolveComponentURI(bindingURI);
+
+ // Find the Service
+ ComponentService targetService = resolveServiceURI(bindingURI, targetComponent);
+
+ // if the target service is a promoted service then find the
+ // service it promotes
+ if ((targetService != null) && (targetService.getService() instanceof CompositeService)) {
+ CompositeService compositeService = (CompositeService)targetService.getService();
+ // Find the promoted component service
+ ComponentService promotedComponentService = getPromotedComponentService(compositeService);
+ if (promotedComponentService != null && !promotedComponentService.isUnresolved()) {
+ targetService = promotedComponentService;
+ }
+ }
+
+ OptimizableBinding optimizableBinding = (OptimizableBinding)binding;
+ optimizableBinding.setTargetComponent(targetComponent);
+ optimizableBinding.setTargetComponentService(targetService);
+ if (targetService != null) {
+ for (Binding serviceBinding : targetService.getBindings()) {
+ if (serviceBinding.getClass() == binding.getClass()) {
+ optimizableBinding.setTargetBinding(serviceBinding);
+ break;
+ }
+ }
+ }
+ }
+ }
+ // FIXME: The SCA Specification is not clear how we should handle multiplicity
+ // for CallableReference
+ if (binding == null) {
+ binding = reference.getBinding(SCABinding.class);
+ if (binding == null) {
+ binding = reference.getBindings().get(0);
+ }
+ }
+ Interface i = reference.getInterfaceContract().getInterface();
+ if (i instanceof JavaInterface) {
+ JavaInterface javaInterface = (JavaInterface)i;
+ if (javaInterface.isUnresolved()) {
+ // Allow privileged access to get ClassLoader. Requires RuntimePermission in
+ // security policy.
+ ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName()));
+ compositeActivator.getCompositeContext().getJavaInterfaceFactory()
+ .createJavaInterface(javaInterface, javaInterface.getJavaClass());
+ //FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO),
+ // this needs to be done here. We usually search for XSDs in the current
+ // contribution at resolve time. Is it possible to locate the current
+ // contribution at runtime?
+ }
+ this.businessInterface = (Class<B>)javaInterface.getJavaClass();
+ }
+ if (binding instanceof BindingBuilderExtension) {
+ ((BindingBuilderExtension)binding).getBuilder().build(component, reference, binding, null);
+ }
+ this.proxyFactory = compositeActivator.getCompositeContext().getProxyFactory();
+ }
+ } else {
+ this.compositeActivator = CompositeContext.getCurrentCompositeActivator();
+ if (this.compositeActivator != null) {
+ this.proxyFactory = this.compositeActivator.getCompositeContext().getProxyFactory();
+ }
+ }
+ }
+
+ /**
+ * Follow a service promotion chain down to the inner most (non composite)
+ * component service.
+ *
+ * @param topCompositeService
+ * @return
+ */
+ private ComponentService getPromotedComponentService(CompositeService compositeService) {
+ ComponentService componentService = compositeService.getPromotedService();
+ if (componentService != null) {
+ Service service = componentService.getService();
+ if (componentService.getName() != null && service instanceof CompositeService) {
+
+ // Continue to follow the service promotion chain
+ return getPromotedComponentService((CompositeService)service);
+
+ } else {
+
+ // Found a non-composite service
+ return componentService;
+ }
+ } else {
+
+ // No promoted service
+ return null;
+ }
+ }
+
+ /**
+ * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
+ */
+ public void writeExternal(ObjectOutput out) throws IOException {
+ try {
+ final String xml = toXMLString();
+ if (xml == null) {
+ out.writeBoolean(false);
+ } else {
+ out.writeBoolean(true);
+ out.writeUTF(xml);
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ throw new IOException(e.toString());
+ }
+ }
+
+ public String toXMLString() throws IOException {
+ if (reference != null) {
+ if (clonedRef == null) {
+ try {
+ clonedRef = (RuntimeComponentReference)reference.clone();
+ } catch (CloneNotSupportedException e) {
+ // will not happen
+ }
+ }
+ if (refParams == null) {
+ refParams = new ReferenceParametersImpl();
+
+ // remove any existing reference parameters from the clone
+ Object toRemove = null;
+ for (Object extension : clonedRef.getExtensions()) {
+ if (extension instanceof ReferenceParameters) {
+ toRemove = extension;
+ }
+ }
+
+ if (toRemove != null) {
+ clonedRef.getExtensions().remove(toRemove);
+ }
+
+ // add the new reference parameter object
+ clonedRef.getExtensions().add(refParams);
+ }
+ refParams.setCallbackID(callbackID);
+ if (conversation != null) {
+ refParams.setConversationID(conversation.getConversationID());
+ }
+ return ((CompositeActivatorImpl2)compositeActivator).getCompositeContext().toXML(component, clonedRef);
+ } else {
+ return scdl;
+ }
+ }
+
+ /**
+ * Create a callback id
+ *
+ * @return the callback id
+ */
+ private String createCallbackID() {
+ return UUID.randomUUID().toString();
+ }
+
+ public void attachCallbackID(Object callbackID) {
+ this.callbackID = callbackID;
+ }
+
+ public void attachConversationID(Object conversationID) {
+ this.conversationID = conversationID;
+ }
+
+ public void attachConversation(ConversationExt conversation) {
+ this.conversation = conversation;
+ }
+
+ public void attachConversation(Object conversationID) {
+ if (conversationID != null) {
+ ConversationExt conversation = conversationManager.getConversation(conversationID);
+ if (conversation == null) {
+ conversation = conversationManager.startConversation(conversationID);
+ }
+ this.conversation = conversation;
+ } else {
+ this.conversation = null;
+ }
+ }
+
+ protected ReferenceParameters getReferenceParameters() {
+ ReferenceParameters parameters = new ReferenceParametersImpl();
+ parameters.setCallbackID(callbackID);
+ if (getConversation() != null) {
+ parameters.setConversationID(conversation.getConversationID());
+ }
+ return parameters;
+ }
+
+ public EndpointReference getEndpointReference() {
+ try {
+ resolve();
+
+ // Use the interface contract of the reference on the component type
+ Reference componentTypeRef = reference.getReference();
+ InterfaceContract sourceContract =
+ componentTypeRef == null ? reference.getInterfaceContract() : componentTypeRef.getInterfaceContract();
+ sourceContract = sourceContract.makeUnidirectional(false);
+ EndpointReference epr = new EndpointReferenceImpl(component, reference, binding, sourceContract);
+ ReferenceParameters parameters = getReferenceParameters();
+ epr.setReferenceParameters(parameters);
+ return epr;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public XMLStreamReader getXMLReader() {
+ return xmlReader;
+ }
+
+ /**
+ * Resolves the specified URI to a Component using the compositeActivator.
+ * There are two cases that we need to handle:
+ * <ul>
+ * <li>URI containing just Composite name(s) (i.e. no Service name specified)
+ * <li>URI containing Composite name(s) and a Service Name
+ * </ul>
+ *
+ * @param componentURI The URI of the Component to resolve
+ * @return The Component for the specified URI or null if not founds
+ */
+ protected Component resolveComponentURI(String componentURI) {
+ // If the URI has come from a binding, it may well start with a '/'. We will need
+ // to remove this so we can match it to the composite names.
+ if (componentURI.startsWith("/")) {
+ componentURI = componentURI.substring(1);
+ }
+
+ // First assume that we are dealing with a Component URI without a Service Name
+ Component component = compositeActivator.resolve(componentURI);
+ if (component != null) {
+ return component;
+ }
+
+ // Perhaps we have a ComponentURI that has a ServiceName on the end of it
+ final int index = componentURI.lastIndexOf('/');
+ if (index > -1) {
+ componentURI = componentURI.substring(0, index);
+ return compositeActivator.resolve(componentURI);
+ }
+
+ // We could not resolve the Component URI
+ return null;
+ }
+
+ /**
+ * Examines the Services on the specified Component and returns the Service that matches the
+ * specified Binding URI.
+ *
+ * @param bindingURI The Binding URI to resolve on the Component
+ * @param targetComponent The Component containing the Services
+ * @return The Service with the specified serviceName or null if no such Service found.
+ */
+ protected ComponentService resolveServiceURI(String bindingURI, Component targetComponent) {
+
+ ComponentService targetService = null;
+
+ if (targetComponent != null) {
+ if (bindingURI.startsWith("/")) {
+ bindingURI = bindingURI.substring(1);
+ }
+
+ final String componentURI = targetComponent.getURI();
+ final String serviceName;
+ if (componentURI.equals(bindingURI)) {
+ // No service specified
+ serviceName = "";
+ } else {
+ // Get the Service name from the Binding URI
+ serviceName = bindingURI.substring(componentURI.length() + 1);
+ }
+
+ if ("".equals(serviceName)) {
+ targetService = CompositeContext.getSingleService(targetComponent);
+ } else {
+ for (ComponentService service : targetComponent.getServices()) {
+ if (service.getName().equals(serviceName)) {
+ targetService = service;
+ break;
+ }
+ }
+ }
+ }
+
+ return targetService;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java
new file mode 100644
index 0000000000..0b4c33c341
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java
@@ -0,0 +1,479 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context.impl;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Endpoint2;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.OptimizableBinding;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.EndpointReferenceBuilder;
+import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint;
+import org.apache.tuscany.sca.context.PropertyValueFactory;
+import org.apache.tuscany.sca.context.RequestContextFactory;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.context.ComponentContextExt;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.RequestContext;
+import org.oasisopen.sca.ServiceReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Implementation of ComponentContext that delegates to a ComponentContextProvider.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentContextImpl implements ComponentContextExt {
+ private final RuntimeComponent component;
+
+ private final CompositeActivator compositeActivator;
+ private final RequestContextFactory requestContextFactory;
+ private final ProxyFactory proxyFactory;
+ private final AssemblyFactory assemblyFactory;
+ private final JavaInterfaceFactory javaInterfaceFactory;
+ private final PropertyValueFactory propertyFactory;
+ private final EndpointReferenceBuilder endpointReferenceBuilder;
+ private final Monitor monitor;
+
+ public ComponentContextImpl(ExtensionPointRegistry registry, RuntimeComponent component) {
+ this.component = component;
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.compositeActivator = utilities.getUtility(CompositeActivator.class);
+ this.requestContextFactory =
+ registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class);
+ this.proxyFactory = new ExtensibleProxyFactory(registry.getExtensionPoint(ProxyFactoryExtensionPoint.class));
+ this.propertyFactory = factories.getFactory(PropertyValueFactory.class);
+
+ this.endpointReferenceBuilder = utilities.getUtility(EndpointReferenceBuilder.class);
+
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ this.monitor = monitorFactory.createMonitor();
+ }
+
+ public String getURI() {
+ return component.getURI();
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ return (R)proxyFactory.cast(target);
+ }
+
+ public <B> B getService(Class<B> businessInterface, String referenceName) {
+ ServiceReference<B> serviceRef = getServiceReference(businessInterface, referenceName);
+ return serviceRef.getService();
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) {
+ try {
+ for (ComponentReference ref : component.getReferences()) {
+ if (referenceName.equals(ref.getName())) {
+ /* ******************** Contribution for issue TUSCANY-2281 ******************** */
+ Multiplicity multiplicity = ref.getMultiplicity();
+ if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) {
+ throw new IllegalArgumentException("Reference " + referenceName
+ + " has multiplicity "
+ + multiplicity);
+ }
+ /* ******************** Contribution for issue TUSCANY-2281 ******************** */
+
+ return getServiceReference(businessInterface, (RuntimeComponentReference)ref, null);
+ }
+ }
+ throw new ServiceRuntimeException("Reference not found: " + referenceName);
+ } catch (ServiceRuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Gets the value for the specified property with the specified type.
+ *
+ * @param type The type of the property value we are getting
+ * @param propertyName The name of the property we are getting
+ * @param B The class of the property value we are getting
+ *
+ * @throws ServiceRuntimeException If a Property for the specified propertyName
+ * is not found
+ *
+ * @see #setPropertyValueFactory(PropertyValueFactory)
+ */
+ public <B> B getProperty(Class<B> type, String propertyName) {
+ for (ComponentProperty p : component.getProperties()) {
+ if (propertyName.equals(p.getName())) {
+ return propertyFactory.createPropertyValue(p, type);
+ }
+ }
+ throw new ServiceRuntimeException("Property not found: " + propertyName);
+ }
+
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) {
+ ComponentService service = CompositeContext.getSingleService(component);
+ try {
+ return createSelfReference(businessInterface, service);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) {
+ try {
+ for (ComponentService service : component.getServices()) {
+ if (serviceName.equals(service.getName())) {
+ return createSelfReference(businessInterface, service);
+ }
+ }
+ throw new ServiceRuntimeException("Service not found: " + serviceName);
+ } catch (ServiceRuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * @param <B>
+ * @param businessInterface
+ * @param service
+ * @return
+ */
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, ComponentService service) {
+ try {
+ RuntimeComponentReference ref =
+ (RuntimeComponentReference)createSelfReference(component, service, businessInterface);
+ ref.setComponent(component);
+ return getServiceReference(businessInterface, ref, null);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public RequestContext getRequestContext() {
+ if (requestContextFactory != null) {
+ return requestContextFactory.createRequestContext(component);
+ } else {
+ return new RequestContextImpl(component);
+ }
+ }
+
+ /**
+ * @param businessInterface
+ * @param reference
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface,
+ RuntimeComponentReference reference,
+ Binding binding) {
+ try {
+ RuntimeComponentReference ref = (RuntimeComponentReference)reference;
+ InterfaceContract interfaceContract = reference.getInterfaceContract();
+ Reference componentTypeReference = reference.getReference();
+ if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) {
+ interfaceContract = componentTypeReference.getInterfaceContract();
+ }
+ InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ if (refInterfaceContract != interfaceContract) {
+ ref = (RuntimeComponentReference)reference.clone();
+ if (interfaceContract != null) {
+ ref.setInterfaceContract(interfaceContract);
+ } else {
+ ref.setInterfaceContract(refInterfaceContract);
+ }
+ }
+ ref.setComponent(component);
+ return new ServiceReferenceImpl<B>(businessInterface, component, ref, binding, proxyFactory,
+ compositeActivator);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * Bind a component reference to a component service
+ * @param <B>
+ * @param businessInterface
+ * @param reference
+ * @param service
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface,
+ RuntimeComponentReference reference,
+ RuntimeComponent component,
+ RuntimeComponentService service) {
+ try {
+ RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone();
+ InterfaceContract interfaceContract = reference.getInterfaceContract();
+ Reference componentTypeReference = reference.getReference();
+ if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) {
+ interfaceContract = componentTypeReference.getInterfaceContract();
+ }
+ InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ if (refInterfaceContract != interfaceContract) {
+ ref = (RuntimeComponentReference)reference.clone();
+ ref.setInterfaceContract(interfaceContract);
+ }
+ ref.getTargets().add(service);
+ ref.getBindings().clear();
+ for (Binding binding : service.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
+ optimizableBinding.setTargetBinding(binding);
+ optimizableBinding.setTargetComponent(component);
+ optimizableBinding.setTargetComponentService(service);
+ ref.getBindings().add(optimizableBinding);
+ } else {
+ ref.getBindings().add(binding);
+ }
+ }
+ return new ServiceReferenceImpl<B>(businessInterface, component, ref, proxyFactory, compositeActivator);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public <B> CallableReference<B> getCallableReference(Class<B> businessInterface,
+ RuntimeComponent component,
+ RuntimeComponentService service) {
+ try {
+ if (businessInterface == null) {
+ InterfaceContract contract = service.getInterfaceContract();
+ businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass();
+ }
+ RuntimeComponentReference ref =
+ (RuntimeComponentReference)createSelfReference(component, service, businessInterface);
+ ref.setComponent(component);
+ return new CallableReferenceImpl<B>(businessInterface, component, ref, null, proxyFactory,
+ compositeActivator);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * Create a self-reference for a component service
+ * @param component
+ * @param service
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ private ComponentReference createSelfReference(Component component,
+ ComponentService service,
+ Class<?> businessInterface) throws CloneNotSupportedException,
+ InvalidInterfaceException {
+ ComponentReference componentReference = assemblyFactory.createComponentReference();
+ componentReference.setName("$self$." + service.getName());
+
+ for (Binding binding : service.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
+ optimizableBinding.setTargetBinding(binding);
+ optimizableBinding.setTargetComponent(component);
+ optimizableBinding.setTargetComponentService(service);
+ componentReference.getBindings().add(optimizableBinding);
+ } else {
+ componentReference.getBindings().add(binding);
+ }
+ }
+
+ componentReference.setCallback(service.getCallback());
+ componentReference.getTargets().add(service);
+ componentReference.getPolicySets().addAll(service.getPolicySets());
+ componentReference.getRequiredIntents().addAll(service.getRequiredIntents());
+
+ InterfaceContract interfaceContract = service.getInterfaceContract();
+ Service componentTypeService = service.getService();
+ if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) {
+ interfaceContract = componentTypeService.getInterfaceContract();
+ }
+ interfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ componentReference.setInterfaceContract(interfaceContract);
+ componentReference.setMultiplicity(Multiplicity.ONE_ONE);
+ // component.getReferences().add(componentReference);
+
+ // create endpoint reference
+ EndpointReference2 endpointReference = assemblyFactory
+ .createEndpointReference();
+ endpointReference.setComponent(component);
+ endpointReference.setReference(componentReference);
+ endpointReference.setUnresolved(false);
+
+ // create endpoint.
+ Endpoint2 endpoint = assemblyFactory.createEndpoint();
+ endpoint.setComponent(component);
+ endpoint.setService(service);
+ endpoint.setUnresolved(true);
+ endpointReference.setTargetEndpoint(endpoint);
+
+ componentReference.getEndpointReferences().add(endpointReference);
+
+ // do binding matching
+ endpointReferenceBuilder.build(endpointReference, monitor);
+
+ return componentReference;
+ }
+
+ /**
+ * @param interfaceContract
+ * @param businessInterface
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface)
+ throws CloneNotSupportedException, InvalidInterfaceException {
+ boolean compatible = false;
+ if (interfaceContract != null && interfaceContract.getInterface() != null) {
+ Interface interfaze = interfaceContract.getInterface();
+ if (interfaze instanceof JavaInterface) {
+ Class<?> cls = ((JavaInterface)interfaze).getJavaClass();
+ if (businessInterface.isAssignableFrom(cls)) {
+ compatible = true;
+ }
+ }
+ }
+
+ if (!compatible) {
+ // The interface is not assignable from the interface contract
+ interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface);
+ interfaceContract.setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ interfaceContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface
+ .getCallbackClass()));
+ }
+ }
+
+ return interfaceContract;
+ }
+
+ /**
+ * @return the compositeActivator
+ */
+ public CompositeActivator getCompositeActivator() {
+ return compositeActivator;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#start(org.apache.tuscany.sca.runtime.RuntimeComponentReference)
+ */
+ public void start(RuntimeComponentReference reference) {
+ compositeActivator.start(component, reference);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#read(java.io.Reader)
+ */
+ public RuntimeComponent read(Reader reader) throws IOException {
+ RuntimeComponent component = compositeActivator.getCompositeContext().read(reader);
+ compositeActivator.configureComponentContext(component);
+ return component;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#write(org.apache.tuscany.sca.runtime.RuntimeComponentReference, java.io.Writer)
+ */
+ public void write(RuntimeComponentReference reference, Writer writer) throws IOException {
+ compositeActivator.getCompositeContext().write(component, reference, writer);
+ }
+
+ /* ******************** Contribution for issue TUSCANY-2281 ******************** */
+
+ /**
+ * @see ComponentContext#getServices(Class<B>, String)
+ */
+ public <B> Collection<B> getServices(Class<B> businessInterface, String referenceName) {
+ ArrayList<B> services = new ArrayList<B>();
+ Collection<ServiceReference<B>> serviceRefs = getServiceReferences(businessInterface, referenceName);
+ for (ServiceReference<B> serviceRef : serviceRefs) {
+ services.add(serviceRef.getService());
+ }
+ return services;
+ }
+
+ /**
+ * @see ComponentContext#getServiceReferences(Class<B>, String)
+ */
+ public <B> Collection<ServiceReference<B>> getServiceReferences(Class<B> businessInterface, String referenceName) {
+ try {
+ for (ComponentReference ref : component.getReferences()) {
+ if (referenceName.equals(ref.getName())) {
+ ArrayList<ServiceReference<B>> serviceRefs = new ArrayList<ServiceReference<B>>();
+ for (Binding binding : ref.getBindings()) {
+ serviceRefs
+ .add(getServiceReference(businessInterface, (RuntimeComponentReference)ref, binding));
+ }
+ return serviceRefs;
+ }
+ }
+ throw new ServiceRuntimeException("Reference not found: " + referenceName);
+ } catch (ServiceRuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+ /* ******************** Contribution for issue TUSCANY-2281 ******************** */
+
+ public CompositeContext getCompositeContext() {
+ return compositeActivator.getCompositeContext();
+ }
+
+ public ExtensionPointRegistry getExtensionPointRegistry() {
+ return getCompositeContext().getExtensionPointRegistry();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CompositeContextImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CompositeContextImpl.java
new file mode 100644
index 0000000000..72789b72a1
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CompositeContextImpl.java
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context.impl;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.OptimizableBinding;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CompositeContextImpl extends CompositeContext {
+ private final ExtensionPointRegistry extensionPointRegistry;
+ private final UtilityExtensionPoint utilityExtensionPoint;
+ private final AssemblyFactory assemblyFactory;
+ private final JavaInterfaceFactory javaInterfaceFactory;
+ private final StAXArtifactProcessorExtensionPoint staxProcessors;
+ private final XMLInputFactory xmlInputFactory;
+ private final XMLOutputFactory xmlOutputFactory;
+ private final ProxyFactory proxyFactory;
+
+ public CompositeContextImpl(ExtensionPointRegistry registry) {
+ this.extensionPointRegistry = registry;
+ this.utilityExtensionPoint = extensionPointRegistry.getExtensionPoint(UtilityExtensionPoint.class);
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.xmlInputFactory = factories.getFactory(XMLInputFactory.class);
+ this.xmlOutputFactory = factories.getFactory(XMLOutputFactory.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
+ this.staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ ProxyFactoryExtensionPoint proxyFactories = extensionPointRegistry.getExtensionPoint(ProxyFactoryExtensionPoint.class);
+ this.proxyFactory = new ExtensibleProxyFactory(proxyFactories);
+ }
+
+ /**
+ * Create a self-reference for a component service
+ * @param component
+ * @param service
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public ComponentReference createSelfReference(Component component,
+ ComponentService service,
+ Class<?> businessInterface) throws CloneNotSupportedException,
+ InvalidInterfaceException {
+ ComponentReference componentReference = assemblyFactory.createComponentReference();
+ componentReference.setName("$self$." + service.getName());
+ for (Binding binding : service.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
+ optimizableBinding.setTargetBinding(binding);
+ optimizableBinding.setTargetComponent(component);
+ optimizableBinding.setTargetComponentService(service);
+ componentReference.getBindings().add(optimizableBinding);
+ } else {
+ componentReference.getBindings().add(binding);
+ }
+ }
+
+ componentReference.setCallback(service.getCallback());
+ componentReference.getTargets().add(service);
+ componentReference.getPolicySets().addAll(service.getPolicySets());
+ componentReference.getRequiredIntents().addAll(service.getRequiredIntents());
+
+ InterfaceContract interfaceContract = service.getInterfaceContract();
+ Service componentTypeService = service.getService();
+ if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) {
+ interfaceContract = componentTypeService.getInterfaceContract();
+ }
+ interfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ componentReference.setInterfaceContract(interfaceContract);
+ componentReference.setMultiplicity(Multiplicity.ONE_ONE);
+ // component.getReferences().add(componentReference);
+ return componentReference;
+ }
+
+ /**
+ * @param interfaceContract
+ * @param businessInterface
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface)
+ throws CloneNotSupportedException, InvalidInterfaceException {
+ Interface interfaze = interfaceContract.getInterface();
+ boolean compatible = false;
+ if (interfaze instanceof JavaInterface) {
+ Class<?> cls = ((JavaInterface)interfaze).getJavaClass();
+ if (businessInterface.isAssignableFrom(cls)) {
+ compatible = true;
+ }
+ }
+ if (!compatible) {
+ // The interface is not assignable from the interface contract
+ interfaceContract = (InterfaceContract)interfaceContract.clone();
+ interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
+ }
+
+ return interfaceContract;
+ }
+
+ /**
+ * Bind a component reference to a component service
+ * @param <B>
+ * @param businessInterface
+ * @param reference
+ * @param service
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ public RuntimeComponentReference bindComponentReference(Class<?> businessInterface,
+ RuntimeComponentReference reference,
+ RuntimeComponent component,
+ RuntimeComponentService service)
+ throws CloneNotSupportedException, InvalidInterfaceException {
+ RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone();
+ InterfaceContract interfaceContract = reference.getInterfaceContract();
+ Reference componentTypeReference = reference.getReference();
+ if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) {
+ interfaceContract = componentTypeReference.getInterfaceContract();
+ }
+ InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ if (refInterfaceContract != interfaceContract) {
+ ref = (RuntimeComponentReference)reference.clone();
+ ref.setInterfaceContract(interfaceContract);
+ }
+ ref.setComponent(component);
+ ref.getTargets().add(service);
+ ref.getBindings().clear();
+ for (Binding binding : service.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
+ optimizableBinding.setTargetBinding(binding);
+ optimizableBinding.setTargetComponent(component);
+ optimizableBinding.setTargetComponentService(service);
+ ref.getBindings().add(optimizableBinding);
+ } else {
+ ref.getBindings().add(binding);
+ }
+ }
+ return ref;
+ }
+
+ public void write(Component component, ComponentReference reference, Writer writer) throws IOException {
+ write(component, reference, null, writer);
+ }
+
+ public void write(Component component, ComponentReference reference, ComponentService service, Writer writer) throws IOException {
+ try {
+ StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
+ Composite composite = assemblyFactory.createComposite();
+ composite.setName(new QName("http://tuscany.apache.org/xmlns/sca/1.1", "default"));
+ Component comp = assemblyFactory.createComponent();
+ comp.setName("default");
+ comp.setURI(component.getURI());
+ composite.getComponents().add(comp);
+ if (reference != null) {
+ comp.getReferences().add(reference);
+ }
+ if (service != null) {
+ comp.getServices().add(service);
+ }
+
+ XMLStreamWriter streamWriter = xmlOutputFactory.createXMLStreamWriter(writer);
+ processor.write(composite, streamWriter);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public String toXML(Component component, ComponentReference reference) throws IOException {
+ StringWriter writer = new StringWriter();
+ write(component, reference, writer);
+ return writer.toString();
+ }
+
+ public String toXML(Component component, ComponentService service) throws IOException {
+ StringWriter writer = new StringWriter();
+ write(component, null, service, writer);
+ return writer.toString();
+ }
+
+ public RuntimeComponent read(Reader reader) throws IOException {
+ try {
+ XMLStreamReader streamReader = xmlInputFactory.createXMLStreamReader(reader);
+ return read(streamReader);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public RuntimeComponent read(XMLStreamReader streamReader) throws IOException {
+ try {
+ StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
+ Composite composite = processor.read(streamReader);
+ RuntimeComponent component = (RuntimeComponent)composite.getComponents().get(0);
+ return component;
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public Component fromXML(String xml) throws IOException {
+ return read(new StringReader(xml));
+ }
+
+ public Component fromXML(XMLStreamReader streamReader) throws IOException {
+ return read(streamReader);
+ }
+
+ public static RuntimeComponent getCurrentComponent() {
+ Message message = ThreadMessageContext.getMessageContext();
+ if (message != null) {
+ EndpointReference to = message.getTo();
+ if (to == null) {
+ return null;
+ }
+ RuntimeComponent component = message.getTo().getComponent();
+ return component;
+ }
+ return null;
+ }
+
+ public static CompositeActivator getCurrentCompositeActivator() {
+ RuntimeComponent component = getCurrentComponent();
+ if (component != null) {
+ ComponentContextImpl context = (ComponentContextImpl)component.getComponentContext();
+ return context.getCompositeActivator();
+ }
+ return null;
+ }
+
+ public static CompositeContext getCurrentCompositeContext() {
+ CompositeActivator activator = getCurrentCompositeActivator();
+ if (activator != null) {
+ return activator.getCompositeContext();
+ }
+ return null;
+ }
+
+ /**
+ * @param component
+ */
+ public static ComponentService getSingleService(Component component) {
+ ComponentService targetService;
+ List<ComponentService> services = component.getServices();
+ List<ComponentService> regularServices = new ArrayList<ComponentService>();
+ for (ComponentService service : services) {
+ if (service.isCallback()) {
+ continue;
+ }
+ String name = service.getName();
+ if (!name.startsWith("$") || name.startsWith("$dynamic$")) {
+ regularServices.add(service);
+ }
+ }
+ if (regularServices.size() == 0) {
+ throw new ServiceRuntimeException("No service is declared on component " + component.getURI());
+ }
+ if (regularServices.size() != 1) {
+ throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI()
+ + ". Service name is required to get the service.");
+ }
+ targetService = regularServices.get(0);
+ return targetService;
+ }
+
+ public ExtensionPointRegistry getExtensionPointRegistry() {
+ return extensionPointRegistry;
+ }
+
+ public ConversationManager getConversationManager() {
+ return utilityExtensionPoint.getUtility(ConversationManager.class);
+ }
+
+ /**
+ * Get the java interface factory
+ * @return
+ */
+ public JavaInterfaceFactory getJavaInterfaceFactory() {
+ return javaInterfaceFactory;
+ }
+
+ /**
+ * Get the proxy factory
+ * @return
+ */
+ public ProxyFactory getProxyFactory() {
+ return proxyFactory;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java
new file mode 100644
index 0000000000..015c80c6fa
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context.impl;
+
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.context.CallableReferenceExt;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.core.invocation.impl.CallbackReferenceImpl;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.RequestContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RequestContextImpl implements RequestContext {
+
+ private ProxyFactoryExtensionPoint proxyFactoryExtensionPoint;
+
+ public RequestContextImpl(RuntimeComponent component) {
+ ExtensionPointRegistry registry = component.getComponentContext().getExtensionPointRegistry();
+ proxyFactoryExtensionPoint = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class);
+ }
+
+ public Subject getSecuritySubject() {
+ Subject subject = null;
+
+ for (Object header : ThreadMessageContext.getMessageContext().getHeaders()){
+ if (header instanceof Subject){
+ subject = (Subject)header;
+ break;
+ }
+ }
+ return subject;
+ }
+
+ public String getServiceName() {
+ return ThreadMessageContext.getMessageContext().getTo().getContract().getName();
+ }
+
+ public <B> CallableReference<B> getServiceReference() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ // FIXME: [rfeng] Is this the service reference matching the caller side?
+ EndpointReference to = msgContext.getTo();
+ RuntimeComponentService service = (RuntimeComponentService) to.getContract();
+ RuntimeComponent component = (RuntimeComponent) to.getComponent();
+
+ CallableReference<B> callableReference = component.getComponentContext().getCallableReference(null, component, service);
+ ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters();
+ ((CallableReferenceExt<B>) callableReference).attachCallbackID(parameters.getCallbackID());
+ ((CallableReferenceExt<B>) callableReference).attachConversation(parameters.getConversationID());
+ return callableReference;
+ }
+
+ public <CB> CB getCallback() {
+ CallableReference<CB> cb = getCallbackReference();
+ if (cb == null) {
+ return null;
+ }
+ return cb.getService();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <CB> CallableReference<CB> getCallbackReference() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ EndpointReference to = msgContext.getTo();
+ RuntimeComponentService service = (RuntimeComponentService) to.getContract();
+ RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference();
+ if (callbackReference == null) {
+ return null;
+ }
+ JavaInterface javaInterface = (JavaInterface) callbackReference.getInterfaceContract().getInterface();
+ Class<CB> javaClass = (Class<CB>)javaInterface.getJavaClass();
+ List<RuntimeWire> wires = callbackReference.getRuntimeWires();
+ ProxyFactory proxyFactory = new ExtensibleProxyFactory(proxyFactoryExtensionPoint);
+ CallbackReferenceImpl ref = CallbackReferenceImpl.newInstance(javaClass, proxyFactory, wires);
+ if (ref != null) {
+ //ref.resolveTarget();
+ ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters();
+ ref.attachCallbackID(parameters.getCallbackID());
+ if (ref.getConversation() != null) {
+ ref.attachConversationID(parameters.getConversationID());
+ }
+ }
+ return ref;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java
new file mode 100644
index 0000000000..8aec07ceda
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.context.impl;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.core.assembly.CompositeActivator;
+import org.apache.tuscany.sca.core.context.CallableReferenceExt;
+import org.apache.tuscany.sca.core.context.ServiceReferenceExt;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * Default implementation of a ServiceReference.
+ *
+ * @version $Rev$ $Date$
+ * @param <B> the type of the business interface
+ */
+public class ServiceReferenceImpl<B> extends CallableReferenceImpl<B> implements ServiceReferenceExt<B> {
+ private static final long serialVersionUID = 6763709434194361540L;
+
+ protected transient Object callback;
+
+ /*
+ * Public constructor for Externalizable serialization/deserialization
+ */
+ public ServiceReferenceImpl() {
+ super();
+ }
+
+ /*
+ * Public constructor for use by XMLStreamReader2CallableReference
+ */
+ public ServiceReferenceImpl(XMLStreamReader xmlReader) throws Exception {
+ super(xmlReader);
+ }
+
+ /**
+ * @param businessInterface
+ * @param wire
+ * @param proxyFactory
+ */
+ public ServiceReferenceImpl(Class<B> businessInterface, RuntimeWire wire, ProxyFactory proxyFactory) {
+ super(businessInterface, wire, proxyFactory);
+ }
+
+ public ServiceReferenceImpl(Class<B> businessInterface,
+ RuntimeComponent component,
+ RuntimeComponentReference reference,
+ ProxyFactory proxyFactory,
+ CompositeActivator compositeActivator) {
+ super(businessInterface, component, reference, null, proxyFactory, compositeActivator);
+ }
+
+ public ServiceReferenceImpl(Class<B> businessInterface,
+ RuntimeComponent component,
+ RuntimeComponentReference reference,
+ Binding binding,
+ ProxyFactory proxyFactory,
+ CompositeActivator compositeActivator) {
+ super(businessInterface, component, reference, binding, proxyFactory, compositeActivator);
+ }
+
+ public Object getConversationID() {
+ return conversationID;
+ }
+
+ public void setConversationID(Object conversationID) throws IllegalStateException {
+ if (conversation == null || conversation.getState() != ConversationState.ENDED) {
+ this.conversationID = conversationID;
+ this.conversation = null;
+ } else {
+ throw new IllegalStateException("Trying to set the conversationId on a service reference but the state of the conversation "
+ + conversation.getConversationID()
+ + " is "
+ + conversation.getState());
+ }
+ }
+
+ public void setCallbackID(Object callbackID) {
+ this.callbackID = callbackID;
+ }
+
+ public Object getCallback() {
+ return callback;
+ }
+
+ public void setCallback(Object callback) {
+ if (callback != null && !(callback instanceof CallableReference)) {
+ //FIXME: need to check if callback object supports the callback interface
+ // returned by reference.getInterfaceContract().getCallbackInterface()
+ }
+ this.callback = callback;
+ }
+
+ @Override
+ protected ReferenceParameters getReferenceParameters() {
+ ReferenceParameters parameters = super.getReferenceParameters();
+ if (callback != null) {
+ if (callback instanceof ServiceReference) {
+ EndpointReference callbackRef = ((CallableReferenceExt)callback).getEndpointReference();
+ parameters.setCallbackReference(callbackRef);
+ } else {
+ EndpointReference callbackRef = getRuntimeWire().getSource().getCallbackEndpoint();
+ parameters.setCallbackReference(callbackRef);
+ parameters.setCallbackObjectID(callback);
+ }
+ }
+ return parameters;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationExt.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationExt.java
new file mode 100644
index 0000000000..9182b080fe
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationExt.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation;
+
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.oasisopen.sca.Conversation;
+
+/**
+ * An extended interface over org.oasisopen.Conversation
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ConversationExt extends Conversation {
+ /**
+ * Get the state of a conversation
+ * @return The state
+ */
+ ConversationState getState();
+
+ /**
+ * @param state the state to set
+ */
+ void setState(ConversationState state);
+
+ /**
+ * @param conversationID the conversationID to set
+ */
+ void setConversationID(Object conversationID);
+
+
+ /**
+ * will check whether this conversation has expired and update state if it has
+ * @return true if it has expired
+ */
+ boolean isExpired();
+
+ /**
+ * updates the last time this conversation was referenced
+ */
+ void updateLastReferencedTime();
+
+ void initializeConversationAttributes(RuntimeComponent targetComponent);
+
+
+ /**
+ * @return true if the conversational attributes have been initialized
+ */
+ boolean conversationalAttributesInitialized();
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java
new file mode 100644
index 0000000000..425fa3af9c
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation;
+
+/**
+ * Listener for the events of a conversation
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ConversationListener {
+ /**
+ * The conversation is started
+ */
+ void conversationStarted(ConversationExt conversation);
+ /**
+ * The conversation is ended
+ */
+ void conversationEnded(ConversationExt conversation);
+ /**
+ * The conversation is expired
+ */
+ void conversationExpired(ConversationExt conversation);
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java
new file mode 100644
index 0000000000..ed858bd499
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation;
+
+/**
+ * The manager of conversations
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ConversationManager {
+ /**
+ * @param conversationID
+ * @return
+ */
+ ConversationExt startConversation(Object conversationID);
+
+ /**
+ * @param conversationID
+ */
+ void endConversation(Object conversationID);
+
+ /**
+ * @param conversationID
+ * @return
+ */
+ ConversationExt getConversation(Object conversationID);
+
+ /**
+ * @param conversationID
+ */
+ void expireConversation(Object conversationID);
+
+ /**
+ * Add a listener to this conversation
+ * @param listener
+ */
+ void addListener(ConversationListener listener);
+
+ /**
+ * Remove a listener from this conversation
+ * @param listener
+ */
+ void removeListener(ConversationListener listener);
+
+ /**
+ * @return the default max age for a conversation
+ */
+ long getMaxAge();
+
+ /**
+ * @return the default max idle time for a conversation
+ */
+ long getMaxIdleTime();
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java
new file mode 100644
index 0000000000..692d6861ba
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation;
+
+/**
+ * The states of a conversation
+ *
+ * @version $Rev$ $Date$
+ */
+public enum ConversationState {
+ STARTED, ENDED, EXPIRED
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ConversationManagerImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ConversationManagerImpl.java
new file mode 100644
index 0000000000..e23659b990
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ConversationManagerImpl.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation.impl;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationListener;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConversationManagerImpl implements ConversationManager {
+
+ private List<ConversationListener> listeners = Collections.synchronizedList(new ArrayList<ConversationListener>());
+ private Map<Object, ConversationExt> conversations = new ConcurrentHashMap<Object, ConversationExt>();
+
+ /**
+ * the default max age. this is set to 1 hour
+ */
+ private static final long DEFAULT_MAX_AGE = 60 * 60 * 1000;;
+
+ /**
+ * the default max idle time. this is set to 1 hour
+ */
+ private static final long DEFAULT_MAX_IDLE_TIME = 60 * 60 * 1000;
+
+ /**
+ * the globally used max age
+ */
+ private final long maxAge;
+
+ /**
+ * the globally used max idle time
+ */
+ private final long maxIdleTime;
+
+ /**
+ * the reaper thread
+ */
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+ /**
+ * constructor
+ */
+ public ConversationManagerImpl() {
+ long mit = DEFAULT_MAX_IDLE_TIME;
+ long ma = DEFAULT_MAX_AGE;
+
+ // Allow privileged access to read system property. Requires PropertyPermission in security
+ // policy.
+ String aProperty = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(ConversationManager.class.getName() + ".MaxIdleTime");
+ }
+ });
+ if (aProperty != null) {
+ try {
+ mit = Long.parseLong(aProperty) * 1000;
+ } catch (NumberFormatException nfe) {
+ // Ignore
+ }
+ }
+
+ // Allow privileged access to read system property. Requires PropertyPermission in security
+ // policy.
+ aProperty = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(ConversationManager.class.getName() + ".MaxAge");
+ }
+ });
+ if (aProperty != null) {
+ try {
+ ma = Long.parseLong(aProperty) * 1000;
+ } catch (NumberFormatException nfe) {
+ // Ignore
+ }
+ }
+
+ maxAge = ma;
+ maxIdleTime = mit;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationManager#addListener(org.apache.tuscany.sca.core.conversation.ConversationListener)
+ */
+ public void addListener(ConversationListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationManager#endConversation(org.apache.tuscany.sca.core.conversation.ConversationExt)
+ */
+ public void endConversation(Object conversationID) {
+ ConversationExt conv = getConversation(conversationID);
+ if (conv != null) {
+ conv.setState(ConversationState.ENDED);
+ for (ConversationListener listener : listeners) {
+ listener.conversationEnded(conv);
+ }
+ conv.setConversationID(null);
+ conversations.remove(conversationID);
+ } else {
+ throw new IllegalStateException("Conversation " + conversationID + " doesn't exist.");
+ }
+ }
+
+ public void expireConversation(Object conversationID) {
+ ConversationExt conv = getConversation(conversationID);
+ if (conv != null) {
+ for (ConversationListener listener : listeners) {
+ listener.conversationExpired(conv);
+ }
+ conversations.remove(conversationID);
+ } else {
+ throw new IllegalStateException("Conversation " + conversationID + " doesn't exist.");
+ }
+
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationManager#getConversation(java.lang.Object)
+ */
+ public ConversationExt getConversation(Object conversationID) {
+ // ConcurrentHashMap cannot take null key
+ return conversationID == null ? null : conversations.get(conversationID);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationManager#removeListener(org.apache.tuscany.sca.core.conversation.ConversationListener)
+ */
+ public void removeListener(ConversationListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * starts the reaper thread
+ */
+ public void scheduleConversation(ExtendedConversationImpl aConversation, long time) {
+ this.scheduler.schedule(aConversation, time, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * stops the reaper thread
+ */
+ public synchronized void stopReaper() {
+
+ // Prevent the scheduler from submitting any additional reapers,
+ // initiate an orderly shutdown if a reaper task is in progress.
+ this.scheduler.shutdown();
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationManager#startConversation(java.lang.Object)
+ */
+ public ConversationExt startConversation(Object conversationID) {
+
+ if (conversationID == null) {
+ conversationID = UUID.randomUUID().toString();
+ }
+ ConversationExt conversation = getConversation(conversationID);
+ if (conversation != null && conversation.getState() != ConversationState.ENDED) {
+ throw new IllegalStateException(conversation + " already exists.");
+ }
+
+ conversation = new ExtendedConversationImpl(this, conversationID, ConversationState.STARTED);
+ conversations.put(conversationID, conversation);
+ for (ConversationListener listener : listeners) {
+ listener.conversationStarted(conversation);
+ }
+ return conversation;
+ }
+
+ /**
+ * return the default max idle time
+ * @param impProvider the implementation Provider to extract any ConversationAttribute details
+ */
+ public long getMaxIdleTime() {
+ return maxIdleTime;
+ }
+
+ /**
+ * returns the default max age
+ * @param impProvider the implementation Provider to extract any ConversationAttribute details
+ */
+ public long getMaxAge() {
+ return maxAge;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ExtendedConversationImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ExtendedConversationImpl.java
new file mode 100644
index 0000000000..34bf8a12d5
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/conversation/impl/ExtendedConversationImpl.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.conversation.impl;
+
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtendedConversationImpl implements ConversationExt, Runnable {
+
+ private final ConversationManagerImpl manager;
+ private volatile Object conversationID;
+ private ConversationState state;
+
+ /**
+ * syncs access to the state
+ */
+ private final Object stateSync = new Object();
+
+ /**
+ * the maximum time a conversation can exist
+ */
+ private long expirationTime = 0;
+
+ /**
+ * the maximum time this conversation can be idle
+ */
+ private long maxIdleTime = 0;
+
+ /**
+ * the maximum age of this conversation
+ */
+ private long maxAge = 0;
+
+ /**
+ * the time that this object was created
+ */
+ private long creationTime;
+
+ /**
+ * the time that this object was last referenced
+ */
+ private long lastReferencedTime;
+
+ /**
+ * boolean to ensure expiry only occurs once
+ */
+ private boolean expired = false;
+
+ /**
+ * boolean to indicate if the conversation attributes have
+ * been set. In the case where a remote binding is used
+ * within a composite the JDKInvocationHandler can create the
+ * conversation but the conversationAttributes are not available
+ * until the conversation is retrieved by the RuntimeWireInvoker
+ */
+ private boolean conversationAttributesInitialized = false;
+
+ /**
+ * Constructor
+ * @param manager the conversation manager
+ * @param conversationID the conversation id associated with this conversation
+ * @param state the initial state of this conversation
+ * @param aMaxAge the maximum age of the conversation
+ * @param aMaxIdleTime the maximum idle time
+ */
+ public ExtendedConversationImpl(ConversationManagerImpl manager,
+ Object conversationID, ConversationState state) {
+ super();
+
+ this.creationTime = System.currentTimeMillis();
+ this.lastReferencedTime = creationTime;
+ this.manager = manager;
+ this.conversationID = conversationID;
+ this.state = state;
+ }
+
+ /**
+ * will check whether this conversation has expired and update state if it has
+ * @return true if it has expired
+ */
+ public boolean isExpired() {
+ long currentTime;
+ synchronized (stateSync) {
+
+ // if the attributes haven't been initialized then
+ // this conversation object can't expire
+ if (conversationAttributesInitialized == false) {
+ return false;
+ }
+
+ // check state first
+ if (state == ConversationState.EXPIRED) {
+ return true;
+ }
+
+ // check whether the time is finished
+ currentTime = System.currentTimeMillis();
+ if (((this.lastReferencedTime + this.maxIdleTime) <= currentTime)
+ || (this.expirationTime <= currentTime)) {
+ setState(ConversationState.EXPIRED);
+ return true;
+ }
+ }
+ scheduleNextExpiryTime(currentTime);
+ return false;
+ }
+
+ /**
+ * schedule next expiry time
+ */
+ public void scheduleNextExpiryTime(long currentTime) {
+ if ((lastReferencedTime + maxIdleTime) < expirationTime){
+ manager.scheduleConversation(this, (lastReferencedTime + maxIdleTime) - currentTime);
+ } else {
+ manager.scheduleConversation(this, expirationTime - currentTime);
+ }
+ }
+ /**
+ * updates the last time this conversation was referenced
+ */
+ public void updateLastReferencedTime() {
+ this.lastReferencedTime = System.currentTimeMillis();
+ if (conversationAttributesInitialized == true){
+ scheduleNextExpiryTime(lastReferencedTime);
+ }
+ }
+
+ public ConversationState getState() {
+ synchronized (stateSync){
+ return state;
+ }
+ }
+
+ public void end() {
+ manager.endConversation(conversationID);
+ }
+
+ public Object getConversationID() {
+ return conversationID;
+ }
+
+ /**
+ * @param state the state to set
+ */
+ public void setState(ConversationState state) {
+ synchronized (stateSync){
+ this.state = state;
+ }
+ }
+
+ /**
+ * @param conversationID the conversationID to set
+ */
+ public void setConversationID(Object conversationID) {
+ synchronized (stateSync){
+ if (state != ConversationState.ENDED) {
+ throw new IllegalStateException("The state of conversation " + conversationID + " " + state);
+ }
+ }
+ this.conversationID = conversationID;
+ }
+
+ /**
+ * @param maxAge the maximum age of this conversation
+ */
+ public void initializeConversationAttributes(RuntimeComponent targetComponent){
+ if (targetComponent != null){
+ this.maxAge = getMaxIdleTime(targetComponent.getImplementationProvider());
+ this.maxIdleTime = getMaxAge(targetComponent.getImplementationProvider());
+ this.expirationTime = creationTime + maxAge;
+ this.conversationAttributesInitialized = true;
+ }
+ }
+
+ /**
+ * @return true if the conversational attributes have been initialized
+ */
+ public boolean conversationalAttributesInitialized(){
+ return this.conversationAttributesInitialized;
+ }
+
+ /**
+ * return the max idle time
+ * @param impProvider the implementation Provider to extract any ConversationAttribute details
+ */
+ private long getMaxIdleTime(ImplementationProvider impProvider) {
+ // Check to see if the maxIdleTime has been specified using @ConversationAttributes.
+ // Implementation annotated attributes are honoured first.
+ if ((impProvider != null) &&
+ (impProvider instanceof ScopedImplementationProvider)) {
+ ScopedImplementationProvider aScopedImpl =
+ (ScopedImplementationProvider) impProvider;
+
+ long maxIdleTime = aScopedImpl.getMaxIdleTime();
+ if (maxIdleTime > 0) {
+ return maxIdleTime;
+ }
+ }
+ return manager.getMaxIdleTime();
+ }
+
+ /**
+ * returns the max age
+ * @param impProvider the implementation Provider to extract any ConversationAttribute details
+ */
+ private long getMaxAge(ImplementationProvider impProvider){
+
+ // Check to see if the maxAge has been specified using @ConversationAttributes.
+ // Implementation annotated attributes are honoured first.
+ if ((impProvider != null) &&
+ (impProvider instanceof ScopedImplementationProvider)) {
+ ScopedImplementationProvider aScopedImpl =
+ (ScopedImplementationProvider) impProvider;
+
+ long maxAge = aScopedImpl.getMaxAge();
+ if (maxAge > 0) {
+ return maxAge;
+ }
+ }
+ return manager.getMaxAge();
+ }
+
+ /**
+ * called when expiring
+ */
+ public void run() {
+ synchronized (stateSync){
+ if (!expired){
+ if (isExpired()) {
+ expired = true;
+ try {
+ manager.expireConversation(getConversationID());
+ } catch (IllegalStateException ise) {
+ // ignore this.. this can occur if another thread has subsequently ended
+ // the conversation
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java
new file mode 100644
index 0000000000..2371897dce
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.factory;
+
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetInitializationException;
+
+
+/**
+ * Provides lifecycle management for an implementation instance associated with
+ * a component for use by the component's associated {@link org.apache.tuscany.sca.core.scope.ScopeContainer}
+ *
+ * @version $Rev$ $Date$
+ */
+public interface InstanceWrapper<T> {
+
+ /**
+ * @return
+ */
+ T getInstance();
+
+ /**
+ * @throws TargetInitializationException
+ */
+ void start() throws TargetInitializationException;
+
+ /**
+ * @throws TargetDestructionException
+ */
+ void stop() throws TargetDestructionException;
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java
new file mode 100644
index 0000000000..d35b27fd24
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.factory;
+
+
+/**
+ * Denotes an error creating a new object instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class ObjectCreationException extends RuntimeException {
+ private static final long serialVersionUID = -6423113430265944499L;
+
+ public ObjectCreationException() {
+ super();
+ }
+
+ public ObjectCreationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ObjectCreationException(String message) {
+ super(message);
+ }
+
+ public ObjectCreationException(Throwable cause) {
+ super(cause);
+ }
+
+}
+
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java
new file mode 100644
index 0000000000..3f64d2405b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.factory;
+
+/**
+ * Implementations create new instances of a particular type
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ObjectFactory<T> {
+
+ /**
+ * Return a instance of the type that this factory creates.
+ *
+ * @return a instance from this factory
+ */
+ T getInstance() throws ObjectCreationException;
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CachedProxy.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CachedProxy.java
new file mode 100644
index 0000000000..8c8f001eb9
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CachedProxy.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.util.WeakHashMap;
+
+public class CachedProxy extends Proxy {
+ private static final long serialVersionUID = 783519311852563060L;
+
+ protected CachedProxy(InvocationHandler handler) {
+ super(handler);
+ }
+
+ // This is a cache containing the proxy class constructor for each business interface.
+ // This improves performance compared to calling Proxy.newProxyInstance()
+ // every time that a proxy is needed.
+ private final static WeakHashMap<Class<?>, Constructor<?>> cache = new WeakHashMap<Class<?>, Constructor<?>>();
+
+ public static Object newProxyInstance(ClassLoader classloader, Class<?> aclass[], InvocationHandler invocationhandler)
+ throws IllegalArgumentException {
+ try {
+ if (invocationhandler == null)
+ throw new NullPointerException();
+ // Lookup cached constructor. aclass[0] is the reference's business interface.
+ Constructor<?> proxyCTOR;
+ synchronized (cache) {
+ proxyCTOR = cache.get(aclass[0]);
+ }
+ if (proxyCTOR == null) {
+ Class<?> proxyClass = getProxyClass(classloader, aclass);
+ proxyCTOR = proxyClass.getConstructor(constructorParams);
+ synchronized (cache) {
+ cache.put(aclass[0], proxyCTOR);
+ }
+ }
+ return proxyCTOR.newInstance(new Object[] {invocationhandler});
+ } catch (NoSuchMethodException e) {
+ throw new InternalError(e.toString());
+ } catch (IllegalAccessException e) {
+ throw new InternalError(e.toString());
+ } catch (InstantiationException e) {
+ throw new InternalError(e.toString());
+ } catch (InvocationTargetException e) {
+ throw new InternalError(e.toString());
+ }
+ }
+
+ private static final Class<?> constructorParams[] = {InvocationHandler.class};
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java
new file mode 100644
index 0000000000..8a54b7568f
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.oasisopen.sca.CallableReference;
+
+/**
+ * Uses a wire to return a CallableReference
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallableReferenceObjectFactory implements ObjectFactory<CallableReference<?>> {
+ private Class<?> businessInterface;
+ private RuntimeComponent component;
+ private RuntimeComponentReference reference;
+ private Binding binding;
+
+ /**
+ * Constructor.
+ *
+ * To support the @Reference protected CallableReference<MyService> ref;
+ *
+ * @param businessInterface the interface to inject
+ * @param component the component defining the reference to be injected
+ * @param reference the reference to be injected
+ * @param binding the binding for the reference
+ */
+ public CallableReferenceObjectFactory(Class<?> businessInterface,
+ RuntimeComponent component,
+ RuntimeComponentReference reference,
+ Binding binding) {
+ this.businessInterface = businessInterface;
+ this.component = component;
+ this.reference = reference;
+ this.binding = binding;
+ }
+
+ public CallableReference<?> getInstance() throws ObjectCreationException {
+ return component.getComponentContext().getServiceReference(businessInterface, reference, binding);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java
new file mode 100644
index 0000000000..1ee922144f
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.oasisopen.sca.NoRegisteredCallbackException;
+
+/**
+ * An interceptor applied to the forward direction of a wire that ensures the callback target implements the required
+ * service contract. This is required as callback targets may be set dynamically by service implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallbackInterfaceInterceptor implements Interceptor {
+ private Invoker next;
+
+ public CallbackInterfaceInterceptor() {
+ }
+
+ public Message invoke(Message msg) {
+ ReferenceParameters parameters = msg.getFrom().getReferenceParameters();
+ if (parameters.getCallbackObjectID() != null || parameters.getCallbackReference() != msg.getFrom()
+ .getCallbackEndpoint()) {
+ return next.invoke(msg);
+ } else {
+ throw new NoRegisteredCallbackException("Callback target does not implement the callback interface");
+ }
+ }
+
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ public Invoker getNext() {
+ return next;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java
new file mode 100644
index 0000000000..b949500ab9
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.core.invocation.impl.CallbackReferenceImpl;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+
+/**
+ * Uses a wire to return a CallableReference
+ *
+ * @version $Rev: 574648 $ $Date: 2007-09-11 18:45:36 +0100 (Tue, 11 Sep 2007) $
+ */
+public class CallbackReferenceObjectFactory implements ObjectFactory<CallableReference<?>> {
+ private Class<?> businessInterface;
+ private ProxyFactory proxyFactory;
+ private List<RuntimeWire> wires;
+
+ public CallbackReferenceObjectFactory(Class<?> interfaze, ProxyFactory proxyFactory, List<RuntimeWire> wires) {
+ this.businessInterface = interfaze;
+ this.proxyFactory = proxyFactory;
+ this.wires = wires;
+ }
+
+ public CallableReference<?> getInstance() throws ObjectCreationException {
+ return CallbackReferenceImpl.newInstance(businessInterface, proxyFactory, wires);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java
new file mode 100644
index 0000000000..2b37c30451
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+
+/**
+ * Returns proxy instance for a wire callback
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallbackWireObjectFactory<B> implements ObjectFactory<B> {
+ private Class<B> businessInterface;
+ private ProxyFactory proxyFactory;
+ private List<RuntimeWire> wires;
+
+ public CallbackWireObjectFactory(Class<B> interfaze, ProxyFactory proxyFactory, List<RuntimeWire> wires) {
+ this.businessInterface = interfaze;
+ this.proxyFactory = proxyFactory;
+ this.wires = wires;
+ }
+
+ public B getInstance() throws ObjectCreationException {
+ return proxyFactory.createCallbackProxy(businessInterface, wires);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java
new file mode 100644
index 0000000000..4c3bee0dc9
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Factory;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+import org.apache.tuscany.sca.core.context.impl.CallableReferenceImpl;
+import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.impl.CallbackReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.impl.JDKCallbackInvocationHandler;
+import org.apache.tuscany.sca.core.invocation.impl.JDKInvocationHandler;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * The implementation of a wire service that uses cglib dynamic proxies
+ *
+ * @version $Rev$ $Date$
+ */
+public class CglibProxyFactory implements ProxyFactory {
+ private MessageFactory messageFactory;
+
+ public CglibProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) {
+ this.messageFactory = messageFactory;
+
+ }
+
+ public <T> T createProxy(Class<T> interfaze, RuntimeWire wire) throws ProxyCreationException {
+ ServiceReference<T> serviceReference = new ServiceReferenceImpl(interfaze, wire, this);
+ return createProxy(serviceReference);
+ }
+
+ /**
+ * create the proxy with cglib. use the same JDKInvocationHandler as
+ * JDKProxyService.
+ */
+ public <T> T createProxy(CallableReference<T> callableReference) throws ProxyCreationException {
+ Enhancer enhancer = new Enhancer();
+ Class<T> interfaze = callableReference.getBusinessInterface();
+ enhancer.setSuperclass(interfaze);
+ enhancer.setCallback(new CglibMethodInterceptor<T>(callableReference));
+ Object proxy = enhancer.create();
+ ((CallableReferenceImpl)callableReference).setProxy(proxy);
+ return interfaze.cast(proxy);
+ }
+
+ /**
+ * create the callback proxy with cglib. use the same
+ * JDKCallbackInvocationHandler as JDKProxyService.
+ */
+ public <T> T createCallbackProxy(Class<T> interfaze, final List<RuntimeWire> wires) throws ProxyCreationException {
+ CallbackReferenceImpl<T> callbackReference = CallbackReferenceImpl.newInstance(interfaze, this, wires);
+ return callbackReference != null ? createCallbackProxy(callbackReference) : null;
+ }
+
+ /**
+ * create the callback proxy with cglib. use the same
+ * JDKCallbackInvocationHandler as JDKProxyService.
+ */
+ public <T> T createCallbackProxy(CallbackReferenceImpl<T> callbackReference) throws ProxyCreationException {
+ Enhancer enhancer = new Enhancer();
+ Class<T> interfaze = callbackReference.getBusinessInterface();
+ enhancer.setSuperclass(interfaze);
+ enhancer.setCallback(new CglibMethodInterceptor<T>(callbackReference));
+ Object proxy = enhancer.create();
+ callbackReference.setProxy(proxy);
+ return interfaze.cast(proxy);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ if (isProxyClass(target.getClass())) {
+ Factory factory = (Factory)target;
+ Callback[] callbacks = factory.getCallbacks();
+ if (callbacks.length != 1 || !(callbacks[0] instanceof CglibMethodInterceptor)) {
+ throw new IllegalArgumentException("The object is not a known proxy.");
+ }
+ CglibMethodInterceptor interceptor = (CglibMethodInterceptor)callbacks[0];
+ return (R)interceptor.invocationHandler.getCallableReference();
+ } else {
+ throw new IllegalArgumentException("The object is not a known proxy.");
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class)
+ */
+ public boolean isProxyClass(Class<?> clazz) {
+ return Factory.class.isAssignableFrom(clazz);
+ }
+
+ private class CglibMethodInterceptor<T> implements MethodInterceptor {
+ private JDKInvocationHandler invocationHandler;
+
+ public CglibMethodInterceptor(CallableReference<T> callableReference) {
+ invocationHandler = new JDKInvocationHandler(messageFactory, callableReference);
+ }
+
+ public CglibMethodInterceptor(CallbackReferenceImpl<T> callbackReference) {
+ invocationHandler = new JDKCallbackInvocationHandler(messageFactory, callbackReference);
+ }
+
+ /*
+ public CglibMethodInterceptor(Class<T> interfaze, RuntimeWire wire) {
+ ServiceReference<T> serviceRef = new ServiceReferenceImpl<T>(interfaze, wire, CglibProxyFactory.this);
+ invocationHandler = new JDKInvocationHandler(messageFactory, serviceRef);
+ }
+
+ public CglibMethodInterceptor(Class<T> interfaze, List<RuntimeWire> wires) {
+ CallbackReferenceImpl ref = new CallbackReferenceImpl(interfaze, CglibProxyFactory.this, wires);
+ invocationHandler = new JDKCallbackInvocationHandler(messageFactory, ref);
+ }
+ */
+
+ /**
+ * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy)
+ */
+ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
+ Object result = invocationHandler.invoke(proxy, method, args);
+ return result;
+ }
+
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java
new file mode 100644
index 0000000000..bb212d5869
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.invocation.impl.JDKProxyFactory;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+
+/**
+ * Default implementation of a ProxyFactoryExtensionPoint.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultProxyFactoryExtensionPoint implements ProxyFactoryExtensionPoint {
+ private InterfaceContractMapper interfaceContractMapper;
+ private MessageFactory messageFactory;
+
+ private ProxyFactory interfaceFactory;
+ private ProxyFactory classFactory;
+
+ public DefaultProxyFactoryExtensionPoint(ExtensionPointRegistry extensionPoints) {
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+
+ FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ this.messageFactory = modelFactories.getFactory(MessageFactory.class);
+
+ interfaceFactory = new JDKProxyFactory(messageFactory, interfaceContractMapper);
+ }
+
+ public DefaultProxyFactoryExtensionPoint(MessageFactory messageFactory, InterfaceContractMapper mapper) {
+ this.interfaceContractMapper = mapper;
+ this.messageFactory = messageFactory;
+ interfaceFactory = new JDKProxyFactory(messageFactory, mapper);
+ }
+
+ public ProxyFactory getClassProxyFactory() {
+ return classFactory;
+ }
+
+ public ProxyFactory getInterfaceProxyFactory() {
+ return interfaceFactory;
+ }
+
+ public void setClassProxyFactory(ProxyFactory factory) {
+ this.classFactory = factory;
+
+ }
+
+ public void setInterfaceProxyFactory(ProxyFactory factory) {
+ this.interfaceFactory = factory;
+
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java
new file mode 100644
index 0000000000..0be6e31b43
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.core.invocation.impl.CallbackReferenceImpl;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+
+/**
+ * An extensible proxy factory.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleProxyFactory implements ProxyFactory {
+
+ private ProxyFactoryExtensionPoint proxyFactories;
+
+ public ExtensibleProxyFactory(ProxyFactoryExtensionPoint proxyFactories) {
+ this.proxyFactories = proxyFactories;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#cast(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ if (interfaceFactory.isProxyClass(target.getClass())) {
+ return (R)interfaceFactory.cast(target);
+ } else if (classFactory != null && classFactory.isProxyClass(target.getClass())) {
+ return (R)classFactory.cast(target);
+ } else {
+ throw new IllegalArgumentException("The target is not a callable proxy");
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createCallbackProxy(java.lang.Class,
+ * java.util.List)
+ */
+ public <T> T createCallbackProxy(Class<T> interfaze, List<RuntimeWire> wires) throws ProxyCreationException {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ if (interfaze.isInterface()) {
+ return interfaceFactory.createCallbackProxy(interfaze, wires);
+ } else {
+ return classFactory.createCallbackProxy(interfaze, wires);
+ }
+ }
+
+ public <T> T createProxy(CallableReference<T> callableReference) throws ProxyCreationException {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ if (callableReference.getBusinessInterface().isInterface()) {
+ return interfaceFactory.createProxy(callableReference);
+ } else {
+ return classFactory.createProxy(callableReference);
+ }
+ }
+
+ public <T> T createCallbackProxy(CallbackReferenceImpl<T> callbackReference) throws ProxyCreationException {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ if (callbackReference.getBusinessInterface().isInterface()) {
+ return interfaceFactory.createCallbackProxy(callbackReference);
+ } else {
+ return classFactory.createCallbackProxy(callbackReference);
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createProxy(java.lang.Class,
+ * org.apache.tuscany.sca.runtime.RuntimeWire)
+ */
+ public <T> T createProxy(Class<T> interfaze, RuntimeWire wire) throws ProxyCreationException {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ if (interfaze.isInterface()) {
+ return interfaceFactory.createProxy(interfaze, wire);
+ } else {
+ return classFactory.createProxy(interfaze, wire);
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class)
+ */
+ public boolean isProxyClass(Class<?> clazz) {
+ ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory();
+ ProxyFactory classFactory = proxyFactories.getClassProxyFactory();
+ return interfaceFactory.isProxyClass(clazz) || (classFactory != null && classFactory.isProxyClass(clazz));
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java
new file mode 100644
index 0000000000..934f2f7aa0
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint;
+
+/**
+ * The default implementation of an extensible <code>WireProcessor</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleWireProcessor implements RuntimeWireProcessor {
+
+ private RuntimeWireProcessorExtensionPoint processors;
+
+ public ExtensibleWireProcessor(RuntimeWireProcessorExtensionPoint processors) {
+ this.processors = processors;
+ }
+
+ public void process(RuntimeWire wire) {
+ for (RuntimeWireProcessor processor : processors.getWireProcessors()) {
+ processor.process(wire);
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java
new file mode 100644
index 0000000000..494cb93d97
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Adds non-blocking behavior to an invocation chain
+ *
+ * @version $Rev$ $Date$
+ */
+public class NonBlockingInterceptor implements Interceptor {
+
+ private static final Message RESPONSE = new ImmutableMessage();
+
+ /**
+ * The JDK logger that will be used to log messages.
+ */
+ private static final Logger LOGGER = Logger.getLogger(NonBlockingInterceptor.class.getName());
+
+ private WorkScheduler workScheduler;
+ private Invoker next;
+
+ public NonBlockingInterceptor(WorkScheduler workScheduler) {
+ this.workScheduler = workScheduler;
+ }
+
+ public NonBlockingInterceptor(WorkScheduler workScheduler, Interceptor next) {
+ this.workScheduler = workScheduler;
+ this.next = next;
+ }
+
+ /**
+ * Sets desired workScheduler to NonBlockingInterceptor. This is a useful function for the extension framework
+ * to set desired workmanager on the InvocationChain, other than default workmanager which is set per Tuscany runtime.
+ * Using this function, extension framework can set desired workmanager on InvocationChain during post wire processing.
+ * @param workScheduler workScheduler which contains workmanager
+ */
+ public void setWorkScheduler(WorkScheduler workScheduler){
+ this.workScheduler = workScheduler;
+ }
+
+ public Message invoke(final Message msg) {
+ // Schedule the invocation of the next interceptor in a new Work instance
+ try {
+ workScheduler.scheduleWork(new Runnable() {
+ public void run() {
+ Message context = ThreadMessageContext.setMessageContext(msg);
+ try {
+ Message response = null;
+
+ Throwable ex = null;
+ try {
+ response = next.invoke(msg);
+ } catch (Throwable t) {
+ ex = t;
+ }
+
+ // Tuscany-2225 - Did the @OneWay method complete successfully?
+ // (i.e. no exceptions)
+ if (response != null && response.isFault()) {
+ // The @OneWay method threw an Exception. Lets log it and
+ // then pass it on to the WorkScheduler so it can notify any
+ // listeners
+ ex = (Throwable)response.getBody();
+ }
+ if (ex != null) {
+ LOGGER.log(Level.SEVERE, "Exception from @OneWay invocation", ex);
+ throw new ServiceRuntimeException("Exception from @OneWay invocation", ex);
+ }
+ } finally {
+ ThreadMessageContext.setMessageContext(context);
+ }
+ }
+ });
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ return RESPONSE;
+ }
+
+ public Invoker getNext() {
+ return next;
+ }
+
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ /**
+ * A dummy message passed back on an invocation
+ */
+ private static class ImmutableMessage implements Message {
+
+ public Object getBody() {
+ return null;
+ }
+
+ public void setBody(Object body) {
+ if (body != null) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void setCallbackWires(LinkedList<RuntimeWire> wires) {
+
+ }
+
+ public Object getMessageID() {
+ return null;
+ }
+
+ public void setMessageID(Object messageId) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isFault() {
+ return false;
+ }
+
+ public void setFaultBody(Object fault) {
+ throw new UnsupportedOperationException();
+ }
+
+ public EndpointReference getFrom() {
+ return null;
+ }
+
+ public EndpointReference getTo() {
+ return null;
+ }
+
+ public void setFrom(EndpointReference from) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setTo(EndpointReference to) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Operation getOperation() {
+ return null;
+ }
+
+ public void setOperation(Operation op) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.invocation.Message#getReplyTo()
+ */
+ public EndpointReference getReplyTo() {
+ return null;
+ }
+
+ public Map<String, Object> getQoSContext() {
+ return null;
+ }
+
+ public List<Object> getHeaders() {
+ return null;
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java
new file mode 100644
index 0000000000..0b36b178f3
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+
+
+/**
+ * Denotes an error creating a proxy
+ *
+ * @version $Rev$ $Date$
+ */
+public class ProxyCreationException extends ObjectCreationException {
+ private static final long serialVersionUID = 8002454344828513781L;
+
+ public ProxyCreationException() {
+ super();
+ }
+
+ public ProxyCreationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ProxyCreationException(String message) {
+ super(message);
+ }
+
+ public ProxyCreationException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java
new file mode 100644
index 0000000000..a5fabdf0f6
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.core.invocation.impl.CallbackReferenceImpl;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+
+/**
+ * Creates proxies that implement Java interfaces and invocation handlers for fronting wires
+ *
+ * @version $Rev$ $Date$
+ */
+
+public interface ProxyFactory {
+
+ /**
+ * Creates a Java proxy for the given wire
+ *
+ * @param interfaze the interface the proxy implements
+ * @param wire the wire to proxy
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createProxy(Class<T> interfaze, RuntimeWire wire) throws ProxyCreationException;
+
+ /**
+ * Creates a Java proxy for the given CallableReference
+ *
+ * @param callableReference The CallableReference
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createProxy(CallableReference<T> callableReference) throws ProxyCreationException;
+
+ /**
+ * Creates a Java proxy for the service contract callback
+ *
+ * @param interfaze the interface the proxy should implement
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createCallbackProxy(Class<T> interfaze, List<RuntimeWire> wires) throws ProxyCreationException;
+
+ /**
+ * Creates a Java proxy for the given callback reference
+ *
+ * @param callableReference The CallableReference
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createCallbackProxy(CallbackReferenceImpl<T> callbackReference) throws ProxyCreationException;
+
+ /**
+ * Cast a proxy to a CallableReference.
+ *
+ * @param target a proxy generated by this implementation
+ * @return a CallableReference (or subclass) equivalent to this proxy
+ * @throws IllegalArgumentException if the object supplied is not a proxy
+ */
+ <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException;
+
+ /**
+ * Test if a given class is a generated proxy class by this factory
+ * @param clazz A java class or interface
+ * @return true if the class is a generated proxy class by this factory
+ */
+ boolean isProxyClass(Class<?> clazz);
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java
new file mode 100644
index 0000000000..875a252798
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+
+/**
+ * The extension point to plug in proxy factories
+ * @version $Rev$ $Date$
+ */
+public interface ProxyFactoryExtensionPoint {
+
+ /**
+ * Get the proxy factory for java interfaces
+ * @return
+ */
+ ProxyFactory getInterfaceProxyFactory();
+
+ /**
+ * Get the proxy factory for java classes
+ * @return
+ */
+ ProxyFactory getClassProxyFactory();
+
+ /**
+ * Set the proxy factory for java interfaces
+ * @param factory
+ */
+ void setInterfaceProxyFactory(ProxyFactory factory);
+
+ /**
+ * Set the proxy factory for java classes
+ * @param factory
+ */
+ void setClassProxyFactory(ProxyFactory factory);
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java
new file mode 100644
index 0000000000..831bb62bd8
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.interfacedef.ConversationSequence;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.ConversationEndedException;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RuntimeWireInvoker implements Invoker{
+ protected ConversationManager conversationManager;
+ protected boolean conversational;
+ protected ConversationExt conversation;
+ protected MessageFactory messageFactory;
+ protected Object conversationID;
+ protected Object callbackID;
+ protected Object callbackObject;
+ protected RuntimeWire wire;
+
+ public RuntimeWireInvoker(MessageFactory messageFactory, ConversationManager conversationManager, RuntimeWire wire) {
+ this.messageFactory = messageFactory;
+ this.wire = wire;
+ this.conversationManager = conversationManager;
+ init(wire);
+ }
+
+ protected void init(RuntimeWire wire) {
+ if (wire != null) {
+ ReferenceParameters parameters = wire.getSource().getReferenceParameters();
+ this.callbackID = parameters.getCallbackID();
+ this.callbackObject = parameters.getCallbackReference();
+ this.conversationID = parameters.getConversationID();
+ InterfaceContract contract = wire.getSource().getInterfaceContract();
+ this.conversational = contract.getInterface().isConversational();
+ }
+ }
+
+ /*
+ * TODO - Introduced to allow the RuntimeWireInvoker to sit on the end of the
+ * service binding chain. Runtime wire invoke needs splitting up into
+ * separate conversation, callback interceptors etc.
+ */
+ public Message invoke(Message msg) {
+
+ try {
+ Object response = invoke(msg.getOperation(),msg);
+ // Hack to put the response back in a message.
+ // shouldn't take it out of the response message in the first place
+ msg.setBody(response);
+ } catch (InvocationTargetException e) {
+ throw new ServiceRuntimeException(e);
+ }
+
+ return msg;
+ }
+
+ public Object invoke(Operation operation, Message msg) throws InvocationTargetException {
+ return invoke(wire, operation, msg);
+ }
+
+ public Object invoke(RuntimeWire wire, Operation operation, Message msg) throws InvocationTargetException {
+ RuntimeWire runtimeWire = wire == null ? this.wire : wire;
+ InvocationChain chain = runtimeWire.getInvocationChain(operation);
+ return invoke(chain, msg, runtimeWire);
+ }
+
+ protected Object invoke(InvocationChain chain, Message msg, RuntimeWire wire) throws InvocationTargetException {
+ EndpointReference from = msg.getFrom();
+ EndpointReference epFrom = wire.getSource();
+ if (from != null) {
+ from.mergeEndpoint(epFrom);
+ } else {
+ msg.setFrom(epFrom);
+ }
+ msg.setTo(wire.getTarget());
+
+ Invoker headInvoker = chain.getHeadInvoker();
+ Operation operation = chain.getTargetOperation();
+ msg.setOperation(operation);
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID();
+
+ ThreadMessageContext.setMessageContext(msg);
+ try {
+ conversationPreinvoke(msg);
+ // handleCallback(msg, currentConversationID);
+ // dispatch the wire down the chain and get the response
+ Message resp = headInvoker.invoke(msg);
+ Object body = resp.getBody();
+ if (resp.isFault()) {
+ throw new InvocationTargetException((Throwable)body);
+ }
+ return body;
+ } catch (InvocationTargetException e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new ServiceRuntimeException(e);
+ } finally {
+ try {
+ conversationPostInvoke(msg);
+ } catch (TargetDestructionException e) {
+ throw new ServiceRuntimeException(e);
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+ }
+ }
+
+ /**
+ * @param msgContext
+ */
+ protected EndpointReference getCallbackEndpoint(Message msgContext) {
+ EndpointReference from = msgContext.getFrom();
+ return from == null ? null : from.getReferenceParameters().getCallbackReference();
+ }
+
+ /**
+ * Pre-invoke for the conversation handling
+ * @param msg
+ * @throws TargetResolutionException
+ */
+ private void conversationPreinvoke(Message msg) {
+ if (conversational) {
+ ReferenceParameters parameters = msg.getFrom().getReferenceParameters();
+ // in some cases the ConversationID that should be used comes in with the
+ // message, e.g. when ws binding is in use.
+ Object convID = parameters.getConversationID();
+ if (convID != null) {
+ conversationID = convID;
+ }
+ conversation = conversationManager.getConversation(conversationID);
+
+ if (conversation == null || conversation.getState() == ConversationState.ENDED) {
+ conversation = conversationManager.startConversation(conversationID);
+ conversation.initializeConversationAttributes(wire.getTarget().getComponent());
+ } else if (conversation.conversationalAttributesInitialized() == false) {
+ conversation.initializeConversationAttributes(wire.getTarget().getComponent());
+ } else if (conversation.isExpired()){
+ throw new ConversationEndedException("Conversation has expired.");
+ }
+
+ conversation.updateLastReferencedTime();
+
+ parameters.setConversationID(conversation.getConversationID());
+ }
+ }
+
+ /**
+ * Post-invoke for the conversation handling
+ * @param wire
+ * @param operation
+ * @throws TargetDestructionException
+ */
+ @SuppressWarnings("unchecked")
+ private void conversationPostInvoke(Message msg) throws TargetDestructionException {
+ if (conversational) {
+ Operation operation = msg.getOperation();
+ ConversationSequence sequence = operation.getConversationSequence();
+ if (sequence == ConversationSequence.CONVERSATION_END) {
+ // in some cases the ConversationID that should be used comes in with the
+ // message, e.g. when ws binding is in use.
+ Object convID = msg.getFrom().getReferenceParameters().getConversationID();
+ if (convID != null) {
+ conversationID = convID;
+ }
+ conversation = conversationManager.getConversation(conversationID);
+
+ // remove conversation id from scope container
+ ScopeContainer scopeContainer = getConversationalScopeContainer(msg);
+
+ if (scopeContainer != null) {
+ scopeContainer.remove(conversation.getConversationID());
+ }
+
+ conversation.end();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private ScopeContainer getConversationalScopeContainer(Message msg) {
+ ScopeContainer scopeContainer = null;
+
+ RuntimeComponent component = msg.getTo().getComponent();
+
+ if (component instanceof ScopedRuntimeComponent) {
+ ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)component;
+ ScopeContainer container = scopedRuntimeComponent.getScopeContainer();
+
+ if ((container != null) && (container.getScope() == Scope.CONVERSATION)) {
+ scopeContainer = container;
+ }
+ }
+
+ return scopeContainer;
+ }
+
+
+ /**
+ * Minimal wrapper for a callback object contained in a ServiceReference
+ */
+ private static class CallbackObjectWrapper<T> implements InstanceWrapper<T> {
+
+ private T instance;
+
+ private CallbackObjectWrapper(T instance) {
+ this.instance = instance;
+ }
+
+ public T getInstance() {
+ return instance;
+ }
+
+ public void start() {
+ // do nothing
+ }
+
+ public void stop() {
+ // do nothing
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java
new file mode 100644
index 0000000000..5ae4a24b36
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.impl.MessageImpl;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * Class for tunnelling a WorkContext through the invocation of a user class.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class ThreadMessageContext {
+
+ private static final ThreadLocal<Message> CONTEXT = new ThreadLocal<Message>() {
+ @Override
+ protected synchronized Message initialValue() {
+ Message msg = new MessageImpl();
+ msg.setFrom(new EndpointReferenceImpl("/"));
+ return msg;
+ }
+ };
+
+ private ThreadMessageContext() {
+ }
+
+ /**
+ * Set the WorkContext for the current thread.
+ * The current work context is returned and must be restored after the invocation is complete.
+ * Typical usage would be:
+ * <pre>
+ * WorkContext old = PojoWorkContextTunnel.setThreadWorkContext(newContext);
+ * try {
+ * ... invoke user code ...
+ * } finally {
+ * PojoWorkContextTunnel.setThreadWorkContext(old);
+ * }
+ * </pre>
+ * @param context
+ * @return the current work context for the thread; this must be restored after the invocation is made
+ */
+ public static Message setMessageContext(Message context) {
+ Message old = CONTEXT.get();
+ CONTEXT.set(context);
+ return old;
+ }
+
+ /**
+ * Returns the WorkContext for the current thread.
+ *
+ * @return the WorkContext for the current thread
+ */
+ public static Message getMessageContext() {
+ return CONTEXT.get();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java
new file mode 100644
index 0000000000..2fc3d6c7eb
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation;
+
+import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.core.invocation.impl.NoMethodForOperationException;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+
+/**
+ * Uses a wire to return an object instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireObjectFactory<T> implements ObjectFactory<T> {
+ private Class<T> interfaze;
+ private RuntimeWire wire;
+ private ProxyFactory proxyService;
+
+ /**
+ * Constructor.
+ *
+ * @param interfaze the interface to inject on the client
+ * @param wire the backing wire
+ * @param proxyService the wire service to create the proxy
+ * @throws NoMethodForOperationException
+ */
+ public WireObjectFactory(Class<T> interfaze, RuntimeWire wire, ProxyFactory proxyService) {
+ this.interfaze = interfaze;
+ this.wire = wire;
+ this.proxyService = proxyService;
+ }
+
+ public T getInstance() throws ObjectCreationException {
+ return new ServiceReferenceImpl<T>(interfaze, wire, proxyService).getProxy();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/CallbackReferenceImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/CallbackReferenceImpl.java
new file mode 100644
index 0000000000..301771d879
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/CallbackReferenceImpl.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.EndpointReference2;
+import org.apache.tuscany.sca.assembly.OptimizableBinding;
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentReferenceImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeWireImpl2;
+import org.apache.tuscany.sca.core.context.CompositeContext;
+import org.apache.tuscany.sca.core.context.impl.CallableReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+
+/**
+ * Returns proxy instance for a wire callback
+ *
+ * @version $Rev: 576055 $ $Date: 2007-09-16 08:11:45 +0100 (Sun, 16 Sep 2007) $
+ */
+public class CallbackReferenceImpl<B> extends CallableReferenceImpl<B> {
+ private RuntimeWire wire;
+ private List<RuntimeWire> wires;
+ private EndpointReference resolvedEndpoint;
+ private Object convID;
+
+ public static CallbackReferenceImpl newInstance(Class interfaze,
+ ProxyFactory proxyFactory,
+ List<RuntimeWire> wires) {
+ if (getCallbackEndpoint(ThreadMessageContext.getMessageContext()) != null) {
+ return new CallbackReferenceImpl(interfaze, proxyFactory, wires);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Public constructor for Externalizable serialization/deserialization.
+ */
+ public CallbackReferenceImpl() {
+ super();
+ }
+
+ private CallbackReferenceImpl(Class<B> interfaze, ProxyFactory proxyFactory, List<RuntimeWire> wires) {
+ super(interfaze, null, proxyFactory);
+ this.wires = wires;
+ init();
+ }
+
+ public void init() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ wire = selectCallbackWire(msgContext);
+ if (wire == null) {
+ //FIXME: need better exception
+ throw new RuntimeException("No callback binding found for " + msgContext.getTo().getURI());
+ }
+ resolvedEndpoint = getCallbackEndpoint(msgContext);
+ convID = msgContext.getFrom().getReferenceParameters().getConversationID();
+ callbackID = msgContext.getFrom().getReferenceParameters().getCallbackID();
+ }
+
+ @Override
+ protected Object createProxy() throws Exception {
+ return proxyFactory.createCallbackProxy(this);
+ }
+
+ protected RuntimeWire getCallbackWire() {
+ if (resolvedEndpoint == null) {
+ return null;
+ } else {
+ return cloneAndBind(wire);
+ }
+ }
+
+ protected Object getConvID() {
+ return convID;
+ }
+
+ protected EndpointReference getResolvedEndpoint() {
+ return resolvedEndpoint;
+ }
+
+ private RuntimeWire selectCallbackWire(Message msgContext) {
+ // look for callback binding with same name as service binding
+ EndpointReference to = msgContext.getTo();
+ if (to == null) {
+ //FIXME: need better exception
+ throw new RuntimeException("Destination for forward call is not available");
+ }
+ for (RuntimeWire wire : wires) {
+ if (wire.getSource().getBinding().getName().equals(to.getBinding().getName())) {
+ return wire;
+ }
+ }
+
+ // if no match, look for callback binding with same type as service binding
+ for (RuntimeWire wire : wires) {
+ if (wire.getSource().getBinding().getClass() == to.getBinding().getClass()) {
+ return wire;
+ }
+ }
+
+ // no suitable callback wire was found
+ return null;
+ }
+
+ /**
+ * @param msgContext
+ */
+ private static EndpointReference getCallbackEndpoint(Message msgContext) {
+ EndpointReference from = msgContext.getFrom();
+ if (from == null) {
+ return null;
+ }
+ return from.getReferenceParameters().getCallbackReference();
+ }
+
+ private RuntimeWire cloneAndBind(RuntimeWire wire) {
+ RuntimeWire boundWire = null;
+ if (resolvedEndpoint != null) {
+ boundWire = ((RuntimeWireImpl2)wire).lookupCache(resolvedEndpoint);
+ if (boundWire != null) {
+ return boundWire;
+ }
+ try {
+ Contract contract = resolvedEndpoint.getContract();
+ RuntimeComponentReference ref = null;
+ if (contract == null) {
+ //TODO - EPR - does it ever go through here?
+ boundWire = (RuntimeWire)wire.clone();
+
+ } else if (contract instanceof RuntimeComponentReference) {
+ ref = (RuntimeComponentReference)contract;
+ //TODO - EPR - get the bound wire based on endpont reference no binding
+ //boundWire = ref.getRuntimeWire(resolvedEndpoint.getBinding());
+ for (RuntimeWire runtimeWire : ref.getRuntimeWires()){
+ if (runtimeWire.getEndpointReference().getBinding().getName().equals(resolvedEndpoint.getBinding().getName())){
+ boundWire = runtimeWire;
+ break;
+ }
+ }
+
+ } else { // contract instanceof RuntimeComponentService
+ ref = bind((RuntimeComponentReference)wire.getSource().getContract(),
+ resolvedEndpoint);
+ boundWire = ref.getRuntimeWires().get(0);
+ }
+ configureWire(boundWire);
+ ((RuntimeWireImpl2)wire).addToCache(resolvedEndpoint, boundWire);
+ } catch (CloneNotSupportedException e) {
+ // will not happen
+ }
+ }
+ return boundWire;
+ }
+
+ // TODO - EPR - why static & convert to ne endpoint reference
+ private static RuntimeComponentReference bind(RuntimeComponentReference reference,
+ EndpointReference resolvedEndpoint) throws CloneNotSupportedException {
+ RuntimeComponent component = resolvedEndpoint.getComponent();
+ RuntimeComponentService service = (RuntimeComponentService)resolvedEndpoint.getContract();
+
+ RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone();
+ ref.getTargets().add(service);
+ ref.getBindings().clear();
+ for (Binding binding : service.getBindings()) {
+ if (binding instanceof OptimizableBinding) {
+ OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
+ optimizableBinding.setTargetBinding(binding);
+ optimizableBinding.setTargetComponent(component);
+ optimizableBinding.setTargetComponentService(service);
+ ref.getBindings().add(optimizableBinding);
+ } else {
+ ref.getBindings().add(binding);
+ }
+ }
+
+ ref.getEndpointReferences().clear();
+
+ for(EndpointReference2 endpointReference : reference.getEndpointReferences()){
+ EndpointReference2 clone = (EndpointReference2)endpointReference.clone();
+
+ clone.setReference(ref);
+ clone.getBinding().setURI(resolvedEndpoint.getURI());
+
+ clone.getTargetEndpoint().setComponent(resolvedEndpoint.getComponent());
+ clone.getTargetEndpoint().setService((ComponentService)resolvedEndpoint.getContract());
+ clone.getTargetEndpoint().setBinding(resolvedEndpoint.getBinding());
+
+ ref.getEndpointReferences().add(clone);
+ }
+
+ return ref;
+ }
+
+ private void configureWire(RuntimeWire wire ) {
+
+ // TODO - EPR - do we actiually need this code? Combine with bind?
+ // need to set the endpoint on the binding also so that when the chains are created next
+ // the sca binding can decide whether to provide local or remote invokers.
+ // TODO - there is a problem here though in that I'm setting a target on a
+ // binding that may possibly be trying to point at two things in the multi threaded
+ // case. Need to confirm the general model here and how the clone and bind part
+ // is intended to work
+ Binding binding = wire.getSource().getBinding();
+ binding.setURI(resolvedEndpoint.getURI());
+
+ // set the target contract as it varies for the sca binding depending on
+ // whether it is local or remote
+ RuntimeComponentReference ref = (RuntimeComponentReference)wire.getSource().getContract();
+
+ // TODO - EPR
+ wire.getEndpointReference().getTargetEndpoint().setInterfaceContract(ref.getBindingProvider(binding).getBindingInterfaceContract());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.callbackID = in.readObject();
+ this.convID = in.readObject();
+
+ this.compositeActivator = CompositeContext.getCurrentCompositeActivator();
+
+ // Get the target Component and Service from the URI
+ final String uri = in.readUTF();
+ final Component targetComponent = super.resolveComponentURI(uri);
+ final ComponentService targetService = super.resolveServiceURI(uri, targetComponent);
+ final InterfaceContract targetServiceIfaceContract = targetService.getInterfaceContract();
+
+ // Re-create the resolved Endpoint
+ this.resolvedEndpoint = new EndpointReferenceImpl(
+ (RuntimeComponent) targetComponent, targetService, null,
+ targetServiceIfaceContract);
+
+ // Copy the Java Interface from the Service
+ final JavaInterface ji = (JavaInterface) targetServiceIfaceContract.getInterface();
+ this.businessInterface = (Class<B>) ji.getJavaClass();
+
+ // We need to re-create the callback wire. We need to do this on a clone of the Service
+ // wire since we need to change some details on it.
+ // FIXME: Is this the best way to do this?
+ final RuntimeWire cbWire = ((RuntimeComponentService) targetService).getRuntimeWires().get(0);
+ try {
+ this.wire = (RuntimeWireImpl2) cbWire.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new IOException(e.toString());
+ }
+
+ // Setup the reference on the cloned wire
+ final RuntimeComponentReference ref = new RuntimeComponentReferenceImpl();
+ ref.setComponent((RuntimeComponent) targetComponent);
+ ref.setInterfaceContract(targetServiceIfaceContract);
+ ((EndpointReferenceImpl) this.wire.getSource()).setContract(ref);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeObject(this.callbackID);
+ out.writeObject(this.convID);
+ out.writeUTF(this.resolvedEndpoint.getURI());
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java
new file mode 100644
index 0000000000..3c7fefb674
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Phase;
+
+/**
+ * Default implementation of an invocation chain
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvocationChainImpl implements InvocationChain {
+ private Operation sourceOperation;
+ private Operation targetOperation;
+ private List<Node> nodes = new ArrayList<Node>();
+
+ // FIXME: Not a good practice to use static reference
+ private static final PhaseManager phaseManager = new PhaseManager();
+ private boolean forReference;
+ private boolean allowsPassByReference;
+
+ public InvocationChainImpl(Operation sourceOperation, Operation targetOperation, boolean forReference) {
+ // TODO - binding invocation chain doesn't provide operations
+ //assert sourceOperation != null;
+ //assert targetOperation != null;
+ this.targetOperation = targetOperation;
+ this.sourceOperation = sourceOperation;
+ this.forReference = forReference;
+ }
+
+ public Operation getTargetOperation() {
+ return targetOperation;
+ }
+
+ public void setTargetOperation(Operation operation) {
+ this.targetOperation = operation;
+ }
+
+ public void addInterceptor(Interceptor interceptor) {
+ String phase = forReference ? Phase.REFERENCE : Phase.SERVICE;
+ addInterceptor(phase, interceptor);
+ }
+
+ public void addInvoker(Invoker invoker) {
+ String phase = forReference ? Phase.REFERENCE_BINDING : Phase.IMPLEMENTATION;
+ addInvoker(phase, invoker);
+ }
+
+ public Invoker getHeadInvoker() {
+ return nodes.isEmpty() ? null : nodes.get(0).getInvoker();
+ }
+
+ public Invoker getTailInvoker() {
+ return nodes.isEmpty() ? null : nodes.get(nodes.size() - 1).getInvoker();
+ }
+
+ /**
+ * @return the sourceOperation
+ */
+ public Operation getSourceOperation() {
+ return sourceOperation;
+ }
+
+ /**
+ * @param sourceOperation the sourceOperation to set
+ */
+ public void setSourceOperation(Operation sourceOperation) {
+ this.sourceOperation = sourceOperation;
+ }
+
+ public void addInterceptor(int index, Interceptor interceptor) {
+ addInterceptor(interceptor);
+ }
+
+ public void addInterceptor(String phase, Interceptor interceptor) {
+ addInvoker(phase, interceptor);
+ }
+
+ private void addInvoker(String phase, Invoker invoker) {
+ int index = phaseManager.getAllPhases().indexOf(phase);
+ if (index == -1) {
+ throw new IllegalArgumentException("Invalid phase name: " + phase);
+ }
+ Node node = new Node(index, invoker);
+ ListIterator<Node> li = nodes.listIterator();
+ Node before = null, after = null;
+ boolean found = false;
+ while (li.hasNext()) {
+ before = after;
+ after = li.next();
+ if (after.getPhaseIndex() > index) {
+ // Move back
+ li.previous();
+ li.add(node);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // Add to the end
+ nodes.add(node);
+ before = after;
+ after = null;
+ }
+
+ // Relink the interceptors
+ if (before != null) {
+ if (before.getInvoker() instanceof Interceptor) {
+ ((Interceptor)before.getInvoker()).setNext(invoker);
+ }
+ }
+ if (after != null) {
+ if (invoker instanceof Interceptor) {
+ ((Interceptor)invoker).setNext(after.getInvoker());
+ }
+ }
+
+ }
+
+ public boolean allowsPassByReference() {
+ if (allowsPassByReference) {
+ // No need to check the invokers
+ return true;
+ }
+ // Check if any of the invokers allows pass-by-reference
+ boolean allowsPBR = false;
+ for (Node i : nodes) {
+ if (i.getInvoker() instanceof DataExchangeSemantics) {
+ if (((DataExchangeSemantics)i.getInvoker()).allowsPassByReference()) {
+ allowsPBR = true;
+ break;
+ }
+ }
+ }
+ return allowsPBR;
+ }
+
+ public void setAllowsPassByReference(boolean allowsPBR) {
+ this.allowsPassByReference = allowsPBR;
+ }
+
+ private static class Node {
+ private int phaseIndex;
+ private Invoker invoker;
+
+ public Node(int phaseIndex, Invoker invoker) {
+ super();
+ this.phaseIndex = phaseIndex;
+ this.invoker = invoker;
+ }
+
+ public int getPhaseIndex() {
+ return phaseIndex;
+ }
+
+ public Invoker getInvoker() {
+ return invoker;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + phaseIndex + ")" + invoker;
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java
new file mode 100644
index 0000000000..9a0540915a
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeWireImpl2;
+import org.apache.tuscany.sca.core.context.impl.CallableReferenceImpl;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.NoRegisteredCallbackException;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Responsible for dispatching to a callback through a wire. <p/> TODO cache
+ * target invoker
+ *
+ * @version $Rev$ $Date$
+ */
+public class JDKCallbackInvocationHandler extends JDKInvocationHandler {
+ private static final long serialVersionUID = -3350283555825935609L;
+
+ public JDKCallbackInvocationHandler(MessageFactory messageFactory, CallbackReferenceImpl ref) {
+ super(messageFactory, ref);
+ this.fixedWire = false;
+ }
+
+ @Override
+ @SuppressWarnings( {"unchecked"})
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (Object.class == method.getDeclaringClass()) {
+ return invokeObjectMethod(method, args);
+ }
+
+ // obtain a dedicated wire to be used for this callback invocation
+ RuntimeWire wire = ((CallbackReferenceImpl)callableReference).getCallbackWire();
+ if (wire == null) {
+ //FIXME: need better exception
+ throw new ServiceRuntimeException("No callback wire found");
+ }
+
+ // set the conversational state based on the interface that
+ // is specified for the reference that this wire belongs to
+ initConversational(wire);
+
+ // set the conversation id into the conversation object. This is
+ // a special case for callbacks as, unless otherwise set manually,
+ // the callback should use the same conversation id as was received
+ // on the incoming call to this component
+ if (conversational) {
+
+ if (conversation == null || conversation.getState() == ConversationState.ENDED) {
+ conversation = null;
+ }
+ Object convID = conversation == null ? null : conversation.getConversationID();
+
+ // create a conversation id if one doesn't exist
+ // already, i.e. the conversation is just starting
+ if (convID == null) {
+ convID = ((CallbackReferenceImpl)callableReference).getConvID();
+ if (convID != null) {
+ conversation = ((RuntimeWireImpl2)wire).getConversationManager().getConversation(convID);
+ if (callableReference != null) {
+ ((CallableReferenceImpl)callableReference).attachConversation(conversation);
+ }
+ }
+ }
+ }
+
+ setEndpoint(((CallbackReferenceImpl)callableReference).getResolvedEndpoint());
+
+ InvocationChain chain = getInvocationChain(method, wire);
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + method);
+ }
+
+ try {
+ return invoke(chain, args, wire, wire.getSource());
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof NoRegisteredCallbackException) {
+ throw t;
+ }
+ throw e;
+ } finally {
+ // allow the cloned wire to be reused by subsequent callbacks
+ ((RuntimeWireImpl2)wire).releaseWire();
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java
new file mode 100644
index 0000000000..8ef17503c4
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java
@@ -0,0 +1,519 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeWireImpl2;
+import org.apache.tuscany.sca.core.context.CallableReferenceExt;
+import org.apache.tuscany.sca.core.context.impl.CallableReferenceImpl;
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.conversation.ConversationState;
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.interfacedef.ConversationSequence;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.ConversationEndedException;
+import org.oasisopen.sca.ServiceReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JDKInvocationHandler implements InvocationHandler, Serializable {
+ private static final long serialVersionUID = -3366410500152201371L;
+
+ protected boolean conversational;
+ protected ConversationExt conversation;
+ protected MessageFactory messageFactory;
+ protected EndpointReference source;
+ protected EndpointReference target;
+ protected RuntimeWire wire;
+ protected CallableReference<?> callableReference;
+ protected Class<?> businessInterface;
+
+ protected boolean fixedWire = true;
+
+ protected transient Map<Method, InvocationChain> chains = new HashMap<Method, InvocationChain>();
+
+ public JDKInvocationHandler(MessageFactory messageFactory, Class<?> businessInterface, RuntimeWire wire) {
+ this.messageFactory = messageFactory;
+ this.wire = wire;
+ this.businessInterface = businessInterface;
+ init(this.wire);
+ }
+
+ public JDKInvocationHandler(MessageFactory messageFactory, CallableReference<?> callableReference) {
+ this.messageFactory = messageFactory;
+ this.callableReference = callableReference;
+ if (callableReference != null) {
+ this.businessInterface = callableReference.getBusinessInterface();
+ this.conversation = (ConversationExt)callableReference.getConversation();
+ this.wire = ((CallableReferenceExt<?>)callableReference).getRuntimeWire();
+ if (wire != null) {
+ init(wire);
+ }
+ }
+ }
+
+ protected void init(RuntimeWire wire) {
+ // TODO - EPR needs fixing when we remove the old EndpointReference
+ if (wire != null) {
+ try {
+ // Clone the endpoint reference so that reference parameters can be changed
+ source = (EndpointReference)wire.getSource().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ initConversational(wire);
+ }
+ }
+
+ protected void initConversational(RuntimeWire wire) {
+ InterfaceContract contract = wire.getSource().getInterfaceContract();
+ this.conversational = contract.getInterface().isConversational();
+ }
+
+ protected Object getCallbackID() {
+ if (callableReference != null) {
+ return callableReference.getCallbackID();
+ } else {
+ return null;
+ }
+ }
+
+ protected Object getConversationID() {
+ if (callableReference != null && callableReference instanceof ServiceReference) {
+ return ((ServiceReference)callableReference).getConversationID();
+ } else {
+ return null;
+ }
+ }
+
+ protected Object getCallbackObject() {
+ if (callableReference != null && callableReference instanceof ServiceReference) {
+ return ((ServiceReference)callableReference).getCallback();
+ } else {
+ return null;
+ }
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (Object.class == method.getDeclaringClass()) {
+ return invokeObjectMethod(method, args);
+ }
+ if (wire == null) {
+ throw new ServiceRuntimeException("No runtime wire is available");
+ }
+ InvocationChain chain = getInvocationChain(method, wire);
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + method);
+ }
+
+ // send the invocation down the wire
+ Object result = invoke(chain, args, wire, source);
+
+ return result;
+ }
+
+ /**
+ * Handle the methods on the Object.class
+ * @param method
+ * @param args
+ */
+ protected Object invokeObjectMethod(Method method, Object[] args) throws Throwable {
+ String name = method.getName();
+ if ("toString".equals(name)) {
+ return "[Proxy - " + toString() + "]";
+ } else if ("equals".equals(name)) {
+ Object obj = args[0];
+ if (obj == null) {
+ return false;
+ }
+ if (!Proxy.isProxyClass(obj.getClass())) {
+ return false;
+ }
+ return equals(Proxy.getInvocationHandler(obj));
+ } else if ("hashCode".equals(name)) {
+ return hashCode();
+ } else {
+ return method.invoke(this);
+ }
+ }
+
+ /**
+ * Determines if the given operation matches the given method
+ *
+ * @return true if the operation matches, false if does not
+ */
+ // FIXME: Should it be in the InterfaceContractMapper?
+ @SuppressWarnings("unchecked")
+ private static boolean match(Operation operation, Method method) {
+ if (operation instanceof JavaOperation) {
+ JavaOperation javaOp = (JavaOperation)operation;
+ Method m = javaOp.getJavaMethod();
+ if (!method.getName().equals(m.getName())) {
+ return false;
+ }
+ if (method.equals(m)) {
+ return true;
+ }
+ } else {
+ if (!method.getName().equals(operation.getName())) {
+ return false;
+ }
+ }
+
+ // For remotable interface, operation is not overloaded.
+ if (operation.getInterface().isRemotable()) {
+ return true;
+ }
+
+ Class<?>[] params = method.getParameterTypes();
+
+ DataType<List<DataType>> inputType = null;
+ if (operation.isWrapperStyle()) {
+ inputType = operation.getWrapper().getUnwrappedInputType();
+ } else {
+ inputType = operation.getInputType();
+ }
+ List<DataType> types = inputType.getLogical();
+ boolean matched = true;
+ if (types.size() == params.length && method.getName().equals(operation.getName())) {
+ for (int i = 0; i < params.length; i++) {
+ Class<?> clazz = params[i];
+ Class<?> type = types.get(i).getPhysical();
+ // Object.class.isAssignableFrom(int.class) returns false
+ if (type != Object.class && (!type.isAssignableFrom(clazz))) {
+ matched = false;
+ }
+ }
+ } else {
+ matched = false;
+ }
+ return matched;
+
+ }
+
+ protected synchronized InvocationChain getInvocationChain(Method method, RuntimeWire wire) {
+ if (fixedWire && chains.containsKey(method)) {
+ return chains.get(method);
+ }
+ InvocationChain found = null;
+ for (InvocationChain chain : wire.getInvocationChains()) {
+ Operation operation = chain.getSourceOperation();
+ if (operation.isDynamic()) {
+ operation.setName(method.getName());
+ found = chain;
+ break;
+ } else if (match(operation, method)) {
+ found = chain;
+ break;
+ }
+ }
+ if (fixedWire) {
+ chains.put(method, found);
+ }
+ return found;
+ }
+
+ protected void setEndpoint(EndpointReference endpoint) {
+ this.target = endpoint;
+ }
+
+ protected Object invoke(InvocationChain chain, Object[] args, RuntimeWire wire, EndpointReference source)
+ throws Throwable {
+ Message msg = messageFactory.createMessage();
+ msg.setFrom(source);
+ if (target != null) {
+ msg.setTo(target);
+ } else {
+ msg.setTo(wire.getTarget());
+ }
+ Invoker headInvoker = chain.getHeadInvoker();
+ Operation operation = chain.getTargetOperation();
+ msg.setOperation(operation);
+ msg.setBody(args);
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID();
+
+ conversationPreinvoke(msg, wire);
+ handleCallback(msg, wire, currentConversationID);
+ ThreadMessageContext.setMessageContext(msg);
+ boolean abnormalEndConversation = false;
+ try {
+ // dispatch the wire down the chain and get the response
+ Message resp = headInvoker.invoke(msg);
+ Object body = resp.getBody();
+ if (resp.isFault()) {
+ // mark the conversation as ended if the exception is not a business exception
+ if (currentConversationID != null ){
+ try {
+ boolean businessException = false;
+
+ for (DataType dataType : operation.getFaultTypes()){
+ if (dataType.getPhysical() == ((Throwable)body).getClass()){
+ businessException = true;
+ break;
+ }
+ }
+
+ if (businessException == false){
+ abnormalEndConversation = true;
+ }
+ } catch (Exception ex){
+ // TODO - sure what the best course of action is here. We have
+ // a system exception in the middle of a business exception
+ }
+ }
+ throw (Throwable)body;
+ }
+ return body;
+ } finally {
+ conversationPostInvoke(msg, wire, abnormalEndConversation);
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+ }
+
+ /**
+ * @param msg
+ * @param wire
+ * @param interfaze
+ * @throws TargetResolutionException
+ */
+ private void handleCallback(Message msg, RuntimeWire wire, Object currentConversationID)
+ throws TargetResolutionException {
+ ReferenceParameters parameters = msg.getFrom().getReferenceParameters();
+ parameters.setCallbackID(getCallbackID());
+ if (msg.getFrom() == null || msg.getFrom().getCallbackEndpoint() == null) {
+ return;
+ }
+
+ parameters.setCallbackReference(msg.getFrom().getCallbackEndpoint());
+
+ // If we are passing out a callback target
+ // register the calling component instance against this
+ // new conversation id so that stateful callbacks will be
+ // able to find it
+ Object callbackObject = getCallbackObject();
+ if (conversational && callbackObject == null) {
+ // the component instance is already registered
+ // so add another registration
+ ScopeContainer<Object> scopeContainer = getConversationalScopeContainer(wire);
+
+ if (scopeContainer != null && currentConversationID != null) {
+ scopeContainer.addWrapperReference(currentConversationID, conversation.getConversationID());
+ }
+ }
+
+ Interface interfaze = msg.getFrom().getCallbackEndpoint().getInterfaceContract().getInterface();
+ if (callbackObject != null) {
+ if (callbackObject instanceof ServiceReference) {
+ EndpointReference callbackRef = ((CallableReferenceExt<?>)callbackObject).getEndpointReference();
+ parameters.setCallbackReference(callbackRef);
+ } else {
+ if (interfaze != null) {
+ if (!interfaze.isConversational()) {
+ throw new IllegalArgumentException(
+ "Callback object for stateless callback is not a ServiceReference");
+ } else {
+ if (!(callbackObject instanceof Serializable)) {
+ throw new IllegalArgumentException(
+ "Callback object for stateful callback is not Serializable");
+ }
+ ScopeContainer scopeContainer = getConversationalScopeContainer(wire);
+ if (scopeContainer != null) {
+ InstanceWrapper wrapper = new CallbackObjectWrapper(callbackObject);
+ scopeContainer.registerWrapper(wrapper, conversation.getConversationID());
+ }
+ parameters.setCallbackObjectID(callbackObject);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Pre-invoke for the conversation handling
+ * @param msg
+ * @throws TargetResolutionException
+ */
+ private void conversationPreinvoke(Message msg, RuntimeWire wire) {
+ if (!conversational) {
+ // Not conversational or the conversation has been started
+ return;
+ }
+
+ ConversationManager conversationManager = ((RuntimeWireImpl2)wire).getConversationManager();
+
+ if (conversation == null || conversation.getState() == ConversationState.ENDED) {
+
+ conversation = conversationManager.startConversation(getConversationID());
+
+ // if this is a local wire then set up the conversation timeouts here based on the
+ // parameters from the component
+ if (wire.getTarget().getComponent() != null){
+ conversation.initializeConversationAttributes(wire.getTarget().getComponent());
+ }
+
+ // connect the conversation to the CallableReference so it can be retrieve in the future
+ if (callableReference != null) {
+ ((CallableReferenceImpl)callableReference).attachConversation(conversation);
+ }
+ } else if (conversation.isExpired()) {
+ throw new ConversationEndedException("Conversation " + conversation.getConversationID() + " has expired.");
+ }
+
+ // if this is a local wire then schedule conversation timeouts based on the timeout
+ // parameters from the service implementation. If this isn't a local wire then
+ // the RuntimeWireInvoker will take care of this
+ if (wire.getTarget().getComponent() != null){
+ conversation.updateLastReferencedTime();
+ }
+
+ msg.getFrom().getReferenceParameters().setConversationID(conversation.getConversationID());
+
+ }
+
+ /**
+ * Post-invoke for the conversation handling
+ * @param wire
+ * @param operation
+ * @throws TargetDestructionException
+ */
+ @SuppressWarnings("unchecked")
+ private void conversationPostInvoke(Message msg, RuntimeWire wire, boolean abnormalEndConversation)
+ throws TargetDestructionException {
+ Operation operation = msg.getOperation();
+ ConversationSequence sequence = operation.getConversationSequence();
+ // We check that conversation has not already ended as there is only one
+ // conversation manager in the runtime and so, in the case of remote bindings,
+ // the conversation will already have been stopped when we get back to the client
+ if ((sequence == ConversationSequence.CONVERSATION_END || abnormalEndConversation) &&
+ (conversation.getState() != ConversationState.ENDED)) {
+
+ // remove conversation id from scope container
+ ScopeContainer scopeContainer = getConversationalScopeContainer(wire);
+
+ if (scopeContainer != null) {
+ scopeContainer.remove(conversation.getConversationID());
+ }
+
+ conversation.end();
+ }
+ }
+
+ private ScopeContainer<Object> getConversationalScopeContainer(RuntimeWire wire) {
+ ScopeContainer<Object> scopeContainer = null;
+
+ RuntimeComponent runtimeComponent = wire.getSource().getComponent();
+
+ if (runtimeComponent instanceof ScopedRuntimeComponent) {
+ ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)runtimeComponent;
+ ScopeContainer<Object> tmpScopeContainer = scopedRuntimeComponent.getScopeContainer();
+
+ if ((tmpScopeContainer != null) && (tmpScopeContainer.getScope() == Scope.CONVERSATION)) {
+ scopeContainer = tmpScopeContainer;
+ }
+ }
+
+ return scopeContainer;
+ }
+
+ /**
+ * Creates a new conversation id
+ *
+ * @return the conversation id
+ */
+ private Object createConversationID() {
+ if (getConversationID() != null) {
+ return getConversationID();
+ } else {
+ return UUID.randomUUID().toString();
+ }
+ }
+
+ /**
+ * @return the callableReference
+ */
+ public CallableReference<?> getCallableReference() {
+ return callableReference;
+ }
+
+ /**
+ * @param callableReference the callableReference to set
+ */
+ public void setCallableReference(CallableReference<?> callableReference) {
+ this.callableReference = callableReference;
+ }
+
+ /**
+ * Minimal wrapper for a callback object contained in a ServiceReference
+ */
+ private static class CallbackObjectWrapper<T> implements InstanceWrapper<T> {
+
+ private T instance;
+
+ private CallbackObjectWrapper(T instance) {
+ this.instance = instance;
+ }
+
+ public T getInstance() {
+ return instance;
+ }
+
+ public void start() {
+ // do nothing
+ }
+
+ public void stop() {
+ // do nothing
+ }
+
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java
new file mode 100644
index 0000000000..dc713353fe
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.lang.reflect.InvocationHandler;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+
+import org.apache.tuscany.sca.core.context.impl.CallableReferenceImpl;
+import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.CachedProxy;
+import org.apache.tuscany.sca.core.invocation.ProxyCreationException;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.RuntimeWire;
+import org.oasisopen.sca.CallableReference;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * the default implementation of a wire service that uses JDK dynamic proxies
+ *
+ * @version $Rev$ $Date$
+ */
+public class JDKProxyFactory implements ProxyFactory {
+ protected InterfaceContractMapper contractMapper;
+ private MessageFactory messageFactory;
+
+ public JDKProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) {
+ this.contractMapper = mapper;
+ this.messageFactory = messageFactory;
+ }
+
+ /**
+ * The original createProxy method assumes that the proxy doesn't want to
+ * share conversation state so sets the conversation object to null
+ */
+ public <T> T createProxy(Class<T> interfaze, RuntimeWire wire) throws ProxyCreationException {
+ ServiceReference<T> serviceReference = new ServiceReferenceImpl(interfaze, wire, this);
+ return createProxy(serviceReference);
+ }
+
+ public <T> T createProxy(CallableReference<T> callableReference) throws ProxyCreationException {
+ assert callableReference != null;
+ final Class<T> interfaze = callableReference.getBusinessInterface();
+ InvocationHandler handler = new JDKInvocationHandler(messageFactory, callableReference);
+ // Allow privileged access to class loader. Requires RuntimePermission in security policy.
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return interfaze.getClassLoader();
+ }
+ });
+ Object proxy = CachedProxy.newProxyInstance(cl, new Class[] {interfaze}, handler);
+ ((CallableReferenceImpl)callableReference).setProxy(proxy);
+ return interfaze.cast(proxy);
+ }
+
+ public <T> T createCallbackProxy(Class<T> interfaze, List<RuntimeWire> wires) throws ProxyCreationException {
+ CallbackReferenceImpl<T> callbackReference = CallbackReferenceImpl.newInstance(interfaze, this, wires);
+ return callbackReference != null ? createCallbackProxy(callbackReference) : null;
+ }
+
+ public <T> T createCallbackProxy(CallbackReferenceImpl<T> callbackReference) throws ProxyCreationException {
+ assert callbackReference != null;
+ Class<T> interfaze = callbackReference.getBusinessInterface();
+ InvocationHandler handler = new JDKCallbackInvocationHandler(messageFactory, callbackReference);
+ ClassLoader cl = interfaze.getClassLoader();
+ Object proxy = CachedProxy.newProxyInstance(cl, new Class[] {interfaze}, handler);
+ callbackReference.setProxy(proxy);
+ return interfaze.cast(proxy);
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ InvocationHandler handler = CachedProxy.getInvocationHandler(target);
+ if (handler instanceof JDKInvocationHandler) {
+ return (R)((JDKInvocationHandler)handler).getCallableReference();
+ } else {
+ throw new IllegalArgumentException("The object is not a known proxy.");
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class)
+ */
+ public boolean isProxyClass(Class<?> clazz) {
+ return CachedProxy.isProxyClass(clazz);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java
new file mode 100644
index 0000000000..6ce2ffca21
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+
+/**
+ * Implementation of MessageFactory.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MessageFactoryImpl implements MessageFactory {
+
+ public Message createMessage() {
+ return new MessageImpl();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java
new file mode 100644
index 0000000000..e81e5a2f31
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+
+/**
+ * The default implementation of a message flowed through a wire during an invocation
+ *
+ * @version $Rev $Date$
+ */
+public class MessageImpl implements Message {
+ private List<Object> headers = new ArrayList<Object>();
+ private Object body;
+ private Object messageID;
+ private boolean isFault;
+ private Operation operation;
+
+ private EndpointReference from;
+ private EndpointReference to;
+
+ public MessageImpl() {
+ this.from = new EndpointReferenceImpl("/");
+ this.to = new EndpointReferenceImpl("/");
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getBody() {
+ return (T)body;
+ }
+
+ public <T> void setBody(T body) {
+ this.isFault = false;
+ this.body = body;
+ }
+
+ public Object getMessageID() {
+ return messageID;
+ }
+
+ public void setMessageID(Object messageId) {
+ this.messageID = messageId;
+ }
+
+ public boolean isFault() {
+ return isFault;
+ }
+
+ public void setFaultBody(Object fault) {
+ this.isFault = true;
+ this.body = fault;
+ }
+
+ public EndpointReference getFrom() {
+ return from;
+ }
+
+ public void setFrom(EndpointReference from) {
+ this.from = from;
+ }
+
+ public EndpointReference getTo() {
+ return to;
+ }
+
+ public void setTo(EndpointReference to) {
+ this.to = to;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(Operation op) {
+ this.operation = op;
+ }
+
+ public List<Object> getHeaders() {
+ return headers;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java
new file mode 100644
index 0000000000..45f4bf52bf
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import org.apache.tuscany.sca.core.invocation.ProxyCreationException;
+
+
+/**
+ * Thrown when an {@link org.apache.tuscany.sca.core.factory.model.Operation} cannot be mapped to a method on an interface
+ * @version $Rev$ $Date$
+ */
+public class NoMethodForOperationException extends ProxyCreationException {
+ private static final long serialVersionUID = 5116536602309483679L;
+
+ public NoMethodForOperationException() {
+ }
+
+ public NoMethodForOperationException(String message) {
+ super(message);
+ }
+
+ public NoMethodForOperationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NoMethodForOperationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java
new file mode 100644
index 0000000000..602958ab5e
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION;
+import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION_POLICY;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_POLICY;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_TRANSPORT;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_WIREFORMAT;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_INTERFACE;
+import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_POLICY;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_OPERATION_SELECTOR;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_POLICY;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_TRANSPORT;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_WIREFORMAT;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_INTERFACE;
+import static org.apache.tuscany.sca.invocation.Phase.SERVICE_POLICY;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PhaseManager {
+ private static final Logger log = Logger.getLogger(PhaseManager.class.getName());
+
+ public static final String STAGE_REFERENCE = "reference";
+ public static final String STAGE_REFERENCE_BINDING = "reference.binding";
+ public static final String STAGE_SERVICE_BINDING = "service.binding";
+ public static final String STAGE_SERVICE = "service";
+ public static final String STAGE_IMPLEMENTATION = "implementation";
+
+ private static final String[] SYSTEM_REFERENCE_PHASES =
+ {REFERENCE, REFERENCE_INTERFACE, REFERENCE_POLICY, REFERENCE_BINDING};
+
+ private static final String[] SYSTEM_REFERENCE_BINDING_PHASES =
+ {REFERENCE_BINDING_WIREFORMAT, REFERENCE_BINDING_POLICY, REFERENCE_BINDING_TRANSPORT};
+
+ private static final String[] SYSTEM_SERVICE_BINDING_PHASES =
+ {SERVICE_BINDING_TRANSPORT, SERVICE_BINDING_OPERATION_SELECTOR, SERVICE_BINDING_WIREFORMAT, SERVICE_BINDING_POLICY};
+
+ private static final String[] SYSTEM_SERVICE_PHASES =
+ {SERVICE_BINDING, SERVICE_POLICY, SERVICE_INTERFACE, SERVICE};
+
+ private static final String[] SYSTEM_IMPLEMENTATION_PHASES = {IMPLEMENTATION_POLICY, IMPLEMENTATION};
+
+ private String pattern = Phase.class.getName();
+ private Map<String, Stage> stages;
+ private List<String> phases;
+
+ public class Stage {
+ private String name;
+ private PhaseSorter<String> sorter = new PhaseSorter<String>();
+ private Set<String> firstSet = new HashSet<String>();
+ private Set<String> lastSet = new HashSet<String>();
+ private List<String> phases = new ArrayList<String>();
+
+ public Stage(String name) {
+ super();
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public PhaseSorter<String> getSorter() {
+ return sorter;
+ }
+
+ public Set<String> getFirstSet() {
+ return firstSet;
+ }
+
+ public Set<String> getLastSet() {
+ return lastSet;
+ }
+
+ public List<String> getPhases() {
+ return phases;
+ }
+
+ @Override
+ public String toString() {
+ return name + phases;
+ }
+ }
+
+ // For unit test purpose
+ PhaseManager(String pattern) {
+ super();
+ this.pattern = pattern;
+ }
+
+ public PhaseManager() {
+ }
+
+ private List<String> getPhases(String stage) {
+ Stage s = getStages().get(stage);
+ return s == null ? null : s.getPhases();
+ }
+
+ public List<String> getReferencePhases() {
+ return getPhases(STAGE_REFERENCE);
+ }
+
+ public List<String> getServicePhases() {
+ return getPhases(STAGE_SERVICE);
+ }
+
+ public List<String> getReferenceBindingPhases() {
+ return getPhases(STAGE_REFERENCE_BINDING);
+ }
+
+ public List<String> getServiceBindingPhases() {
+ return getPhases(STAGE_SERVICE_BINDING);
+ }
+
+ public List<String> getImplementationPhases() {
+ return getPhases(STAGE_IMPLEMENTATION);
+ }
+
+ public synchronized List<String> getAllPhases() {
+ if (phases == null) {
+ phases = new ArrayList<String>();
+ phases.addAll(getReferencePhases());
+ phases.addAll(getReferenceBindingPhases());
+ phases.addAll(getServiceBindingPhases());
+ phases.addAll(getServicePhases());
+ phases.addAll(getImplementationPhases());
+ }
+ return phases;
+ }
+
+ public synchronized Map<String, Stage> getStages() {
+ if (stages != null) {
+ return stages;
+ }
+ init();
+
+ Set<ServiceDeclaration> services;
+ try {
+ services = ServiceDiscovery.getInstance().getServiceDeclarations(pattern);
+ } catch (IOException e) {
+ throw new ServiceRuntimeException(e);
+ }
+
+ for (ServiceDeclaration d : services) {
+ if (log.isLoggable(Level.FINE)) {
+ log.fine(d.getLocation() + ": " + d.getAttributes());
+ }
+ String name = d.getAttributes().get("name");
+ if (name == null) {
+ throw new ServiceRuntimeException("Required attribute 'name' is missing.");
+ }
+ String stageName = d.getAttributes().get("stage");
+ if (stageName == null) {
+ throw new ServiceRuntimeException("Required attribute 'stage' is missing.");
+ }
+ Stage stage = stages.get(stageName);
+ if (stage == null) {
+ throw new ServiceRuntimeException("Invalid stage: " + stageName);
+ }
+ PhaseSorter<String> graph = stage.getSorter();
+ Set<String> firstSet = stage.getFirstSet(), lastSet = stage.getLastSet();
+
+ String before = d.getAttributes().get("before");
+ String after = d.getAttributes().get("after");
+ if (before != null) {
+ StringTokenizer tokenizer = new StringTokenizer(before);
+ while (tokenizer.hasMoreTokens()) {
+ String p = tokenizer.nextToken();
+ if (!"*".equals(p)) {
+ graph.addEdge(name, p);
+ } else {
+ firstSet.add(name);
+ }
+ }
+ }
+ if (after != null) {
+ StringTokenizer tokenizer = new StringTokenizer(after);
+ while (tokenizer.hasMoreTokens()) {
+ String p = tokenizer.nextToken();
+ if (!"*".equals(p)) {
+ graph.addEdge(p, name);
+ } else {
+ lastSet.add(name);
+ }
+ }
+ }
+ graph.addVertext(name);
+ if(firstSet.size()>1) {
+ log.warning("More than one phases are declared to be first: "+firstSet);
+ }
+ for (String s : firstSet) {
+ for (String v : new HashSet<String>(graph.getVertices().keySet())) {
+ if (!firstSet.contains(v)) {
+ graph.addEdge(s, v);
+ }
+ }
+ }
+ if(lastSet.size()>1) {
+ log.warning("More than one phases are declared to be the last: "+lastSet);
+ }
+ for (String s : lastSet) {
+ for (String v : new HashSet<String>(graph.getVertices().keySet())) {
+ if (!lastSet.contains(v)) {
+ graph.addEdge(v, s);
+ }
+ }
+ }
+
+ }
+
+ for (Stage s : stages.values()) {
+ List<String> phases = s.getSorter().topologicalSort(false);
+ s.getPhases().clear();
+ s.getPhases().addAll(phases);
+ }
+ if (log.isLoggable(Level.FINE)) {
+ log.fine("Stages: " + stages);
+ }
+ return stages;
+ }
+
+ private void init() {
+ stages = new HashMap<String, Stage>();
+
+ Stage referenceStage = new Stage(STAGE_REFERENCE);
+ for (int i = 1; i < SYSTEM_REFERENCE_PHASES.length; i++) {
+ referenceStage.getSorter().addEdge(SYSTEM_REFERENCE_PHASES[i - 1], SYSTEM_REFERENCE_PHASES[i]);
+ }
+ referenceStage.getLastSet().add(REFERENCE_BINDING);
+ stages.put(referenceStage.getName(), referenceStage);
+
+ Stage referenceBindingStage = new Stage(STAGE_REFERENCE_BINDING);
+ for (int i = 1; i < SYSTEM_REFERENCE_BINDING_PHASES.length; i++) {
+ referenceBindingStage.getSorter().addEdge(SYSTEM_REFERENCE_BINDING_PHASES[i - 1], SYSTEM_REFERENCE_BINDING_PHASES[i]);
+ }
+ stages.put(referenceBindingStage.getName(), referenceBindingStage);
+
+ Stage serviceBindingStage = new Stage(STAGE_SERVICE_BINDING);
+ for (int i = 1; i < SYSTEM_SERVICE_BINDING_PHASES.length; i++) {
+ serviceBindingStage.getSorter().addEdge(SYSTEM_SERVICE_BINDING_PHASES[i - 1], SYSTEM_SERVICE_BINDING_PHASES[i]);
+ }
+ stages.put(serviceBindingStage.getName(), serviceBindingStage);
+
+
+ Stage serviceStage = new Stage(STAGE_SERVICE);
+ for (int i = 1; i < SYSTEM_SERVICE_PHASES.length; i++) {
+ serviceStage.getSorter().addEdge(SYSTEM_SERVICE_PHASES[i - 1], SYSTEM_SERVICE_PHASES[i]);
+ }
+ stages.put(serviceStage.getName(), serviceStage);
+
+ Stage implementationStage = new Stage(STAGE_IMPLEMENTATION);
+ for (int i = 1; i < SYSTEM_IMPLEMENTATION_PHASES.length; i++) {
+ implementationStage.getSorter().addEdge(SYSTEM_IMPLEMENTATION_PHASES[i - 1],
+ SYSTEM_IMPLEMENTATION_PHASES[i]);
+ }
+ implementationStage.getLastSet().add(IMPLEMENTATION);
+ stages.put(implementationStage.getName(), implementationStage);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java
new file mode 100644
index 0000000000..175f3463ad
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Directed, weighted graph
+ *
+ * @param <V> The type of vertex object
+ * @param <E> The type of edge object
+ *
+ * @version $Rev$ $Date$
+ */
+public class PhaseSorter<V> implements Cloneable {
+ private final Map<V, Vertex> vertices = new HashMap<V, Vertex>();
+
+ /**
+ * Vertex of a graph
+ */
+ public final class Vertex {
+ private V value;
+
+ // TODO: Do we want to support multiple edges for a vertex pair? If so,
+ // we should use a List instead of Map
+ private Map<Vertex, Edge> outEdges = new HashMap<Vertex, Edge>();
+ private Map<Vertex, Edge> inEdges = new HashMap<Vertex, Edge>();
+
+ private Vertex(V value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + value + ")";
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public Map<Vertex, Edge> getOutEdges() {
+ return outEdges;
+ }
+
+ public Map<Vertex, Edge> getInEdges() {
+ return inEdges;
+ }
+
+ }
+
+ /**
+ * An Edge connects two vertices in one direction
+ */
+ public final class Edge {
+ private Vertex sourceVertex;
+
+ private Vertex targetVertex;
+
+ public Edge(Vertex source, Vertex target) {
+ this.sourceVertex = source;
+ this.targetVertex = target;
+ }
+
+ @Override
+ public String toString() {
+ return sourceVertex + "->" + targetVertex;
+ }
+
+ public Vertex getTargetVertex() {
+ return targetVertex;
+ }
+
+ public void setTargetVertex(Vertex vertex) {
+ this.targetVertex = vertex;
+ }
+
+ public Vertex getSourceVertex() {
+ return sourceVertex;
+ }
+
+ public void setSourceVertex(Vertex sourceVertex) {
+ this.sourceVertex = sourceVertex;
+ }
+ }
+
+ public void addEdge(V source, V target) {
+ Vertex s = getVertex(source);
+ if (s == null) {
+ s = new Vertex(source);
+ vertices.put(source, s);
+ }
+ Vertex t = getVertex(target);
+ if (t == null) {
+ t = new Vertex(target);
+ vertices.put(target, t);
+ }
+ Edge edge = new Edge(s, t);
+ s.outEdges.put(t, edge);
+ t.inEdges.put(s, edge);
+ }
+
+ public void addVertext(V source) {
+ Vertex s = getVertex(source);
+ if (s == null) {
+ s = new Vertex(source);
+ vertices.put(source, s);
+ }
+ }
+
+ public Vertex getVertex(V source) {
+ Vertex s = vertices.get(source);
+ return s;
+ }
+
+ public boolean removeEdge(V source, V target) {
+ Vertex s = getVertex(source);
+ if (s == null) {
+ return false;
+ }
+
+ Vertex t = getVertex(target);
+ if (t == null) {
+ return false;
+ }
+
+ return s.outEdges.remove(t) != null && t.inEdges.remove(s) != null;
+
+ }
+
+ public void removeEdge(Edge edge) {
+ edge.sourceVertex.outEdges.remove(edge.targetVertex);
+ edge.targetVertex.inEdges.remove(edge.sourceVertex);
+ }
+
+ public void removeVertex(Vertex vertex) {
+ vertices.remove(vertex.getValue());
+ for (Edge e : new ArrayList<Edge>(vertex.outEdges.values())) {
+ removeEdge(e);
+ }
+ for (Edge e : new ArrayList<Edge>(vertex.inEdges.values())) {
+ removeEdge(e);
+ }
+ }
+
+ public Edge getEdge(Vertex source, Vertex target) {
+ return source.outEdges.get(target);
+ }
+
+ public Edge getEdge(V source, V target) {
+ Vertex sv = getVertex(source);
+ if (sv == null) {
+ return null;
+ }
+ Vertex tv = getVertex(target);
+ if (tv == null) {
+ return null;
+ }
+ return getEdge(getVertex(source), getVertex(target));
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (Vertex v : vertices.values()) {
+ sb.append(v.outEdges.values()).append("\n");
+ }
+ return sb.toString();
+ }
+
+ public Map<V, Vertex> getVertices() {
+ return vertices;
+ }
+
+ public void addGraph(PhaseSorter<V> otherGraph) {
+ for (Vertex v : otherGraph.vertices.values()) {
+ for (Edge e : v.outEdges.values()) {
+ addEdge(e.sourceVertex.value, e.targetVertex.value);
+ }
+ }
+ }
+
+ private Vertex getFirst() {
+ for (Vertex v : vertices.values()) {
+ if (v.inEdges.isEmpty()) {
+ return v;
+ }
+ }
+ if (!vertices.isEmpty()) {
+ throw new IllegalArgumentException("Circular ordering has been detected: " + toString());
+ } else {
+ return null;
+ }
+ }
+
+ public List<V> topologicalSort(boolean readOnly) {
+ PhaseSorter<V> graph = (!readOnly) ? this : (PhaseSorter<V>)clone();
+ List<V> list = new ArrayList<V>();
+ while (true) {
+ Vertex v = graph.getFirst();
+ if (v == null) {
+ break;
+ }
+ list.add(v.getValue());
+ graph.removeVertex(v);
+ }
+
+ return list;
+ }
+
+ @Override
+ public Object clone() {
+ PhaseSorter<V> copy = new PhaseSorter<V>();
+ copy.addGraph(this);
+ return copy;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java
new file mode 100644
index 0000000000..4674456925
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * Implements functionality common to scope contexts.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractScopeContainer<KEY> implements ScopeContainer<KEY> {
+ protected Map<KEY, InstanceWrapper<?>> wrappers = new ConcurrentHashMap<KEY, InstanceWrapper<?>>();
+ protected final Scope scope;
+
+ protected RuntimeComponent component;
+ protected volatile int lifecycleState = UNINITIALIZED;
+
+
+ public AbstractScopeContainer(Scope scope, RuntimeComponent component) {
+ this.scope = scope;
+ this.component = component;
+ }
+
+ protected void checkInit() {
+ if (getLifecycleState() != RUNNING) {
+ throw new IllegalStateException("Scope container not running [" + getLifecycleState() + "]");
+ }
+ }
+
+ /**
+ * Creates a new physical instance of a component, wrapped in an
+ * InstanceWrapper.
+ *
+ * @param component the component whose instance should be created
+ * @return a wrapped instance that has been injected but not yet started
+ * @throws TargetResolutionException if there was a problem creating the
+ * instance
+ */
+ protected InstanceWrapper createInstanceWrapper() throws TargetResolutionException {
+ ImplementationProvider implementationProvider = component.getImplementationProvider();
+ if (implementationProvider instanceof ScopedImplementationProvider) {
+ return ((ScopedImplementationProvider)implementationProvider).createInstanceWrapper();
+ }
+ return null;
+ }
+
+ public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException {
+ return getWrapper(contextId); // TODO: what is this method supposed to do diff than getWrapper?
+ }
+
+ public Scope getScope() {
+ return scope;
+ }
+
+ public InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException {
+ return wrappers.get(contextId);
+ }
+
+ public void addWrapperReference(KEY existingContextId, KEY newContextId)
+ throws TargetResolutionException {
+ // do nothing here. the conversational scope container implements this
+ }
+
+ public void registerWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetResolutionException {
+ // do nothing here. the conversational scope container implements this
+ }
+
+ protected boolean isEagerInit() {
+ ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider();
+ if (implementationProvider instanceof ScopedImplementationProvider) {
+ return ((ScopedImplementationProvider)implementationProvider).isEagerInit();
+ }
+ return false;
+ }
+
+ public void returnWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetDestructionException {
+ }
+
+ /**
+ * Default implementation of remove which does nothing
+ *
+ * @param contextId the identifier of the context to remove.
+ */
+ public void remove(KEY contextId)
+ throws TargetDestructionException {
+ }
+
+ public synchronized void start() {
+ int lifecycleState = getLifecycleState();
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ setLifecycleState(RUNNING);
+ }
+
+ public void startContext(KEY contextId) {
+ if(isEagerInit()) {
+ try {
+ getWrapper(contextId);
+ } catch (TargetResolutionException e) {
+ //
+ }
+ }
+ }
+
+ public synchronized void stop() {
+ int lifecycleState = getLifecycleState();
+ if (lifecycleState != RUNNING) {
+ throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]");
+ }
+ setLifecycleState(STOPPED);
+ }
+
+ public void stopContext(KEY contextId) {
+ wrappers.remove(contextId);
+ }
+
+ @Override
+ public String toString() {
+ String s;
+ switch (lifecycleState) {
+ case ScopeContainer.CONFIG_ERROR:
+ s = "CONFIG_ERROR";
+ break;
+ case ScopeContainer.ERROR:
+ s = "ERROR";
+ break;
+ case ScopeContainer.INITIALIZING:
+ s = "INITIALIZING";
+ break;
+ case ScopeContainer.INITIALIZED:
+ s = "INITIALIZED";
+ break;
+ case ScopeContainer.RUNNING:
+ s = "RUNNING";
+ break;
+ case ScopeContainer.STOPPING:
+ s = "STOPPING";
+ break;
+ case ScopeContainer.STOPPED:
+ s = "STOPPED";
+ break;
+ case ScopeContainer.UNINITIALIZED:
+ s = "UNINITIALIZED";
+ break;
+ default:
+ s = "UNKNOWN";
+ break;
+ }
+ return "In state [" + s + ']';
+ }
+
+ public RuntimeComponent getComponent() {
+ return component;
+ }
+
+ public void setComponent(RuntimeComponent component) {
+ this.component = component;
+ }
+
+ public int getLifecycleState() {
+ return lifecycleState;
+ }
+
+ /**
+ * Set the current state of the Lifecycle.
+ *
+ * @param lifecycleState the new state
+ */
+ protected void setLifecycleState(int lifecycleState) {
+ this.lifecycleState = lifecycleState;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java
new file mode 100644
index 0000000000..b6857be97a
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.core.scope.impl.CompositeScopeContainerFactory;
+import org.apache.tuscany.sca.core.scope.impl.ConversationalScopeContainerFactory;
+import org.apache.tuscany.sca.core.scope.impl.RequestScopeContainerFactory;
+import org.apache.tuscany.sca.core.scope.impl.ScopeRegistryImpl;
+import org.apache.tuscany.sca.core.scope.impl.StatelessScopeContainerFactory;
+
+/**
+ * A default scope registry implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultScopeRegistry extends ScopeRegistryImpl implements ScopeRegistry {
+
+ public DefaultScopeRegistry() {
+ ScopeContainerFactory[] factories =
+ new ScopeContainerFactory[] {new CompositeScopeContainerFactory(), new StatelessScopeContainerFactory(),
+ new RequestScopeContainerFactory(),
+ new ConversationalScopeContainerFactory(),
+ // new HttpSessionScopeContainer(monitor)
+ };
+ for (ScopeContainerFactory f : factories) {
+ register(f);
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java
new file mode 100644
index 0000000000..0a20d793f7
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+/**
+ * The default implementation scopes supported by assemblies.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Scope {
+ public static final Scope STATELESS = new Scope("STATELESS");
+ public static final Scope REQUEST = new Scope("REQUEST");
+ public static final Scope SESSION = new Scope("SESSION");
+ public static final Scope CONVERSATION = new Scope("CONVERSATION");
+ public static final Scope COMPOSITE = new Scope("COMPOSITE");
+ public static final Scope SYSTEM = new Scope("SYSTEM");
+ public static final Scope UNDEFINED = new Scope("UNDEFINED");
+
+ private String scope;
+
+ public Scope(String scope) {
+ this.scope = scope.toUpperCase().intern();
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final Scope scope1 = (Scope) o;
+ return !(scope != null ? scope != scope1.scope.intern() : scope1.scope != null);
+ }
+
+ @Override
+ public int hashCode() {
+ return scope != null ? scope.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return scope;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java
new file mode 100644
index 0000000000..2398ecea3e
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+
+/**
+ * Manages the lifecycle and visibility of instances associated with a an {@link RuntimeComponent}.
+ *
+ * @version $Rev$ $Date$
+ * @param <KEY> the type of IDs that this container uses to identify its contexts.
+ * For example, for COMPOSITE scope this could be the URI of the composite component,
+ * or for HTTP Session scope it might be the HTTP session ID.
+ */
+public interface ScopeContainer<KEY> {
+
+ /**
+ * Returns the Scope that this container supports.
+ *
+ * @return the Scope that this container supports
+ */
+ Scope getScope();
+
+ /**
+ * Start a new context with the supplied ID.
+ *
+ * @param contextId an ID that uniquely identifies the context.
+ */
+ void startContext(KEY contextId);
+
+ /**
+ * Stop the context with the supplied ID.
+ *
+ * @param contextId an ID that uniquely identifies the context.
+ */
+ void stopContext(KEY contextId);
+
+ /**
+ * Returns an instance wrapper associated with the current scope context, creating one if necessary
+ * @param contextId the id for the scope context
+ *
+ * @return the wrapper for the target instance
+ * @throws TargetResolutionException if there was a problem instantiating the target instance
+ */
+ InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException;
+
+ /**
+ * Allows a component to be registered against more than one context id. This is required in the
+ * case of stateful callbacks where we want to identify the originating client component instance
+ * as the callback target but we don't want to reuse the clients original conversation id
+ *
+ * @param existingContextId an id that identifies an existing component instance
+ * @param newContextId a new id against which this component will also be registered
+ * @throws TargetResolutionException
+ */
+ void addWrapperReference(KEY existingContextId, KEY newContextId)
+ throws TargetResolutionException;
+
+ /**
+ * Register an existing instance against a context id. This is needed
+ * for a stateful callback where the service reference for the forward call
+ * contains a callback object that is not a service reference.
+ *
+ * @param wrapper the instance wrapper for the instance to be registered
+ * @param contextId the id for the scope context
+ * @throws TargetResolutionException
+ */
+ void registerWrapper(InstanceWrapper wrapper, KEY contextId)
+ throws TargetResolutionException;
+
+ /**
+ * Returns an implementation instance associated with the current scope context.
+ * If no instance is found, a {@link TargetNotFoundException} is thrown.
+ * @param contextId the id for the scope context
+ *
+ * @return the wrapper for the target instance
+ * @throws TargetResolutionException if there was a problem instantiating the target instance
+ */
+ InstanceWrapper getAssociatedWrapper(KEY contextId)
+ throws TargetResolutionException;
+
+ /**
+ * Return a wrapper after use (for example, after invoking the instance).
+ * @param wrapper the wrapper for the target instance being returned
+ * @param contextId the id for the scope context
+ *
+ * @throws TargetDestructionException if there was a problem returning the target instance
+ */
+ void returnWrapper(InstanceWrapper wrapper, KEY contextId)
+ throws TargetDestructionException;
+
+ /**
+ * Removes an identified component implementation instance associated with the current
+ * context from persistent storage
+ *
+ * @param contextId the identifier of the context to remove.
+ */
+ void remove(KEY contextId)
+ throws TargetDestructionException;
+
+ /* A configuration error state */
+ int CONFIG_ERROR = -1;
+ /* Has not been initialized */
+ int UNINITIALIZED = 0;
+ /* In the process of being configured and initialized */
+ int INITIALIZING = 1;
+ /* Instantiated and configured */
+ int INITIALIZED = 2;
+ /* Configured and initialized */
+ int RUNNING = 4;
+ /* In the process of being shutdown */
+ int STOPPING = 5;
+ /* Has been shutdown and removed from the composite */
+ int STOPPED = 6;
+ /* In an error state */
+ int ERROR = 7;
+
+ /**
+ * Returns the lifecycle state
+ *
+ * @see #UNINITIALIZED
+ * @see #INITIALIZING
+ * @see #INITIALIZED
+ * @see #RUNNING
+ * @see #STOPPING
+ * @see #STOPPED
+ */
+ int getLifecycleState();
+
+ /**
+ * Starts the Lifecycle.
+ */
+ void start();
+
+ /**
+ * Stops the Lifecycle.
+ */
+ void stop();
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java
new file mode 100644
index 0000000000..b19c14b3e0
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * Factory to create ScopeContainer for components
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ScopeContainerFactory {
+ ScopeContainer createScopeContainer(RuntimeComponent component);
+ Scope getScope();
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java
new file mode 100644
index 0000000000..842ed4c547
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+
+/**
+ * Manages {@link ScopeContainer}s in the runtime
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ScopeRegistry {
+
+ /**
+ * Returns the scope container for the given scope or null if one not found
+ *
+ * @param scope the scope
+ * @return the scope container for the given scope or null if one not found
+ */
+ ScopeContainer getScopeContainer(RuntimeComponent component);
+
+ /**
+ * @param factory
+ */
+ void register(ScopeContainerFactory factory);
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java
new file mode 100644
index 0000000000..30d5c77181
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+
+/**
+ * A component implementation can implement this interface to provide scope
+ * management for the components
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ScopedImplementationProvider extends ImplementationProvider {
+ /**
+ * Get the scope for the component implementation
+ *
+ * @return The scope for the component implementation, if null is returned,
+ * STATELESS will be used
+ */
+ Scope getScope();
+
+ /**
+ * Indicate if the component needs to be eagerly initialized
+ *
+ * @return true if the component is marked to be eagerly initialized, false
+ * otherwise
+ */
+ boolean isEagerInit();
+
+ /**
+ * @return the maxAge
+ */
+ long getMaxAge();
+
+ /**
+ * @return the maxIdleTime
+ */
+ long getMaxIdleTime();
+
+ /**
+ * Create a wrapper for the component instance for the scope management
+ *
+ * @return A wrapper for the component instance
+ */
+ InstanceWrapper createInstanceWrapper();
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java
new file mode 100644
index 0000000000..c27b112f8a
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * Scoped runtime component
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ScopedRuntimeComponent extends RuntimeComponent {
+ /**
+ * Set the associated scope container
+ * @param scopeContainer
+ */
+ void setScopeContainer(ScopeContainer scopeContainer);
+ /**
+ * Get the assoicated scope container
+ * @return
+ */
+ ScopeContainer getScopeContainer();
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java
new file mode 100644
index 0000000000..0f83dad97d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+/**
+ * Denotes an error destroying a target
+ *
+ * @version $Rev$ $Date$
+ */
+public class TargetDestructionException extends TargetResolutionException {
+ private static final long serialVersionUID = -6126684147851674709L;
+
+ public TargetDestructionException() {
+ super();
+ }
+
+ public TargetDestructionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TargetDestructionException(String message) {
+ super(message);
+ }
+
+ public TargetDestructionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java
new file mode 100644
index 0000000000..15959c0608
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+/**
+ * Denotes an error initializing a target
+ *
+ * @version $Rev$ $Date$
+ */
+public class TargetInitializationException extends TargetResolutionException {
+ private static final long serialVersionUID = -6228778208649752698L;
+
+ public TargetInitializationException() {
+ super();
+ }
+
+ public TargetInitializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TargetInitializationException(String message) {
+ super(message);
+ }
+
+ public TargetInitializationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java
new file mode 100644
index 0000000000..bb46a2499b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+/**
+ * Thrown when a target of an operation cannot be found
+ *
+ * @version $Rev$ $Date$
+ */
+public class TargetNotFoundException extends TargetResolutionException {
+ private static final long serialVersionUID = 5541830480658471186L;
+
+ public TargetNotFoundException() {
+ super();
+ }
+
+ public TargetNotFoundException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TargetNotFoundException(String message) {
+ super(message);
+ }
+
+ public TargetNotFoundException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java
new file mode 100644
index 0000000000..ea8d0e876c
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope;
+
+/**
+ * Denotes an error retrieving a target instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class TargetResolutionException extends Exception {
+ private static final long serialVersionUID = 2912513650522019405L;
+
+ public TargetResolutionException() {
+ super();
+ }
+
+ public TargetResolutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TargetResolutionException(String message) {
+ super(message);
+ }
+
+ public TargetResolutionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java
new file mode 100644
index 0000000000..6763c8117d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.scope.AbstractScopeContainer;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetNotFoundException;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * A scope context which manages atomic component instances keyed by composite
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeScopeContainer<KEY> extends AbstractScopeContainer<KEY> {
+ private InstanceWrapper<?> wrapper;
+
+ public CompositeScopeContainer(RuntimeComponent component) {
+ super(Scope.COMPOSITE, component);
+ }
+
+ @Override
+ public synchronized void stop() {
+ super.stop();
+ if (wrapper != null) {
+ try {
+ wrapper.stop();
+ } catch (TargetDestructionException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ wrapper = null;
+ }
+
+ @Override
+ public synchronized InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException {
+ if (wrapper == null) {
+ wrapper = createInstanceWrapper();
+ wrapper.start();
+ }
+ return wrapper;
+ }
+
+ @Override
+ public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException {
+ if (wrapper == null) {
+ throw new TargetNotFoundException(component.getURI());
+ }
+ return wrapper;
+ }
+
+ @Override
+ public synchronized void start() {
+ super.start();
+ if (isEagerInit()) {
+ try {
+ getWrapper(null);
+ } catch (TargetResolutionException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java
new file mode 100644
index 0000000000..f61e70a598
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CompositeScopeContainerFactory implements ScopeContainerFactory {
+
+ public ScopeContainer createScopeContainer(RuntimeComponent component) {
+ return new CompositeScopeContainer(component);
+ }
+
+ public Scope getScope() {
+ return Scope.COMPOSITE;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainer.java
new file mode 100644
index 0000000000..1ae7bd58e1
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainer.java
@@ -0,0 +1,293 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.core.conversation.ConversationExt;
+import org.apache.tuscany.sca.core.conversation.ConversationListener;
+import org.apache.tuscany.sca.core.conversation.ConversationManager;
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.core.scope.AbstractScopeContainer;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * A scope context which manages atomic component instances keyed on ConversationID
+ *
+ * @version $Rev$ $Date$
+ */
+public class ConversationalScopeContainer extends AbstractScopeContainer<Object> implements ConversationListener {
+ private ConversationManager conversationManager;
+ private Map<Object, InstanceLifeCycleWrapper> instanceLifecycleCollection =
+ new ConcurrentHashMap<Object, InstanceLifeCycleWrapper>();
+
+ public ConversationalScopeContainer(RuntimeComponent component) {
+ super(Scope.CONVERSATION, component);
+
+ // Note: aStore is here to preserve the original factory interface. It is not currently used in this
+ // implementation since we do not support instance persistence.
+
+ // Check System properties to see if timeout values have been specified. All timeout values
+ // will be specified in seconds.
+ //
+
+ }
+
+
+ protected InstanceWrapper getInstanceWrapper(boolean create, Object contextId) throws TargetResolutionException {
+
+ // we might get a null context if the target service has
+ // conversational scope but only its callback interface
+ // is conversational. In this case we need to invent a
+ // conversation Id here to store the service against
+ // and populate the thread context
+ if (contextId == null) {
+ contextId = UUID.randomUUID().toString();
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ if (msgContext != null) {
+ msgContext.getFrom().getReferenceParameters().setConversationID(contextId);
+ }
+ }
+
+ InstanceLifeCycleWrapper anInstanceWrapper = this.instanceLifecycleCollection.get(contextId);
+
+ if (anInstanceWrapper == null && !create)
+ return null;
+
+ if (anInstanceWrapper == null) {
+ anInstanceWrapper = new InstanceLifeCycleWrapper(contextId);
+ this.instanceLifecycleCollection.put(contextId, anInstanceWrapper);
+ }
+
+ return anInstanceWrapper.getInstanceWrapper(contextId);
+
+ }
+
+ @Override
+ public InstanceWrapper getWrapper(Object contextId) throws TargetResolutionException {
+ return getInstanceWrapper(true, contextId);
+ }
+
+ /**
+ * This method allows a new context id to be registered alongside an existing one. This happens in
+ * one case, when a conversation includes a stateful callback. The client component instance
+ * must be registered against all outgoing conversation ids so that the component instance
+ * can be found when the callback arrives
+ *
+ * @param existingContextId the context id against which the component is already registered
+ * @param context this should be a conversation object so that the conversation can b stored
+ * and reset when the component instance is removed
+ */
+ @Override
+ public void addWrapperReference(Object existingContextId, Object contextId) throws TargetResolutionException {
+
+
+ // get the instance wrapper via the existing id
+ InstanceLifeCycleWrapper existingInstanceWrapper = this.instanceLifecycleCollection.get(existingContextId);
+ InstanceLifeCycleWrapper newInstanceWrapper = this.instanceLifecycleCollection.get(contextId);
+
+ // only add the extra reference once
+ if (newInstanceWrapper == null) {
+ // add the id to the list of ids that the wrapper holds. Used for reference
+ // counting and conversation resetting on destruction.
+ existingInstanceWrapper.addCallbackConversation(contextId);
+
+ // add the reference to the collection
+ this.instanceLifecycleCollection.put(contextId, existingInstanceWrapper);
+ }
+ }
+
+ @Override
+ public void registerWrapper(InstanceWrapper wrapper, Object contextId) throws TargetResolutionException {
+ // if a wrapper for a different instance is already registered for this contextId, remove it
+ InstanceLifeCycleWrapper anInstanceWrapper = this.instanceLifecycleCollection.get(contextId);
+ if (anInstanceWrapper != null) {
+ if (anInstanceWrapper.getInstanceWrapper(contextId).getInstance() != wrapper.getInstance()) {
+ remove(contextId);
+ } else {
+ return;
+ }
+ }
+
+ anInstanceWrapper = new InstanceLifeCycleWrapper(wrapper, contextId);
+ this.instanceLifecycleCollection.put(contextId, anInstanceWrapper);
+ }
+
+ // The remove is invoked when a conversation is explicitly ended. This can occur by using the @EndsConversation or API.
+ // In this case the instance is immediately removed. A new conversation will be started on the next operation
+ // associated with this conversationId's service reference.
+ //
+ @Override
+ public void remove(Object contextId) throws TargetDestructionException {
+ if (contextId != null) {
+ if (this.instanceLifecycleCollection.containsKey(contextId)) {
+ InstanceLifeCycleWrapper anInstanceLifeCycleWrapper = this.instanceLifecycleCollection.get(contextId);
+ this.instanceLifecycleCollection.remove(contextId);
+ anInstanceLifeCycleWrapper.removeInstanceWrapper(contextId);
+ }
+ }
+ }
+
+ /*
+ * This is an inner class that keeps track of the lifecycle of a conversation scoped
+ * implementation instance.
+ *
+ */
+
+ private class InstanceLifeCycleWrapper {
+ private Object clientConversationId;
+ private List<Object> callbackConversations = new ArrayList<Object>();
+
+ private InstanceLifeCycleWrapper(Object contextId) throws TargetResolutionException {
+ this.clientConversationId = contextId;
+ this.createInstance(contextId);
+ }
+
+ private InstanceLifeCycleWrapper(InstanceWrapper wrapper, Object contextId) throws TargetResolutionException {
+ this.clientConversationId = contextId;
+ wrappers.put(contextId, wrapper);
+ }
+
+
+ // Associates a callback conversation with this instance. Each time the scope container
+ // is asked to remove an object given a ontextId an associated conversation object will
+ // have its conversationId reset to null. When the list of ids is empty the component instance
+ // will be removed from the scope container
+ private void addCallbackConversation(Object conversationID) {
+ InstanceWrapper ctx = getInstanceWrapper(clientConversationId);
+ callbackConversations.add(conversationID);
+ wrappers.put(conversationID, ctx);
+ }
+
+ //
+ // Return the backing implementation instance
+ //
+ private InstanceWrapper getInstanceWrapper(Object contextId) {
+ InstanceWrapper ctx = wrappers.get(contextId);
+ return ctx;
+ }
+
+ private void removeInstanceWrapper(Object contextId) throws TargetDestructionException {
+ InstanceWrapper ctx = getInstanceWrapper(contextId);
+ wrappers.remove(contextId);
+
+ // find out if we are dealing with the original client conversation id
+ // and reset accordingly
+ if ( ( clientConversationId != null ) && ( clientConversationId.equals(contextId)) ) {
+ clientConversationId = null;
+ } else {
+ // reset the conversationId in the conversation object if present
+ // so that and ending callback causes the conversation in the originating
+ // service reference in the client to be reset
+ callbackConversations.remove(contextId);
+ }
+
+ // stop the component if this removes the last reference
+ if (clientConversationId == null && callbackConversations.isEmpty()) {
+ ctx.stop();
+ }
+ }
+
+ private void createInstance(Object contextId) throws TargetResolutionException {
+ InstanceWrapper instanceWrapper = createInstanceWrapper();
+ instanceWrapper.start();
+ wrappers.put(contextId, instanceWrapper);
+ }
+
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationEnded(org.apache.tuscany.sca.core.conversation.ConversationExt)
+ */
+ public void conversationEnded(ConversationExt conversation) {
+ try {
+ remove(conversation.getConversationID());
+ } catch (Exception ex) {
+
+ }
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationExpired(org.apache.tuscany.sca.core.conversation.ConversationExt)
+ */
+ public void conversationExpired(ConversationExt conversation) {
+
+ Object conversationId = conversation.getConversationID();
+ InstanceLifeCycleWrapper ilcw = instanceLifecycleCollection.get(conversationId);
+ if (ilcw != null) {
+ // cycle through all the references to this instance and
+ // remove them from the underlying wrappers collection and
+ // from the lifecycle wrappers collection
+
+ for (Object conversationID : ilcw.callbackConversations) {
+ try{
+ ilcw.removeInstanceWrapper(conversationID);
+ remove(conversationID);
+ } catch(TargetDestructionException tde) {
+ System.out.println("Could not remove conversation id " + conversationID);
+ }
+ }
+
+
+ if (ilcw.clientConversationId != null) {
+ try{
+ ilcw.removeInstanceWrapper(ilcw.clientConversationId);
+ remove(ilcw.clientConversationId);
+ } catch(TargetDestructionException tde) {
+ System.out.println("Could not remove conversation id " + ilcw.clientConversationId);
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationStarted(org.apache.tuscany.sca.core.conversation.ConversationExt)
+ */
+ public void conversationStarted(ConversationExt conversation) {
+ startContext(conversation.getConversationID());
+ }
+
+ /**
+ * @return the conversationManager
+ */
+ public ConversationManager getConversationManager() {
+ return conversationManager;
+ }
+
+ /**
+ * @param conversationManager the conversationManager to set
+ */
+ public void setConversationManager(ConversationManager conversationManager) {
+ this.conversationManager = conversationManager;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainerFactory.java
new file mode 100644
index 0000000000..f8ffc027a1
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ConversationalScopeContainerFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConversationalScopeContainerFactory implements ScopeContainerFactory {
+
+ public ConversationalScopeContainerFactory() {
+ super();
+ }
+
+ public ScopeContainer createScopeContainer(RuntimeComponent component) {
+ return new ConversationalScopeContainer(component);
+ }
+
+ public Scope getScope() {
+ return Scope.CONVERSATION;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainer.java
new file mode 100644
index 0000000000..bfe197255d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainer.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.scope.AbstractScopeContainer;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * A scope context which manages atomic component instances keyed on HTTP
+ * session
+ *
+ * @version $Rev$ $Date$
+ */
+public class HttpSessionScopeContainer extends AbstractScopeContainer<Object> {
+
+ public HttpSessionScopeContainer(RuntimeComponent component) {
+ super(Scope.SESSION, component);
+ }
+
+ @Override
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ @Override
+ public synchronized void stop() {
+ lifecycleState = STOPPED;
+ }
+
+ protected InstanceWrapper getInstanceWrapper(boolean create) throws TargetResolutionException {
+// Object key = workContext.getIdentifier(Scope.SESSION);
+ // FIXME: Need to fix this
+ Object key ="http-session-id";
+ assert key != null : "HTTP session key not bound in work context";
+ InstanceWrapper ctx = wrappers.get(key);
+ if (ctx == null && !create) {
+ return null;
+ }
+ if (ctx == null) {
+ ctx = super.createInstanceWrapper();
+ ctx.start();
+ wrappers.put(key, ctx);
+ }
+ return ctx;
+ }
+
+ @Override
+ public InstanceWrapper getWrapper(Object contextId) throws TargetResolutionException {
+ return getInstanceWrapper(true);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainerFactory.java
new file mode 100644
index 0000000000..d6aaa4cc84
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/HttpSessionScopeContainerFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class HttpSessionScopeContainerFactory implements ScopeContainerFactory {
+
+ public HttpSessionScopeContainerFactory() {
+ super();
+ }
+
+ public ScopeContainer createScopeContainer(RuntimeComponent component) {
+ return new HttpSessionScopeContainer(component);
+ }
+
+ public Scope getScope() {
+ return Scope.SESSION;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainer.java
new file mode 100644
index 0000000000..7519af2341
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainer.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.scope.AbstractScopeContainer;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * A scope context which manages atomic component instances keyed on the current
+ * request context
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeContainer extends AbstractScopeContainer<Thread> {
+ private final Map<Thread, InstanceWrapper> contexts;
+
+ public RequestScopeContainer(RuntimeComponent component) {
+ super(Scope.REQUEST, component);
+ contexts = new ConcurrentHashMap<Thread, InstanceWrapper>();
+ }
+
+ @Override
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ @Override
+ public synchronized void stop() {
+ contexts.clear();
+ // synchronized (destroyQueues) {
+ // destroyQueues.clear();
+ // }
+ lifecycleState = STOPPED;
+ }
+
+ protected InstanceWrapper getInstanceWrapper(boolean create) throws TargetResolutionException {
+ InstanceWrapper ctx = wrappers.get(Thread.currentThread());
+ if (ctx == null && !create) {
+ return null;
+ }
+ if (ctx == null) {
+ ctx = super.createInstanceWrapper();
+ ctx.start();
+ wrappers.put(Thread.currentThread(), ctx);
+ }
+ return ctx;
+ }
+
+ @Override
+ public InstanceWrapper getWrapper(Thread contextId) throws TargetResolutionException {
+ return getInstanceWrapper(true);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainerFactory.java
new file mode 100644
index 0000000000..9d1cf88d96
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/RequestScopeContainerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeContainerFactory implements ScopeContainerFactory {
+
+ public ScopeContainer createScopeContainer(RuntimeComponent component) {
+ return new RequestScopeContainer(component);
+ }
+
+ public Scope getScope() {
+ return Scope.REQUEST;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java
new file mode 100644
index 0000000000..f11295c9fa
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.core.scope.ScopeRegistry;
+import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * The default implementation of a scope registry
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeRegistryImpl implements ScopeRegistry {
+ private final Map<Scope, ScopeContainerFactory> scopeCache = new ConcurrentHashMap<Scope, ScopeContainerFactory>();
+
+ public void register(ScopeContainerFactory factory) {
+ scopeCache.put(factory.getScope(), factory);
+ }
+
+ public ScopeContainer getScopeContainer(RuntimeComponent runtimeComponent) {
+ if (!(runtimeComponent instanceof ScopedRuntimeComponent)) {
+ return null;
+ }
+ ScopedRuntimeComponent component = (ScopedRuntimeComponent)runtimeComponent;
+ if (component.getScopeContainer() != null) {
+ return component.getScopeContainer();
+ }
+ ImplementationProvider implementationProvider = component.getImplementationProvider();
+ if (implementationProvider instanceof ScopedImplementationProvider) {
+ ScopedImplementationProvider provider = (ScopedImplementationProvider)implementationProvider;
+ Scope scope = provider.getScope();
+ if (scope == null) {
+ scope = Scope.STATELESS;
+ }
+ ScopeContainerFactory factory = scopeCache.get(scope);
+ ScopeContainer container = factory.createScopeContainer(component);
+ component.setScopeContainer(container);
+ return container;
+ }
+ return null;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java
new file mode 100644
index 0000000000..0639b8885b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.factory.InstanceWrapper;
+import org.apache.tuscany.sca.core.scope.AbstractScopeContainer;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.TargetDestructionException;
+import org.apache.tuscany.sca.core.scope.TargetResolutionException;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * A scope context which manages stateless atomic component instances in a non-pooled fashion.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StatelessScopeContainer<KEY> extends AbstractScopeContainer<KEY> {
+
+ public StatelessScopeContainer(RuntimeComponent component) {
+ super(Scope.STATELESS, component);
+ }
+
+ @Override
+ public InstanceWrapper getWrapper(KEY contextId)
+ throws TargetResolutionException {
+ InstanceWrapper ctx = createInstanceWrapper();
+ ctx.start();
+ return ctx;
+ }
+
+ @Override
+ public InstanceWrapper getAssociatedWrapper(KEY contextId)
+ throws TargetResolutionException {
+ return getWrapper(contextId);
+ }
+
+ @Override
+ public void returnWrapper(InstanceWrapper wrapper, KEY contextId)
+ throws TargetDestructionException {
+ wrapper.stop();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java
new file mode 100644
index 0000000000..5bf20a6a5f
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.scope.impl;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopeContainerFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class StatelessScopeContainerFactory implements ScopeContainerFactory {
+
+ public ScopeContainer createScopeContainer(RuntimeComponent component) {
+ return new StatelessScopeContainer(component);
+ }
+
+ public Scope getScope() {
+ return Scope.STATELESS;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java
new file mode 100644
index 0000000000..3df2f7188b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.tuscany.sca.work.NotificationListener;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.apache.tuscany.sca.work.WorkSchedulerException;
+
+/**
+ * A work scheduler implementation based on a JSR 237 work manager.
+ * <p/>
+ * <p/>
+ * This needs a JSR 237 work manager implementation available for scheduling work. Instances can be configured with a
+ * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work
+ * manager implementation available. For example, if the managed environment supports work manager the runtime can use
+ * the appropriate lookup mechanism to inject the work manager implementation. </p>
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultWorkScheduler implements WorkScheduler {
+
+ /**
+ * Underlying JSR-237 work manager
+ */
+ private ThreadPoolWorkManager jsr237WorkManager;
+
+ /**
+ * Initializes the JSR 237 work manager.
+ *
+ * @param jsr237WorkManager JSR 237 work manager.
+ */
+ public DefaultWorkScheduler() {
+ }
+
+ private synchronized ThreadPoolWorkManager getWorkManager() {
+ if (jsr237WorkManager != null) {
+ return jsr237WorkManager;
+ }
+// try {
+// InitialContext ctx = new InitialContext();
+// jsr237WorkManager = (ThreadPoolWorkManager)ctx.lookup("java:comp/env/wm/TuscanyWorkManager");
+// } catch (Throwable e) {
+// // ignore
+// }
+ if (jsr237WorkManager == null) {
+ jsr237WorkManager = new ThreadPoolWorkManager(10);
+ }
+ return jsr237WorkManager;
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ */
+ public <T extends Runnable> void scheduleWork(T work) {
+ scheduleWork(work, null);
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ * @param listener Notification listener for callbacks.
+ */
+ public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) {
+
+ if (work == null) {
+ throw new IllegalArgumentException("Work cannot be null");
+ }
+
+ Work<T> jsr237Work = new Work<T>(work);
+ try {
+ if (listener == null) {
+ getWorkManager().schedule(jsr237Work);
+ } else {
+ Jsr237WorkListener<T> jsr237WorkListener = new Jsr237WorkListener<T>(listener, work);
+ getWorkManager().schedule(jsr237Work, jsr237WorkListener);
+ }
+ } catch (IllegalArgumentException ex) {
+ if (listener != null) {
+ listener.workRejected(work);
+ } else {
+ throw new WorkSchedulerException(ex);
+ }
+ } catch (Exception ex) {
+ throw new WorkSchedulerException(ex);
+ }
+
+ }
+
+ public void destroy() {
+ if (jsr237WorkManager instanceof ThreadPoolWorkManager) {
+ // Allow privileged access to modify threads. Requires RuntimePermission in security
+ // policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ ((ThreadPoolWorkManager)jsr237WorkManager).destroy();
+ return null;
+ }
+ });
+ }
+ }
+
+ /*
+ * WorkListener for keeping track of work status callbacks.
+ *
+ */
+ private class Jsr237WorkListener<T extends Runnable> implements WorkListener {
+
+ // Notification listener
+ private NotificationListener<T> listener;
+
+ // Work
+ private T work;
+
+ /*
+ * Initializes the notification listener.
+ */
+ public Jsr237WorkListener(NotificationListener<T> listener, T work) {
+ this.listener = listener;
+ this.work = work;
+ }
+
+ /*
+ * Callback when the work is accepted.
+ */
+ public void workAccepted(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workAccepted(work);
+ }
+
+ /*
+ * Callback when the work is rejected.
+ */
+ public void workRejected(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workRejected(work);
+ }
+
+ /*
+ * Callback when the work is started.
+ */
+ public void workStarted(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workStarted(work);
+ }
+
+ /*
+ * Callback when the work is completed.
+ */
+ public void workCompleted(WorkEvent workEvent) {
+ T work = getWork();
+ Exception exception = workEvent.getException();
+ if (exception != null) {
+ listener.workFailed(work, exception);
+ } else {
+ listener.workCompleted(work);
+ }
+ }
+
+ /*
+ * Gets the underlying work from the work event.
+ */
+ private T getWork() {
+ return work;
+ }
+
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java
new file mode 100644
index 0000000000..12fa4a485d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.rmi.server.UID;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.tuscany.sca.work.WorkSchedulerException;
+import org.oasisopen.sca.annotation.Destroy;
+
+/**
+ * A thread-pool based implementation for the JSR-237 work manager.
+ * <p/>
+ * <p/>
+ * This implementation supports only local work.
+ * <p/>
+ * TODO Elaborate the implementation. </p>
+ *
+ * @version $Rev$ $Date$
+ */
+public class ThreadPoolWorkManager {
+
+ // Map of work items currently handled by the work manager
+ private Map<WorkItem, WorkListener> workItems = new ConcurrentHashMap<WorkItem, WorkListener>();
+
+ // Thread-pool
+ private ExecutorService executor;
+
+ /**
+ * Initializes the thread-pool.
+ *
+ * @param threadPoolSize Thread-pool size.
+ * @throws IllegalArgumentException if threadPoolSize < 1
+ */
+ public ThreadPoolWorkManager(int threadPoolSize) {
+ if (threadPoolSize < 1) {
+ throw new IllegalArgumentException("Invalid threadPoolSize of "
+ + threadPoolSize + ". It must be >= 1");
+ }
+
+ // Creates a new Executor, use a custom ThreadFactory that
+ // creates daemon threads.
+ executor = Executors.newFixedThreadPool(threadPoolSize, new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r);
+ thread.setDaemon(true);
+ return thread;
+ }
+ });
+ }
+
+ /**
+ * Schedules a unit of work asynchronously.
+ *
+ * @param work Work that needs to be scheduled.
+ * @return Work Work item representing the asynchronous work
+ */
+ public WorkItem schedule(Work<?> work) throws IllegalArgumentException {
+ return schedule(work, null);
+ }
+
+ /**
+ * Schedules a unit of work asynchronously.
+ *
+ * @param work Work that needs to be scheduled.
+ * @param workListener Work listener for callbacks.
+ * @return Work Work item representing the asynchronous work
+ */
+ public WorkItem schedule(Work<?> work, WorkListener workListener) throws IllegalArgumentException {
+
+ WorkItem workItem = new WorkItem(new UID().toString(), work);
+ if (workListener != null) {
+ workItems.put(workItem, workListener);
+ }
+ workAccepted(workItem, work);
+ if (scheduleWork(work, workItem)) {
+ return workItem;
+ } else {
+ workItem.setStatus(WorkEvent.WORK_REJECTED);
+ if (workListener != null) {
+ workListener.workRejected(new WorkEvent(workItem));
+ }
+ throw new IllegalArgumentException("Unable to schedule work");
+ }
+ }
+
+ /**
+ * Wait for all the specified units of work to finish.
+ *
+ * @param works Units of the work that need to finish.
+ * @param timeout Timeout for waiting for the units of work to finish.
+ */
+ public boolean waitForAll(Collection<Work<?>> works, long timeout) {
+ throw new UnsupportedOperationException("waitForAll not supported");
+ }
+
+ /**
+ * Wait for any of the specified units of work to finish.
+ *
+ * @param works Units of the work that need to finish.
+ * @param timeout Timeout for waiting for the units of work to finish.
+ */
+ public Collection<Work<?>> waitForAny(Collection<Work<?>> works, long timeout) {
+ throw new UnsupportedOperationException("waitForAny not supported");
+ }
+
+ /**
+ * Method provided for subclasses to indicate a work acceptance.
+ *
+ * @param workItem Work item representing the work that was accepted.
+ * @param work Work that was accepted.
+ */
+ private void workAccepted(final WorkItem workItem, final Work<?> work) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_ACCEPTED);
+ WorkEvent event = new WorkEvent(workItem);
+ listener.workAccepted(event);
+ }
+ }
+
+ /*
+ * Method to indicate a work start.
+ */
+ private void workStarted(final WorkItem workItem, final Work<?> work) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_STARTED);
+ WorkEvent event = new WorkEvent(workItem);
+ listener.workStarted(event);
+ }
+ }
+
+ /*
+ * Method to indicate a work completion.
+ */
+ private void workCompleted(final WorkItem workItem, final Work<?> work) {
+ workCompleted(workItem, work, null);
+ }
+
+ /*
+ * Method to indicate a work completion.
+ */
+ private void workCompleted(final WorkItem workItem, final Work<?> work, final WorkSchedulerException exception) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_COMPLETED);
+ workItem.setResult(work);
+ workItem.setException(exception);
+ WorkEvent event = new WorkEvent(workItem);
+ listener.workCompleted(event);
+ workItems.remove(workItem);
+ }
+ }
+
+ /*
+ * Schedules the work using the ThreadPool.
+ */
+ private boolean scheduleWork(final Work<?> work, final WorkItem workItem) {
+ try {
+ executor.execute(new DecoratingWork(workItem, work));
+ return true;
+ } catch (RejectedExecutionException ex) {
+ return false;
+ }
+ }
+
+ /*
+ * Class that decorates the original worker so that it can get callbacks when work is done.
+ */
+ private final class DecoratingWork implements Runnable {
+
+ // Work item for this work.
+ private WorkItem workItem;
+
+ // The original work.
+ private Work decoratedWork;
+
+ /*
+ * Initializes the work item and underlying work.
+ */
+ private DecoratingWork(final WorkItem workItem, final Work decoratedWork) {
+ this.workItem = workItem;
+ this.decoratedWork = decoratedWork;
+ }
+
+ /*
+ * Overrides the run method.
+ */
+ public void run() {
+ workStarted(workItem, decoratedWork);
+ try {
+ decoratedWork.run();
+ workCompleted(workItem, decoratedWork);
+ } catch (Throwable th) {
+ workCompleted(workItem, decoratedWork, new WorkSchedulerException(th.getMessage(), th));
+ }
+ }
+
+ }
+
+ @Destroy
+ public void destroy() {
+ executor.shutdown();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java
new file mode 100644
index 0000000000..ca06d0e854
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+/**
+ * JCA work wrapper.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Work<T extends Runnable> {
+
+ // Work that is being executed.
+ private T work;
+
+ /*
+ * Initializes the work instance.
+ */
+ public Work(T work) {
+ this.work = work;
+ }
+
+ /*
+ * Returns the completed work.
+ */
+ public T getWork() {
+ return work;
+ }
+
+ /*
+ * Release the work.
+ */
+ public void release() {
+ }
+
+ /*
+ * Work attributes are not daemon.
+ */
+ public boolean isDaemon() {
+ return false;
+ }
+
+ /*
+ * Runs the work.
+ */
+ public void run() {
+ work.run();
+ }
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java
new file mode 100644
index 0000000000..4580011806
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import org.apache.tuscany.sca.work.WorkSchedulerException;
+
+
+
+/**
+ * Default immutable implementation of the <code>WorkEvent</code> class.
+ *
+ * @version $Rev$ $Date$
+ */
+class WorkEvent {
+
+ public static final int WORK_ACCEPTED = 1;
+ public static final int WORK_REJECTED = 2;
+ public static final int WORK_STARTED = 3;
+ public static final int WORK_COMPLETED = 4;
+
+ // Work item for this event
+ private WorkItem workItem;
+
+ // Exception if something has gone wrong
+ private WorkSchedulerException exception;
+
+ /**
+ * Instantiates the event.
+ *
+ * @param workItem Work item for this event.
+ */
+ public WorkEvent(final WorkItem workItem) {
+ this.workItem = workItem;
+ this.exception = workItem.getException();
+ }
+
+ /**
+ * Returns the work type based on whether the work was accepted, started,
+ * rejected or completed.
+ *
+ * @return Work type.
+ */
+ public int getType() {
+ return workItem.getStatus();
+ }
+
+ /**
+ * Returns the work item associated with this work type.
+ *
+ * @return Work item.
+ */
+ public WorkItem getWorkItem() {
+ return workItem;
+ }
+
+ /**
+ * Returns the exception if the work completed with an exception.
+ *
+ * @return Work exception.
+ */
+ public WorkSchedulerException getException() {
+ return exception;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java
new file mode 100644
index 0000000000..0fc104d0fc
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import org.apache.tuscany.sca.work.WorkSchedulerException;
+
+/**
+ * An identity based immutable implementation of the <code>WorkItem</code>
+ * interface.
+ *
+ * @version $Rev$ $Date$
+ */
+class WorkItem {
+
+ // Id scoped for the VM
+ private String id;
+
+ // Status
+ private int status = -1;
+
+ // Result
+ private Work<?> result;
+
+ // Original work
+ private Work<?> originalWork;
+
+ // Exception
+ private WorkSchedulerException exception;
+
+ /**
+ * Instantiates an id for this item.
+ *
+ * @param id of this work event.
+ */
+ protected WorkItem(final String id, final Work<?> orginalWork) {
+ this.id = id;
+ this.originalWork = orginalWork;
+ }
+
+ /**
+ * Returns the id.
+ *
+ * @return Id of this item.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the original work.
+ *
+ * @return Original work.
+ */
+ public Work<?> getOriginalWork() {
+ return originalWork;
+ }
+
+ /**
+ * Returns the work result if the work completed.
+ *
+ * @return Work.
+ * @throws WorkException If the work completed with an exception.
+ */
+ public Work<?> getResult() {
+ return result;
+ }
+
+ /**
+ * Sets the result.
+ *
+ * @param result Result.
+ */
+ protected void setResult(final Work<?> result) {
+ this.result = result;
+ }
+
+ /**
+ * Returns the exception if work completed with an exception.
+ *
+ * @return Work exception.
+ */
+ protected WorkSchedulerException getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the exception.
+ *
+ * @param exception Exception.
+ */
+ protected void setException(final WorkSchedulerException exception) {
+ this.exception = exception;
+ }
+
+ /**
+ * Returns the work type based on whether the work was accepted, started,
+ * rejected or completed.
+ *
+ * @return Work status.
+ */
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the status.
+ *
+ * @param status Status.
+ */
+ protected void setStatus(final int status) {
+ this.status = status;
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param obj Object to be compared.
+ * @return true if this object is the same as the obj argument; false
+ * otherwise..
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ return (obj != null) && (obj.getClass() == WorkItem.class) && ((WorkItem) obj).id.equals(id);
+ }
+
+ /**
+ * Compares this object with the specified object for order. Returns a
+ * negative integer, zero, or a positive integer as this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * @param o Object to be compared.
+ * @return A negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ * @throws ClassCastException needs better documentation.
+ */
+ public int compareTo(final Object o) {
+ if (o.getClass() != WorkItem.class) {
+ throw new ClassCastException(o.getClass().getName());
+ } else {
+ return ((WorkItem) o).getId().compareTo(getId());
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java
new file mode 100644
index 0000000000..facb2dfe56
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+public interface WorkListener {
+
+ long IMMEDIATE = 0;
+ long INDEFINITE = java.lang.Long.MAX_VALUE;
+
+ void workAccepted(WorkEvent event);
+ void workCompleted(WorkEvent event);
+ void workRejected(WorkEvent event);
+ void workStarted(WorkEvent event);
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory
new file mode 100644
index 0000000000..e118d5967b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+org.apache.tuscany.sca.core.context.DefaultComponentContextFactory \ No newline at end of file
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory
new file mode 100644
index 0000000000..171588cc7b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+org.apache.tuscany.sca.core.context.DefaultRequestContextFactory \ No newline at end of file
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..97a1d70d49
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.core.assembly.impl.ReferenceParameterProcessor;qname=http://tuscany.apache.org/xmlns/sca/1.1#referenceParameters,model=org.apache.tuscany.sca.runtime.ReferenceParameters
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.assembly.CompositeActivator b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.assembly.CompositeActivator
new file mode 100644
index 0000000000..67f5bede89
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.assembly.CompositeActivator
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.assembly.impl.CompositeActivatorImpl2
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.conversation.ConversationManager b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.conversation.ConversationManager
new file mode 100644
index 0000000000..67cec934b4
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.conversation.ConversationManager
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.conversation.impl.ConversationManagerImpl
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint
new file mode 100644
index 0000000000..af281d8f4d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.invocation.DefaultProxyFactoryExtensionPoint
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry
new file mode 100644
index 0000000000..a4a0154987
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.scope.DefaultScopeRegistry
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory
new file mode 100644
index 0000000000..00a33e1656
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.invocation.impl.MessageFactoryImpl
diff --git a/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler
new file mode 100644
index 0000000000..9923ba5927
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+org.apache.tuscany.sca.core.work.impl.DefaultWorkScheduler
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/CallbackInterfaceInterceptorTestCase.java.fixme b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/CallbackInterfaceInterceptorTestCase.java.fixme
new file mode 100644
index 0000000000..b11eaa9621
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/CallbackInterfaceInterceptorTestCase.java.fixme
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.wire;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.core.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.CallbackInterfaceInterceptor;
+import org.apache.tuscany.sca.core.invocation.impl.MessageFactoryImpl;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Message;
+import org.easymock.EasyMock;
+import org.oasisopen.sca.NoRegisteredCallbackException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CallbackInterfaceInterceptorTestCase extends TestCase {
+
+ public void testHasCallbackObject() {
+ CallbackInterfaceInterceptor interceptor = new CallbackInterfaceInterceptor();
+ Interceptor next = EasyMock.createMock(Interceptor.class);
+ EasyMock.expect(next.invoke(EasyMock.isA(Message.class))).andReturn(null);
+ EasyMock.replay(next);
+ interceptor.setNext(next);
+ Message msg = new MessageFactoryImpl().createMessage();
+ msg.setFrom(new EndpointReferenceImpl("uri"));
+ msg.getFrom().getReferenceParameters().setCallbackObjectID("ABC");
+ interceptor.invoke(msg);
+ EasyMock.verify(next);
+ }
+
+ public void testNoCallbackObject() {
+ CallbackInterfaceInterceptor interceptor = new CallbackInterfaceInterceptor();
+ Message msg = new MessageFactoryImpl().createMessage();
+ msg.setFrom(new EndpointReferenceImpl("uri"));
+ msg.getFrom().getReferenceParameters().setCallbackObjectID(null);
+ try {
+ interceptor.invoke(msg);
+ fail();
+ } catch (NoRegisteredCallbackException e) {
+ // expected
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java
new file mode 100644
index 0000000000..d6367163fa
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.OperationImpl;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.junit.Test;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class InvocationChainImplTestCase {
+
+ @Test
+ public void testInsertAtEnd() throws Exception {
+ Operation op = newOperation("foo");
+ InvocationChain chain = new InvocationChainImpl(op, op, true);
+ Interceptor inter2 = new MockInterceptor();
+ Interceptor inter1 = new MockInterceptor();
+ chain.addInterceptor(inter1);
+ chain.addInterceptor(inter2);
+ Interceptor head = (Interceptor)chain.getHeadInvoker();
+ assertEquals(inter1, head);
+ assertEquals(inter2, head.getNext());
+ assertEquals(inter2, chain.getTailInvoker());
+
+ }
+
+ @Test
+ public void testAddByPhase() throws Exception {
+ Operation op = newOperation("foo");
+ InvocationChain chain = new InvocationChainImpl(op, op, false);
+ Interceptor inter1 = new MockInterceptor();
+ Interceptor inter2 = new MockInterceptor();
+ Interceptor inter3 = new MockInterceptor();
+ Interceptor inter4 = new MockInterceptor();
+ chain.addInterceptor(inter3); // SERVICE
+ chain.addInterceptor(Phase.IMPLEMENTATION_POLICY, inter4);
+ chain.addInterceptor(Phase.SERVICE_POLICY, inter2);
+ chain.addInterceptor(Phase.SERVICE_BINDING, inter1);
+ Interceptor head = (Interceptor)chain.getHeadInvoker();
+ assertEquals(inter1, head);
+ assertEquals(inter2, inter1.getNext());
+ assertEquals(inter3, inter2.getNext());
+ assertEquals(inter4, inter3.getNext());
+ assertEquals(inter4, chain.getTailInvoker());
+ }
+
+ private class MockInterceptor implements Interceptor {
+
+ private Invoker next;
+
+ public Message invoke(Message msg) {
+ return null;
+ }
+
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ public Invoker getNext() {
+ return next;
+ }
+
+ }
+
+ private static Operation newOperation(String name) {
+ Operation operation = new OperationImpl();
+ operation.setName(name);
+ return operation;
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/NonBlockingInterceptorTestCase.java.fixme b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/NonBlockingInterceptorTestCase.java.fixme
new file mode 100644
index 0000000000..b8150d4edc
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/NonBlockingInterceptorTestCase.java.fixme
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.wire;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.getCurrentArguments;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class NonBlockingInterceptorTestCase extends TestCase {
+
+ public void testInvoke() throws Exception {
+ WorkScheduler scheduler = createMock(WorkScheduler.class);
+ scheduler.scheduleWork(isA(Runnable.class));
+ expectLastCall().andStubAnswer(new IAnswer<Object>() {
+ public Object answer() throws Throwable {
+ Runnable runnable = (Runnable) getCurrentArguments()[0];
+ runnable.run();
+ return null;
+ }
+ });
+ replay(scheduler);
+ Message context = createMock(Message.class);
+ //String convID = "convID";
+ //TODO port to the new way of dealing with conversation IDs later
+ //EasyMock.expect(context.getConversationID()).andReturn(convID);
+ EasyMock.replay(context);
+ ThreadMessageContext.setMessageContext(context);
+ Message msg = createMock(Message.class);
+ //TODO port to the new way of dealing with conversation IDs later
+ //msg.setConversationID(convID);
+ Interceptor next = EasyMock.createMock(Interceptor.class);
+ EasyMock.expect(next.invoke(EasyMock.eq(msg))).andReturn(msg);
+ EasyMock.expect(msg.isFault()).andReturn(false);
+ EasyMock.replay(next);
+ EasyMock.replay(msg);
+ Interceptor interceptor = new NonBlockingInterceptor(scheduler, next);
+ interceptor.invoke(msg);
+ verify(context);
+ verify(next);
+ verify(msg);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java
new file mode 100644
index 0000000000..8fcead004d
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PhaseManagerTestCase {
+
+ @Test
+ public void testDiscovery() {
+ PhaseManager pm = new PhaseManager("org.apache.tuscany.sca.invocation.PhaseTest");
+ List<String> phases = pm.getAllPhases();
+ System.out.println(phases.size());
+ System.out.println(phases);
+ // Assert.assertEquals(15, phases.size());
+ Assert.assertEquals("reference.first", phases.get(0));
+
+ int rt = phases.indexOf("reference.transaction");
+ Assert.assertTrue(rt > phases.indexOf("reference.interface"));
+
+ int st = phases.indexOf("service.transaction");
+ Assert.assertTrue(st > phases.indexOf("service.binding"));
+
+ int it = phases.indexOf("implementation.transaction");
+ Assert.assertTrue(it < phases.indexOf("implementation.policy"));
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java
new file mode 100644
index 0000000000..c268e133e4
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.invocation.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PhaseSorterTestCase {
+ private PhaseSorter<String> graph;
+
+ @Before
+ public void setUp() throws Exception {
+ graph = new PhaseSorter<String>();
+ }
+
+ @Test
+ public void testSort() {
+ graph.addEdge("a", "b");
+ graph.addEdge("a", "c");
+ graph.addEdge("c", "d");
+ graph.addEdge("b", "c");
+ List<String> order = graph.topologicalSort(true);
+ assertEquals(Arrays.asList("a", "b", "c", "d"), order);
+ assertTrue(!graph.getVertices().isEmpty());
+
+ graph.addEdge("d", "a");
+ try {
+ order = graph.topologicalSort(true);
+ assertTrue("Should have failed", false);
+ } catch (IllegalArgumentException e) {
+ assertTrue(true);
+ }
+
+ graph.removeEdge("d", "a");
+ order = graph.topologicalSort(false);
+ assertEquals(Arrays.asList("a", "b", "c", "d"), order);
+ assertTrue(graph.getVertices().isEmpty());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java
new file mode 100644
index 0000000000..16ca5fd00e
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+
+
+/**
+ * Simple Work item that will throw an exception
+ *
+ * @version $Rev$ $Date$
+ */
+public class FailingWork extends Work {
+
+ public FailingWork() {
+ super(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDaemon() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void release() {
+ }
+
+ /**
+ * Throws an IllegalArgumentException
+ */
+ public void run() {
+ System.out.println("Starting " + this + " and throwing an Exception");
+ throw new IllegalArgumentException("Sample exception from " + this);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java
new file mode 100644
index 0000000000..2d791e5012
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+/**
+ * Simple Runnable that throws an IllegalArgumentException
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSR237MyFailingRunnable extends JSR237MyRunnable {
+
+ /**
+ * Constructor
+ */
+ public JSR237MyFailingRunnable() {
+ super(-1);
+ }
+
+ /**
+ * Sleeps for a period of time defined by sleepTime
+ */
+ @Override
+ public void run() {
+ System.out.println("Starting " + this + " and throwing an Exception");
+ throw new IllegalArgumentException("Sample exception from " + this);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java
new file mode 100644
index 0000000000..c0183b6f9b
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Simple Runnable that is used for testing Jsr237WorkScheduler
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSR237MyRunnable implements Runnable {
+
+ /**
+ * Count of workAccepted() method calls
+ */
+ private AtomicInteger runCompletedCount = new AtomicInteger();
+
+ /**
+ * The amount of time to sleep in the Run loop
+ */
+ private final long sleepTime;
+
+ /**
+ * Constructor
+ *
+ * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method
+ */
+ public JSR237MyRunnable(long sleepTime) {
+ this.sleepTime = sleepTime;
+ }
+
+ /**
+ * Sleeps for a period of time defined by sleepTime
+ */
+ public void run() {
+ System.out.println("Starting " + this);
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("Done " + this);
+ runCompletedCount.incrementAndGet();
+ }
+
+ /**
+ * Returns the number of completed calls to run()
+ *
+ * @return The number of completed calls to run()
+ */
+ public int getRunCompletedCount() {
+ return runCompletedCount.get();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java
new file mode 100644
index 0000000000..307f24aca7
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tuscany.sca.work.NotificationListener;
+
+/**
+ * Simple NotificationListener that is used for testing Jsr237WorkScheduler
+ *
+ * @version $Rev$ $Date$
+ */
+public class JSR237MyRunnerListener implements NotificationListener<JSR237MyRunnable> {
+
+ /**
+ * Count of workAccepted() method calls
+ */
+ private AtomicInteger workAcceptedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workStarted() method calls
+ */
+ private AtomicInteger workStartedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workCompleted() method calls
+ */
+ private AtomicInteger workCompletedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workFailed() method calls
+ */
+ private AtomicInteger workFailedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workRejected() method calls
+ */
+ private AtomicInteger workRejectedCallCount = new AtomicInteger();
+
+ /**
+ * List of all exceptions thrown by Work items
+ */
+ private List<Throwable> workExceptions = Collections.synchronizedList(new ArrayList<Throwable>());
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workAccepted(JSR237MyRunnable work) {
+ workAcceptedCallCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workCompleted(JSR237MyRunnable work) {
+ workCompletedCallCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workFailed(JSR237MyRunnable work, Throwable error) {
+ workExceptions.add(error);
+ workFailedCallCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workRejected(JSR237MyRunnable work) {
+ workRejectedCallCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workStarted(JSR237MyRunnable work) {
+ workStartedCallCount.incrementAndGet();
+ }
+
+ /**
+ * Returns the number of calls to workAccepted()
+ *
+ * @return The number of calls to workAccepted()
+ */
+ public int getWorkAcceptedCallCount() {
+ return workAcceptedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workStarted()
+ *
+ * @return The number of calls to workStarted()
+ */
+ public int getWorkStartedCallCount() {
+ return workStartedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workCompleted()
+ *
+ * @return The number of calls to workCompleted()
+ */
+ public int getWorkCompletedCallCount() {
+ return workCompletedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workFailed()
+ *
+ * @return The number of calls to workFailed()
+ */
+ public int getWorkFailedCallCount() {
+ return workFailedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workRejected()
+ *
+ * @return The number of calls to workRejected()
+ */
+ public int getWorkRejectedCallCount() {
+ return workRejectedCallCount.get();
+ }
+
+ /**
+ * Returns a List of all exceptions that are thrown by the Work items
+ *
+ * @return A List of all exceptions that are thrown by the Work items
+ */
+ public List<Throwable> getWorkExceptions() {
+ return Collections.unmodifiableList(workExceptions);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java
new file mode 100644
index 0000000000..904f4ca5e0
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test case for Jsr237WorkScheduler
+ *
+ * @version $Rev$ $Date$
+ */
+public class Jsr237WorkSchedulerTestCase {
+
+ /**
+ * Wait up to 20 seconds for the Work units to complete
+ */
+ private static final long WAIT_TIMEOUT = 20000;
+
+ /**
+ * This is the shared instance of the ThreadPoolWorkManager used by the tests
+ */
+ private static DefaultWorkScheduler workSchedular = null;
+
+ /**
+ * Setup the Jsr237WorkScheduler
+ */
+ @BeforeClass
+ public static void setup() {
+ workSchedular = new DefaultWorkScheduler();
+ }
+
+ /**
+ * Make sure that the Jsr237WorkScheduler is stopped after running the tests
+ */
+ @AfterClass
+ public static void destroy() {
+ if (workSchedular != null) {
+ workSchedular.destroy();
+ }
+ }
+
+ /**
+ * Tests running a single fast job on the Jsr237WorkScheduler
+ */
+ @Test
+ public void testSingleFastJob() {
+ // Create the work and register it
+ JSR237MyRunnable fast = new JSR237MyRunnable(10);
+ JSR237MyRunnerListener listener = new JSR237MyRunnerListener();
+ workSchedular.scheduleWork(fast, listener);
+
+ // Wait for the 1 job to complete
+ waitForWorkToComplete(listener, 1);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(1, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(1, listener.getWorkStartedCallCount());
+ Assert.assertEquals(1, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(0, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a single job that fails on the Jsr237WorkScheduler
+ */
+ @Test
+ public void testSingleFailingJob() {
+ // Create the work and register it
+ JSR237MyFailingRunnable fail = new JSR237MyFailingRunnable();
+ JSR237MyRunnerListener listener = new JSR237MyRunnerListener();
+ workSchedular.scheduleWork(fail, listener);
+
+ // Wait for the 1 job to complete
+ waitForWorkToComplete(listener, 1);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(1, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(1, listener.getWorkStartedCallCount());
+ Assert.assertEquals(0, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(1, listener.getWorkFailedCallCount());
+ Assert.assertEquals(1, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a mixture of fast and slow jobs on the Jsr237WorkScheduler
+ */
+ @Test
+ public void testMultipleJobs() {
+ // Create the work and register it
+ JSR237MyRunnable fast1 = new JSR237MyRunnable(5);
+ JSR237MyRunnable fast2 = new JSR237MyRunnable(10);
+ JSR237MyRunnable fast3 = new JSR237MyRunnable(20);
+ JSR237MyRunnable slow1= new JSR237MyRunnable(200);
+ JSR237MyRunnable slow2 = new JSR237MyRunnable(200);
+ JSR237MyRunnerListener listener = new JSR237MyRunnerListener();
+ workSchedular.scheduleWork(fast1, listener);
+ workSchedular.scheduleWork(fast2, listener);
+ workSchedular.scheduleWork(fast3, listener);
+ workSchedular.scheduleWork(slow1, listener);
+ workSchedular.scheduleWork(slow2, listener);
+
+ // Wait for the 5 jobs to complete
+ waitForWorkToComplete(listener, 5);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(5, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(5, listener.getWorkStartedCallCount());
+ Assert.assertEquals(5, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(0, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a mixture of fast and slow jobs some of which fail on the
+ * Jsr237WorkScheduler
+ */
+ @Test
+ public void testMultipleJobsSomeFail() {
+ // Create the work and register it
+ JSR237MyRunnable fast1 = new JSR237MyRunnable(5);
+ JSR237MyRunnable fast2 = new JSR237MyRunnable(10);
+ JSR237MyRunnable fast3 = new JSR237MyRunnable(20);
+ JSR237MyRunnable slow1= new JSR237MyRunnable(200);
+ JSR237MyRunnable slow2 = new JSR237MyRunnable(200);
+ JSR237MyFailingRunnable fail1 = new JSR237MyFailingRunnable();
+ JSR237MyFailingRunnable fail2 = new JSR237MyFailingRunnable();
+ JSR237MyRunnerListener listener = new JSR237MyRunnerListener();
+ workSchedular.scheduleWork(fast1, listener);
+ workSchedular.scheduleWork(fast2, listener);
+ workSchedular.scheduleWork(fail1, listener);
+ workSchedular.scheduleWork(fast3, listener);
+ workSchedular.scheduleWork(slow1, listener);
+ workSchedular.scheduleWork(fail2, listener);
+ workSchedular.scheduleWork(slow2, listener);
+
+ // Wait for the 7 jobs to complete
+ waitForWorkToComplete(listener, 7);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(7, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(7, listener.getWorkStartedCallCount());
+ Assert.assertEquals(5, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(2, listener.getWorkFailedCallCount());
+ Assert.assertEquals(2, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a single job that has no listener
+ */
+ @Test
+ public void testSingleFastJobWithNoListener() {
+ // Create the work and register it
+ JSR237MyRunnable fast = new JSR237MyRunnable(10);
+ workSchedular.scheduleWork(fast);
+
+ // Wait for the job to complete
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ int completedCount = fast.getRunCompletedCount();
+ if (completedCount == 1) {
+ break;
+ }
+
+ if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) {
+ Assert.fail("Only " + completedCount + " work items completed before timeout");
+ return;
+ }
+
+ // Lets wait for the job to complete
+ try {
+ Thread.sleep(25);
+ } catch (InterruptedException ex) {
+ Assert.fail("Unexpected exception: " + ex);
+ }
+ }
+ }
+
+ /**
+ * Tests scheduling a null as the work item
+ */
+ @Test
+ public void testNullWork() {
+ try {
+ workSchedular.scheduleWork(null);
+ Assert.fail("Should have thrown IllegalArgumentException ");
+ } catch (IllegalArgumentException ex) {
+ // As expected
+ Assert.assertTrue(ex.toString().indexOf("null") != -1);
+ }
+ }
+
+ /**
+ * Waits for the specified number of jobs to complete or the timeout to fire.
+ *
+ * @param listener The listener to use to track Work unit completion
+ * @param completedWorkItemsToWaitFor The number of Work items to complete
+ */
+ private void waitForWorkToComplete(JSR237MyRunnerListener listener, int completedWorkItemsToWaitFor) {
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ int completedCount = listener.getWorkCompletedCallCount() + listener.getWorkFailedCallCount();
+ if (completedCount == completedWorkItemsToWaitFor) {
+ return;
+ }
+
+ if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) {
+ Assert.fail("Only " + completedCount + " work items completed before timeout");
+ return;
+ }
+
+ // Lets wait for more jobs to complete
+ try {
+ Thread.sleep(25);
+ } catch (InterruptedException ex) {
+ Assert.fail("Unexpected exception: " + ex);
+ }
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java
new file mode 100644
index 0000000000..a452d6f371
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tuscany.sca.work.WorkSchedulerException;
+import org.junit.Assert;
+
+/**
+ * A simple WorkListener that tracks invocations to it.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TestWorkListener implements WorkListener {
+
+ /**
+ * Count of workAccepted() method calls
+ */
+ private AtomicInteger workAcceptedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workStarted() method calls
+ */
+ private AtomicInteger workStartedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workCompleted() method calls
+ */
+ private AtomicInteger workCompletedCallCount = new AtomicInteger();
+
+ /**
+ * Count of workRejected() method calls
+ */
+ private AtomicInteger workRejectedCallCount = new AtomicInteger();
+
+ /**
+ * List of all exceptions thrown by Work items
+ */
+ private List<WorkSchedulerException> workExceptions = Collections.synchronizedList(new ArrayList<WorkSchedulerException>());
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workAccepted(WorkEvent work) {
+ workAcceptedCallCount.incrementAndGet();
+
+ // Validate the WorkEvent
+ Assert.assertNotNull(work.getWorkItem());
+ Assert.assertEquals(WorkEvent.WORK_ACCEPTED, work.getType());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workStarted(WorkEvent work) {
+ workStartedCallCount.incrementAndGet();
+
+ // Validate the WorkEvent
+ Assert.assertNotNull(work.getWorkItem());
+ Assert.assertEquals(WorkEvent.WORK_STARTED, work.getType());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workCompleted(WorkEvent work) {
+ if (work.getException() != null) {
+ workExceptions.add(work.getException());
+ }
+
+ // Validate the WorkEvent
+ Assert.assertNotNull(work.getWorkItem());
+ Assert.assertEquals(WorkEvent.WORK_COMPLETED, work.getType());
+
+ workCompletedCallCount.incrementAndGet();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void workRejected(WorkEvent work) {
+ workRejectedCallCount.incrementAndGet();
+
+ // Validate the WorkEvent
+ Assert.assertNotNull(work.getWorkItem());
+ Assert.assertEquals(WorkEvent.WORK_REJECTED, work.getType());
+ }
+
+ /**
+ * Returns the number of calls to workAccepted()
+ *
+ * @return The number of calls to workAccepted()
+ */
+ public int getWorkAcceptedCallCount() {
+ return workAcceptedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workStarted()
+ *
+ * @return The number of calls to workStarted()
+ */
+ public int getWorkStartedCallCount() {
+ return workStartedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workCompleted()
+ *
+ * @return The number of calls to workCompleted()
+ */
+ public int getWorkCompletedCallCount() {
+ return workCompletedCallCount.get();
+ }
+
+ /**
+ * Returns the number of calls to workRejected()
+ *
+ * @return The number of calls to workRejected()
+ */
+ public int getWorkRejectedCallCount() {
+ return workRejectedCallCount.get();
+ }
+
+ /**
+ * Returns a List of all exceptions that are thrown by the Work items
+ *
+ * @return A List of all exceptions that are thrown by the Work items
+ */
+ public List<WorkSchedulerException> getWorkExceptions() {
+ return Collections.unmodifiableList(workExceptions);
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java
new file mode 100644
index 0000000000..b66fa75828
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This test case will test the ThreadPoolWorkManager
+ *
+ * @version $Rev$ $Date$
+ */
+public class ThreadPoolWorkManagerTestCase {
+
+ /**
+ * Wait up to 20 seconds for the Work units to complete
+ */
+ private static final long WAIT_TIMEOUT = 20000;
+
+ /**
+ * This is the shared instance of the ThreadPoolWorkManager used by the tests
+ */
+ private static ThreadPoolWorkManager workManager = null;
+
+ /**
+ * Setup the ThreadPoolWorkManager
+ */
+ @BeforeClass
+ public static void setup() {
+ workManager = new ThreadPoolWorkManager(10);
+ }
+
+ /**
+ * Make sure that the ThreadPoolWorkManager is stopped after running the tests
+ */
+ @AfterClass
+ public static void destroy() {
+ if (workManager != null) {
+ workManager.destroy();
+ }
+ }
+
+ /**
+ * Tests running a single fast job on the ThreadPoolWorkManager
+ */
+ @Test
+ public void testSingleFastJob() {
+ // Create the work and register it
+ TimeDelayWork fast = new TimeDelayWork(10);
+ TestWorkListener listener = new TestWorkListener();
+ workManager.schedule(fast, listener);
+
+ // Wait for the 1 job to complete
+ waitForWorkToComplete(listener, 1);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(1, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(1, listener.getWorkStartedCallCount());
+ Assert.assertEquals(1, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(0, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a single job that fails on the ThreadPoolWorkManager
+ */
+ @Test
+ public void testSingleFailingJob() {
+ // Create the work and register it
+ FailingWork fail = new FailingWork();
+ TestWorkListener listener = new TestWorkListener();
+ workManager.schedule(fail, listener);
+
+ // Wait for the 1 job to complete
+ waitForWorkToComplete(listener, 1);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(1, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(1, listener.getWorkStartedCallCount());
+ Assert.assertEquals(1, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(1, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a mixture of fast and slow jobs on the ThreadPoolWorkManager
+ */
+ @Test
+ public void testMultipleJobs() {
+ // Create the work and register it
+ TimeDelayWork fast1 = new TimeDelayWork(5);
+ TimeDelayWork fast2 = new TimeDelayWork(10);
+ TimeDelayWork fast3 = new TimeDelayWork(20);
+ TimeDelayWork slow1= new TimeDelayWork(200);
+ TimeDelayWork slow2 = new TimeDelayWork(200);
+ TestWorkListener listener = new TestWorkListener();
+ workManager.schedule(fast1, listener);
+ workManager.schedule(fast2, listener);
+ workManager.schedule(fast3, listener);
+ workManager.schedule(slow1, listener);
+ workManager.schedule(slow2, listener);
+
+ // Wait for the 5 jobs to complete
+ waitForWorkToComplete(listener, 5);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(5, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(5, listener.getWorkStartedCallCount());
+ Assert.assertEquals(5, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(0, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests running a mixture of fast and slow jobs some of which fail on the
+ * ThreadPoolWorkManager
+ */
+ @Test
+ public void testMultipleJobsSomeFail() {
+ // Create the work and register it
+ TimeDelayWork fast1 = new TimeDelayWork(5);
+ TimeDelayWork fast2 = new TimeDelayWork(10);
+ TimeDelayWork fast3 = new TimeDelayWork(20);
+ TimeDelayWork slow1= new TimeDelayWork(200);
+ TimeDelayWork slow2 = new TimeDelayWork(200);
+ FailingWork fail1 = new FailingWork();
+ FailingWork fail2 = new FailingWork();
+ TestWorkListener listener = new TestWorkListener();
+ workManager.schedule(fast1, listener);
+ workManager.schedule(fast2, listener);
+ workManager.schedule(fail1, listener);
+ workManager.schedule(fast3, listener);
+ workManager.schedule(slow1, listener);
+ workManager.schedule(fail2, listener);
+ workManager.schedule(slow2, listener);
+
+ // Wait for the 7 jobs to complete
+ waitForWorkToComplete(listener, 7);
+
+ // Test that the job completed successfully.
+ Assert.assertEquals(7, listener.getWorkAcceptedCallCount());
+ Assert.assertEquals(0, listener.getWorkRejectedCallCount());
+ Assert.assertEquals(7, listener.getWorkStartedCallCount());
+ Assert.assertEquals(7, listener.getWorkCompletedCallCount());
+ Assert.assertEquals(2, listener.getWorkExceptions().size());
+ }
+
+ /**
+ * Tests creating a ThreadPoolWorkManager with invalid pool sizes of -10 to 0
+ * inclusive
+ */
+ @Test
+ public void testThreadPoolWorkManagerLessThan1Size() {
+ for (int i = 0; i >= -10; i--) {
+ try {
+ new ThreadPoolWorkManager(i);
+ Assert.fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ Assert.assertTrue(ex.toString().indexOf(Integer.toString(i)) != -1);
+ }
+ }
+ }
+
+ /**
+ * Tests running a single job that has no listener
+ */
+ @Test
+ public void testSingleFastJobWithNoListener() {
+ // Create the work and register it
+ TimeDelayWork fast = new TimeDelayWork(10);
+ workManager.schedule(fast);
+
+ // Wait for the job to complete
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ int completedCount = fast.getRunCompletedCount();
+ if (completedCount == 1) {
+ break;
+ }
+
+ if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) {
+ Assert.fail("Only " + completedCount + " work items completed before timeout");
+ return;
+ }
+
+ // Lets wait for the job to complete
+ try {
+ Thread.sleep(25);
+ } catch (InterruptedException ex) {
+ Assert.fail("Unexpected exception: " + ex);
+ }
+ }
+
+ // Make sure we have got one completed run
+ Assert.assertEquals(1, fast.getRunCompletedCount());
+ }
+
+ /**
+ * Waits for the specified number of jobs to complete or the timeout to fire.
+ *
+ * @param listener The listener to use to track Work unit completion
+ * @param completedWorkItemsToWaitFor The number of Work items to complete
+ */
+ private void waitForWorkToComplete(TestWorkListener listener, int completedWorkItemsToWaitFor) {
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ int completedCount = listener.getWorkCompletedCallCount();
+ if (completedCount == completedWorkItemsToWaitFor) {
+ return;
+ }
+
+ if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) {
+ Assert.fail("Only " + completedCount + " work items completed before timeout");
+ return;
+ }
+
+ // Lets wait for more jobs to complete
+ try {
+ Thread.sleep(25);
+ } catch (InterruptedException ex) {
+ Assert.fail("Unexpected exception: " + ex);
+ }
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java
new file mode 100644
index 0000000000..f6435659ef
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.core.work.impl;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Simple Work item that will sleep in the run() method for the specified
+ * period of time
+ *
+ * @version $Rev$ $Date$
+ */
+public class TimeDelayWork extends Work {
+
+ /**
+ * Count of completed run() method calls
+ */
+ private AtomicInteger runCompletedCount = new AtomicInteger();
+
+ /**
+ * The amount of time to sleep in the Run loop
+ */
+ private final long sleepTime;
+
+ /**
+ * Constructor
+ *
+ * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method
+ */
+ public TimeDelayWork(long sleepTime) {
+ super(null);
+ this.sleepTime = sleepTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isDaemon() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void release() {
+ }
+
+ /**
+ * Sleeps for a period of time defined by sleepTime
+ */
+ public void run() {
+ System.out.println("Starting " + this);
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ System.out.println("Done " + this);
+ runCompletedCount.incrementAndGet();
+ }
+
+ /**
+ * Returns the number of completed calls to run()
+ *
+ * @return The number of completed calls to run()
+ */
+ public int getRunCompletedCount() {
+ return runCompletedCount.get();
+ }
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java
new file mode 100644
index 0000000000..ca7bf9b3d7
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.sca.scope;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.junit.Test;
+/**
+ * @version $Rev$ $Date$
+ */
+public class ScopeTestCase {
+
+ @Test
+ public void testEquals() throws Exception {
+ Scope scope = new Scope("COMPOSITE");
+ assertTrue(scope.equals(Scope.COMPOSITE));
+ }
+
+ @Test
+ public void testEqualsNew() throws Exception {
+ Scope foo = new Scope("foo");
+ Scope foo2 = new Scope("FOO");
+ assertTrue(foo.equals(foo2));
+ }
+
+ @Test
+ public void testNotEquals() throws Exception {
+ Scope foo = new Scope("BAR");
+ Scope foo2 = new Scope("FOO");
+ assertFalse(foo.equals(foo2));
+ }
+
+ @Test
+ public void testNotEqualsDifferent() throws Exception {
+ Scope foo = new Scope("FOO");
+ assertFalse(foo.equals(new Bar("FOO")));
+ }
+
+ public class Bar {
+ String scope;
+
+ public Bar(String scope) {
+ this.scope = scope;
+ }
+ }
+
+
+}
diff --git a/branches/sca-java-2.0-M2/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest b/branches/sca-java-2.0-M2/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest
new file mode 100644
index 0000000000..ad23df3761
--- /dev/null
+++ b/branches/sca-java-2.0-M2/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+name=implementation.last, stage=implementation, after=*
+name=reference.first, stage=reference, before=*
+name=reference.transaction, stage=reference, after=reference.interface
+name=reference.binding.header, stage=reference.binding, after=reference.binding.transport
+name=service.binding.header, stage=service.binding, after=service.binding.transport
+name=service.transaction, stage=service, after=service.binding, before=component.service
+name=implementation.transaction, stage=implementation, before=implementation.policy