summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java75
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java689
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/DomainRegistryImpl.java285
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java198
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java49
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java98
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java121
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java139
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java66
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java1285
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java840
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/WSDLHelper.java514
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java72
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java41
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java292
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java558
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java126
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java430
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java49
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java48
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java36
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncContext.java42
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java107
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.java47
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java58
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseInvoker.java351
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseService.java50
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java58
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackHandler.java53
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java60
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java50
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java48
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java155
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java38
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java95
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java128
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java51
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/InterceptorAsyncImpl.java111
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKAsyncResponseInvoker.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java197
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java48
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java96
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java54
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java210
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java56
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java285
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java740
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java68
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java197
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java313
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java153
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java436
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java248
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java43
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java114
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java45
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java313
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java236
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java1206
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java38
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java181
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java63
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java160
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java32
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java43
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java56
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java41
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java45
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java45
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java44
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java45
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java89
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java70
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java61
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java40
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java210
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java232
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java65
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java80
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java167
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java32
85 files changed, 14610 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java
new file mode 100644
index 0000000000..790cc6ec98
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.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.assembly;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+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.DefaultAssemblyFactory;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+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.core.assembly.impl.RuntimeEndpointImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl;
+
+
+/**
+ * The runtime version of assembly factory
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory {
+
+ public RuntimeAssemblyFactory(ExtensionPointRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public Component createComponent() {
+ return new RuntimeComponentImpl();
+ }
+
+ @Override
+ public ComponentReference createComponentReference() {
+ return new RuntimeComponentReferenceImpl();
+ }
+
+ @Override
+ public ComponentService createComponentService() {
+ return new RuntimeComponentServiceImpl();
+ }
+
+ @Override
+ public Endpoint createEndpoint() {
+ // Create an instance of EndpointImpl that can be serialized/deserialized using the Tuscany
+ // runtime extension points and extensions
+ return new RuntimeEndpointImpl(registry);
+ }
+
+ @Override
+ public EndpointReference createEndpointReference() {
+ return new RuntimeEndpointReferenceImpl(registry);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java
new file mode 100644
index 0000000000..c3cb51d8d1
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java
@@ -0,0 +1,689 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+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.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+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.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.provider.EndpointReferenceAsyncProvider;
+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.RuntimeProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.ActivationException;
+import org.apache.tuscany.sca.runtime.CompositeActivator;
+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.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CompositeActivatorImpl implements CompositeActivator {
+ final Logger logger = Logger.getLogger(CompositeActivatorImpl.class.getName());
+
+ private final ScopeRegistry scopeRegistry;
+ private final ProviderFactoryExtensionPoint providerFactories;
+ private Monitor monitor;
+
+ public CompositeActivatorImpl(ExtensionPointRegistry extensionPoints) {
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ this.scopeRegistry = utilities.getUtility(ScopeRegistry.class);
+ this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class);
+ this.monitor = utilities.getUtility(MonitorFactory.class).createMonitor();
+ }
+
+ //=========================================================================
+ // Activation
+ //=========================================================================
+
+ // Composite activation/deactivation
+
+ public void activate(CompositeContext compositeContext, Composite composite) throws ActivationException {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating composite: " + composite.getName());
+ }
+ for (Component component : composite.getComponents()) {
+ activateComponent(compositeContext, 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(CompositeContext compositeContext, 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(compositeContext, (Composite) implementation);
+ } else if (implementation != null) {
+ addImplementationProvider((RuntimeComponent) component,
+ implementation);
+ addScopeContainer(component);
+ }
+
+ for (ComponentService service : component.getServices()) {
+ activate(compositeContext,
+ (RuntimeComponent) component, (RuntimeComponentService) service);
+ }
+
+ for (ComponentReference reference : component.getReferences()) {
+ activate(compositeContext,
+ (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);
+ 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);
+ runtimeComponent.setScopeContainer(scopeContainer);
+ }
+
+ private void removeScopeContainer(Component component) {
+ if (!(component instanceof ScopedRuntimeComponent)) {
+ return;
+ }
+ ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component;
+ ScopeContainer scopeContainer = runtimeComponent.getScopeContainer();
+ runtimeComponent.setScopeContainer(null);
+ }
+
+
+ // Service activation/deactivation
+
+ public void activate(CompositeContext compositeContext, 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;
+ }
+
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating component service: " + component.getURI() + "#" + service.getName());
+ }
+
+ // Add a wire for each service Endpoint
+ for ( Endpoint endpoint : service.getEndpoints()){
+ RuntimeEndpoint ep = (RuntimeEndpoint) endpoint;
+ activate(compositeContext, ep);
+
+ // 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));
+ }
+ }
+
+ public void activate(CompositeContext compositeContext, RuntimeEndpoint ep) {
+ ep.bind(compositeContext);
+
+ // Check that the service binding interface is compatible with the
+ // service interface
+ ep.validateServiceInterfaceCompatibility();
+ }
+
+ public void deactivate(RuntimeComponent component, RuntimeComponentService service) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating component service: " + component.getURI() + "#" + service.getName());
+ }
+ for(Endpoint ep: service.getEndpoints()) {
+ if(ep instanceof RuntimeEndpoint) {
+ deactivate((RuntimeEndpoint) ep);
+ }
+ }
+ }
+
+ public void deactivate(RuntimeEndpoint ep) {
+ ep.unbind();
+ }
+
+ // Reference activation/deactivation
+
+ public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Activating component reference: " + component.getURI() + "#" + reference.getName());
+ }
+
+ // 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);
+ for(EndpointReference epr: reference.getEndpointReferences()) {
+ activate(compositeContext, (RuntimeEndpointReference) epr);
+ }
+
+ }
+
+ public void deactivate(RuntimeComponent component, RuntimeComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Deactivating component reference: " + component.getURI() + "#" + reference.getName());
+ }
+ for(EndpointReference endpointReference: reference.getEndpointReferences()) {
+ deactivate((RuntimeEndpointReference)endpointReference);
+ }
+ }
+
+ public void activate(CompositeContext compositeContext, RuntimeEndpointReference epr) {
+ // create the wire
+ // null endpoint passed in here as the endpoint reference may
+ // not be resolved yet
+ epr.bind(compositeContext);
+
+ ComponentReference reference = epr.getReference();
+ InterfaceContract sourceContract = epr.getComponentTypeReferenceInterfaceContract();
+
+ // TODO - EPR - interface contract seems to be null in the implementation.web
+ // case. Not introspecting the CT properly?
+ if (sourceContract == null){
+ // TODO - Can't do this with move of matching to wire
+ // take the contract from the service to which the reference is connected
+ sourceContract = ((RuntimeEndpoint) epr.getTargetEndpoint()).getComponentTypeServiceInterfaceContract();
+ reference.setInterfaceContract(sourceContract);
+ }
+
+ // endpointReference.setInterfaceContract(sourceContract.makeUnidirectional(false));
+
+ // if the reference already has a binding we can check the reference binding interface
+ // and reference interfaces for compatibility. If we can't check now compatibility
+ // will be checked when the endpoint reference is resolved.
+ if (epr.getStatus() == EndpointReference.Status.RESOLVED_BINDING){
+ epr.validateReferenceInterfaceCompatibility();
+ }
+ }
+
+ public void deactivate(RuntimeEndpointReference endpointReference) {
+ endpointReference.unbind();
+ }
+
+ //=========================================================================
+ // Start
+ //=========================================================================
+
+ // Composite start/stop
+
+ public void start(CompositeContext compositeContext, Composite composite) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting composite: " + composite.getName());
+ }
+ for (Component component : composite.getComponents()) {
+ start(compositeContext, component);
+ }
+
+ for (Component component : composite.getComponents()) {
+ if (component instanceof ScopedRuntimeComponent) {
+ start(compositeContext, (ScopedRuntimeComponent)component);
+ }
+ }
+
+ // start reference last. In allowing references to start at "start" time
+ // as well as when they are first used (for late bound references) we need
+ // to make sure that all potential target services and component implementations
+ // are started first to take account of the default binding optimization case
+ for (Component component : composite.getComponents()) {
+ for (ComponentReference reference : component.getReferences()) {
+ start(compositeContext,
+ (RuntimeComponent)component,
+ (RuntimeComponentReference)reference);
+ }
+ }
+ }
+
+ public void stop(CompositeContext compositeContext, Composite composite) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping composite: " + composite.getName());
+ }
+ for (final Component component : composite.getComponents()) {
+ stop(compositeContext, component);
+ }
+ }
+
+ // Component start/stop
+
+ public void start(CompositeContext compositeContext, Component component) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component: " + component.getURI());
+ }
+ RuntimeComponent runtimeComponent = ((RuntimeComponent)component);
+ if(runtimeComponent.isStarted()) {
+ return;
+ }
+
+ compositeContext.bindComponent(runtimeComponent);
+ Implementation implementation = component.getImplementation();
+
+ List<RuntimeProvider> providers = new ArrayList<RuntimeProvider>();
+ try {
+
+ if (implementation instanceof Composite) {
+ try {
+ start(compositeContext, (Composite)implementation);
+ } catch (Throwable e) {
+ try {
+ stop(compositeContext, (Composite) implementation);
+ } catch (Throwable e1) {
+ Monitor.error(monitor, this, "core-messages", "StopException", e1);
+ }
+ rethrow(e);
+ }
+ } else {
+ for (PolicyProvider policyProvider : runtimeComponent.getPolicyProviders()) {
+ policyProvider.start();
+ providers.add(policyProvider);
+ }
+ ImplementationProvider implementationProvider = runtimeComponent.getImplementationProvider();
+ if (implementationProvider != null) {
+ implementationProvider.start();
+ providers.add(implementationProvider);
+ }
+ }
+
+ for (ComponentService service : component.getServices()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component service: " + component.getURI() + "#" + service.getName());
+ }
+ for (Endpoint endpoint : service.getEndpoints()) {
+ RuntimeEndpoint ep = (RuntimeEndpoint)endpoint;
+ startEndpoint(compositeContext, ep, providers);
+ }
+ }
+
+ // Reference start is done after all components have been started to make sure everything
+ // is up and running before we try and connect references to services
+
+ } catch (Throwable e) {
+ // any providers (binding, implementation, policy) that were started
+ // before the error occured are stopped here
+ for (int i = providers.size() - 1; i >= 0; i--) {
+ try {
+ providers.get(i).stop();
+ } catch (Throwable e1) {
+ Monitor.error(monitor, this, "core-messages", "StopException", e1);
+ }
+ }
+ rethrow(e);
+ } finally {
+ providers.clear();
+ }
+
+ // mark a successful start
+ runtimeComponent.setStarted(true);
+ }
+
+ private void rethrow(Throwable e) throws Error {
+ if(e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else if(e instanceof Error) {
+ throw (Error) e;
+ }
+ }
+
+ public void stop(CompositeContext compositeContext, 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 (Endpoint endpoint : service.getEndpoints()) {
+ RuntimeEndpoint ep = (RuntimeEndpoint) endpoint;
+ stop(ep);
+ }
+ }
+ for (ComponentReference reference : component.getReferences()) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName());
+ }
+
+ for (EndpointReference endpointReference : reference.getEndpointReferences()) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference;
+ stop(epr);
+ }
+ }
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ stop(compositeContext, (Composite)implementation);
+ } else {
+ final ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider();
+ if (implementationProvider != null) {
+ try {
+ // Allow bindings to read properties. Requires PropertyPermission read in security policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ implementationProvider.stop();
+ return null;
+ }
+ });
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ for (PolicyProvider policyProvider : ((RuntimeComponent)component).getPolicyProviders()) {
+ try {
+ policyProvider.stop();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ }
+
+ if (component instanceof ScopedRuntimeComponent) {
+ ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component;
+ if (runtimeComponent.getScopeContainer() != null &&
+ runtimeComponent.getScopeContainer().getLifecycleState() != ScopeContainer.STOPPED) {
+ try {
+ runtimeComponent.getScopeContainer().stop();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ }
+
+ ((RuntimeComponent)component).setStarted(false);
+ }
+
+
+ // Scope container start/stop
+ // separate off from component start that all endpoints are
+ // registered before any @EagerInit takes place
+ public void start(CompositeContext compositeContext, ScopedRuntimeComponent scopedRuntimeComponent) {
+ if (scopedRuntimeComponent.getScopeContainer() != null) {
+ try {
+ scopedRuntimeComponent.getScopeContainer().start();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StartException", ex);
+ rethrow(ex);
+ }
+ }
+ }
+
+ // Service start/stop
+
+ public void start(CompositeContext compositeContext, RuntimeEndpoint ep) {
+ startEndpoint(compositeContext, ep, null);
+ }
+
+ private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep, final List<RuntimeProvider> providers) {
+ // FIXME: Should the policy providers be started before the endpoint is started?
+ for (PolicyProvider policyProvider : ep.getPolicyProviders()) {
+ policyProvider.start();
+ if (providers != null) {
+ try {
+ providers.add(policyProvider);
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StartException", ex);
+ rethrow(ex);
+ }
+ }
+ }
+
+ final ServiceBindingProvider bindingProvider = ep.getBindingProvider();
+ if (bindingProvider != null) {
+ try {
+ // bindingProvider.start();
+ // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.start();
+ if (providers != null) {
+ providers.add(bindingProvider);
+ }
+ return null;
+ }
+ });
+ compositeContext.getEndpointRegistry().addEndpoint(ep);
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StartException", ex);
+ rethrow(ex);
+ }
+ }
+ }
+
+ public void stop(RuntimeEndpoint ep) {
+ ep.getCompositeContext().getEndpointRegistry().removeEndpoint(ep);
+ final ServiceBindingProvider bindingProvider = ep.getBindingProvider();
+ if (bindingProvider != null) {
+ try {
+ // Allow bindings to read properties. Requires PropertyPermission read in security policy.
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ bindingProvider.stop();
+ return null;
+ }
+ });
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ for (PolicyProvider policyProvider : ep.getPolicyProviders()) {
+ try {
+ policyProvider.stop();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ }
+
+
+ // Reference start/stop
+
+ public void start(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference reference) {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName());
+ }
+
+ for (EndpointReference endpointReference : reference.getEndpointReferences()){
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference;
+
+ // If the reference is already resolved then start it now. This currently
+ // important for async references which have native async bindings as the
+ // reference provider has to register a response listener regardless of
+ // whether the reference has been used or not.
+ if (epr.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED ||
+ epr.getStatus() == EndpointReference.Status.RESOLVED_BINDING){
+
+ // As we only care about starting references at build time in the
+ // async case at the moment check that the binding supports native async
+ // and that the reference is an async reference
+ ReferenceBindingProvider bindingProvider = epr.getBindingProvider();
+ if (bindingProvider instanceof EndpointReferenceAsyncProvider &&
+ ((EndpointReferenceAsyncProvider)bindingProvider).supportsNativeAsync() &&
+ epr.isAsyncInvocation()){
+ // it's resolved so start it now
+ try {
+ // The act of getting invocation chains starts the reference in the late binding case
+ // so just use that here
+ epr.getInvocationChains();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StartException", ex);
+ rethrow(ex);
+ }
+ }
+ }
+ }
+ }
+
+ 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 ( EndpointReference endpointReference : runtimeRef.getEndpointReferences()){
+ RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference;
+ stop(epr);
+ }
+ }
+
+ @Deprecated
+ public void start(CompositeContext compositeContext, RuntimeEndpointReference endpointReference) {
+ compositeContext.getEndpointRegistry().addEndpointReference(endpointReference);
+
+ // The act of getting invocation chains starts the reference in the late binding case
+ // so just use that here
+ endpointReference.getInvocationChains();
+ }
+
+ public void stop(RuntimeEndpointReference epr) {
+ if (epr.isStarted()) {
+ CompositeContext compositeContext = epr.getCompositeContext();
+ if (compositeContext == null) {
+ throw new IllegalStateException("The endpoint reference is not bound");
+ }
+ compositeContext.getEndpointRegistry().removeEndpointReference(epr);
+ ReferenceBindingProvider bindingProvider = epr.getBindingProvider();
+ if (bindingProvider != null) {
+ try {
+ bindingProvider.stop();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ for (PolicyProvider policyProvider : epr.getPolicyProviders()) {
+ try {
+ policyProvider.stop();
+ } catch (Throwable ex){
+ Monitor.error(monitor, this, "core-messages", "StopException", ex);
+ }
+ }
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/DomainRegistryImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/DomainRegistryImpl.java
new file mode 100644
index 0000000000..21e1e4cf38
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/DomainRegistryImpl.java
@@ -0,0 +1,285 @@
+/*
+ * 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.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.LifeCycleListener;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.runtime.BaseDomainRegistry;
+import org.apache.tuscany.sca.runtime.ContributionDescription;
+import org.apache.tuscany.sca.runtime.ContributionListener;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+import org.apache.tuscany.sca.runtime.EndpointListener;
+import org.apache.tuscany.sca.runtime.RuntimeProperties;
+
+/**
+ * A DomainRegistry implementation that sees registrations from the same JVM
+ */
+public class DomainRegistryImpl extends BaseDomainRegistry implements DomainRegistry, LifeCycleListener {
+ private final Logger logger = Logger.getLogger(DomainRegistryImpl.class.getName());
+
+ private List<Endpoint> endpoints = new ArrayList<Endpoint>();
+ private Map<String, Map<String, Composite>> runningComposites = new HashMap<String, Map<String, Composite>>();
+ private Map<String, ContributionDescription> contributionDescriptions = new HashMap<String, ContributionDescription>();
+
+ protected boolean quietLogging;
+
+ public DomainRegistryImpl(ExtensionPointRegistry extensionPoints, String endpointRegistryURI, String domainURI) {
+ super(extensionPoints, null, endpointRegistryURI, domainURI);
+ Properties runtimeProps = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class).getUtility(RuntimeProperties.class).getProperties();
+ quietLogging = Boolean.parseBoolean(runtimeProps.getProperty(RuntimeProperties.QUIET_LOGGING));
+ }
+
+ public synchronized void addEndpoint(Endpoint endpoint) {
+ endpoints.add(endpoint);
+ for (EndpointListener listener : listeners) {
+ listener.endpointAdded(endpoint);
+ }
+ if (logger.isLoggable(quietLogging ? Level.FINE : Level.INFO)) {
+ String uri = null;
+ Binding b = endpoint.getBinding();
+ if (b != null) {
+ uri = b.getURI();
+ if (uri != null && uri.startsWith("/")) {
+ uri = uri.substring(1);
+ }
+ }
+ String msg = "Add endpoint - " + (uri == null ? endpoint.getURI() : b.getType().getLocalPart()+" - " + uri);
+ if (quietLogging) {
+ logger.fine(msg);
+ } else {
+ logger.info(msg);
+ }
+ }
+ }
+
+ public List<Endpoint> findEndpoint(String uri) {
+ List<Endpoint> foundEndpoints = new ArrayList<Endpoint>();
+ for (Endpoint endpoint : endpoints) {
+ if (endpoint.matches(uri)) {
+ foundEndpoints.add(endpoint);
+ logger.fine("Found endpoint with matching service - " + endpoint);
+ }
+ // else the service name doesn't match
+ }
+ return foundEndpoints;
+ }
+
+ public synchronized void removeEndpoint(Endpoint endpoint) {
+ endpoints.remove(endpoint);
+ endpointRemoved(endpoint);
+ if (logger.isLoggable(quietLogging ? Level.FINE : Level.INFO)) {
+ String uri = null;
+ Binding b = endpoint.getBinding();
+ if (b != null) {
+ uri = b.getURI();
+ if (uri != null && uri.startsWith("/")) {
+ uri = uri.substring(1);
+ }
+ }
+ String msg = "Remove endpoint - " + (uri == null ? endpoint.getURI() : b.getType().getLocalPart()+" - "+uri);
+ if (quietLogging) {
+ logger.fine(msg);
+ } else {
+ logger.info(msg);
+ }
+ }
+ }
+
+ public synchronized List<Endpoint> getEndpoints() {
+ return endpoints;
+ }
+
+ public synchronized Endpoint getEndpoint(String uri) {
+ for (Endpoint ep : endpoints) {
+ String epURI =
+ ep.getComponent().getURI() + "#" + ep.getService().getName() + "/" + ep.getBinding().getName();
+ if (epURI.equals(uri)) {
+ return ep;
+ }
+ if (ep.getBinding().getName() == null || ep.getBinding().getName().equals(ep.getService().getName())) {
+ epURI = ep.getComponent().getURI() + "#" + ep.getService().getName();
+ if (epURI.equals(uri)) {
+ return ep;
+ }
+ }
+ }
+ return null;
+
+ }
+
+ public synchronized void updateEndpoint(String uri, Endpoint endpoint) {
+ Endpoint oldEndpoint = getEndpoint(uri);
+ if (oldEndpoint == null) {
+ throw new IllegalArgumentException("Endpoint is not found: " + uri);
+ }
+ endpoints.remove(oldEndpoint);
+ endpoints.add(endpoint);
+ for (EndpointListener listener : listeners) {
+ listener.endpointUpdated(oldEndpoint, endpoint);
+ }
+ }
+
+ public synchronized void start() {
+ }
+
+ public synchronized void stop() {
+ for (Iterator<Endpoint> i = endpoints.iterator(); i.hasNext();) {
+ Endpoint ep = i.next();
+ i.remove();
+ endpointRemoved(ep);
+ }
+ endpointreferences.clear();
+ listeners.clear();
+ }
+
+ public void addRunningComposite(String curi, Composite composite) {
+ Map<String, Composite> cs = runningComposites.get(curi);
+ if (cs == null) {
+ cs = new HashMap<String, Composite>();
+ runningComposites.put(curi, cs);
+ }
+ cs.put(composite.getURI(), composite);
+ }
+
+ public void removeRunningComposite(String curi, String compositeURI) {
+ Map<String, Composite> cs = runningComposites.get(curi);
+ if (cs != null) {
+ cs.remove(compositeURI);
+ }
+ }
+
+ public Composite getRunningComposite(String curi, String compositeURI) {
+ Map<String, Composite> cs = runningComposites.get(curi);
+ if (cs != null) {
+ return cs.get(compositeURI);
+ }
+ return null;
+ }
+
+ public Map<String, List<String>> getRunningCompositeURIs() {
+ Map<String, List<String>> compositeURIs = new HashMap<String, List<String>>();
+ for (String curi : runningComposites.keySet()) {
+ if (runningComposites.get(curi).size() > 0) {
+ List<String> uris = new ArrayList<String>();
+ compositeURIs.put(curi, uris);
+ for (String uri : runningComposites.get(curi).keySet()) {
+ uris.add(uri);
+ }
+ }
+ }
+ return compositeURIs;
+ }
+
+ public void installContribution(ContributionDescription cd) {
+ contributionDescriptions.put(cd.getURI(), cd);
+ for (ContributionListener listener : contributionlisteners) {
+ listener.contributionInstalled(cd.getURI());
+ }
+ }
+
+ public void uninstallContribution(String uri) {
+ // TUSCANY-4025 - iterate through this list in reverse
+ // in the expectation that a node listener
+ // will appear in the list before and other
+ // listener that appears in the list and which
+ // relies on the node still have the contribution
+ // information.
+ ListIterator<ContributionListener> listenerIterator = contributionlisteners.listIterator(contributionlisteners.size());
+ while (listenerIterator.hasPrevious()) {
+ ContributionListener listener = listenerIterator.previous();
+ listener.contributionRemoved(uri);
+ }
+ contributionDescriptions.remove(uri);
+ }
+
+ public List<String> getInstalledContributionURIs() {
+ return new ArrayList<String>(contributionDescriptions.keySet());
+ }
+
+ public ContributionDescription getInstalledContribution(String uri) {
+ return contributionDescriptions.get(uri);
+ }
+
+ @Override
+ public void updateInstalledContribution(ContributionDescription cd) {
+ contributionDescriptions.put(cd.getURI(), cd);
+ for (ContributionListener listener : contributionlisteners) {
+ listener.contributionUpdated(cd.getURI());
+ }
+ }
+
+ private static final String LOCAL_MEMBER_NAME = "LocalOnly";
+ @Override
+ public List<String> getNodeNames() {
+ return Arrays.asList(new String[]{LOCAL_MEMBER_NAME});
+ }
+
+ @Override
+ public String getLocalNodeName() {
+ return LOCAL_MEMBER_NAME;
+ }
+
+ @Override
+ public String getRunningNodeName(String contributionURI, String compositeURI) {
+ if (getRunningComposite(contributionURI, compositeURI) != null) {
+ return LOCAL_MEMBER_NAME;
+ }
+ return null;
+ }
+
+ @Override
+ public String remoteCommand(String memberName, Callable<String> command) {
+ // TODO or should it just ensure the member name is LocalOnly and the run the command locally?
+ throw new IllegalStateException("not supportted for " + LOCAL_MEMBER_NAME);
+ }
+
+ @Override
+ public String getContainingCompositesContributionURI(String componentName) {
+ for (Map<String, Composite> cs : runningComposites.values()) {
+ for (Composite c : cs.values()) {
+ if (c.getComponent(componentName) != null) {
+ return c.getContributionURI();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isDistributed() {
+ return false;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java
new file mode 100644
index 0000000000..8cdb0363e9
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java
@@ -0,0 +1,198 @@
+/*
+ * 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.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+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.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.definitions.Definitions;
+import org.apache.tuscany.sca.policy.BindingType;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.util.PolicyHelper;
+import org.apache.tuscany.sca.runtime.EndpointSerializer;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+public class EndpointSerializerImpl implements EndpointSerializer {
+ private ExtensionPointRegistry registry;
+ private XMLInputFactory inputFactory;
+ private XMLOutputFactory outputFactory;
+ private StAXArtifactProcessor<Endpoint> processor;
+ private StAXArtifactProcessor<EndpointReference> refProcessor;
+
+ public EndpointSerializerImpl(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ inputFactory = factories.getFactory(XMLInputFactory.class);
+ outputFactory = factories.getFactory(XMLOutputFactory.class);
+ StAXArtifactProcessorExtensionPoint processors =
+ registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ processor = processors.getProcessor(Endpoint.class);
+ refProcessor = processors.getProcessor(EndpointReference.class);
+ }
+
+ public Endpoint readEndpoint(String xml) {
+ try {
+ //System.out.println("Read Endpoint string >> " + xml);
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml));
+ Endpoint result = processor.read(reader, new ProcessorContext(registry));
+ result.setRemote(true);
+ reader.close();
+ return result;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public void resolveEndpoint(Endpoint endpoint) {
+ CompositeContext compositeContext = ((RuntimeEndpoint)endpoint).getCompositeContext();
+
+ if (compositeContext == null){
+ // will be null if this is the SCAClient
+ return;
+ }
+
+ Definitions systemDefinitions = compositeContext.getSystemDefinitions();
+ if (systemDefinitions != null){
+ // Find pre-resolved intents from the system definition
+ List<Intent> intents = new ArrayList<Intent>();
+
+ for (Intent intent : endpoint.getRequiredIntents()){
+ Intent resolvedIntent = PolicyHelper.getIntent(systemDefinitions, intent.getName());
+
+ if (resolvedIntent != null){
+ intents.add(resolvedIntent);
+ } else {
+ // look to see if this intent is provided by the binding
+ BindingType bindingType = systemDefinitions.getBindingType(endpoint.getBinding().getType());
+
+ if (bindingType != null){
+ for (Intent apIntent : bindingType.getAlwaysProvidedIntents()){
+ if (apIntent.getName().equals(intent.getName())){
+ resolvedIntent = apIntent;
+ break;
+ }
+ }
+
+ if (resolvedIntent == null){
+ for (Intent mpIntent : bindingType.getMayProvidedIntents()){
+ if (mpIntent.getName().equals(intent.getName())){
+ resolvedIntent = mpIntent;
+ break;
+ }
+ }
+ }
+ }
+
+ if (resolvedIntent != null){
+ intents.add(resolvedIntent);
+ } else {
+ throw new ServiceRuntimeException("Remote endpoint " +
+ endpoint +
+ " has intent " +
+ intent +
+ " that can't be found in the local system definitions in node " +
+ compositeContext.getNodeURI());
+ }
+ }
+ }
+
+ endpoint.getRequiredIntents().clear();
+ endpoint.getRequiredIntents().addAll(intents);
+
+ // Find pre-resolved policy sets from the system definition
+ List<PolicySet> policySets = new ArrayList<PolicySet>();
+
+ for (PolicySet policySet : endpoint.getPolicySets()){
+ PolicySet resolvedPolicySet = PolicyHelper.getPolicySet(systemDefinitions, policySet.getName());
+ if (resolvedPolicySet != null){
+ policySets.add(resolvedPolicySet);
+ } else {
+ throw new ServiceRuntimeException("Remote endpoint " +
+ endpoint +
+ " has policy set " +
+ policySet +
+ " that can't be found in the local system definitions in node " +
+ compositeContext.getNodeURI());
+ }
+ }
+
+ endpoint.getPolicySets().clear();
+ endpoint.getPolicySets().addAll(policySets);
+ }
+ }
+
+ public String write(Endpoint endpoint) {
+ StringWriter sw = new StringWriter();
+ try {
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw);
+ processor.write(endpoint, writer, new ProcessorContext(registry));
+ writer.flush();
+ writer.close();
+ String endpointString = sw.toString();
+ //System.out.println("Write Endpoint string >> " + endpointString);
+ return endpointString;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public EndpointReference readEndpointReference(String xml) {
+ try {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml));
+ EndpointReference result = refProcessor.read(reader, new ProcessorContext(registry));
+ reader.close();
+ return result;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public String write(EndpointReference endpointReference) {
+ StringWriter sw = new StringWriter();
+ try {
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw);
+ refProcessor.write(endpointReference, writer, new ProcessorContext(registry));
+ writer.flush();
+ writer.close();
+ return sw.toString();
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java
new file mode 100644
index 0000000000..002eb774ef
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.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.assembly.impl;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.runtime.BaseDomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+
+/**
+ * The utility responsible for finding the endpoint regstry by the scheme and creating instances for the
+ * given domain
+ */
+public class LocalDomainRegistryFactory extends BaseDomainRegistryFactory {
+ private final static String[] schemes = new String[] {"local", "vm"};
+
+ /**
+ * @param extensionRegistry
+ */
+ public LocalDomainRegistryFactory(ExtensionPointRegistry registry) {
+ super(registry);
+ }
+
+ protected DomainRegistry createEndpointRegistry(String endpointRegistryURI, String domainURI) {
+ DomainRegistry domainRegistry =
+ new DomainRegistryImpl(registry, endpointRegistryURI, domainURI);
+ return domainRegistry;
+ }
+
+ public String[] getSupportedSchemes() {
+ return schemes;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java
new file mode 100644
index 0000000000..4d6a98ca5f
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java
@@ -0,0 +1,98 @@
+/*
+ * 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.ProcessorContext;
+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.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) {
+ }
+
+ /**
+ * @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, ProcessorContext)
+ */
+ public ReferenceParameters read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException {
+ ReferenceParameters parameters = new ReferenceParametersImpl();
+ parameters.setCallbackID(reader.getAttributeValue(null, "callbackID"));
+ return parameters;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter, ProcessorContext)
+ */
+ public void write(ReferenceParameters model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException,
+ XMLStreamException {
+ writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(),
+ REFERENCE_PARAMETERS.getLocalPart(),
+ REFERENCE_PARAMETERS.getNamespaceURI());
+ writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI());
+
+ 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, ProcessorContext)
+ */
+ public void resolve(ReferenceParameters model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException {
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java
new file mode 100644
index 0000000000..7bd56271a5
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java
@@ -0,0 +1,121 @@
+/*
+ * 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.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ReferenceParametersImpl implements ReferenceParameters {
+ private Object callbackID;
+ 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;
+ }
+
+ /**
+ * @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());
+ 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;
+
+ return true;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java
new file mode 100644
index 0000000000..a78cf6057e
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.CompositeService;
+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;
+import org.oasisopen.sca.ServiceReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * @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();
+ }
+
+ @Override
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String serviceName) {
+ RuntimeComponentContext componentContext = null;
+
+ // TUSCANY-3904 Removed implementation.composite path
+
+ componentContext = getComponentContext();
+ if (serviceName != null) {
+ return componentContext.createSelfReference(businessInterface, serviceName);
+ } else {
+ return componentContext.createSelfReference(businessInterface);
+ }
+
+ }
+
+ // TUSCANY-3988
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeComponentImpl clone = (RuntimeComponentImpl)super.clone();
+ clone.policyProviders = new ArrayList<PolicyProvider>();
+ return clone;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java
new file mode 100644
index 0000000000..2eea60ccea
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.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.assembly.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+
+/**
+ * Implementation of a Component Reference.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RuntimeComponentReferenceImpl extends ComponentReferenceImpl implements RuntimeComponentReference {
+
+ private RuntimeComponent component;
+
+ public RuntimeComponentReferenceImpl() {
+ super();
+ }
+
+ /**
+ * @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();
+ return ref;
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java
new file mode 100644
index 0000000000..bc7e6df878
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.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.assembly.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * Implementation of a Component Service.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RuntimeComponentServiceImpl extends ComponentServiceImpl implements RuntimeComponentService {
+
+ public RuntimeComponentServiceImpl() {
+ super();
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java
new file mode 100644
index 0000000000..09cbab76d1
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java
@@ -0,0 +1,1285 @@
+/*
+ * 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.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.wsdl.Definition;
+import javax.wsdl.WSDLException;
+import javax.wsdl.factory.WSDLFactory;
+import javax.wsdl.xml.WSDLWriter;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.stream.StreamSource;
+
+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.CompositeReference;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.impl.EndpointImpl;
+import org.apache.tuscany.sca.assembly.xml.InterfaceContractProcessor;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistryLocator;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseService;
+import org.apache.tuscany.sca.core.invocation.Constants;
+import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor;
+import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
+import org.apache.tuscany.sca.core.invocation.RuntimeInvoker;
+import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl;
+import org.apache.tuscany.sca.core.invocation.impl.PhaseManager;
+import org.apache.tuscany.sca.interfacedef.Compatibility;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.InterceptorAsync;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+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.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.EndpointAsyncProvider;
+import org.apache.tuscany.sca.provider.EndpointProvider;
+import org.apache.tuscany.sca.provider.ImplementationAsyncProvider;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.provider.OptimisingBindingProvider;
+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.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+import org.apache.tuscany.sca.runtime.DomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.EndpointSerializer;
+import org.apache.tuscany.sca.runtime.ExtensibleDomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.apache.tuscany.sca.xsd.XSDefinition;
+import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaImport;
+import org.apache.ws.commons.schema.XmlSchemaInclude;
+import org.apache.ws.commons.schema.XmlSchemaObject;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Runtime model for Endpoint that supports java serialization
+ */
+public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint, Externalizable {
+ private static final long serialVersionUID = 1L;
+ private static final byte separator[] = {'_', 'X', '_'};
+
+ private transient CompositeContext compositeContext;
+ private transient RuntimeWireProcessor wireProcessor;
+ private transient ProviderFactoryExtensionPoint providerFactories;
+ private transient InterfaceContractMapper interfaceContractMapper;
+ private transient WorkScheduler workScheduler;
+ private transient PhaseManager phaseManager;
+ private transient MessageFactory messageFactory;
+ private transient RuntimeInvoker invoker;
+ private transient EndpointSerializer serializer;
+
+ private transient List<InvocationChain> chains;
+ private transient Map<Operation, InvocationChain> invocationChainMap =
+ new ConcurrentHashMap<Operation, InvocationChain>();
+ private transient InvocationChain bindingInvocationChain;
+
+ private transient ServiceBindingProvider bindingProvider;
+ private transient List<PolicyProvider> policyProviders;
+ private String xml;
+ private String interfaceContractXML;
+
+ protected InterfaceContract bindingInterfaceContract;
+ protected InterfaceContract serviceInterfaceContract;
+
+ private RuntimeEndpoint delegateEndpoint;
+
+ /**
+ * No-arg constructor for Java serialization
+ */
+ public RuntimeEndpointImpl() {
+ super(null);
+ }
+
+ public RuntimeEndpointImpl(ExtensionPointRegistry registry) {
+ super(registry);
+ }
+
+ protected void copyFrom(RuntimeEndpointImpl copy) {
+ this.xml = copy.xml;
+
+ this.component = copy.component;
+ this.service = copy.service;
+ this.interfaceContract = copy.interfaceContract;
+ this.serviceInterfaceContract = copy.serviceInterfaceContract;
+
+ this.binding = copy.binding;
+ this.bindingInterfaceContract = copy.interfaceContract;
+ this.bindingInvocationChain = copy.bindingInvocationChain;
+
+ this.callbackEndpointReferences = copy.callbackEndpointReferences;
+
+ this.requiredIntents = copy.requiredIntents;
+ this.policySets = copy.policySets;
+
+ this.uri = copy.uri;
+ this.remote = copy.remote;
+ this.unresolved = copy.unresolved;
+
+ this.chains = copy.chains;
+ this.invocationChainMap = copy.invocationChainMap;
+ this.bindingProvider = copy.bindingProvider;
+ this.policyProviders = copy.policyProviders;
+
+ if (this.compositeContext == null && copy.compositeContext != null) {
+ bind(copy.compositeContext);
+ }
+ }
+
+ public void bind(CompositeContext compositeContext) {
+ this.compositeContext = compositeContext;
+ bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry());
+ }
+
+ public void bind(ExtensionPointRegistry registry, DomainRegistry domainRegistry) {
+ if (compositeContext == null) {
+ compositeContext = new CompositeContext(registry, domainRegistry);
+ }
+
+ // if interfaceContractMapper is already initialized then all the rest will be too
+ if (interfaceContractMapper != null) {
+ return;
+ }
+ this.registry = registry;
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+ this.workScheduler = utilities.getUtility(WorkScheduler.class);
+ this.wireProcessor =
+ new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class));
+
+ this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class);
+ this.invoker = new RuntimeInvoker(registry, this);
+
+ this.phaseManager = utilities.getUtility(PhaseManager.class);
+ this.serializer = utilities.getUtility(EndpointSerializer.class);
+ this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class);
+ this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ this.contractBuilder = builders.getContractBuilder();
+ }
+
+ public void unbind() {
+ compositeContext = null;
+ bindingInvocationChain = null;
+ chains = null;
+ bindingProvider = null;
+ policyProviders = null;
+ invocationChainMap.clear();
+ }
+
+ public synchronized List<InvocationChain> getInvocationChains() {
+ if (chains == null) {
+ initInvocationChains();
+ }
+ return chains;
+ }
+
+ public synchronized InvocationChain getBindingInvocationChain() {
+ if (bindingInvocationChain == null) {
+ bindingInvocationChain = new InvocationChainImpl(null, null, false, phaseManager, isAsyncInvocation());
+ initServiceBindingInvocationChains();
+ }
+
+ // Init the operation invocation chains now. We know they will
+ // be needed as well as the binding invocation chain and this
+ // makes the wire processors run
+ getInvocationChains();
+
+ return bindingInvocationChain;
+ }
+
+ /**
+ * A dummy invocation chain representing null as ConcurrentHashMap doesn't allow null values
+ */
+ private static final InvocationChain NULL_CHAIN = new InvocationChainImpl(null, null, false, null, false);
+
+ public InvocationChain getInvocationChain(Operation operation) {
+ InvocationChain cached = invocationChainMap.get(operation);
+ if (cached == null) {
+ for (InvocationChain chain : getInvocationChains()) {
+ Operation op = chain.getTargetOperation();
+
+ // We used to check compatibility here but this is now validated when the
+ // chain is created. As the chain operations are the real interface types
+ // they may be incompatible just because they are described in different
+ // IDLs
+ if (operation.getInterface().isRemotable()) {
+ if (operation.getName().equals(op.getName())) {
+ invocationChainMap.put(operation, chain);
+ return chain;
+ }
+ if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) {
+ invocationChainMap.put(operation, chain);
+ return chain;
+ }
+ } else {
+ // [rfeng] We need to run the compatibility check for local operations as they
+ // can be overloaded
+ if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) {
+ invocationChainMap.put(operation, chain);
+ return chain;
+ }
+ }
+ }
+ // Cache it with the NULL_CHAIN to avoid NPE
+ invocationChainMap.put(operation, NULL_CHAIN);
+ return null;
+ } else {
+ if (cached == NULL_CHAIN) {
+ cached = null;
+ }
+ return cached;
+ }
+ }
+
+ public Message invoke(Message msg) {
+ // Deal with async callback
+ // Ensure invocation chains are built...
+ getInvocationChains();
+ // async callback handling
+ if( this.isAsyncInvocation() && !this.getCallbackEndpointReferences().isEmpty() ) {
+ RuntimeEndpointReference asyncEPR = (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0);
+ // Place a link to the callback EPR into the message headers...
+ msg.getHeaders().put(Constants.ASYNC_CALLBACK, asyncEPR );
+ }
+ // end of async callback handling
+ return invoker.invokeBinding(msg);
+ }
+
+ public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
+ return invoker.invoke(operation, args);
+ }
+
+ public Message invoke(Operation operation, Message msg) {
+ return invoker.invoke(operation, msg);
+ }
+
+ public void invokeAsync(Message msg){
+ invoker.invokeBindingAsync(msg);
+ } // end method invokeAsync(Message)
+
+ public void invokeAsync(Operation operation, Message msg){
+ msg.setOperation(operation);
+ invoker.invokeAsync(msg);
+ } // end method invokeAsync(Operation, Message)
+
+ public void invokeAsyncResponse(Message msg){
+ resolve();
+ invoker.invokeAsyncResponse(msg);
+ }
+
+ /**
+ * Navigate the component/componentType inheritance chain to find the leaf contract
+ * @param contract
+ * @return
+ */
+ private Contract getLeafContract(Contract contract) {
+ Contract prev = null;
+ Contract current = contract;
+ while (current != null) {
+ prev = current;
+ if (current instanceof ComponentReference) {
+ current = ((ComponentReference)current).getReference();
+ } else if (current instanceof CompositeReference) {
+ current = ((CompositeReference)current).getPromotedReferences().get(0);
+ } else if (current instanceof ComponentService) {
+ current = ((ComponentService)current).getService();
+ } else if (current instanceof CompositeService) {
+ current = ((CompositeService)current).getPromotedService();
+ } else {
+ break;
+ }
+ if (current == null) {
+ return prev;
+ }
+ }
+ return current;
+ }
+
+ /**
+ * Initialize the invocation chains
+ */
+ private void initInvocationChains() {
+ chains = new ArrayList<InvocationChain>();
+ InterfaceContract sourceContract = getBindingInterfaceContract();
+
+ // It's the service wire
+ RuntimeComponentService service = (RuntimeComponentService)getService();
+ RuntimeComponent serviceComponent = (RuntimeComponent)getComponent();
+
+ //InterfaceContract targetContract = getInterfaceContract();
+ // TODO - EPR - why is this looking at the component types. The endpoint should have the right interface contract by this time
+ InterfaceContract targetContract = getComponentTypeServiceInterfaceContract();
+ // setInterfaceContract(targetContract);
+ validateServiceInterfaceCompatibility();
+ 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, phaseManager, isAsyncInvocation());
+ if (operation.isNonBlocking()) {
+ addNonBlockingInterceptor(chain);
+ }
+ addServiceBindingInterceptor(chain, operation);
+ addImplementationInterceptor(serviceComponent, service, chain, targetOperation);
+ chains.add(chain);
+
+ // Handle cases where the operation is an async server
+ if( targetOperation.isAsyncServer() ) {
+ createAsyncServerCallback();
+ } // end if
+ }
+
+ wireProcessor.process(this);
+
+ // If we have to support async and there is no binding chain
+ // then set the response path to point directly to the
+ // binding provided async response handler
+ if (isAsyncInvocation() &&
+ bindingInvocationChain == null){
+ // fix up the operation chain response path to point back to the
+ // binding provided async response handler
+ ServiceBindingProvider serviceBindingProvider = getBindingProvider();
+ if (serviceBindingProvider instanceof EndpointAsyncProvider){
+ EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider;
+ InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker();
+
+ for (InvocationChain chain : getInvocationChains()){
+ Invoker invoker = chain.getHeadInvoker();
+ if (invoker instanceof InterceptorAsync){
+ ((InterceptorAsync)invoker).setPrevious(asyncResponseInvoker);
+ } else {
+ //TODO - throw error once the old async code is removed
+ } // end if
+ } // end for
+ } else {
+ // TODO - throw error once the old async code is removed
+ } // end if
+ } // end if
+
+ ServiceBindingProvider provider = getBindingProvider();
+ if ((provider != null) && (provider instanceof OptimisingBindingProvider)) {
+ //TODO - remove this comment once optimisation codepath is tested
+ ((OptimisingBindingProvider)provider).optimiseBinding( this );
+ } // end if
+
+ } // end method initInvocationChains
+
+ /**
+ * Creates the async callback for this Endpoint, if it does not already exist
+ * and stores it into the Endpoint
+ */
+ public void createAsyncServerCallback( ) {
+ // No need to create a callback if the Binding supports async natively...
+ if( hasNativeAsyncBinding(this) ) return;
+
+ // Check to see if the callback already exists
+ if( asyncCallbackExists( this ) ) return;
+
+ RuntimeEndpointReference asyncEPR = createAsyncEPR( this );
+
+ // Store the new callback EPR into the Endpoint
+ this.getCallbackEndpointReferences().add(asyncEPR);
+
+ // Also store the callback EPR into the DomainRegistry
+ DomainRegistry epReg = getEndpointRegistry( registry );
+ if( epReg != null ) epReg.addEndpointReference(asyncEPR);
+ } // end method createAsyncServerCallback
+
+ public RuntimeEndpointReference getAsyncServerCallback() {
+
+ return (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0);
+ } // end method getAsyncServerCallback
+
+
+ /**
+ * Indicates if a given endpoint has a Binding that supports native async invocation
+ * @param endpoint - the endpoint
+ * @return - true if the endpoint has a binding that supports native async, false otherwise
+ */
+ private boolean hasNativeAsyncBinding(RuntimeEndpoint endpoint) {
+ ServiceBindingProvider provider = endpoint.getBindingProvider();
+ if( provider instanceof EndpointAsyncProvider ) {
+ EndpointAsyncProvider asyncProvider = (EndpointAsyncProvider) provider;
+ if( asyncProvider.supportsNativeAsync() ) return true;
+ } // end if
+ return false;
+ } // end method hasNativeAsyncBinding
+
+ /**
+ * Creates the Endpoint object for the async callback
+ * @param endpoint - the endpoint which has the async server operations
+ * @return the EndpointReference object representing the callback
+ */
+ private RuntimeEndpointReference createAsyncEPR( RuntimeEndpoint endpoint ){
+ CompositeContext compositeContext = endpoint.getCompositeContext();
+ RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory( compositeContext );
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)assemblyFactory.createEndpointReference();
+ epr.bind( compositeContext );
+
+ // Create pseudo-component
+ epr.setComponent(component);
+
+ // Create pseudo-reference
+ ComponentReference reference = assemblyFactory.createComponentReference();
+ ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ JavaInterfaceFactory javaInterfaceFactory = (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class);
+ JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ try {
+ interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseService.class));
+ } catch (InvalidInterfaceException e1) {
+ // Nothing to do here - will not happen
+ } // end try
+ reference.setInterfaceContract(interfaceContract);
+ String referenceName = endpoint.getService().getName() + "_asyncCallback";
+ reference.setName(referenceName);
+ reference.setForCallback(true);
+ // Add in "implementation" reference (really a dummy, but with correct interface)
+ Reference implReference = assemblyFactory.createReference();
+ implReference.setInterfaceContract(interfaceContract);
+ implReference.setName(referenceName);
+ implReference.setForCallback(true);
+
+ reference.setReference(implReference);
+ // Set the created ComponentReference into the EPR
+ epr.setReference(reference);
+
+ // Create a binding
+ Binding binding = createMatchingBinding( endpoint.getBinding(), (RuntimeComponent)endpoint.getComponent(), reference, registry );
+ epr.setBinding(binding);
+
+ // Need to establish policies here (binding has some...)
+ epr.getRequiredIntents().addAll( endpoint.getRequiredIntents() );
+ epr.getPolicySets().addAll( endpoint.getPolicySets() );
+
+ // Attach a dummy endpoint to the epr
+ RuntimeEndpoint ep = (RuntimeEndpoint)assemblyFactory.createEndpoint();
+ ep.setUnresolved(false);
+ epr.setTargetEndpoint(ep);
+ //epr.setStatus(EndpointReference.Status.RESOLVED_BINDING);
+ epr.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
+ epr.setUnresolved(false);
+
+ // Set the URI for the EPR
+ String eprURI = endpoint.getComponent().getName() + "#reference-binding(" + referenceName + "/" + referenceName + ")";
+ epr.setURI(eprURI);
+
+ return epr;
+ } // end method RuntimeEndpointReference
+
+ private boolean asyncCallbackExists( RuntimeEndpoint endpoint ) {
+ if( endpoint.getCallbackEndpointReferences().isEmpty() ) return false;
+ return true;
+ } // end method asyncCallbackExists
+
+ /**
+ * Create a matching binding to a supplied binding
+ * - the matching binding has the same binding type, but is for the supplied component and service
+ * @param matchBinding - the binding to match
+ * @param component - the component
+ * @param service - the service
+ * @param registry - registry for extensions
+ * @return - the matching binding, or null if it could not be created
+ */
+ @SuppressWarnings("unchecked")
+ private Binding createMatchingBinding( Binding matchBinding, RuntimeComponent component,
+ ComponentReference reference, ExtensionPointRegistry registry ) {
+ // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of
+ // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName
+ // and then read the XML using the processor for that XML...
+ QName bindingName = matchBinding.getType();
+ String bindingXML = "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>";
+
+ StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName);
+
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class);
+ StreamSource source = new StreamSource( new StringReader(bindingXML) );
+
+ ProcessorContext context = new ProcessorContext();
+ try {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(source);
+ reader.next();
+ Binding newBinding = (Binding) processor.read(reader, context );
+ newBinding.setName(reference.getName());
+
+ // Create a URI address for the callback based on the Component_Name/Reference_Name pattern
+ //String callbackURI = "/" + component.getName() + "/" + reference.getName();
+ //newBinding.setURI(callbackURI);
+
+ BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ BindingBuilder builder = builders.getBindingBuilder(newBinding.getType());
+ if (builder != null) {
+ org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
+ builder.build(component, reference, newBinding, builderContext, true);
+ } // end if
+
+ return newBinding;
+ } catch (ContributionReadException e) {
+ e.printStackTrace();
+ } catch (XMLStreamException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ } // end method createMatchingBinding
+
+ /**
+ * Gets a RuntimeAssemblyFactory from the CompositeContext
+ * @param compositeContext
+ * @return the RuntimeAssemblyFactory
+ */
+ private RuntimeAssemblyFactory getAssemblyFactory( CompositeContext compositeContext ) {
+ ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
+ } // end method RuntimeAssemblyFactory
+
+ /**
+ * Check that endpoint has compatible interface at the component and binding ends.
+ * The user can specify the interfaces at both ends so there is a danger that they won't be compatible.
+ */
+ public void validateServiceInterfaceCompatibility() {
+
+ InterfaceContract serviceContract = getComponentServiceInterfaceContract();
+ InterfaceContract bindingContract = getBindingInterfaceContract();
+
+ if ((serviceContract != bindingContract) &&
+ (serviceContract != null) && (bindingContract != null)) {
+
+ boolean bindingHasCallback = bindingContract.getCallbackInterface() != null;
+
+ try {
+
+ // Use the normalized contract if the interface types are different or if
+ // a normalized contract has been previously generate, for example, by virtue
+ // of finding a JAXWS annotation on a Java class that references a WSDL file
+ if (serviceContract.getClass() != bindingContract.getClass() ||
+ serviceContract.getNormalizedWSDLContract() != null ||
+ bindingContract.getNormalizedWSDLContract() != null) {
+ interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(serviceContract),
+ getGeneratedWSDLContract(bindingContract),
+ Compatibility.SUBSET,
+ !bindingHasCallback, // ignore callbacks if binding doesn't have one
+ false);
+ } else {
+ interfaceContractMapper.checkCompatibility(serviceContract,
+ bindingContract,
+ Compatibility.SUBSET,
+ !bindingHasCallback, // ignore callbacks if binding doesn't have one
+ false);
+ }
+ } catch (Exception ex){
+ throw new ServiceRuntimeException("Component " +
+ this.getComponent().getName() +
+ " Service " +
+ getService().getName() +
+ " interface is incompatible with the interface of the service binding - " +
+ getBinding().getName() +
+ " - " +
+ ex.getMessage() +
+ " - [" + this.toString() + "]");
+ }
+ }
+
+ }
+
+ private void initServiceBindingInvocationChains() {
+
+ // add the binding interceptors to the service binding wire
+ ServiceBindingProvider provider = getBindingProvider();
+ if ((provider != null) && (provider instanceof EndpointProvider)) {
+ ((EndpointProvider)provider).configure();
+ }
+
+ // add the policy interceptors to the service binding wire
+ List<PolicyProvider> pps = getPolicyProviders();
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createBindingInterceptor();
+ if (interceptor != null) {
+ bindingInvocationChain.addInterceptor(interceptor);
+ } // end if
+ } // end for
+ } // end if
+
+ // This is strategically placed before the RuntimeInvoker is added to the end of the
+ // binding chain as the RuntimeInvoker doesn't need to take part in the response
+ // processing and doesn't implement InvokerAsyncResponse
+ ServiceBindingProvider serviceBindingProvider = getBindingProvider();
+ if (isAsyncInvocation() &&
+ serviceBindingProvider instanceof EndpointAsyncProvider &&
+ ((EndpointAsyncProvider)serviceBindingProvider).supportsNativeAsync()){
+ // fix up the invocation chains to point back to the
+ // binding chain so that async response messages
+ // are processed correctly
+ for (InvocationChain chain : getInvocationChains()){
+ Invoker invoker = chain.getHeadInvoker();
+ ((InterceptorAsync)invoker).setPrevious((InvokerAsyncResponse)bindingInvocationChain.getTailInvoker());
+ } // end for
+
+ // fix up the binding chain response path to point back to the
+ // binding provided async response handler
+ EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider;
+ InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker();
+ ((InterceptorAsync)bindingInvocationChain.getHeadInvoker()).setPrevious(asyncResponseInvoker);
+ } // end if
+
+ // Add the runtime invoker to the end of the binding chain.
+ // It mediates between the binding chain and selects the
+ // correct invocation chain based on the operation that's
+ // been selected
+ bindingInvocationChain.addInvoker(invoker);
+
+ } // end method initServiceBindingInvocationChains
+
+ /**
+ * Add the interceptor for a binding
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ * @param operation
+ */
+ private void addServiceBindingInterceptor(InvocationChain chain, Operation operation) {
+ List<PolicyProvider> pps = getPolicyProviders();
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createInterceptor(operation);
+ if (interceptor != null) {
+ chain.addInterceptor(interceptor);
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a non-blocking interceptor if the service binding needs it
+ *
+ * @param service
+ * @param binding
+ * @param chain
+ */
+ private void addNonBlockingInterceptor(InvocationChain chain) {
+ ServiceBindingProvider provider = getBindingProvider();
+ 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) {
+
+ if (service.getService() instanceof CompositeService) {
+ CompositeService compositeService = (CompositeService)service.getService();
+ component = getPromotedComponent(compositeService);
+ service = getPromotedComponentService(compositeService);
+ }
+
+ ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider();
+
+ if (provider != null) {
+ Invoker invoker = null;
+ RuntimeComponentService runtimeService = (RuntimeComponentService)service;
+ if (runtimeService.getName().endsWith("_asyncCallback")){
+ if (provider instanceof ImplementationAsyncProvider){
+ invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncResponseInvoker(operation);
+ } else {
+ // TODO - This should be an error but taking account of the
+ // existing non-native async support
+ invoker = provider.createInvoker((RuntimeComponentService)service, operation);
+/*
+ throw new ServiceRuntimeException("Component " +
+ this.getComponent().getName() +
+ " Service " +
+ getService().getName() +
+ " implementation provider doesn't implement ImplementationAsyncProvider but the implementation uses a " +
+ "refrence interface with the asyncInvocation intent set" +
+ " - [" + this.toString() + "]");
+*/
+ }
+ } else if (isAsyncInvocation() &&
+ provider instanceof ImplementationAsyncProvider){
+ invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncInvoker((RuntimeComponentService)service, operation);
+ } else {
+ 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(interceptor);
+ }
+ }
+ }
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeEndpointImpl copy = (RuntimeEndpointImpl)super.clone();
+ copy.invoker = new RuntimeInvoker(registry, copy);
+ return copy;
+ }
+
+ /**
+ * Follow a service promotion chain down to the inner most (non composite)
+ * component service.
+ *
+ * @param topCompositeService
+ * @return
+ */
+ public 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;
+ }
+ }
+
+ /**
+ * Follow a service promotion chain down to the innermost (non-composite) component.
+ *
+ * @param compositeService
+ * @return
+ */
+ public Component getPromotedComponent(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 getPromotedComponent((CompositeService)service);
+
+ } else {
+
+ // Found a non-composite service
+ return compositeService.getPromotedComponent();
+ }
+ } else {
+
+ // No promoted service
+ return null;
+ }
+ }
+
+ public synchronized ServiceBindingProvider getBindingProvider() {
+ resolve();
+ if (bindingProvider == null) {
+ BindingProviderFactory factory =
+ (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass());
+ if (factory == null) {
+ throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding()
+ .getType());
+ }
+ this.bindingProvider = factory.createServiceBindingProvider(this);
+ }
+ return bindingProvider;
+ }
+
+ public synchronized List<PolicyProvider> getPolicyProviders() {
+ resolve();
+ if (policyProviders == null) {
+ policyProviders = new ArrayList<PolicyProvider>();
+ for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) {
+ PolicyProvider provider = factory.createServicePolicyProvider(this);
+ if (provider != null) {
+ policyProviders.add(provider);
+ }
+ }
+ }
+ return policyProviders;
+ }
+
+ public void setBindingProvider(ServiceBindingProvider provider) {
+ this.bindingProvider = provider;
+ }
+
+ public Contract getContract() {
+ return getService();
+ }
+
+ public CompositeContext getCompositeContext() {
+ return compositeContext;
+ }
+
+ @Override
+ protected void reset() {
+ super.reset();
+ this.xml = null;
+ }
+
+ @Override
+ protected synchronized void resolve() {
+ if (xml != null && component == null) {
+ // TUSCANY-3958 - when an endpoint arrives at the remote side of the
+ // domain registry it's composite context is set, but to
+ // a default that's not that useful. We can tell because it
+ // doesn't set the system definitions
+ if (compositeContext == null ||
+ compositeContext.getSystemDefinitions() == null) {
+ compositeContext = CompositeContext.getCurrentCompositeContext();
+ if (compositeContext != null) {
+ bind(compositeContext);
+ }
+ } // end if
+ if (serializer != null) {
+ RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml);
+ copyFrom(ep);
+ serializer.resolveEndpoint(this);
+ } else {
+ // In this case, we assume that we're running on a detached (non Tuscany) thread and
+ // as a result we need to connect back to the Tuscany environment...
+ ExtensionPointRegistry registry = ExtensionPointRegistryLocator.getExtensionPointRegistry();
+ if( registry != null ) {
+ this.registry = registry;
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+ this.serializer = utilities.getUtility(EndpointSerializer.class);
+ RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml);
+ // Find the actual Endpoint in the DomainRegistry
+ ep = findActualEP( ep, registry );
+ if( ep != null ){
+ copyFrom( ep );
+ } // end if
+ } // end if
+ } // end if
+ setNormalizedWSDLContract();
+ } // end if
+ super.resolve();
+ } // end method resolve
+
+ /**
+ * Find the actual Endpoint in the DomainRegistry which corresponds to the configuration described
+ * in a deserialized Endpoint
+ * @param ep The deserialized endpoint
+ * @param registry - the main extension point Registry
+ * @return the corresponding Endpoint from the DomainRegistry, or null if no match can be found
+ */
+ private RuntimeEndpointImpl findActualEP(RuntimeEndpointImpl ep,
+ ExtensionPointRegistry registry) {
+ DomainRegistry domainRegistry = getEndpointRegistry( registry );
+
+ if( domainRegistry == null ) return null;
+
+ for( Endpoint endpoint : domainRegistry.findEndpoint(ep.getURI()) ) {
+ // TODO: For the present, simply return the first matching endpoint
+ return (RuntimeEndpointImpl) endpoint;
+ } // end for
+
+ return null;
+ } // end method findActualEP
+
+ /**
+ * Get the DomainRegistry
+ * @param registry - the ExtensionPoint registry
+ * @return the DomainRegistry - will be null if the DomainRegistry cannot be found
+ */
+ private DomainRegistry getEndpointRegistry( ExtensionPointRegistry registry) {
+ DomainRegistryFactory domainRegistryFactory = ExtensibleDomainRegistryFactory.getInstance(registry);
+
+ if( domainRegistryFactory == null ) return null;
+
+ // TODO: For the moment, just use the first (and only!) DomainRegistry...
+ DomainRegistry domainRegistry = (DomainRegistry) domainRegistryFactory.getEndpointRegistries().toArray()[0];
+
+ return domainRegistry;
+ } // end method
+
+ public InterfaceContract getBindingInterfaceContract() {
+ resolve();
+ if (bindingInterfaceContract != null) {
+ return bindingInterfaceContract;
+ }
+ bindingInterfaceContract = getBindingProvider().getBindingInterfaceContract();
+ if (bindingInterfaceContract == null) {
+ bindingInterfaceContract = getComponentServiceInterfaceContract();
+ }
+ if (bindingInterfaceContract == null) {
+ bindingInterfaceContract = getComponentTypeServiceInterfaceContract();
+ }
+ return bindingInterfaceContract;
+ }
+
+ public InterfaceContract getComponentTypeServiceInterfaceContract() {
+ resolve();
+ if (serviceInterfaceContract != null) {
+ return serviceInterfaceContract;
+ }
+ if (service == null) {
+ return getComponentServiceInterfaceContract();
+ }
+ serviceInterfaceContract = getLeafContract(service).getInterfaceContract();
+ if (serviceInterfaceContract == null) {
+ serviceInterfaceContract = getComponentServiceInterfaceContract();
+ }
+ return serviceInterfaceContract;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ this.uri = in.readUTF();
+ this.xml = in.readUTF();
+ this.interfaceContractXML = in.readUTF();
+/*
+ this.wsdlCallback = in.readUTF();
+*/
+
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeUTF(getURI());
+ if (serializer == null && xml != null) {
+ out.writeUTF(xml);
+ } else {
+ if (serializer != null) {
+ out.writeUTF(serializer.write(this));
+ } else {
+ throw new IllegalStateException("No serializer is configured");
+ }
+ }
+
+ if (interfaceContractXML == null) {
+ interfaceContractXML = getXMLFromTuscanyInterfaceContract();
+ }
+ out.writeUTF(interfaceContractXML);
+ }
+
+ public String getAsXML() {
+ if (xml == null) {
+ this.xml = serializer.write(this);
+ }
+ return xml;
+ }
+
+ private String getXMLFromTuscanyInterfaceContract() throws IOException{
+ String interfaceContract = null;
+ try {
+ InterfaceContractProcessor processor = new InterfaceContractProcessor(registry);
+ ProcessorContext context = new ProcessorContext();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class);
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(bos);
+ processor.write(getComponentServiceInterfaceContract(), writer, context);
+ writer.close();
+ interfaceContract = bos.toString();
+ } catch (Exception ex){
+ throw new IOException(ex);
+ }
+ //System.out.println("Generated IC XML: " + interfaceContract);
+ return interfaceContract;
+ }
+
+ private InterfaceContract getTuscanyInterfaceContractFromXML() {
+ InterfaceContract interfaceContract = null;
+ //System.out.println("Reading IC XML: " + interfaceContractXML);
+ if (interfaceContractXML != null && interfaceContractXML.length() > 0){
+ try {
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ InterfaceContractProcessor processor = new InterfaceContractProcessor(registry);
+ ProcessorContext context = new ProcessorContext();
+ ByteArrayInputStream bis = new ByteArrayInputStream(interfaceContractXML.getBytes());
+ XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(bis);
+ interfaceContract = processor.read(reader, context);
+ } catch (Exception ex){
+ new ServiceRuntimeException(ex);
+ }
+ }
+ return interfaceContract;
+ }
+
+ private String getWsdl() {
+ InterfaceContract ic = getComponentServiceInterfaceContract();
+ if (ic == null || ic.getInterface() == null || !ic.getInterface().isRemotable()) {
+ return "";
+ }
+
+ WSDLInterfaceContract wsdlIC = null;
+ try {
+ wsdlIC = (WSDLInterfaceContract)getGeneratedWSDLContract(ic);
+ } catch (Exception ex){
+ // ignore WSDL generation errors as the service interface may have
+ // types that can't be converted to XML easily
+ return "";
+ }
+
+ if (wsdlIC == null) {
+ return "";
+ }
+
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+
+ try {
+ // write out a flattened WSDL along with XSD
+ WSDLInterface wsdl = (WSDLInterface)wsdlIC.getInterface();
+ WSDLDefinition wsdlDefinition = wsdl.getWsdlDefinition();
+ writeWSDL(outStream, wsdlDefinition);
+ } catch (Exception e){
+ throw new RuntimeException(e);
+ }
+
+ String wsdlString = outStream.toString();
+
+ return wsdlString;
+ }
+
+ private String getWsdlCallback() {
+ InterfaceContract ic = getComponentServiceInterfaceContract();
+ if (ic == null || ic.getCallbackInterface() == null || !ic.getCallbackInterface().isRemotable()) {
+ return "";
+ }
+
+ WSDLInterfaceContract wsdlIC = null;
+ try {
+ wsdlIC = (WSDLInterfaceContract)getGeneratedWSDLContract(ic);
+ } catch (Exception ex){
+ // ignore WSDL generation errors as the service interface may have
+ // types that can't be converted to XML easily
+ return "";
+ }
+
+ if (wsdlIC == null) {
+ return "";
+ }
+
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+
+ try {
+ // write out a flattened Callback WSDL along with XSD
+ WSDLInterface wsdl = (WSDLInterface)wsdlIC.getCallbackInterface();
+ WSDLDefinition wsdlDefinition = wsdl.getWsdlDefinition();
+ writeWSDL(outStream, wsdlDefinition);
+ } catch (Exception e){
+ throw new RuntimeException(e);
+ }
+
+ String wsdlString = outStream.toString();
+
+ return wsdlString;
+ }
+
+ /**
+ * Write the WSDL followed by all it's XSD
+ *
+ * @param outStream
+ * @param wsdlDefinition
+ * @throws IOException
+ * @throws WSDLException
+ */
+ private void writeWSDL(OutputStream outStream, WSDLDefinition wsdlDefinition) throws IOException, WSDLException {
+ Definition definition = wsdlDefinition.getDefinition();
+ WSDLWriter writer = WSDLFactory.newInstance().newWSDLWriter();
+ String baseURI = null;
+ if (wsdlDefinition.getLocation() != null) {
+ baseURI = wsdlDefinition.getLocation().toString();
+ } else {
+ baseURI = "generated.wsdl";
+ }
+ outStream.write(baseURI.getBytes());
+ outStream.write(separator);
+ writer.writeWSDL(definition, outStream);
+ for (WSDLDefinition importedWSDLDefintion : wsdlDefinition.getImportedDefinitions()){
+ outStream.write(separator);
+ baseURI = importedWSDLDefintion.getLocation().toString();
+ outStream.write(baseURI.getBytes());
+ outStream.write(separator);
+ writer.writeWSDL(importedWSDLDefintion.getDefinition(), outStream);
+ }
+/* Exclude the XSD for the time being to see if we can get comparison working
+ * with the operation signatures but ignoring parameter types
+ for (XSDefinition xsdDefinition : wsdlDefinition.getXmlSchemas()){
+ // we store a reference to the schema schema. We don't need to write that out.
+ if (!xsdDefinition.getNamespace().equals("http://www.w3.org/2001/XMLSchema") &&
+ xsdDefinition.getSchema() != null){
+ writeSchema(outStream, xsdDefinition.getSchema());
+ }
+ }
+*/
+ }
+
+ /**
+ * Write an XSD
+ *
+ * @param outStream
+ * @param schema
+ * @throws IOException
+ */
+ private void writeSchema(OutputStream outStream, XmlSchema schema) throws IOException {
+ // TODO - this doesn't write schema in the non-namespace namespace
+ if (schema != null &&
+/*
+ schema.getTargetNamespace() != null &&
+ !schema.getTargetNamespace().equals("http://www.w3.org/2001/XMLSchema") &&
+*/
+ schema.getNamespaceContext() != null){
+ outStream.write(separator);
+ String baseURI = schema.getSourceURI();
+ outStream.write(baseURI.getBytes());
+ outStream.write(separator);
+ schema.write(outStream);
+
+ for (Iterator<?> i = schema.getIncludes().getIterator(); i.hasNext();) {
+ XmlSchemaObject obj = (XmlSchemaObject)i.next();
+ XmlSchema ext = null;
+ if (obj instanceof XmlSchemaInclude) {
+ ext = ((XmlSchemaInclude)obj).getSchema();
+ }
+ if (obj instanceof XmlSchemaImport) {
+ ext = ((XmlSchemaImport)obj).getSchema();
+ }
+ writeSchema(outStream, ext);
+ }
+ }
+ }
+
+ private void setNormalizedWSDLContract() {
+ if (interfaceContractXML == null || interfaceContractXML.length() < 1) {
+ return;
+ }
+ InterfaceContract ic = getComponentServiceInterfaceContract();
+ if (ic != null) {
+/*
+ ic.setNormalizedWSDLContract(WSDLHelper.createWSDLInterfaceContract(registry, wsdl, wsdlCallback));
+*/
+ ic.setNormalizedWSDLContract(getTuscanyInterfaceContractFromXML());
+ }
+ }
+
+ public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) {
+
+ if ( interfaceContract.getNormalizedWSDLContract() == null){
+ if (getComponentServiceInterfaceContract() instanceof JavaInterfaceContract){
+ if (contractBuilder == null){
+ throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString());
+ }
+ contractBuilder.build(interfaceContract, null);
+ }
+ }
+
+ return interfaceContract.getNormalizedWSDLContract();
+ }
+
+ @Override
+ public RuntimeEndpoint getDelegateEndpoint() {
+ return delegateEndpoint;
+ }
+
+ @Override
+ public void setDelegateEndpoint(RuntimeEndpoint delegateEndpoint) {
+ this.delegateEndpoint = delegateEndpoint;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java
new file mode 100644
index 0000000000..cfc997b261
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java
@@ -0,0 +1,840 @@
+/*
+ * 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.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.CompositeReference;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.impl.EndpointReferenceImpl;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistryLocator;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseService;
+import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor;
+import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor;
+import org.apache.tuscany.sca.core.invocation.RuntimeInvoker;
+import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl;
+import org.apache.tuscany.sca.core.invocation.impl.PhaseManager;
+import org.apache.tuscany.sca.interfacedef.Compatibility;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract;
+import org.apache.tuscany.sca.invocation.Interceptor;
+import org.apache.tuscany.sca.invocation.InterceptorAsync;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+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.monitor.MonitorFactory;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.EndpointReferenceProvider;
+import org.apache.tuscany.sca.provider.ImplementationAsyncProvider;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+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.runtime.DomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+import org.apache.tuscany.sca.runtime.EndpointSerializer;
+import org.apache.tuscany.sca.runtime.ExtensibleDomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessor;
+import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Runtime model for Endpoint that supports java serialization
+ */
+public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implements RuntimeEndpointReference, Externalizable {
+ private transient CompositeContext compositeContext;
+ private transient RuntimeWireProcessor wireProcessor;
+ private transient InterfaceContractMapper interfaceContractMapper;
+ private transient WorkScheduler workScheduler;
+ private transient PhaseManager phaseManager;
+ private transient MessageFactory messageFactory;
+ private transient RuntimeInvoker invoker;
+ private transient DomainRegistry domainRegistry;
+
+ private transient List<InvocationChain> chains;
+ private transient Map<Operation, InvocationChain> invocationChainMap =
+ new ConcurrentHashMap<Operation, InvocationChain>();
+ private transient InvocationChain bindingInvocationChain;
+
+ private transient EndpointReferenceBinder eprBinder;
+ private transient ReferenceBindingProvider bindingProvider;
+ private transient ProviderFactoryExtensionPoint providerFactories;
+ private transient List<PolicyProvider> policyProviders;
+ private transient EndpointSerializer serializer;
+
+ protected InterfaceContract bindingInterfaceContract;
+ protected InterfaceContract referenceInterfaceContract;
+
+ //protected InterfaceContract generatedReferenceWSDLInterfaceContract;
+
+ private String xml;
+
+ private boolean started;
+
+ private RuntimeEndpointReference delegateEndpointReference;
+ private boolean bindingURIaltered;
+
+ /**
+ * No-arg constructor for Java serilization
+ */
+ public RuntimeEndpointReferenceImpl() {
+ super(null);
+ }
+
+ public RuntimeEndpointReferenceImpl(ExtensionPointRegistry registry) {
+ super(registry);
+ }
+
+ protected void copyFrom(RuntimeEndpointReferenceImpl copy) {
+ this.xml = copy.xml;
+
+ this.component = copy.component;
+ this.reference = copy.reference;
+ this.interfaceContract = copy.interfaceContract;
+ this.referenceInterfaceContract = copy.referenceInterfaceContract;
+ this.callbackEndpoint = copy.callbackEndpoint;
+ this.targetEndpoint = copy.targetEndpoint;
+
+ this.binding = copy.binding;
+ this.bindingInterfaceContract = copy.interfaceContract;
+ this.bindingInvocationChain = copy.bindingInvocationChain;
+
+ this.requiredIntents = copy.requiredIntents;
+ this.policySets = copy.policySets;
+
+ this.uri = copy.uri;
+ this.unresolved = copy.unresolved;
+ this.status = copy.status;
+
+ this.chains = copy.chains;
+ this.invocationChainMap = copy.invocationChainMap;
+ this.bindingProvider = copy.bindingProvider;
+ this.policyProviders = copy.policyProviders;
+
+ if (this.compositeContext == null && copy.compositeContext != null) {
+ bind(copy.compositeContext);
+ }
+ }
+
+ public void bind(CompositeContext compositeContext) {
+ this.compositeContext = compositeContext;
+ bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry());
+ }
+
+ public void bind(ExtensionPointRegistry registry, DomainRegistry domainRegistry) {
+ if (compositeContext == null) {
+ compositeContext = new CompositeContext(registry, domainRegistry);
+ }
+ this.registry = registry;
+ this.domainRegistry = domainRegistry;
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+ this.workScheduler = utilities.getUtility(WorkScheduler.class);
+ this.wireProcessor =
+ new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class));
+
+ this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class);
+ this.invoker = new RuntimeInvoker(registry, this);
+
+ this.phaseManager = utilities.getUtility(PhaseManager.class);
+ this.serializer = utilities.getUtility(EndpointSerializer.class);
+ this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class);
+
+ this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ this.contractBuilder = builders.getContractBuilder();
+ }
+
+ public synchronized List<InvocationChain> getInvocationChains() {
+ if (chains == null) {
+ initInvocationChains();
+ }
+ return chains;
+ }
+
+ public synchronized InvocationChain getBindingInvocationChain() {
+ if (bindingInvocationChain == null) {
+ bindingInvocationChain = new InvocationChainImpl(null, null, true, phaseManager, isAsyncInvocation());
+ initReferenceBindingInvocationChains();
+ }
+ return bindingInvocationChain;
+ }
+
+ public InvocationChain getInvocationChain(Operation operation) {
+ InvocationChain cached = invocationChainMap.get(operation);
+ if (cached == null) {
+ for (InvocationChain chain : getInvocationChains()) {
+ Operation op = chain.getSourceOperation();
+
+ // We used to check compatibility here but this is now validated when the
+ // chain is created. As the chain operations are the real interface types
+ // they may be incompatible just because they are described in different
+ // IDLs
+ if (operation.getName().equals(op.getName())) {
+ invocationChainMap.put(operation, chain);
+ return chain;
+ }
+ }
+ invocationChainMap.put(operation, null);
+ return null;
+ } else {
+ return cached;
+ }
+ }
+
+ public Message invoke(Message msg) {
+ return invoker.invoke(msg);
+ }
+
+ public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
+ return invoker.invoke(operation, args);
+ }
+
+ public Message invoke(Operation operation, Message msg) {
+ return invoker.invoke(operation, msg);
+ }
+
+ public void invokeAsync(Operation operation, Message msg){
+ msg.setOperation(operation);
+ invoker.invokeAsync(msg);
+ }
+
+ public void invokeAsync(Message msg){
+ invoker.invokeAsync(msg);
+ }
+
+ public void invokeAsyncResponse(Message msg){
+ // If there is a Binding Chain, invoke it first...
+ InvocationChain chain = this.getBindingInvocationChain();
+ if( chain != null ) {
+ Invoker tailInvoker = chain.getTailInvoker();
+ if (tailInvoker != null) {
+ ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg);
+ } // end if
+ } // end if
+
+ chain = this.getInvocationChain(msg.getOperation());
+ Invoker tailInvoker = chain.getTailInvoker();
+ ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg);
+ } // end method invokeAsyncResponse
+
+ /**
+ * Navigate the component/componentType inheritence chain to find the leaf contract
+ * @param contract
+ * @return
+ */
+ private Contract getLeafContract(Contract contract) {
+ Contract prev = null;
+ Contract current = contract;
+ while (current != null) {
+ prev = current;
+ if (current instanceof ComponentReference) {
+ current = ((ComponentReference)current).getReference();
+ } else if (current instanceof CompositeReference) {
+ current = ((CompositeReference)current).getPromotedReferences().get(0);
+ } else if (current instanceof ComponentService) {
+ current = ((ComponentService)current).getService();
+ } else if (current instanceof CompositeService) {
+ current = ((CompositeService)current).getPromotedService();
+ } else {
+ break;
+ }
+ if (current == null) {
+ return prev;
+ }
+ }
+ return current;
+ }
+
+ /**
+ * Initialize the invocation chains
+ */
+ private void initInvocationChains() {
+ InterfaceContract sourceContract = getComponentTypeReferenceInterfaceContract();
+ // TODO - EPR why is this looking at the component types. The endpoint reference should have the right interface contract by this time
+ //InterfaceContract sourceContract = getLeafInterfaceContract(endpointReference);
+
+ // It's the reference wire
+ resolveEndpointReference();
+
+ InterfaceContract targetContract = getBindingInterfaceContract();
+ // TODO - EPR why is this looking at the component types. The endpoint should have the right interface contract by this time
+ //InterfaceContract targetContract = getLeafInterfaceContract(endpoint);
+
+ if (sourceContract == null && targetContract != null) {
+ // TODO: until the web component introspection is brought up
+ try {
+ sourceContract = (InterfaceContract)targetContract.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ validateReferenceInterfaceCompatibility();
+
+ List<InvocationChain> chainList = new ArrayList<InvocationChain>();
+ if(sourceContract != null && targetContract != null) {
+ RuntimeComponentReference reference = (RuntimeComponentReference)getReference();
+ 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 "
+ + getComponent().getURI()
+ + "#"
+ + reference.getName());
+ }
+ InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true, phaseManager, isAsyncInvocation());
+ if (operation.isNonBlocking()) {
+ addNonBlockingInterceptor(chain);
+ }
+ chainList.add(chain);
+ addReferenceBindingInterceptor(chain, operation);
+ }
+ }
+
+ // Set the chains until it's fully populated. If we initialize too early, any exception could
+ // leave this endpoint reference in a wrong state with an empty chain.
+ chains = chainList;
+ wireProcessor.process(this);
+
+ // reset the binding uri altered flag
+ bindingURIaltered = false;
+
+ if (isAsyncInvocation()){
+ // Fix up all of the operation chain response paths to point back to the implementation provided
+ // async response handler
+ //ImplementationProvider implementationProvider = ((RuntimeComponent)getComponent()).getImplementationProvider();
+ RuntimeComponentReference theReference = (RuntimeComponentReference)this.getReference();
+ RuntimeComponent theComponent = theReference.getComponent();
+ ImplementationProvider implementationProvider = theComponent.getImplementationProvider();
+ if (implementationProvider instanceof ImplementationAsyncProvider){
+ for (InvocationChain chain : getInvocationChains()){
+ InvokerAsyncResponse asyncResponseInvoker = ((ImplementationAsyncProvider)implementationProvider).createAsyncResponseInvoker(chain.getSourceOperation());
+ if (chain.getHeadInvoker() instanceof InterceptorAsync){
+ ((InterceptorAsync)chain.getHeadInvoker()).setPrevious(asyncResponseInvoker);
+ } else {
+ //TODO - throw error once the old async code is removed
+ } // end if
+ } // end for
+ } // end if
+ } // end if
+ } // end method initInvocationChains
+
+ /**
+ * Check that endpoint reference has compatible interface at the component and binding ends.
+ * The user can specify the interfaces at both ends so there is a danger that they won't be compatible.
+ * There is checking in the activator but of course endpoint references may not have a binding assigned
+ * until final resolution.
+ */
+ public void validateReferenceInterfaceCompatibility() {
+
+ InterfaceContract referenceContract = getComponentReferenceInterfaceContract();
+ InterfaceContract bindingContract = getBindingInterfaceContract();
+
+ if ((referenceContract != null) &&
+ (bindingContract != null)){
+
+ boolean bindingHasCallback = bindingContract.getCallbackInterface() != null;
+
+ try {
+ // Use the normalized contract if the interface types are different or if
+ // a normalized contract has been previously generate, for example, by virtue
+ // of finding a JAXWS annotation on a Java class that references a WSDL file
+ if (referenceContract.getClass() != bindingContract.getClass() ||
+ referenceContract.getNormalizedWSDLContract() != null ||
+ bindingContract.getNormalizedWSDLContract() != null) {
+ interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(referenceContract),
+ getGeneratedWSDLContract(bindingContract),
+ Compatibility.SUBSET,
+ !bindingHasCallback, // ignore callbacks if binding doesn't have one
+ false);
+ } else {
+ interfaceContractMapper.checkCompatibility(referenceContract,
+ bindingContract,
+ Compatibility.SUBSET,
+ !bindingHasCallback, // ignore callbacks if binding doesn't have one
+ false);
+ }
+ } catch (Exception ex){
+ throw new ServiceRuntimeException("Component " +
+ this.getComponent().getName() +
+ " Reference " +
+ getReference().getName() +
+ " interface is incompatible with the interface of the reference binding " +
+ getBinding().getName() +
+ " - " +
+ ex.getMessage() +
+ " - [" + this.toString() + "]");
+ }
+ }
+ }
+
+ /**
+ * This code used to be in the activator but has moved here as
+ * the endpoint reference may not now be resolved until the wire
+ * is first used
+ */
+ private void resolveEndpointReference() {
+ resolve();
+
+ eprBinder.bindRunTime(domainRegistry, this);
+
+ // start the binding provider
+ final ReferenceBindingProvider bindingProvider = getBindingProvider();
+
+ 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 (PolicyProvider policyProvider : getPolicyProviders()) {
+ policyProvider.start();
+ }
+
+ started = true;
+
+ Contract ref = getReference();
+ String refName = ref.getName();
+ if (!refName.startsWith("$self$.") && !refName.startsWith("$sca.client$.") && !ref.isForCallback())
+ compositeContext.getEndpointRegistry().addEndpointReference(this);
+
+ // InterfaceContract bindingContract = getBindingInterfaceContract();
+ // endpoint.setInterfaceContract(bindingContract);
+ }
+
+ private void initReferenceBindingInvocationChains() {
+
+ // add the binding interceptors to the reference binding wire
+ ReferenceBindingProvider provider = getBindingProvider();
+ if ((provider != null) && (provider instanceof EndpointReferenceProvider)) {
+ ((EndpointReferenceProvider)provider).configure();
+ }
+
+ // add the policy interceptors to the service binding wire
+ // find out which policies are active
+ for (PolicyProvider p : getPolicyProviders()) {
+ Interceptor interceptor = p.createBindingInterceptor();
+ if (interceptor != null) {
+ bindingInvocationChain.addInterceptor(interceptor);
+ }
+ }
+ }
+
+ 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;
+ invocationChainMap.clear();
+
+ if (getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED){
+ setStatus(EndpointReference.Status.NOT_CONFIGURED);
+ }
+
+ // TODO - cheating here as I fixed the RuntimeComponentService code
+ // to call this when it resets the interface contract
+ //endpointReference.setInterfaceContract(epr.getInterfaceContract());
+ }
+
+ /**
+ * Add the interceptor for a reference binding
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ * @param operation
+ */
+ private void addReferenceBindingInterceptor(InvocationChain chain, Operation operation) {
+ ReferenceBindingProvider provider = getBindingProvider();
+ if (provider != null) {
+ Invoker invoker = provider.createInvoker(operation);
+ if (invoker != null) {
+ chain.addInvoker(invoker);
+ }
+ }
+ List<PolicyProvider> pps = getPolicyProviders();
+ if (pps != null) {
+ for (PolicyProvider p : pps) {
+ Interceptor interceptor = p.createInterceptor(operation);
+ if (interceptor != null) {
+ chain.addInterceptor(interceptor);
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a non-blocking interceptor if the reference binding needs it
+ *
+ * @param reference
+ * @param binding
+ * @param chain
+ */
+ private void addNonBlockingInterceptor(InvocationChain chain) {
+ ReferenceBindingProvider provider = getBindingProvider();
+ if (provider != null) {
+ boolean supportsOneWayInvocation = provider.supportsOneWayInvocation();
+ if (!supportsOneWayInvocation) {
+ chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler));
+ }
+ }
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RuntimeEndpointReferenceImpl copy = (RuntimeEndpointReferenceImpl)super.clone();
+ copy.invoker = new RuntimeInvoker(registry, copy);
+ return copy;
+ }
+
+ public boolean isOutOfDate() {
+ resolve();
+ return bindingURIaltered || eprBinder.isOutOfDate(domainRegistry, this);
+ }
+
+ public synchronized ReferenceBindingProvider getBindingProvider() {
+ resolve();
+ // For the case that binding.sca is implemented by another binding
+ if (binding == null) {
+ return null;
+ }
+ if (bindingProvider == null) {
+ BindingProviderFactory factory =
+ (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass());
+ if (factory == null) {
+ throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding()
+ .getType());
+ }
+ this.bindingProvider = factory.createReferenceBindingProvider(this);
+ }
+ return bindingProvider;
+ }
+
+ public void setBindingProvider(ReferenceBindingProvider bindingProvider) {
+ this.bindingProvider = bindingProvider;
+ }
+
+ public synchronized List<PolicyProvider> getPolicyProviders() {
+ resolve();
+ if (policyProviders == null) {
+ policyProviders = new ArrayList<PolicyProvider>();
+ for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) {
+ PolicyProvider provider = factory.createReferencePolicyProvider(this);
+ if (provider != null) {
+ policyProviders.add(provider);
+ }
+ }
+ }
+ return policyProviders;
+ }
+
+ public void unbind() {
+ bindingInvocationChain = null;
+ chains = null;
+ bindingProvider = null;
+ policyProviders = null;
+ invocationChainMap.clear();
+ }
+
+ public Contract getContract() {
+ return getReference();
+ }
+
+ public CompositeContext getCompositeContext() {
+ return compositeContext;
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ resolve();
+ if (bindingInterfaceContract != null) {
+ return bindingInterfaceContract;
+ }
+ ReferenceBindingProvider provider = getBindingProvider();
+ if (provider != null) {
+ bindingInterfaceContract = provider.getBindingInterfaceContract();
+ }
+ if (bindingInterfaceContract == null) {
+ bindingInterfaceContract = getComponentReferenceInterfaceContract();
+ }
+ if (bindingInterfaceContract == null) {
+ bindingInterfaceContract = getComponentTypeReferenceInterfaceContract();
+ }
+ return bindingInterfaceContract;
+ }
+
+ public InterfaceContract getComponentTypeReferenceInterfaceContract() {
+ resolve();
+ if (referenceInterfaceContract != null) {
+ return referenceInterfaceContract;
+ }
+ if (reference == null) {
+ return getComponentReferenceInterfaceContract();
+ }
+ referenceInterfaceContract = getLeafContract(reference).getInterfaceContract();
+ if (referenceInterfaceContract == null) {
+ referenceInterfaceContract = getComponentReferenceInterfaceContract();
+ }
+ return referenceInterfaceContract;
+ }
+
+ @Override
+ protected synchronized void resolve() {
+ if (xml != null && component == null) {
+ if (compositeContext == null) {
+ compositeContext = CompositeContext.getCurrentCompositeContext();
+ if (compositeContext != null) {
+ bind(compositeContext);
+ }
+ }
+ if (serializer != null) {
+ RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml);
+ copyFrom(epr);
+ } else {
+ // In this case, we assume that we're running on a detached (non Tuscany) thread and
+ // as a result we need to connect back to the Tuscany environment...
+ ExtensionPointRegistry registry = ExtensionPointRegistryLocator.getExtensionPointRegistry();
+ if( registry != null ) {
+ this.registry = registry;
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.serializer = utilities.getUtility(EndpointSerializer.class);
+ RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml);
+ // Find the actual Endpoint in the DomainRegistry
+ epr = findActualEPR( epr, registry );
+ if( epr != null ){
+ copyFrom( epr );
+ } // end if
+ } // end if
+ } // end if
+ }
+ super.resolve();
+ } // end method resolve
+
+ /**
+ * Find the actual EndpointReference in the DomainRegistry which corresponds to the configuration described
+ * in a deserialized EndpointReference
+ * @param ep The deserialized endpointReference
+ * @param registry - the main extension point Registry
+ * @return the corresponding EndpointReference from the DomainRegistry, or null if no match can be found
+ */
+ private RuntimeEndpointReferenceImpl findActualEPR(RuntimeEndpointReferenceImpl epr,
+ ExtensionPointRegistry registry) {
+ // Get the DomainRegistry
+ DomainRegistryFactory domainRegistryFactory = ExtensibleDomainRegistryFactory.getInstance(registry);
+ if( domainRegistryFactory == null ) return null;
+
+ // TODO: For the moment, just use the first (and only!) DomainRegistry...
+ DomainRegistry domainRegistry = (DomainRegistry) domainRegistryFactory.getEndpointRegistries().toArray()[0];
+ if( domainRegistry == null ) return null;
+
+ for( EndpointReference epReference : domainRegistry.getEndpointReferences() ) {
+ // TODO: For the present, simply return the first matching endpointReference
+ if( epReference.getURI().equals(epr.getURI()) ) {
+ return (RuntimeEndpointReferenceImpl) epReference;
+ } // end if
+ } // end for
+
+ return null;
+ } // end method findActualEPR
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ this.uri = in.readUTF();
+ this.xml = in.readUTF();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeUTF(getURI());
+ if (serializer == null && xml != null) {
+ out.writeUTF(xml);
+ } else {
+ if (serializer != null) {
+ out.writeUTF(serializer.write(this));
+ } else {
+ throw new IllegalStateException("No serializer is configured");
+ }
+ }
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) {
+
+ if ( interfaceContract.getNormalizedWSDLContract() == null){
+ if (getComponentReferenceInterfaceContract() instanceof JavaInterfaceContract){
+ if (contractBuilder == null){
+ throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString());
+ }
+ contractBuilder.build(interfaceContract, null);
+ }
+ }
+
+ return interfaceContract.getNormalizedWSDLContract();
+ }
+
+ public void createAsyncCallbackEndpoint(){
+ CompositeContext compositeContext = getCompositeContext();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ RuntimeAssemblyFactory assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
+
+ RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
+ endpoint.bind(compositeContext);
+ endpoint.setComponent(getComponent());
+
+ // Create pseudo-service
+ ComponentService service = assemblyFactory.createComponentService();
+ JavaInterfaceFactory javaInterfaceFactory =
+ (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class);
+ JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ try {
+ interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseService.class));
+ } catch (InvalidInterfaceException e1) {
+ // Nothing to do here - will not happen
+ } // end try
+
+ service.setInterfaceContract(interfaceContract);
+
+ String serviceName = getReference().getName() + "_asyncCallback";
+ service.setName(serviceName);
+ service.getEndpoints().add(endpoint);
+ service.setForCallback(true);
+ endpoint.setService(service);
+
+ // Set pseudo-service onto the component
+ getComponent().getServices().add(service);
+
+ // if the reference has a WSDL contract reset the response endpoint to be WSDL also
+ InterfaceContract referenceInterfaceContract = getComponentTypeReferenceInterfaceContract();
+ if (referenceInterfaceContract instanceof WSDLInterfaceContract){
+ WSDLInterfaceContract wsdlInterfaceContract = (WSDLInterfaceContract)endpoint.getGeneratedWSDLContract(interfaceContract);
+ service.setInterfaceContract(wsdlInterfaceContract);
+ }
+
+ // Create a binding
+ // Mike had to go via the XML but I don't remember why
+ Binding binding = null;
+ try {
+ binding = (Binding)getBinding().clone();
+ } catch (Exception ex){
+ //
+ }
+ String callbackURI = "/" + component.getName() + "/" + service.getName();
+ binding.setURI(callbackURI);
+
+ BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ BindingBuilder builder = builders.getBindingBuilder(binding.getType());
+ if (builder != null) {
+ org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
+ builder.build(component, service, binding, builderContext, true);
+ } // end if
+
+ endpoint.setBinding(binding);
+
+ // Need to establish policies here (binding has some...)
+ endpoint.getRequiredIntents().addAll(getRequiredIntents());
+ endpoint.getPolicySets().addAll(getPolicySets());
+ String epURI = getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")";
+ endpoint.setURI(epURI);
+ endpoint.setUnresolved(false);
+
+ setCallbackEndpoint(endpoint);
+ }
+
+ @Override
+ public RuntimeEndpointReference getDelegateEndpointReference() {
+ return delegateEndpointReference;
+ }
+
+ @Override
+ public void setDelegateEndpointReference(RuntimeEndpointReference delegateEndpointReference) {
+ this.delegateEndpointReference = delegateEndpointReference;
+ }
+
+ /**
+ * Gets the async response invoker for an asynchronous invocation.
+ */
+ public InvokerAsyncResponse getAsyncResponseInvoker(Operation op) {
+ InvocationChain chain = getInvocationChain(op);
+ Invoker headInvoker = chain.getHeadInvoker();
+ if( headInvoker instanceof InterceptorAsync ) {
+ InvokerAsyncResponse responseInvoker = ((InterceptorAsync)headInvoker).getPrevious();
+ return responseInvoker;
+ }
+ return null;
+ }
+
+ public void setBindingURI(String uri) {
+ binding.setURI(uri);
+ bindingURIaltered = true;
+ BindingBuilder builder = builders.getBindingBuilder(binding.getType());
+ if (builder != null) {
+ BuilderContext builderContext = new BuilderContext(null, null, null);
+ builder.build(component, reference, binding, builderContext, true);
+ }
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/WSDLHelper.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/WSDLHelper.java
new file mode 100644
index 0000000000..c677b99b93
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/WSDLHelper.java
@@ -0,0 +1,514 @@
+/*
+ * 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.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.wsdl.Definition;
+import javax.wsdl.PortType;
+import javax.wsdl.Types;
+import javax.wsdl.WSDLException;
+import javax.wsdl.extensions.ExtensibilityElement;
+import javax.wsdl.extensions.UnknownExtensibilityElement;
+import javax.wsdl.extensions.schema.Schema;
+import javax.wsdl.xml.WSDLLocator;
+import javax.wsdl.xml.WSDLReader;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
+import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract;
+import org.apache.tuscany.sca.xsd.XSDFactory;
+import org.apache.tuscany.sca.xsd.XSDefinition;
+import org.apache.tuscany.sca.xsd.xml.XSDModelResolver;
+import org.apache.ws.commons.schema.XmlSchema;
+import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.resolver.DefaultURIResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+public class WSDLHelper {
+
+ /**
+ * This creates a WSDLInterfaceContract from a WSDL document
+ * TODO: Presently this writes the wsdl string to a temporary file which is then used by the Tuscany contribution
+ * code to turn the wsdl into the correctly populated Tuscany model objects. There must/should be a way to have
+ * that happen without needing the external file but i've not been able to find the correct configuration to
+ * get that to happen with all the schema objects created correctly.
+ */
+/*
+ public static WSDLInterfaceContract createWSDLInterfaceContractViaFile(ExtensionPointRegistry registry, String wsdl) {
+ File wsdlFile = null;
+ try {
+
+ wsdlFile = writeToFile(wsdl);
+ System.out.println("wsdl: " + wsdlFile);
+
+ FactoryExtensionPoint fep = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ URLArtifactProcessorExtensionPoint apep = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class);
+ ExtensibleURLArtifactProcessor aproc = new ExtensibleURLArtifactProcessor(apep);
+ ProcessorContext ctx = new ProcessorContext();
+
+ ContributionFactory cf = fep.getFactory(ContributionFactory.class);
+ final Contribution c = cf.createContribution();
+ c.setURI("temp");
+ c.setLocation(wsdlFile.toURI().toURL().toString());
+ c.setModelResolver(new ExtensibleModelResolver(c, registry.getExtensionPoint(ModelResolverExtensionPoint.class), fep));
+
+ WSDLDefinition wd = aproc.read(null, new URI("temp.wsdl"), wsdlFile.toURI().toURL(), ctx, WSDLDefinition.class);
+ c.getModelResolver().addModel(wd, ctx);
+ c.getModelResolver().resolveModel(WSDLDefinition.class, wd, ctx);
+ PortType pt = (PortType)wd.getDefinition().getAllPortTypes().values().iterator().next();
+
+ WSDLFactory wsdlFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(WSDLFactory.class);
+ WSDLInterface nwi = wsdlFactory.createWSDLInterface(pt, wd, c.getModelResolver(), null);
+ nwi.setWsdlDefinition(wd);
+ WSDLInterfaceContract wsdlIC = wsdlFactory.createWSDLInterfaceContract();
+ wsdlIC.setInterface(nwi);
+
+ wsdlFile.delete();
+
+ return wsdlIC;
+
+// } catch (InvalidWSDLException e) {
+// //* TODO: Also, this doesn't seem to work reliably and sometimes the schema objects don't get built correctly
+// //* org.apache.tuscany.sca.interfacedef.wsdl.impl.InvalidWSDLException: Element cannot be resolved: {http://sample/}sayHello
+// //* at org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLOperationIntrospectorImpl$WSDLPart.<init>(WSDLOperationIntrospectorImpl.java:276)
+// //* It seems like it works ok for me with IBM JDK but not with a Sun one
+// // I'm still trying to track this down but committing like this to see if anyone has any ideas
+// e.printStackTrace();
+// return null;
+
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (wsdlFile != null) {
+ wsdlFile.delete();
+ }
+ }
+ }
+
+ private static File writeToFile(String wsdl) throws FileNotFoundException, IOException {
+ File f = File.createTempFile("endpoint", ".wsdl");
+ Writer out = new OutputStreamWriter(new FileOutputStream(f));
+ try {
+ out.write(wsdl);
+ }
+ finally {
+ out.close();
+ }
+ return f;
+ }
+*/
+
+ /*
+ * A rework of the above code that
+ *
+ * 1 - doesn't use a intermediate file
+ * 2 - doesn't use the Tuscany contribution code
+ * 3 - takes care of imports/includes
+ * 4 - takes care of call and callback interfaces
+ *
+ * Re. point 1 - In theory it's neater but the Tuscany processors/resolvers don't know how to do this
+ * so there is quite a bit of code here. I don't really like it but we can sleep on it
+ * and look at how to integrate it into the runtime or even take a different approach to
+ * moving the interface about
+ */
+ public static WSDLInterfaceContract createWSDLInterfaceContract(ExtensionPointRegistry registry, String wsdl, String wsdlCallback) {
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory wsdlFactory = modelFactories.getFactory(org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory.class);
+
+ WSDLInterfaceContract wsdlInterfaceContract = wsdlFactory.createWSDLInterfaceContract();
+ wsdlInterfaceContract.setInterface(createWSDLInterface(registry, wsdl));
+ if (wsdlCallback != null && wsdlCallback.length() > 0){
+ wsdlInterfaceContract.setCallbackInterface(createWSDLInterface(registry, wsdlCallback));
+ }
+
+ return wsdlInterfaceContract;
+ }
+
+ /**
+ * Read a single WSDL interface and it's associated XSD from a string
+ *
+ * @param registry
+ * @param wsdl
+ * @return
+ */
+ public static WSDLInterface createWSDLInterface(ExtensionPointRegistry registry, String wsdl) {
+ try {
+ // Read all the WSDL and XSD in from the wsdl string. The WSDL and XSD appear sequentially in
+ // the following format:
+ //
+ // filename
+ // _X_
+ // wsdl xml
+ // _X_
+ // xsd xml
+ // _X_
+ // xsd xml
+ //
+ // So we need to read each WSDL and XSD separately and then fix up the includes/imports as appropriate
+ String xmlArray[] = wsdl.split("_X_");
+
+ String topWSDLLocation = null;
+ Map<String, XMLString> xmlMap = new HashMap<String, XMLString>();
+
+ for (int i = 0; i < xmlArray.length; i = i + 2){
+ String location = xmlArray[i];
+ String xml = xmlArray[i+1];
+ // strip the file name out of the location
+ location = location.substring(location.lastIndexOf("/") + 1);
+
+ if (location.endsWith(".wsdl")){
+ xmlMap.put(location,
+ new WSDLInfo(xmlArray[i],
+ xml));
+
+ if (topWSDLLocation == null){
+ topWSDLLocation = location;
+ }
+ } else {
+ xmlMap.put(location,
+ new XSDInfo(xmlArray[i],
+ xml));
+ }
+ }
+
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory wsdlFactory = modelFactories.getFactory(org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory.class);
+ XSDFactory xsdFactory = modelFactories.getFactory(XSDFactory.class);
+ XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
+ schemaCollection.setSchemaResolver(new XSDURIResolverImpl(xmlMap));
+ ContributionFactory contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ final org.apache.tuscany.sca.contribution.Contribution contribution = contributionFactory.createContribution();
+ ProcessorContext processorContext = new ProcessorContext();
+
+ ExtensibleModelResolver extensibleResolver = new ExtensibleModelResolver(contribution, registry.getExtensionPoint(ModelResolverExtensionPoint.class), modelFactories);
+ ModelResolver wsdlResolver = (ModelResolver)extensibleResolver.getModelResolverInstance(WSDLDefinition.class);
+ XSDModelResolver xsdResolver = (XSDModelResolver)extensibleResolver.getModelResolverInstance(XSDefinition.class);
+ contribution.setURI("temp");
+ contribution.setLocation(topWSDLLocation);
+ contribution.setModelResolver(extensibleResolver);
+
+ // read
+ for (XMLString xmlString : xmlMap.values()){
+ if (xmlString instanceof WSDLInfo){
+ WSDLReader reader;
+ try {
+ reader = AccessController.doPrivileged(new PrivilegedExceptionAction<WSDLReader>() {
+ public WSDLReader run() throws WSDLException {
+ return javax.wsdl.factory.WSDLFactory.newInstance().newWSDLReader();
+ }
+ });
+ } catch (PrivilegedActionException e){
+ throw (WSDLException)e.getException();
+ }
+ reader.setFeature("javax.wsdl.verbose", false);
+ reader.setFeature("javax.wsdl.importDocuments", true);
+ final WSDLLocatorImpl locator = new WSDLLocatorImpl(xmlString.getBaseURI(), xmlMap);
+ final WSDLReader freader = reader;
+ Definition readDefinition;
+ try {
+ readDefinition = AccessController.doPrivileged(new PrivilegedExceptionAction<Definition>() {
+ public Definition run() throws WSDLException {
+ return freader.readWSDL(locator);
+ }
+ });
+ } catch (PrivilegedActionException e){
+ throw (WSDLException)e.getException();
+ }
+
+ WSDLDefinition wsdlDefinition = wsdlFactory.createWSDLDefinition();
+ wsdlDefinition.setDefinition(readDefinition);
+ wsdlDefinition.setLocation(new URI(xmlString.getBaseURI()));
+
+ ((WSDLInfo)xmlString).setWsdlDefintion(wsdlDefinition);
+ wsdlResolver.addModel(wsdlDefinition, processorContext);
+
+ } else {
+ InputStream inputStream = new ByteArrayInputStream(xmlString.getXmlString().getBytes());
+ InputSource inputSource = new InputSource(inputStream);
+ inputSource.setSystemId(xmlString.getBaseURI());
+ XmlSchema schema = schemaCollection.read(inputSource, null);
+ inputStream.close();
+
+ XSDefinition xsdDefinition = xsdFactory.createXSDefinition();
+ xsdDefinition.setSchema(schema);
+
+ ((XSDInfo)xmlString).setXsdDefinition(xsdDefinition);
+ xsdResolver.addModel(xsdDefinition, processorContext);
+ }
+ }
+
+ // resolve
+ for (XMLString xmlString : xmlMap.values()){
+ if (xmlString instanceof WSDLInfo){
+ WSDLDefinition wsdlDefinition = ((WSDLInfo)xmlString).getWsdlDefintion();
+
+ // link to imports
+ for (Map.Entry<String, List<javax.wsdl.Import>> entry :
+ ((Map<String, List<javax.wsdl.Import>>)wsdlDefinition.getDefinition().getImports()).entrySet()) {
+ for (javax.wsdl.Import imp : entry.getValue()) {
+ String wsdlName = imp.getDefinition().getDocumentBaseURI();
+ WSDLInfo wsdlInfo = (WSDLInfo)xmlMap.get(getFilenameWithoutPath(wsdlName));
+ wsdlDefinition.getImportedDefinitions().add(wsdlInfo.getWsdlDefintion());
+ }
+ }
+
+ // extract any in-line types in the Tuscany model
+ Types types = wsdlDefinition.getDefinition().getTypes();
+ if ( types != null){
+/* read XSD from WSDL rather than from registry
+ for (int i=0; i < types.getExtensibilityElements().size(); i++){
+
+ String schemaName = xmlString.getBaseURI() + "#" + i++;
+ XSDInfo xsdInfo = (XSDInfo)xmlMap.get(getFilenameWithoutPath(schemaName));
+ if (xsdInfo != null){
+ wsdlDefinition.getXmlSchemas().add(xsdInfo.getXsdDefinition());
+ }
+*/
+ int index = 0;
+ for (Object ext : types.getExtensibilityElements()) {
+ ExtensibilityElement extElement = (ExtensibilityElement)ext;
+ Element element = null;
+ if (extElement instanceof Schema) {
+ element = ((Schema)extElement).getElement();
+ }
+ if (element != null) {
+ XSDefinition xsDefinition = xsdFactory.createXSDefinition();
+ xsDefinition.setUnresolved(true);
+ xsDefinition.setNamespace(element.getAttribute("targetNamespace"));
+ xsDefinition.setDocument(element.getOwnerDocument());
+ XmlSchema schema = schemaCollection.read(element, null);
+ xsDefinition.setSchema(schema);
+ xsDefinition.setLocation(URI.create(xmlString.getBaseURI() + "#" + index));
+ wsdlDefinition.getXmlSchemas().add(xsDefinition);
+ index++;
+ }
+ }
+ }
+ } else {
+ // TODO
+ }
+ }
+
+ WSDLInfo topWSDL = (WSDLInfo)xmlMap.get(topWSDLLocation);
+ WSDLDefinition topWSDLDefinition = topWSDL.getWsdlDefintion();
+
+ PortType portType = (PortType)topWSDLDefinition.getDefinition().getAllPortTypes().values().iterator().next();
+ WSDLInterface readWSDLInterface = wsdlFactory.createWSDLInterface(portType, topWSDLDefinition, extensibleResolver, null);
+
+ return readWSDLInterface;
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /*
+ * WSDL is provided in the following string form:
+ *
+ * _X_
+ * the_original_path_to_a_wsdl_file
+ * _X_
+ * the WSDL XML
+ * _X_
+ * the_original_path_to_a_related_xsd_file
+ * _X_
+ * the XSD XML
+ * etc.
+ *
+ * This structure, and the classes that specialize it, represent this format in memory
+ */
+ private static class XMLString {
+ private String baseURI;
+ private String xmlString;
+
+ public XMLString(String baseURI, String xmlString){
+ this.baseURI = baseURI;
+ this.xmlString = xmlString;
+ }
+
+ public String getBaseURI() {
+ return baseURI;
+ }
+
+ public String getXmlString() {
+ return xmlString;
+ }
+ }
+
+ private static class XSDInfo extends XMLString {
+
+ XSDefinition xsdDefinition;
+
+ public XSDInfo(String baseURI, String xmlString) {
+ super(baseURI, xmlString);
+ }
+
+ public void setXsdDefinition(XSDefinition xsdDefinition) {
+ this.xsdDefinition = xsdDefinition;
+ }
+
+ public XSDefinition getXsdDefinition() {
+ return xsdDefinition;
+ }
+ }
+
+ private static class WSDLInfo extends XMLString {
+
+ WSDLDefinition wsdlDefintion;
+
+ public WSDLInfo(String baseURI, String xmlString) {
+ super(baseURI, xmlString);
+ }
+
+ public void setWsdlDefintion(WSDLDefinition wsdlDefintion) {
+ this.wsdlDefintion = wsdlDefintion;
+ }
+
+ public WSDLDefinition getWsdlDefintion() {
+ return wsdlDefintion;
+ }
+ }
+
+ /*
+ * A WSDL locator used to find WSDL in memory based on the map
+ * of all WSDL/XSD that have been read from the input string
+ */
+ private static class WSDLLocatorImpl implements WSDLLocator {
+ private Map<String, XMLString> xmlMap;
+ private String baseURI;
+ private String latestImportURI;
+
+ public WSDLLocatorImpl(String baseURI, Map<String, XMLString> xmlMap) {
+ this.baseURI = baseURI;
+ this.xmlMap = xmlMap;
+ }
+
+ public void close() {
+/*
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+*/
+ }
+
+ public InputSource getBaseInputSource() {
+ return getInputSource(getFilenameWithoutPath(baseURI), xmlMap);
+ }
+
+ public String getBaseURI() {
+ return baseURI;
+ }
+
+ public InputSource getImportInputSource(String parentLocation, String importLocation) {
+ latestImportURI = importLocation;
+ return getInputSource(getFilenameWithoutPath(importLocation), xmlMap);
+ }
+
+ public String getLatestImportURI() {
+ return latestImportURI;
+ }
+ }
+
+ /*
+ * A local URIResolver used to find XSD in memory based on the map
+ * of all WSDL/XSD that have been read from the input string
+ */
+ private static class XSDURIResolverImpl extends DefaultURIResolver {
+
+ private Map<String, XMLString> xmlMap;
+
+ public XSDURIResolverImpl(Map<String, XMLString> xmlMap) {
+ this.xmlMap = xmlMap;
+ }
+
+ @Override
+ protected URL getURL(URL contextURL, String spec) throws IOException {
+ return super.getURL(contextURL, spec);
+ }
+ @Override
+ public InputSource resolveEntity(String namespace,
+ String schemaLocation,
+ String baseUri) {
+ return getInputSource(getFilenameWithoutPath(schemaLocation), xmlMap);
+ }
+ }
+
+ /*
+ * Retrieve the input source for the given URI
+ */
+ private static InputSource getInputSource(String uri, Map<String, XMLString> xmlMap){
+ String xmlString = xmlMap.get(uri).getXmlString();
+ InputStream inputStream = new ByteArrayInputStream(xmlString.getBytes());
+ InputSource inputSource = new InputSource(inputStream);
+ inputSource.setSystemId(uri);
+ return inputSource;
+ }
+
+ /*
+ * Remove path from filename so that XSD/WSDL data can be found in memory
+ * rather than on the remote file system
+ */
+ private static String getFilenameWithoutPath(String filename){
+ // work out what the file name is that is being imported
+ // XSDs imports are written out by Tuscany with an relative web address such as
+ // /services/AccountService?xsd=wsdl-serialize.xsd
+ // for the time being just string the file name off the end. We are making
+ // assumption that the interface doesn't involve two files with the same
+ // name in different locations
+ int xsdIndex = filename.lastIndexOf("?xsd=");
+ int wsdlIndex = filename.lastIndexOf("/");
+ if ( xsdIndex >= 0){
+ return filename.substring(xsdIndex + 5);
+ } else {
+ return filename.substring(wsdlIndex + 1);
+ }
+ // What happens with generated WSDL?
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java
new file mode 100644
index 0000000000..d2528784fd
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java
@@ -0,0 +1,72 @@
+/*
+ * 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.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.context.ComponentContextFactory;
+import org.apache.tuscany.sca.context.CompositeContext;
+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.context.impl.ComponentContextImpl;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.runtime.CompositeActivator;
+import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.oasisopen.sca.ComponentContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DefaultComponentContextFactory implements ComponentContextFactory {
+ private final ExtensionPointRegistry registry;
+ private AssemblyFactory assemblyFactory;
+ private JavaInterfaceFactory javaInterfaceFactory;
+ private CompositeActivator compositeActivator;
+ private RequestContextFactory requestContextFactory;
+ private PropertyValueFactory propertyFactory;
+ private EndpointReferenceBinder eprBinder;
+ private ExtensibleProxyFactory proxyFactory;
+
+ public DefaultComponentContextFactory(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
+ this.compositeActivator = utilities.getUtility(CompositeActivator.class);
+ this.requestContextFactory =
+ registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class);
+ this.propertyFactory = factories.getFactory(PropertyValueFactory.class);
+ this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class);
+ this.proxyFactory = ExtensibleProxyFactory.getInstance(registry);
+ }
+
+ public ComponentContext createComponentContext(CompositeContext compositeContext, RuntimeComponent component) {
+ return new ComponentContextImpl(registry, assemblyFactory, javaInterfaceFactory, compositeActivator,
+ requestContextFactory, propertyFactory, eprBinder, proxyFactory,
+ compositeContext, component);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java
new file mode 100644
index 0000000000..ace4dc48e1
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java
new file mode 100644
index 0000000000..5856ab114b
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.runtime.TuscanyServiceReference;
+
+/**
+ * Extended ServiceReference
+ */
+public interface ServiceReferenceExt<B> extends TuscanyServiceReference<B>, Externalizable {
+
+ /**
+ * Return the EndpointReference that sits behind this service reference
+ * @return endpoint reference
+ */
+ RuntimeEndpointReference getEndpointReference();
+
+ B getProxy();
+ void setProxy(B proxy);
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java
new file mode 100644
index 0000000000..4c206ec5db
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java
@@ -0,0 +1,292 @@
+/*
+ * 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 java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.SCABinding;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+import org.apache.tuscany.sca.core.invocation.CallbackHandler;
+import org.apache.tuscany.sca.core.invocation.Constants;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Represent the reference to the callback service. This class basically wraps a Tuscany EndpointReference.
+ * The callback EPR is selected based on the are 3 basic scenarios we are trying to cater for
+ *
+ * A/ <component name="MyComponent">
+ * <service name="MyService>
+ * blank OR <binding.sca/>
+ * </service>
+ * </component>
+ *
+ * B/ <component name="MyComponent">
+ * <service name="MyService>
+ * <binding.someremotebinding/>
+ * </service>
+ * </component>
+ *
+ * C/ <component name="MyComponent">
+ * <service name="MyService>
+ * some binding
+ * <callback>
+ * <binding.someremotebinding/>
+ * </callback>
+ * </service>
+ * </component>
+ *
+ * A - the callback binding will default to binding.sca and the expectation is that
+ * the callback endpoint will be established by looking it up in the registry
+ * hence the forward call must contain the SCA target name referring to the
+ * callback service
+ *
+ * B - the callback binding defaults to be the forward binding taking all of its
+ * configuration. The callback target URI is taken from the forward message and
+ * put into the callback binding URI
+ *
+ * C - the callback binding is as specified by the user. If the user has not specified
+ * a binding URI then the URI from the forward message will be placed in the
+ * callback binding URI. This may or may not lead to happiness depending on whether
+ * the forward and callback bindings are compatible
+ *
+ * The callback proxy, and this class, is instantiated whenever a new callback proxy is
+ * required as follows:
+ *
+ * If the service component implementation is STATELESS then each incoming message
+ * creates a new service instance and hence a new set of callback proxies
+ *
+ * If the service component implementation is COMPOSITE then only a single instance
+ * of the component implementation will exist and the callback proxy will be retrieved
+ * via the RequestContext.
+ *
+ * Following the Tuscany runtime model for normal references we don't cache callback
+ * proxies across component implementation instances. Hence there will be one
+ * instance of this class for each callback proxy, however created, and the class
+ * will refer to a single callback service. To put it another way, messages from
+ * multiple clients (presenting different callback services) will be called back to
+ * via different callback proxies and hence a single instance of this class will
+ * not be required to handle more than one callback address.
+ *
+ */
+public class CallbackServiceReferenceImpl<B> extends ServiceReferenceImpl<B> {
+ private static final Logger logger = Logger.getLogger(CallbackServiceReferenceImpl.class.getName());
+ private RuntimeEndpointReference callbackEPR;
+ private List<? extends EndpointReference> callbackEPRs;
+ private Endpoint resolvedEndpoint;
+ // Holds the ID of the Message that caused the creation of this CallbackServiceReference
+ private String msgID;
+
+ // Holds the URI of the target callback service from the Message that caused the
+ // creation of this CallbackServiceReference
+ private CallbackHandler callbackHandler;
+
+ /*
+ * Public constructor for Externalizable serialization/deserialization
+ * TODO - we need to serialize the msgID and callbackURI
+ */
+ public CallbackServiceReferenceImpl() {
+ super();
+ }
+
+ public CallbackServiceReferenceImpl(Class<B> interfaze,
+ List<? extends EndpointReference> callbackEPRs) {
+ super(interfaze, null, getCompositeContext(callbackEPRs));
+ this.callbackEPRs = callbackEPRs;
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ // Capture the Message ID from the message which caused the creation of this
+ // CallBackServiceReference
+ this.msgID = (String) msgContext.getHeaders().get(Constants.MESSAGE_ID);
+
+ // Capture the callback URI from the message which caused the creation of this
+ // CallBackServiceReference. This code is more complex that needs be for the time being
+ // to cater for bindings that still use the approach of constructing a callback endpoint
+ // to model the callback URI. With these changes the binding can just set a CallbackHandler
+ // in the forward message to get the same effect. Some bindings don't do that hence
+ // the various checks
+ this.resolvedEndpoint = null;
+
+ if (msgContext.getFrom() != null){
+ resolvedEndpoint = msgContext.getFrom().getCallbackEndpoint();
+ }
+
+ if (resolvedEndpoint != null){
+ if (resolvedEndpoint.getBinding() == null){
+ this.callbackHandler = new CallbackHandler(resolvedEndpoint.getURI());
+ } else if (resolvedEndpoint.getBinding().getType().equals(SCABinding.TYPE)){
+ this.callbackHandler = new CallbackHandler(resolvedEndpoint.getURI());
+ } else {
+ this.callbackHandler = new CallbackHandler(resolvedEndpoint.getBinding().getURI());
+ }
+ } else {
+ this.callbackHandler = (CallbackHandler)msgContext.getHeaders().get(Constants.CALLBACK);
+
+ if (callbackHandler == null){
+ this.callbackHandler = new CallbackHandler(null);
+ }
+ }
+
+ if (callbackHandler.getCallbackTargetURI() != null){
+ logger.log(Level.FINE, "Selecting callback EPR using address from forward message: " + callbackHandler.getCallbackTargetURI());
+ } else {
+ logger.log(Level.FINE, "Selecting callback EPR using address but callback URI is null");
+ }
+
+ // Work out which callback EPR to use
+ callbackEPR = selectCallbackEPR(msgContext);
+ if (callbackEPR == null) {
+ throw new ServiceRuntimeException("No callback binding found for " + msgContext.getTo().toString());
+ }
+
+ // configure the callback EPR with the callback address
+ if (callbackHandler.getCallbackTargetURI() != null) {
+ callbackEPR = setCallbackAddress(callbackEPR);
+ }
+
+ this.resolvedEndpoint = callbackEPR.getTargetEndpoint();
+ }
+
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ /**
+ * Gets the message ID associated with this callback reference. All calls through the proxy backed by
+ * this CallbackServiceReference will use the same msgID
+ *
+ * @return the message ID
+ */
+ public String getMsgID() {
+ return msgID;
+ }
+
+
+ private static CompositeContext getCompositeContext(List<? extends EndpointReference> callbackEPRs) {
+ if(!callbackEPRs.isEmpty()) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference) callbackEPRs.get(0);
+ return epr.getCompositeContext();
+ }
+ return null;
+ }
+
+ @Override
+ protected B createProxy() throws Exception {
+ return proxyFactory.createCallbackProxy(this);
+ }
+
+ public RuntimeEndpointReference getCallbackEPR() {
+ return callbackEPR;
+ }
+
+ public Endpoint getResolvedEndpoint() {
+ return resolvedEndpoint;
+ }
+
+ private RuntimeEndpointReference selectCallbackEPR(Message msgContext) {
+
+ // look for callback binding with same name as service binding
+ Endpoint to = msgContext.getTo();
+ if (to == null) {
+ //FIXME: need better exception
+ throw new ServiceRuntimeException("Destination for forward call is not available");
+ }
+ for (EndpointReference epr : callbackEPRs) {
+ if (epr.getBinding().getName().equals(to.getBinding().getName())) {
+ return (RuntimeEndpointReference) epr;
+ }
+ }
+
+ // if no match, look for callback binding with same type as service binding
+ for (EndpointReference epr : callbackEPRs) {
+ if (epr.getBinding().getType().equals(to.getBinding().getType())) {
+ return (RuntimeEndpointReference) epr;
+ }
+ }
+
+ // no suitable callback wire was found
+ return null;
+ }
+
+ private RuntimeEndpointReference setCallbackAddress(RuntimeEndpointReference endpointReference) {
+ try {
+
+ RuntimeEndpointReference epr = endpointReference;
+
+ if (callbackHandler.getCloneCallbackWire()){
+ epr = (RuntimeEndpointReference)endpointReference.clone();
+ }
+
+ // TUSCANY-3932
+ // If it's the default binding then we're going to look the callback endpoint
+ // up in the registry. Most remote protocols, which may be used as delegates
+ // for binding.sca, will expect to deal with absolute URLs so flip the
+ // callback endpoint back to force the lookup to happen
+ if (epr.getBinding().getType().equals(SCABinding.TYPE)){
+ // A/ create a callback endpoint to allow the
+ // callback lookup to take place
+ epr.setStatus(EndpointReference.Status.WIRED_TARGET_NOT_FOUND);
+
+ // if an endpoint it provided in the forward message use it or
+ // if not create one
+ if (resolvedEndpoint == null ){
+ RuntimeEndpoint callbackEndpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
+ callbackEndpoint.setURI(callbackHandler.getCallbackTargetURI());
+ callbackEndpoint.setUnresolved(true);
+ epr.setTargetEndpoint(callbackEndpoint);
+ } else {
+ epr.setTargetEndpoint(resolvedEndpoint);
+ }
+ } else {
+ // B/ and C/ assume that the callback EPR is already resolved
+ // and set the binding URI if one is provided with the
+ // forward message. Some bindings may want to do other
+ // things to determine the callback URI to the
+ // CallbackHandler will be sent in the callback message
+ // header. This is particularly true if the clone isn't
+ // called above because resetting the URI will not
+ // be thread safe.
+ epr.setStatus(EndpointReference.Status.RESOLVED_BINDING);
+
+ if ( callbackHandler.getCallbackTargetURI() != null ){
+ epr.getBinding().setURI(callbackHandler.getCallbackTargetURI());
+ } else {
+ // do nothing and rely on whatever the user has configured
+ // in the SCDL
+ }
+ }
+
+ return epr;
+ } catch (CloneNotSupportedException e) {
+ // will not happen
+ throw new ServiceRuntimeException(e);
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java
new file mode 100644
index 0000000000..18587b2f6d
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java
@@ -0,0 +1,558 @@
+/*
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+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.CompositeService;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.SCABinding;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.context.CompositeContext;
+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.invocation.ProxyFactory;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.runtime.CompositeActivator;
+import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
+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.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.runtime.TuscanyServiceReference;
+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 RuntimeComponentContext {
+ private final RuntimeComponent component;
+
+ private final CompositeContext compositeContext;
+ 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 EndpointReferenceBinder eprBinder;
+ private final ExtensionPointRegistry registry;
+
+ public ComponentContextImpl(ExtensionPointRegistry registry,
+ AssemblyFactory assemblyFactory,
+ JavaInterfaceFactory javaInterfaceFactory,
+ CompositeActivator compositeActivator,
+ RequestContextFactory requestContextFactory,
+ PropertyValueFactory propertyFactory,
+ EndpointReferenceBinder eprBinder,
+ ProxyFactory proxyFactory,
+ CompositeContext compositeContext,
+ RuntimeComponent component) {
+ this.registry = registry;
+ this.assemblyFactory = assemblyFactory;
+ this.javaInterfaceFactory = javaInterfaceFactory;
+ this.compositeActivator = compositeActivator;
+ this.requestContextFactory = requestContextFactory;
+ this.propertyFactory = propertyFactory;
+ this.eprBinder = eprBinder;
+ this.proxyFactory = proxyFactory;
+ this.compositeContext = compositeContext;
+ this.component = component;
+ }
+
+ public String getURI() {
+ return component.getURI();
+ }
+
+ public <B> ServiceReference<B> cast(B target) throws IllegalArgumentException {
+ return proxyFactory.cast(target);
+ }
+
+ public <B> B getService(Class<B> businessInterface, String referenceName) throws IllegalArgumentException {
+ B service = null;
+
+ ServiceReference<B> serviceRef = getServiceReference(businessInterface, referenceName);
+ if (serviceRef != null) {
+ service = serviceRef.getService();
+ }
+
+ return service;
+ }
+
+ public <B> TuscanyServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName)
+ throws IllegalArgumentException {
+
+ for (ComponentReference ref : component.getReferences()) {
+ if (referenceName.equals(ref.getName())) {
+ Multiplicity multiplicity = ref.getMultiplicity();
+ if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) {
+ throw new IllegalArgumentException("Reference " + referenceName
+ + " has multiplicity "
+ + multiplicity);
+ }
+ if (ref.getEndpointReferences().size() < 1) {
+ return null;
+ }
+ TuscanyServiceReference<B> sr =
+ getServiceReference(businessInterface, (RuntimeEndpointReference)getEndpointReference(ref));
+ if (sr == null) {
+ throw new IllegalArgumentException("Reference " + referenceName + " is null");
+ }
+ return sr;
+ }
+ }
+ throw new IllegalArgumentException("[JCA80011] Reference not found: " + referenceName);
+
+ }
+
+ /**
+ * Select an endpoint reference from the component reference
+ * @param ref
+ * @return
+ */
+ private EndpointReference getEndpointReference(ComponentReference ref) {
+ List<EndpointReference> eprs = ref.getEndpointReferences();
+ if (eprs.size() == 1) {
+ // Return 1st one
+ return eprs.get(0);
+ } else {
+ for (EndpointReference epr : eprs) {
+ // Try to see if there is an EPR using binding.sca
+ if (epr.getBinding().getType().equals(SCABinding.TYPE)) {
+ return epr;
+ }
+ }
+ return eprs.get(0);
+ }
+ }
+
+ /**
+ * Select an endpoint reference from the component reference
+ * @param ref
+ * @return
+ */
+ private Endpoint getEndpoint(ComponentService service, String bindingName) {
+ if (bindingName == null) {
+ // The default binding name is the name of the promoted service
+ bindingName = getPromotedService(service).getName();
+ }
+ Endpoint returnEp = null;
+ List<Endpoint> eps = service.getEndpoints();
+ for (Endpoint ep : eps) {
+ Binding binding = ep.getBinding();
+ if (bindingName.equals(binding.getName()) || binding.getName() == null) {
+ returnEp = ep;
+ break;
+ }
+ }
+ //TUSCANY-3543
+ if (returnEp == null) {
+ returnEp = eps.get(0);
+ }
+
+ return returnEp;
+ }
+
+ private ComponentService getPromotedService(ComponentService componentService) {
+ Service service = componentService.getService();
+ if (service instanceof CompositeService) {
+ return getPromotedService(((CompositeService)service).getPromotedService());
+ } else {
+ return componentService;
+ }
+
+ }
+
+ /**
+ * 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 IllegalArgumentException("Property not found: " + propertyName);
+ }
+
+ /**
+ * @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.isForCallback()) {
+ 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 <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) {
+ ComponentService service = getSingleService(component);
+ try {
+ return createSelfReference(businessInterface, service);
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) {
+ if (serviceName == null) {
+ return createSelfReference(businessInterface);
+ }
+ try {
+ String bindingName = null;
+ int index = serviceName.indexOf('/');
+ if (index != -1) {
+ bindingName = serviceName.substring(index + 1);
+ serviceName = serviceName.substring(0, index);
+ }
+ for (ComponentService service : component.getServices()) {
+ if (serviceName.equals(service.getName())) {
+ Endpoint endpoint = getEndpoint(service, bindingName);
+ if (endpoint == null) {
+ break;
+ }
+ return getServiceReference(businessInterface, (RuntimeEndpoint)endpoint);
+ }
+ }
+ throw new IllegalArgumentException("Service not found: " + serviceName);
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } 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 {
+ RuntimeEndpointReference ref =
+ (RuntimeEndpointReference)createEndpointReference(component, service, null, businessInterface);
+ ref.setComponent(component);
+ return getServiceReference(businessInterface, ref);
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } 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> TuscanyServiceReference<B> getServiceReference(Class<B> businessInterface,
+ RuntimeEndpointReference endpointReference) {
+ TuscanyServiceReference<B> result = null;
+
+ try {
+ InterfaceContract interfaceContract = endpointReference.getComponentTypeReferenceInterfaceContract();
+ if (businessInterface == null) {
+ businessInterface = (Class<B>)((JavaInterface)interfaceContract.getInterface()).getJavaClass();
+ }
+ RuntimeComponentReference ref = (RuntimeComponentReference)endpointReference.getReference();
+ InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
+ if (refInterfaceContract != null) {
+ if (refInterfaceContract != interfaceContract) {
+ ref = (RuntimeComponentReference)ref.clone();
+ if (interfaceContract != null) {
+ ref.setInterfaceContract(interfaceContract);
+ } else {
+ ref.setInterfaceContract(refInterfaceContract);
+ }
+ }
+
+ ref.setComponent(component);
+ result =
+ new ServiceReferenceImpl<B>(businessInterface, endpointReference, component.getComponentContext()
+ .getCompositeContext());
+ }
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+
+ return result;
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, RuntimeEndpoint endpoint) {
+ try {
+ if (businessInterface == null) {
+ InterfaceContract contract = endpoint.getBindingInterfaceContract();
+ if (contract.getInterface() instanceof JavaInterface) {
+ businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass();
+ } else {
+ contract = endpoint.getComponentTypeServiceInterfaceContract();
+ if (contract.getInterface() instanceof JavaInterface) {
+ businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass();
+ }
+ }
+ }
+ RuntimeEndpointReference ref =
+ (RuntimeEndpointReference)createEndpointReference(endpoint, businessInterface);
+ ref.setComponent(component);
+ return new ServiceReferenceImpl<B>(businessInterface, ref, compositeContext);
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * Create a self-reference for a component service
+ * @param component
+ * @param service
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ private EndpointReference createEndpointReference(Component component,
+ ComponentService service,
+ String bindingName,
+ Class<?> businessInterface) throws CloneNotSupportedException,
+ InvalidInterfaceException {
+
+ Endpoint endpoint = getEndpoint(service, bindingName);
+ return createEndpointReference(endpoint, businessInterface);
+ }
+
+ private EndpointReference createEndpointReference(Endpoint endpoint, Class<?> businessInterface)
+ throws CloneNotSupportedException, InvalidInterfaceException {
+ Component component = endpoint.getComponent();
+ ComponentService service = endpoint.getService();
+ ComponentReference componentReference = assemblyFactory.createComponentReference();
+ componentReference.setName("$self$." + service.getName());
+
+ componentReference.setCallback(service.getCallback());
+ componentReference.getTargets().add(service);
+ componentReference.getPolicySets().addAll(service.getPolicySets());
+ componentReference.getRequiredIntents().addAll(service.getRequiredIntents());
+ componentReference.getBindings().add(endpoint.getBinding());
+
+ // For the self-reference, allows pass by reference
+ componentReference.setAllowsPassByReference(true);
+
+ 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
+ EndpointReference endpointReference = assemblyFactory.createEndpointReference();
+ endpointReference.setComponent(component);
+ endpointReference.setReference(componentReference);
+ endpointReference.setBinding(endpoint.getBinding());
+ endpointReference.setUnresolved(false);
+ endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
+
+ endpointReference.setTargetEndpoint(endpoint);
+
+ componentReference.getEndpointReferences().add(endpointReference);
+ ((RuntimeComponentReference)componentReference).setComponent((RuntimeComponent)component);
+ ((RuntimeEndpointReference)endpointReference).bind(compositeContext);
+
+ return endpointReference;
+ }
+
+ /**
+ * @param interfaceContract
+ * @param businessInterface
+ * @return
+ * @throws CloneNotSupportedException
+ * @throws InvalidInterfaceException
+ */
+ private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface)
+ throws CloneNotSupportedException, InvalidInterfaceException {
+ if (businessInterface == null) {
+ return interfaceContract;
+ }
+ if (interfaceContract == null) {
+ JavaInterfaceContract ic = javaInterfaceFactory.createJavaInterfaceContract();
+ ic.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
+ return ic;
+ }
+ 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) {
+ InterfaceContract biContract = javaInterfaceFactory.createJavaInterfaceContract();
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface);
+ biContract.setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ biContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface
+ .getCallbackClass()));
+ }
+ InterfaceContractMapper ifcm = registry.getExtensionPoint(InterfaceContractMapper.class);
+ compatible = ifcm.isCompatibleSubset(biContract, interfaceContract);
+ // If the business interface class is not assignable from the service interface class but
+ // they are compatible, we need to return an InterfaceContract with the business interface
+ // class to store on the reference side.
+ if ( compatible ) {
+ return biContract;
+ }
+ }
+
+ }
+ }
+
+ if (!compatible) {
+ // JCA-9011
+ throw new IllegalArgumentException("Business interface " + businessInterface.getName()
+ + " is not compatible with "
+ + interfaceContract.getInterface());
+ }
+
+ return interfaceContract;
+ }
+
+ /* ******************** 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())) {
+ if (ref.getMultiplicity() == Multiplicity.ONE_ONE)
+ throw new IllegalArgumentException("Reference " + referenceName
+ + " is not a valid argument for getServiceReferences because it has a multiplicity of 1..1");
+ if (ref.getMultiplicity() == Multiplicity.ZERO_ONE)
+ throw new IllegalArgumentException("Reference " + referenceName
+ + " is not a valid argument for getServiceReferences because it has a multiplicity of 0..1");
+
+ ArrayList<ServiceReference<B>> serviceRefs = new ArrayList<ServiceReference<B>>();
+ for (EndpointReference endpointReference : ref.getEndpointReferences()) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference;
+ serviceRefs.add(getServiceReference(businessInterface, epr));
+ }
+ return serviceRefs;
+ }
+ }
+ throw new IllegalArgumentException("Reference not found: " + referenceName);
+ } catch (IllegalArgumentException iae) {
+ throw iae;
+ } catch (ServiceRuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ /* ******************** Contribution for issue TUSCANY-2281 ******************** */
+
+ public CompositeContext getCompositeContext() {
+ return compositeContext;
+ }
+
+ public ExtensionPointRegistry getExtensionPointRegistry() {
+ return getCompositeContext().getExtensionPointRegistry();
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java
new file mode 100644
index 0000000000..6aaa6186b9
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java
@@ -0,0 +1,126 @@
+/*
+ * 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.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.Message;
+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.RuntimeEndpoint;
+import org.oasisopen.sca.RequestContext;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class RequestContextImpl implements RequestContext {
+
+ public RequestContextImpl(RuntimeComponent component) {
+ }
+
+ public Subject getSecuritySubject() {
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ if (msgContext == null){
+ // message in thread context could be null if the user has
+ // spun up a new thread inside their component implementation
+ return null;
+ }
+
+ Subject subject = null;
+ for (Object header : msgContext.getHeaders().values()){
+ if (header instanceof Subject){
+ subject = (Subject)header;
+ break;
+ }
+ }
+ return subject;
+ }
+
+ public String getServiceName() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ if (msgContext != null &&
+ msgContext.getTo() != null){
+ return msgContext.getTo().getService().getName();
+ } else {
+ // message in thread context could be null (or the default message where to == null)
+ // if the user has spun up a new thread inside their component implementation
+ return null;
+ }
+ }
+
+ public <B> ServiceReference<B> getServiceReference() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ if (msgContext == null ||
+ msgContext.getTo() == null){
+ // message in thread context could be null (or the default message where to == null)
+ // if the user has spun up a new thread inside their component implementation
+ return null;
+ }
+ // FIXME: [rfeng] Is this the service reference matching the caller side?
+ RuntimeEndpoint to = (RuntimeEndpoint) msgContext.getTo();
+ RuntimeComponent component = (RuntimeComponent) to.getComponent();
+
+ ServiceReference<B> callableReference = component.getComponentContext().getServiceReference(null, to);
+
+ return callableReference;
+ }
+
+ public <CB> CB getCallback() {
+ ServiceReference<CB> cb = getCallbackReference();
+ if (cb == null) {
+ return null;
+ }
+ return cb.getService();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <CB> ServiceReference<CB> getCallbackReference() {
+ Message msgContext = ThreadMessageContext.getMessageContext();
+ if (msgContext == null ||
+ msgContext.getTo() == null){
+ // message in thread context could be null (or the default message where to == null)
+ // if the user has spun up a new thread inside their component implementation
+ return null;
+ }
+
+ Endpoint to = msgContext.getTo();
+ RuntimeComponentService service = (RuntimeComponentService) to.getService();
+ RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference();
+ if (callbackReference == null) {
+ return null;
+ }
+ JavaInterface javaInterface = (JavaInterface) callbackReference.getInterfaceContract().getInterface();
+ Class<CB> javaClass = (Class<CB>)javaInterface.getJavaClass();
+ List<EndpointReference> wires = callbackReference.getEndpointReferences();
+ ServiceReferenceImpl ref = new CallbackServiceReferenceImpl(javaClass, wires);
+
+ return ref;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java
new file mode 100644
index 0000000000..6fa53dcea2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java
@@ -0,0 +1,430 @@
+/*
+ * 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.io.StringWriter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+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.ComponentService;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+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.assembly.RuntimeAssemblyFactory;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl;
+import org.apache.tuscany.sca.core.context.ServiceReferenceExt;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.interfacedef.Interface;
+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.runtime.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Default implementation of a ServiceReference.
+ *
+ * @version $Rev$ $Date$
+ * @param <B> the type of the business interface
+ */
+public class ServiceReferenceImpl<B> implements ServiceReferenceExt<B> {
+ private static final long serialVersionUID = 6763709434194361540L;
+
+ protected transient ProxyFactory proxyFactory;
+ protected transient Class<B> businessInterface;
+ protected transient B proxy;
+
+ protected Object callbackID; // The callbackID should be serializable
+
+ protected transient RuntimeEndpointReference endpointReference;
+
+// protected String scdl;
+//
+// private transient XMLStreamReader xmlReader;
+
+ protected transient CompositeContext compositeContext;
+ protected ExtensionPointRegistry registry;
+ protected FactoryExtensionPoint modelFactories;
+ protected RuntimeAssemblyFactory assemblyFactory;
+ protected StAXArtifactProcessorExtensionPoint staxProcessors;
+ protected StAXArtifactProcessor<EndpointReference> staxProcessor;
+ protected XMLInputFactory xmlInputFactory;
+ protected XMLOutputFactory xmlOutputFactory;
+ protected BuilderExtensionPoint builders;
+
+ /*
+ * Public constructor for Externalizable serialization/deserialization
+ */
+ public ServiceReferenceImpl() {
+ super();
+ }
+
+ public ServiceReferenceImpl(Class<B> businessInterface,
+ Invocable endpointReference,
+ CompositeContext compositeContext) {
+ this.businessInterface = businessInterface;
+ this.endpointReference = (RuntimeEndpointReference) endpointReference;
+ if (compositeContext == null) {
+ compositeContext = endpointReference.getCompositeContext();
+ }
+ bind(compositeContext);
+ }
+
+ public ServiceReferenceImpl(Class<B> businessInterface,
+ Invocable endpointReference) {
+ this(businessInterface, endpointReference, null);
+ }
+
+ protected void bind(CompositeContext context) {
+ this.compositeContext = context;
+ this.registry = compositeContext.getExtensionPointRegistry();
+ this.modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
+ this.xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ this.xmlOutputFactory = modelFactories.getFactory(XMLOutputFactory.class);
+ this.staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ this.staxProcessor = staxProcessors.getProcessor(EndpointReference.class);
+ this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ this.proxyFactory = ExtensibleProxyFactory.getInstance(registry);
+ }
+
+ public RuntimeEndpointReference getEndpointReference() {
+ return endpointReference;
+ }
+
+ public B getProxy() throws ObjectCreationException {
+ try {
+ if (proxy == null) {
+ proxy = createProxy();
+ }
+ return proxy;
+ } catch (Exception e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+
+ public void setProxy(B proxy) {
+ this.proxy = proxy;
+ }
+
+ protected B 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);
+ }
+ }
+
+ /**
+ * 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;
+ }
+ }
+
+ // ============ WRITE AND READ THE REFERENCE TO EXTERNAL XML ========================
+
+ /**
+ * write the reference to a stream
+ *
+ * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
+ */
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(endpointReference);
+ /*
+ try {
+ String xml = null;
+ if (scdl == null) {
+ xml = toXMLString();
+ } else {
+ xml = scdl;
+ }
+
+ if (xml == null) {
+ out.writeBoolean(false);
+ } else {
+ out.writeBoolean(true);
+ out.writeUTF(xml);
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ throw new IOException(e.toString());
+ }
+ */
+ }
+
+ /**
+ * write the endpoint reference into an xml string
+ */
+ public String toXMLString() throws IOException, XMLStreamException, ContributionWriteException {
+ StringWriter writer = new StringWriter();
+ XMLStreamWriter streamWriter = xmlOutputFactory.createXMLStreamWriter(writer);
+ staxProcessor.write(endpointReference, streamWriter, new ProcessorContext(registry));
+ return writer.toString();
+ }
+
+ /**
+ * Read the reference from a stream
+ *
+ * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
+ */
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ this.endpointReference = (RuntimeEndpointReference) in.readObject();
+ // Force resolve
+ endpointReference.getComponent();
+ bind(endpointReference.getCompositeContext());
+
+ RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
+ reference.setComponent((RuntimeComponent)endpointReference.getComponent());
+
+ 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()));
+ JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext);
+
+ try {
+ javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass());
+ } catch (InvalidInterfaceException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ //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();
+ }
+
+ Binding binding = endpointReference.getBinding();
+ if (binding != null) {
+ BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType());
+ if (bindingBuilder != null) {
+ org.apache.tuscany.sca.assembly.builder.BuilderContext context = new BuilderContext(registry);
+ bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context, false);
+ }
+ }
+
+ this.proxyFactory = getProxyFactory(this.compositeContext);
+
+ /*
+ endpointReference.bind(CompositeContext.getCurrentCompositeContext());
+ endpointReference.rebuild();
+ */
+ /*
+ final boolean hasSCDL = in.readBoolean();
+ if (hasSCDL) {
+ this.scdl = in.readUTF();
+ } else {
+ this.scdl = null;
+ }
+ */
+ }
+
+ /**
+ * Read xml string into the endpoint reference
+ */
+ /*
+ public void fromXMLString() throws IOException, XMLStreamException, ContributionReadException {
+
+ XMLStreamReader streamReader = xmlReader;
+
+ if (scdl != null) {
+ Reader reader = new StringReader(scdl);
+
+ if (xmlInputFactory == null) {
+ // this is a reference being read from a external stream
+ // so set up enough of the reference in order to resolved the
+ // xml being read
+ bind(CompositeContext.getCurrentCompositeContext());
+ }
+
+ streamReader = xmlInputFactory.createXMLStreamReader(reader);
+ }
+
+ endpointReference = (RuntimeEndpointReference) staxProcessor.read(streamReader, new ProcessorContext(registry));
+
+ // ok to GC
+ xmlReader = null;
+ scdl = null;
+ }
+ */
+
+ /**
+ * @throws IOException
+ */
+ private synchronized void resolve() throws Exception {
+ /*
+ if ((scdl != null || xmlReader != null) && endpointReference == null) {
+ fromXMLString();
+
+ compositeContext.bindComponent((RuntimeComponent) endpointReference.getComponent());
+
+ RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference();
+ reference.setComponent((RuntimeComponent)endpointReference.getComponent());
+
+ ReferenceParameters parameters = null;
+ for (Object ext : reference.getExtensions()) {
+ if (ext instanceof ReferenceParameters) {
+ parameters = (ReferenceParameters)ext;
+ break;
+ }
+ }
+
+ if (parameters != null) {
+ this.callbackID = parameters.getCallbackID();
+ }
+
+ 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()));
+ JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext);
+
+ javaInterfaceFactory.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();
+ }
+
+ Binding binding = endpointReference.getBinding();
+ if (binding != null) {
+ BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType());
+ if (bindingBuilder != null) {
+ BuilderContext context = new BuilderContext(registry);
+ bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context);
+ }
+ }
+
+ this.proxyFactory = getProxyFactory(this.compositeContext);
+ } else if (compositeContext == null) {
+ this.compositeContext = CompositeContext.getCurrentCompositeContext();
+ if (this.compositeContext != null) {
+ this.proxyFactory = getProxyFactory(this.compositeContext);
+ }
+ }
+ */
+ }
+
+ private JavaInterfaceFactory getJavaInterfaceFactory(CompositeContext compositeContext) {
+ ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry();
+ FactoryExtensionPoint factories = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class);
+ JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);
+ return javaInterfaceFactory;
+ }
+
+ private ProxyFactory getProxyFactory(CompositeContext compositeContext) {
+ ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry();
+ return ExtensibleProxyFactory.getInstance(extensionPointRegistry);
+ }
+
+ // ==================================================================================
+
+ /*
+ public XMLStreamReader getXMLReader() {
+ return xmlReader;
+ }
+ */
+
+ public void setBindingURI(String uri) {
+ ((RuntimeEndpointReferenceImpl)endpointReference).setBindingURI(uri);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java
new file mode 100644
index 0000000000..4b563b0079
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.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.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$
+ * @tuscany.spi.extension.asclient
+ */
+public interface InstanceWrapper<T> {
+
+ /**
+ * @return
+ */
+ T getInstance();
+
+ /**
+ * @throws TargetInitializationException
+ */
+ void start() throws TargetInitializationException;
+
+ /**
+ * @throws TargetDestructionException
+ */
+ void stop() throws TargetDestructionException;
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java
new file mode 100644
index 0000000000..820faf6259
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.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;
+
+
+/**
+ * Denotes an error creating a new object instance
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java
new file mode 100644
index 0000000000..db10b6cff2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.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.factory;
+
+/**
+ * Implementations create new instances of a particular type
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncContext.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncContext.java
new file mode 100644
index 0000000000..b91bfcca8e
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncContext.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.invocation;
+
+/**
+ * Allows extensions to associate data with a client's async request.
+ */
+public interface AsyncContext {
+
+ /**
+ * Looks up an attribute value by name.
+ * @param name The name of the attribute
+ * @return The value of the attribute
+ */
+ public Object getAttribute(String name);
+
+ /**
+ * Sets the value of an attribute.
+ *
+ * @param name The name of the attribute
+ * @param value
+ */
+ public void setAttribute(String name, Object value);
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java
new file mode 100644
index 0000000000..b35d493d3c
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java
@@ -0,0 +1,107 @@
+/*
+ * 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.InvocationTargetException;
+
+/**
+ * A class which is used to wrap an Exception of any type thrown by an asynchronous service operation and
+ * which is returned through a separate one-way message sent asynchronously from the server to the client.
+ *
+ */
+public class AsyncFaultWrapper {
+
+ private String faultClassName = null;
+ private String faultMessage = null;
+ private AsyncFaultWrapper containedFault = null;
+
+
+ public AsyncFaultWrapper() {
+ super();
+ }
+
+ /**
+ * Constructor which creates an AsyncFaultWrapper which wraps the supplied Throwable
+ * @param e - a Throwable which is wrapped by this AsyncFaultWrapper
+ */
+ public AsyncFaultWrapper( Throwable e ) {
+ super();
+ storeFault( e );
+ }
+
+ /**
+ * Stores a given Throwable in this AsyncFaultWrapper
+ * If the supplied Throwable itself contains an embedded Throwable ("cause"), this is recursively
+ * wrapped by a nested AsyncFaultWrapper
+ * @param e - the Throwable
+ */
+ public void storeFault( Throwable e ) {
+ setFaultClassName( e.getClass().getCanonicalName() );
+ setFaultMessage( e.getMessage() );
+ Throwable cause = e.getCause();
+ if( cause != null ) setContainedFault( new AsyncFaultWrapper( cause ) );
+ }
+
+ /**
+ * Retrieves the Throwable wrapped by this AsyncFaultWrapper
+ *
+ * Note: When this method is invoked, the method attempts to instantiate an instance of the wrapped Throwable.
+ * It does this using the Thread Context Class Loader (TCCL) - the caller *MUST* ensure that the TCCL has access
+ * to the class of the wrapped Throwable and also to the classes of any nested Throwables. If this is not done,
+ * a ClassNotFound exception is thrown
+ *
+ * @return - the Throwable wrapped by this AsyncFaultWrapper - the Throwable will contain any nested Throwable(s)
+ * in its cause property
+ * @throws ClassNotFound exception, if the class of the wrapped Throwable is not accessible from the TCCL
+ */
+ public Throwable retrieveFault( ) {
+ try {
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Class<?> faultClass = tccl.loadClass(faultClassName);
+ Class<Throwable> xclass = (Class<Throwable>) faultClass;
+ if( containedFault != null ) {
+ // If there is a nested fault, retrieve this recursively
+ Constructor cons = xclass.getConstructor(String.class, Throwable.class);
+ return (Throwable) cons.newInstance(faultMessage, getContainedFault().retrieveFault());
+ } else {
+ try {
+ Constructor cons = xclass.getConstructor(String.class);
+ return (Throwable) cons.newInstance(faultMessage);
+ } catch (NoSuchMethodException e) {
+ Constructor cons = xclass.getConstructor();
+ return (Throwable) cons.newInstance();
+ }
+ } // end if
+ } catch (Exception e) {
+ return e;
+ } // end try
+ } // end method retrieveFault
+
+ public void setFaultClassName( String name ) { this.faultClassName = name; }
+ public String getFaultClassName() { return this.faultClassName; }
+
+ public String getFaultMessage() { return faultMessage; }
+ public void setFaultMessage(String faultMessage) { this.faultMessage = faultMessage; }
+
+ public AsyncFaultWrapper getContainedFault() { return containedFault; }
+ public void setContainedFault(AsyncFaultWrapper containedFault) { this.containedFault = containedFault; }
+
+} // end class AsyncFaultWrapper
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.java
new file mode 100644
index 0000000000..df90c3286d
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.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;
+
+/**
+ * An exception which is used to signal that a service has been invoked asynchronously
+ * and that the result will be sent separately
+ *
+ */
+public class AsyncResponseException extends RuntimeException {
+
+ private static final long serialVersionUID = 457954562860541631L;
+
+ public AsyncResponseException() {
+ super();
+ }
+
+ public AsyncResponseException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public AsyncResponseException(String arg0) {
+ super(arg0);
+ }
+
+ public AsyncResponseException(Throwable arg0) {
+ super(arg0);
+ }
+
+} // end class AsyncResponseException
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java
new file mode 100644
index 0000000000..306a141433
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java
@@ -0,0 +1,58 @@
+/*
+ * 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.oasisopen.sca.annotation.OneWay;
+import org.oasisopen.sca.annotation.Remotable;
+
+/**
+ * An interface which describes a general response pattern for the asynchronous invocation of a service
+ *
+ * @param <V> - the type of the non-fault response
+ */
+public interface AsyncResponseHandler<V> extends AsyncResponseService<V> {
+
+ /**
+ * Async process completed with a wrapped Fault. Must only be invoked once
+ * <inherited>
+ * @param e - the wrapper containing the Fault to send
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ */
+ @OneWay
+ public void setWrappedFault(AsyncFaultWrapper w);
+
+ /**
+ * Async process completed with a Fault. Must only be invoked once.
+ * @param e - the Fault to send
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ */
+ @OneWay
+ public void setFault( Throwable e );
+
+ /**
+ * Async process completed with a response message. Must only be invoked once
+ * <inherited>
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ * @param res - the response message, which is of type V
+ */
+ @OneWay
+ public void setResponse(V res);
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseInvoker.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseInvoker.java
new file mode 100644
index 0000000000..1ebc9c633a
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseInvoker.java
@@ -0,0 +1,351 @@
+/*
+ * 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.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistryLocator;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.provider.EndpointAsyncProvider;
+import org.apache.tuscany.sca.runtime.DomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+import org.apache.tuscany.sca.runtime.ExtensibleDomainRegistryFactory;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+/**
+ * A class that wraps the mechanics for sending async responses
+ * and hides the decision about whether the response will be processed
+ * natively or non-natively
+ *
+ * This class is generic, based on the type of targetAddress information required by
+ * the Binding that creates it
+ */
+public class AsyncResponseInvoker<T> implements InvokerAsyncResponse, Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7992598227671386588L;
+
+ private transient RuntimeEndpoint requestEndpoint;
+ private transient RuntimeEndpointReference responseEndpointReference;
+ private T responseTargetAddress;
+ private String relatesToMsgID;
+ private String operationName;
+ private transient MessageFactory messageFactory;
+ private String bindingType = "";
+ private boolean isNativeAsync;
+
+ private String endpointURI;
+ private String endpointReferenceURI;
+ private String domainURI;
+
+ private transient DomainRegistry domainRegistry;
+ private transient ExtensionPointRegistry registry;
+
+ public AsyncResponseInvoker(RuntimeEndpoint requestEndpoint,
+ RuntimeEndpointReference responseEndpointReference,
+ T responseTargetAddress, String relatesToMsgID,
+ String operationName, MessageFactory messageFactory) {
+ super();
+ this.requestEndpoint = requestEndpoint;
+ this.responseEndpointReference = responseEndpointReference;
+ this.responseTargetAddress = responseTargetAddress;
+ this.relatesToMsgID = relatesToMsgID;
+ this.operationName = operationName;
+ this.messageFactory = messageFactory;
+
+ CompositeContext context = null;
+ if(requestEndpoint != null ) {
+ endpointURI = requestEndpoint.getURI();
+ context = requestEndpoint.getCompositeContext();
+ } // end if
+ if(responseEndpointReference != null ) {
+ endpointReferenceURI = responseEndpointReference.getURI();
+ context = responseEndpointReference.getCompositeContext();
+ }
+
+ if( context != null ) {
+ domainURI = context.getDomainURI();
+ registry = context.getExtensionPointRegistry();
+ } // end if
+
+ if ((requestEndpoint.getBindingProvider() instanceof EndpointAsyncProvider) &&
+ (((EndpointAsyncProvider)requestEndpoint.getBindingProvider()).supportsNativeAsync())){
+ isNativeAsync = true;
+ } else {
+ isNativeAsync = false;
+ } // end if
+ } // end constructor
+
+ /**
+ * If you have a Tuscany message you can call this
+ */
+ public void invokeAsyncResponse(Message responseMessage) {
+ responseMessage.getHeaders().put(Constants.ASYNC_RESPONSE_INVOKER, this);
+ responseMessage.getHeaders().put(Constants.RELATES_TO, relatesToMsgID);
+
+ if (isNativeAsync){
+ // process the response as a native async response
+ requestEndpoint.invokeAsyncResponse(responseMessage);
+ } else {
+ // process the response as a non-native async response
+ responseEndpointReference.invoke(responseMessage);
+ }
+ } // end method invokeAsyncReponse(Message)
+
+ public T getResponseTargetAddress() {
+ return responseTargetAddress;
+ }
+
+ public void setResponseTargetAddress(T responseTargetAddress) {
+ this.responseTargetAddress = responseTargetAddress;
+ }
+
+ public String getRelatesToMsgID() {
+ return relatesToMsgID;
+ }
+
+ public void setRelatesToMsgID(String relatesToMsgID) {
+ this.relatesToMsgID = relatesToMsgID;
+ }
+
+ /**
+ * Invokes the async response where the parameter is Java bean(s)
+ * - this method creates a Tuscany message
+ *
+ * @param args the response data
+ * @param headers - any header
+ */
+ public void invokeAsyncResponse(Object args, Map<String, Object> headers) {
+
+ Message msg = messageFactory.createMessage();
+
+ msg.setOperation(getOperation( args ));
+
+ // If this is not native async, then any Throwable is being passed as a parameter and
+ // requires wrapping
+ if( !isNativeAsync && args instanceof Throwable ) {
+ args = new AsyncFaultWrapper( (Throwable) args );
+ } // end if
+
+ // If this is not native async, then the message must contain an array of args since
+ // this is what is expected when invoking an EPR for the async response...
+ if( !isNativeAsync ) {
+ Object[] objs = new Object[1];
+ objs[0] = args;
+ args = objs;
+ } // end if
+
+ msg.setTo(requestEndpoint);
+ msg.setFrom(responseEndpointReference);
+
+ if( headers != null ) {
+ msg.getHeaders().putAll(headers);
+ }
+
+ if( args instanceof Throwable ) {
+ msg.setFaultBody(args);
+ } else {
+ msg.setBody(args);
+ } // end if
+
+ invokeAsyncResponse(msg);
+
+ } // end method invokeAsyncResponse(Object)
+
+ private Operation getOperation( Object args ) {
+ if( isNativeAsync ) {
+ List<Operation> ops = requestEndpoint.getService().getInterfaceContract().getInterface().getOperations();
+ for (Operation op : ops) {
+ if( operationName.equals(op.getName()) ) return op;
+ } // end for
+ return null;
+ } else {
+ operationName = "setResponse";
+ if( args instanceof Throwable ) { operationName = "setWrappedFault"; }
+ List<Operation> ops = responseEndpointReference.getReference().getInterfaceContract().getInterface().getOperations();
+ for (Operation op : ops) {
+ if( operationName.equals(op.getName()) ) return op;
+ } // end for
+ return null;
+ } // end if
+ } // end getOperation
+
+ public void setBindingType(String bindingType) {
+ this.bindingType = bindingType;
+ } // end method setBindingType
+
+ public String getBindingType() {
+ return bindingType;
+ } // end method getBindingType
+
+ public RuntimeEndpoint getRequestEndpoint() {
+ return this.requestEndpoint;
+ }
+
+ public RuntimeEndpointReference getResponseEndpointReference() {
+ return this.responseEndpointReference;
+ }
+
+ public void setResponseEndpointReference(
+ RuntimeEndpointReference responseEndpointReference) {
+ this.responseEndpointReference = responseEndpointReference;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+
+ requestEndpoint = retrieveEndpoint(endpointURI);
+ responseEndpointReference = retrieveEndpointReference(endpointReferenceURI);
+
+ messageFactory = getMessageFactory();
+
+ if (responseTargetAddress instanceof EndpointReference){
+ // fix the target as in this case it will be an EPR
+ EndpointReference epr = (EndpointReference)responseTargetAddress;
+ responseTargetAddress = (T)retrieveEndpointReference(epr.getURI());
+ } // end if
+ } // end method readObject
+
+ /**
+ * Gets a message factory
+ * @return
+ */
+ private MessageFactory getMessageFactory() {
+ return registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class);
+ } // end method getMessageFactory
+
+ /**
+ * Fetches the EndpointReference identified by an endpoint reference URI
+ * @param uri - the URI of the endpoint reference
+ * @return - the EndpointReference matching the supplied URI - null if no EPR is found which
+ * matches the URI
+ */
+ private RuntimeEndpointReference retrieveEndpointReference(String uri) {
+ if( uri == null ) return null;
+ if( domainRegistry == null ) return null;
+ List<EndpointReference> refs = domainRegistry.findEndpointReferences( uri );
+ // If there is more than EndpointReference with the uri...
+ if( refs.isEmpty() ) return null;
+ // TODO: what if there is more than 1 EPR with the given URI?
+ return (RuntimeEndpointReference) refs.get(0);
+ } // end method retrieveEndpointReference
+
+ /**
+ * Fetches the Endpoint identified by an endpoint URI
+ * - the Endpoint is retrieved from the DomainRegistry
+ * @param uri - the URI of the Endpoint
+ * @return - the Endpoint corresponding to the URI, or null if no Endpoint is found which has the
+ * supplied URI
+ */
+ private RuntimeEndpoint retrieveEndpoint(String uri) {
+ if( uri == null ) return null;
+ if( domainRegistry == null ) domainRegistry = getEndpointRegistry( uri );
+ if( domainRegistry == null ) return null;
+ // TODO what if more than one Endpoint gets returned??
+ return (RuntimeEndpoint) domainRegistry.findEndpoint(uri).get(0);
+ } // end method retrieveEndpoint
+
+ /**
+ * Gets the DomainRegistry which contains an Endpoint with the supplied URI
+ * @param uri - The URI of an Endpoint
+ * @return - the DomainRegistry containing the Endpoint with the supplied URI - null if no
+ * such DomainRegistry can be found
+ */
+ private DomainRegistry getEndpointRegistry(String uri) {
+ ExtensionPointRegistry registry = null;
+ DomainRegistry domainRegistry = null;
+
+ CompositeContext context = CompositeContext.getCurrentCompositeContext();
+ if( context == null && requestEndpoint != null ) context = requestEndpoint.getCompositeContext();
+ if( context != null ) {
+ registry = context.getExtensionPointRegistry();
+ domainRegistry = getEndpointRegistry( registry );
+ if( domainRegistry != null ) {
+ this.registry = registry;
+ return domainRegistry;
+ } // end if
+ } // end if
+
+ // Deal with the case where there is no context available
+ for(ExtensionPointRegistry r : ExtensionPointRegistryLocator.getExtensionPointRegistries()) {
+ registry = r;
+ if( registry != null ) {
+ // Find the actual Endpoint in the DomainRegistry
+ domainRegistry = getEndpointRegistry( registry );
+
+ if( domainRegistry != null ) {
+ for( Endpoint endpoint : domainRegistry.findEndpoint(uri) ) {
+ // TODO: For the present, simply return the first registry with a matching endpoint
+ this.registry = registry;
+ return domainRegistry;
+ } // end for
+ } // end if
+ } // end if
+ } // end for
+
+ return null;
+ } // end method getEndpointRegistry
+
+ /**
+ * Get the DomainRegistry
+ * @param registry - the ExtensionPoint registry
+ * @return the DomainRegistry - will be null if the DomainRegistry cannot be found
+ */
+ private DomainRegistry getEndpointRegistry( ExtensionPointRegistry registry) {
+ DomainRegistryFactory domainRegistryFactory = ExtensibleDomainRegistryFactory.getInstance(registry);
+
+ if( domainRegistryFactory == null ) return null;
+
+ // Find the first endpoint registry that matches the domain name
+ if( domainURI != null ) {
+ for( DomainRegistry domainRegistry : domainRegistryFactory.getEndpointRegistries() ) {
+ if( domainURI.equals( domainRegistry.getDomainURI() ) ) return domainRegistry;
+ } // end for
+ } // end if
+
+ // if there was no domainName to match, simply return the first DomainRegistry if there is one...
+
+ if (domainRegistryFactory.getEndpointRegistries().size() > 0){
+ DomainRegistry domainRegistry = (DomainRegistry) domainRegistryFactory.getEndpointRegistries().toArray()[0];
+ return domainRegistry;
+ } else {
+ return null;
+ }
+
+ } // end method
+
+} // end class
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseService.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseService.java
new file mode 100644
index 0000000000..62d7f74505
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseService.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;
+
+import org.oasisopen.sca.annotation.OneWay;
+import org.oasisopen.sca.annotation.Remotable;
+
+/**
+ * An interface which describes the client response service interface for a non-native binding
+ * performing an asynchronous invocation of a service
+ *
+ * @param <V> - the type of the non-fault response
+ */
+@Remotable()
+public interface AsyncResponseService<V> {
+
+ /**
+ * Async process completed with a wrapped Fault. Must only be invoked once
+ * @param e - the wrapper containing the Fault to send
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ */
+ @OneWay
+ public void setWrappedFault(AsyncFaultWrapper w);
+
+ /**
+ * Async process completed with a response message. Must only be invoked once
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ * @param res - the response message, which is of type V
+ */
+ @OneWay
+ public void setResponse(V res);
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java
new file mode 100644
index 0000000000..400bb333fd
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * Uses a wire to return a CallableReference
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class CallableReferenceObjectFactory implements ObjectFactory<ServiceReference<?>> {
+ private Class<?> businessInterface;
+ private RuntimeEndpointReference endpointReference;
+
+ /**
+ * 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,
+ RuntimeEndpointReference endpointReference) {
+ this.businessInterface = businessInterface;
+ this.endpointReference = endpointReference;
+ }
+
+ public ServiceReference<?> getInstance() throws ObjectCreationException {
+ RuntimeComponent component = (RuntimeComponent) endpointReference.getComponent();
+ return component.getComponentContext().getServiceReference(businessInterface, endpointReference);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackHandler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackHandler.java
new file mode 100644
index 0000000000..bccce0d20a
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackHandler.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;
+
+/**
+ * Models callback information arriving in the forward message
+ */
+public class CallbackHandler {
+ private String callbackTargetURI;
+ private boolean cloneCallbackWire = true;
+
+ public CallbackHandler(String callbackTargetURI){
+ setCallbackTargetURI(callbackTargetURI);
+ }
+
+ public CallbackHandler(String callbackTargetURI, boolean cloneCallbackWire){
+ setCallbackTargetURI(callbackTargetURI);
+ setCloneCallbackWire(cloneCallbackWire);
+ }
+
+ public String getCallbackTargetURI() {
+ return callbackTargetURI;
+ }
+
+ public boolean getCloneCallbackWire() {
+ return cloneCallbackWire;
+ }
+
+ public void setCallbackTargetURI(String callbackTargetURI) {
+ this.callbackTargetURI = callbackTargetURI;
+ }
+
+ public void setCloneCallbackWire(boolean cloneCallbackWire) {
+ this.cloneCallbackWire = cloneCallbackWire;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java
new file mode 100644
index 0000000000..588eaa2d15
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+/**
+ * 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) {
+
+ /* TODO - EPR - not required for OASIS
+ 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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java
new file mode 100644
index 0000000000..a56983a5d3
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.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;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * Uses a wire to return a CallableReference
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class CallbackReferenceObjectFactory implements ObjectFactory<ServiceReference<?>> {
+ private Class<?> businessInterface;
+ private ProxyFactory proxyFactory;
+ private List<EndpointReference> wires;
+
+ public CallbackReferenceObjectFactory(Class<?> interfaze, ProxyFactory proxyFactory, List<EndpointReference> wires) {
+ this.businessInterface = interfaze;
+ this.proxyFactory = proxyFactory;
+ this.wires = wires;
+ }
+
+ public ServiceReference<?> getInstance() throws ObjectCreationException {
+ return new CallbackServiceReferenceImpl(businessInterface, wires);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java
new file mode 100644
index 0000000000..fff3727d87
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.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 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.Invocable;
+
+/**
+ * Returns proxy instance for a wire callback
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class CallbackWireObjectFactory<B> implements ObjectFactory<B> {
+ private Class<B> businessInterface;
+ private ProxyFactory proxyFactory;
+ private List<Invocable> wires;
+
+ public CallbackWireObjectFactory(Class<B> interfaze, ProxyFactory proxyFactory, List<Invocable> wires) {
+ this.businessInterface = interfaze;
+ this.proxyFactory = proxyFactory;
+ this.wires = wires;
+ }
+
+ public B getInstance() throws ObjectCreationException {
+ return proxyFactory.createCallbackProxy(businessInterface, wires);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java
new file mode 100644
index 0000000000..a597f8b1ee
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java
@@ -0,0 +1,155 @@
+/*
+ * 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.ServiceReferenceExt;
+import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl;
+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.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * The implementation of a wire service that uses cglib dynamic proxies
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class CglibProxyFactory implements ProxyFactory {
+ private MessageFactory messageFactory;
+
+ public CglibProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) {
+ this.messageFactory = messageFactory;
+
+ }
+
+ public <T> T createProxy(final Class<T> interfaze, Invocable invocable) throws ProxyCreationException {
+ if (invocable instanceof RuntimeEndpoint) {
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(interfaze);
+ enhancer.setCallback(new CglibMethodInterceptor<T>(interfaze, invocable));
+ Object proxy = enhancer.create();
+ return interfaze.cast(proxy);
+ }
+ ServiceReference<T> serviceReference = new ServiceReferenceImpl(interfaze, invocable, null);
+ return createProxy(serviceReference);
+ }
+
+ /**
+ * create the proxy with cglib. use the same JDKInvocationHandler as
+ * JDKProxyService.
+ */
+ public <T> T createProxy(ServiceReference<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();
+ ((ServiceReferenceImpl)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<? extends Invocable> wires) throws ProxyCreationException {
+ ServiceReferenceImpl<T> callbackReference = new ServiceReferenceImpl(interfaze, wires.get(0), null);
+ return callbackReference != null ? createCallbackProxy(callbackReference) : null;
+ }
+
+ /**
+ * create the callback proxy with cglib. use the same
+ * JDKCallbackInvocationHandler as JDKProxyService.
+ */
+ public <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException {
+ Enhancer enhancer = new Enhancer();
+ Class<T> interfaze = callbackReference.getBusinessInterface();
+ enhancer.setSuperclass(interfaze);
+ enhancer.setCallback(new CglibMethodInterceptor<T>(callbackReference));
+ Object object = enhancer.create();
+ T proxy = interfaze.cast(object);
+ ((ServiceReferenceExt<T>)callbackReference).setProxy(proxy);
+ return proxy;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <B, R extends ServiceReference<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(ServiceReference<T> callableReference) {
+ invocationHandler = new JDKInvocationHandler(messageFactory, callableReference);
+ }
+
+ public CglibMethodInterceptor(Class<?> interfaze, Invocable invocable) {
+ invocationHandler = new JDKInvocationHandler(messageFactory, interfaze, invocable);
+ }
+
+ public CglibMethodInterceptor(ServiceReferenceImpl<T> callbackReference) {
+ invocationHandler = new JDKCallbackInvocationHandler(messageFactory, callbackReference);
+ }
+
+ /**
+ * @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;
+ }
+
+ }
+
+ public void removeProxiesForContribution(ClassLoader contributionClassloader){
+ // do nothing, no cache to clear
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java
new file mode 100644
index 0000000000..00c650ada6
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Constants used during invocation in the runtime
+ *
+ */
+public interface Constants {
+ public static final String MESSAGE_ID = "MESSAGE_ID";
+ public static final String RELATES_TO = "RELATES_TO";
+ public static final String ASYNC_RESPONSE_INVOKER = "ASYNC_RESPONSE_INVOKER";
+ public static final String ASYNC_CALLBACK = "ASYNC_CALLBACK";
+ public static final String CALLBACK = "CALLBACK";
+
+ /**
+ * If you've set the TCCL in your binding impl according to OASIS rules you can prevent
+ * the implementation provider from repeating the process by including this header
+ */
+ public static final String SUPPRESS_TCCL_SWAP = "SUPPRESS_TCCL_SWAP";
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java
new file mode 100644
index 0000000000..03505da302
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.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;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.LifeCycleListener;
+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, LifeCycleListener {
+ private InterfaceContractMapper interfaceContractMapper;
+ private MessageFactory messageFactory;
+
+ private ProxyFactory interfaceFactory;
+ private ProxyFactory classFactory;
+
+ public DefaultProxyFactoryExtensionPoint(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.messageFactory = modelFactories.getFactory(MessageFactory.class);
+
+ interfaceFactory = new JDKProxyFactory(registry, messageFactory, interfaceContractMapper);
+ }
+
+ // public DefaultProxyFactoryExtensionPoint(MessageFactory messageFactory, InterfaceContractMapper mapper) {
+ // this.interfaceContractMapper = mapper;
+ // this.messageFactory = messageFactory;
+ // interfaceFactory = new JDKProxyFactory(null, 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;
+
+ }
+
+ public void start() {
+ if (interfaceFactory instanceof LifeCycleListener) {
+ ((LifeCycleListener)interfaceFactory).start();
+ }
+ if (classFactory instanceof LifeCycleListener) {
+ ((LifeCycleListener)classFactory).start();
+ }
+ }
+
+ public void stop() {
+ if (interfaceFactory instanceof LifeCycleListener) {
+ ((LifeCycleListener)interfaceFactory).stop();
+ }
+ if (classFactory instanceof LifeCycleListener) {
+ ((LifeCycleListener)classFactory).stop();
+ }
+
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java
new file mode 100644
index 0000000000..3cb9445d2d
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java
@@ -0,0 +1,128 @@
+/*
+ * 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.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.runtime.Invocable;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * An extensible proxy factory.
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class ExtensibleProxyFactory implements ProxyFactory {
+
+ private ProxyFactoryExtensionPoint proxyFactories;
+
+ public ExtensibleProxyFactory(ProxyFactoryExtensionPoint proxyFactories) {
+ this.proxyFactories = proxyFactories;
+ }
+
+ public ExtensibleProxyFactory(ExtensionPointRegistry registry) {
+ this.proxyFactories = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class);
+ }
+
+ public static ExtensibleProxyFactory getInstance(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ return utilities.getUtility(ExtensibleProxyFactory.class);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#cast(java.lang.Object)
+ */
+ @SuppressWarnings("unchecked")
+ public <B, R extends ServiceReference<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<? extends Invocable> 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(ServiceReference<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(ServiceReference<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.Invocable)
+ */
+ public <T> T createProxy(Class<T> interfaze, Invocable 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));
+ }
+
+ public void removeProxiesForContribution(ClassLoader contributionClassloader){
+ // do nothing, no cache to clear
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java
new file mode 100644
index 0000000000..08019ec3e2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java
@@ -0,0 +1,51 @@
+/*
+ * 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.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+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(RuntimeEndpoint endpoint) {
+ for (RuntimeWireProcessor processor : processors.getWireProcessors()) {
+ processor.process(endpoint);
+ }
+ }
+
+ public void process(RuntimeEndpointReference endpointReference) {
+ for (RuntimeWireProcessor processor : processors.getWireProcessors()) {
+ processor.process(endpointReference);
+ }
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/InterceptorAsyncImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/InterceptorAsyncImpl.java
new file mode 100644
index 0000000000..265311fe6b
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/InterceptorAsyncImpl.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.invocation;
+
+
+import org.apache.tuscany.sca.invocation.InterceptorAsync;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncRequest;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * A base class that holds the mechanics for representing
+ * chained interceptors and for driving processing up and
+ * down the chain.
+ *
+ */
+public abstract class InterceptorAsyncImpl implements InterceptorAsync {
+
+ protected Invoker next;
+ protected InvokerAsyncResponse previous;
+
+ public Invoker getNext() {
+ return (Invoker)next;
+ }
+
+ public void setNext(Invoker next) {
+ this.next = next;
+ }
+
+ public InvokerAsyncResponse getPrevious() {
+ return previous;
+ }
+
+ public void setPrevious(InvokerAsyncResponse previous) {
+ this.previous = previous;
+ }
+
+ public Message invoke(Message msg) {
+ msg = processRequest(msg);
+ Message resultMsg = getNext().invoke(msg);
+ resultMsg = processResponse(resultMsg);
+ return resultMsg;
+ }
+
+ public void invokeAsyncRequest(Message msg) throws Throwable {
+ try{
+ msg = processRequest(msg);
+ InvokerAsyncRequest theNext = (InvokerAsyncRequest)getNext();
+ if( theNext != null ) theNext.invokeAsyncRequest(msg);
+ postProcessRequest(msg);
+ } catch (Throwable e) {
+ postProcessRequest(msg, e);
+ } // end try
+ } // end method invokeAsyncRequest
+
+ public void invokeAsyncResponse(Message msg) {
+ msg = processResponse(msg);
+ InvokerAsyncResponse thePrevious = (InvokerAsyncResponse)getPrevious();
+ if (thePrevious != null ) thePrevious.invokeAsyncResponse(msg);
+ } // end method invokeAsyncResponse
+
+ /**
+ * Basic null version of postProcessRequest - subclasses should override for any required
+ * real processing
+ */
+ public Message postProcessRequest(Message msg) {
+ // Default processing is to do nothing
+ return msg;
+ } // end method postProcessRequest
+
+ /**
+ * Basic null version of postProcessRequest - subclasses should override for any required
+ * real processing
+ * @throws Throwable
+ */
+ public Message postProcessRequest(Message msg, Throwable e) throws Throwable {
+ // Default processing is to rethrow the exception
+ throw e;
+ } // end method postProcessRequest
+
+
+ /**
+ * A testing method while I use the local SCA binding wire to look
+ * at how the async response path works. This allows me to detect the
+ * point where the reference wire turns into the service with in the
+ * optimized case
+ *
+ * @return
+ */
+ public boolean isLocalSCABIndingInvoker() {
+ return false;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKAsyncResponseInvoker.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKAsyncResponseInvoker.java
new file mode 100644
index 0000000000..60958ed6f9
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKAsyncResponseInvoker.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.invocation;
+
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+
+public interface JDKAsyncResponseInvoker extends InvokerAsyncResponse {
+
+ /**
+ * Registers an Async response, which provides an ID which identifies a given response
+ * and an object which can handle the response
+ * @param id - the ID
+ * @param responseHandler - the response handler object
+ */
+ public void registerAsyncResponse( String id, Object responseHandler );
+
+ /**
+ * Returns the registered async response for a given ID
+ * @param id - the ID
+ * @return responseHandler - the response handler object
+ */
+ public Object getAsyncResponse( String id );
+
+} // end interface JDKAsyncResponseInvoker
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java
new file mode 100644
index 0000000000..7108728206
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+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.work.WorkScheduler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Adds non-blocking behavior to an invocation chain
+ *
+ * @version $Rev$ $Date$
+ */
+public class NonBlockingInterceptor extends InterceptorAsyncImpl {
+
+ 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;
+
+ 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;
+ }
+
+ /**
+ * For request/response messages use the workScheduler to break the connection between
+ * requests and the void response
+ */
+ @Override
+ 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;
+ }
+
+ /**
+ * For forward async responses we just pass the message along
+ * as this is naturally one way
+ */
+ public Message processRequest(Message msg) {
+ return msg;
+ }
+
+ /**
+ * This should never be called as a one way message won't
+ * expect a response
+ */
+ public Message processResponse(Message msg) {
+ return null;
+ }
+
+ /**
+ * A dummy message passed back on an invocation
+ */
+ private static class ImmutableMessage implements Message {
+
+ public <T> T getBody() {
+ return null;
+ }
+
+ public void setBody(Object body) {
+ if (body != null) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ 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 Endpoint getTo() {
+ return null;
+ }
+
+ public void setFrom(EndpointReference from) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setTo(Endpoint to) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Operation getOperation() {
+ return null;
+ }
+
+ public void setOperation(Operation op) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map<String, Object> getHeaders() {
+ return null;
+ }
+ public <T> T getBindingContext() {
+ return null;
+ }
+
+ public <T> void setBindingContext(T bindingContext) {
+ }
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java
new file mode 100644
index 0000000000..0b36b178f3
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java
new file mode 100644
index 0000000000..8d9612315a
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java
@@ -0,0 +1,96 @@
+/*
+ * 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.runtime.Invocable;
+import org.oasisopen.sca.ServiceReference;
+
+/**
+ * Creates proxies that implement Java interfaces and invocation handlers for fronting wires
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+
+public interface ProxyFactory {
+
+ /**
+ * Creates a Java proxy for the given wire
+ *
+ * @param interfaze the interface the proxy implements
+ * @param invocable the wire to proxy
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createProxy(Class<T> interfaze, Invocable invocable) throws ProxyCreationException;
+
+ /**
+ * Creates a Java proxy for the given CallableReference
+ *
+ * @param callableReference The CallableReference
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createProxy(ServiceReference<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<? extends Invocable> invocables) throws ProxyCreationException;
+
+ /**
+ * Creates a Java proxy for the given callback reference
+ *
+ * @param callableReference The CallableReference
+ * @return the proxy
+ * @throws ProxyCreationException
+ */
+ <T> T createCallbackProxy(ServiceReference<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 ServiceReference<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);
+
+ /**
+ * Allow cached proxies to be removed when a contribution is removed. The proxy
+ * cache holds the application interface so will pin the contribution classloader
+ *
+ * @param contributionClassloader the classloader of the contribution being removed
+ */
+ void removeProxiesForContribution(ClassLoader contributionClassloader);
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java
new file mode 100644
index 0000000000..3e0bd7cb17
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.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.invocation;
+
+
+/**
+ * The extension point to plug in proxy factories
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java
new file mode 100644
index 0000000000..8f093d62ed
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java
@@ -0,0 +1,210 @@
+/*
+ * 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 java.util.UUID;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+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.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncRequest;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.runtime.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Invoker for a endpoint or endpoint reference
+ * @version $Rev$ $Date$
+ */
+public class RuntimeInvoker implements Invoker, InvokerAsyncRequest {
+ protected ExtensionPointRegistry registry;
+ protected MessageFactory messageFactory;
+ protected Invocable invocable;
+
+ // Run async service invocations using a ThreadPoolExecutor
+ private ExecutorService theExecutor;
+
+ public RuntimeInvoker(ExtensionPointRegistry registry, Invocable invocable) {
+ this.registry = registry;
+ this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class);
+ this.invocable = invocable;
+
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ WorkScheduler scheduler = utilities.getUtility(WorkScheduler.class);
+ theExecutor = scheduler.getExecutorService();
+ }
+
+ public Message invokeBinding(Message msg) {
+ Message context = ThreadMessageContext.setMessageContext(msg);
+ try {
+ return invocable.getBindingInvocationChain().getHeadInvoker().invoke(msg);
+ } finally {
+ ThreadMessageContext.setMessageContext(context);
+ }
+ } // end method invokeBinding
+
+ /**
+ * Async Invoke of the Binding Chain
+ * @param msg - the message to use in the invocation
+ */
+ public void invokeBindingAsync(Message msg) {
+ Message context = ThreadMessageContext.setMessageContext(msg);
+ try {
+ ((InvokerAsyncRequest)invocable.getBindingInvocationChain().getHeadInvoker()).invokeAsyncRequest(msg);
+ } catch (Throwable t ) {
+ // TODO - consider what best to do with exception
+ t.printStackTrace();
+ } finally {
+ ThreadMessageContext.setMessageContext(context);
+ } // end try
+ } // end method invokeBindingAsync
+
+ public Message invoke(Message msg) {
+ return invoke(msg.getOperation(), msg);
+ }
+
+ public Object invoke(Operation operation, Object[] args) throws InvocationTargetException {
+ Message msg = messageFactory.createMessage();
+ msg.setBody(args);
+ Message resp = invoke(operation, msg);
+ Object body = resp.getBody();
+ if (resp.isFault()) {
+ throw new InvocationTargetException((Throwable)body);
+ }
+ return body;
+ }
+
+
+ public Message invoke(Operation operation, Message msg) {
+ InvocationChain chain = invocable.getInvocationChain(operation);
+ return invoke(chain, msg);
+ }
+
+ public Message invoke(InvocationChain chain, Message msg) {
+
+ if (invocable instanceof Endpoint) {
+ msg.setTo((Endpoint)invocable);
+ } else if (invocable instanceof EndpointReference) {
+ msg.setFrom((EndpointReference)invocable);
+ }
+
+ Invoker headInvoker = chain.getHeadInvoker();
+ Operation operation = chain.getTargetOperation();
+ msg.setOperation(operation);
+
+ Message msgContext = ThreadMessageContext.setMessageContext(msg);
+ try {
+ return headInvoker.invoke(msg);
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+ }
+
+ /**
+ * Initiate the sending of the forward part of an asynchronous
+ * exchange along the request part of the wire.
+ *
+ * @param msg the request message
+ */
+ public void invokeAsync(Message msg) {
+ if (invocable instanceof Endpoint) {
+ Endpoint ep = (Endpoint)invocable;
+ msg.setTo(ep);
+ if (!ep.isAsyncInvocation()){
+ throw new ServiceRuntimeException("Calling invokeAsync on a non-async endpoint - " +
+ ep);
+ }
+ } else if (invocable instanceof EndpointReference) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)invocable;
+ if (!epr.isAsyncInvocation()){
+ throw new ServiceRuntimeException("Calling invokeAsync on a non-async endpoint reference - " +
+ epr);
+ }
+ if (epr.isOutOfDate()) {
+ epr.rebuild();
+ }
+ msg.setFrom(epr);
+ msg.setTo(epr.getTargetEndpoint());
+ }
+
+ Operation operation = msg.getOperation();
+ InvocationChain chain = invocable.getInvocationChain(operation);
+
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + operation.getName());
+ }
+
+ // create an async message ID if there isn't one there already
+ if (!msg.getHeaders().containsKey(Constants.MESSAGE_ID)){
+ msg.getHeaders().put(Constants.MESSAGE_ID, UUID.randomUUID().toString());UUID.randomUUID().toString();
+ }
+
+ // Perform the async invocation
+ Invoker headInvoker = chain.getHeadInvoker();
+
+ Message msgContext = ThreadMessageContext.setMessageContext(msg);
+ try {
+ try {
+ ((InvokerAsyncRequest)headInvoker).invokeAsyncRequest(msg);
+ } catch (ServiceRuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex) {
+ // temporary fix to swallow the dummy exception that's
+ // thrown back to get past the response chain processing.
+ if (!(ex instanceof AsyncResponseException)){
+ throw new ServiceRuntimeException(ex);
+ }
+ }
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+
+ return;
+ }
+
+ /**
+ * Initiate the sending of the response part of an asynchronous
+ * exchange along the response part of the wire.
+ *
+ * @param msg the response message
+ */
+ public void invokeAsyncResponse(Message msg) {
+ InvocationChain chain = invocable.getInvocationChain(msg.getOperation());
+ Invoker tailInvoker = chain.getTailInvoker();
+ ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg);
+ } // end method invokeAsyncResponse
+
+ @Override
+ public void invokeAsyncRequest(Message msg) throws Throwable {
+ invokeAsync(msg);
+ } // end method invokeAsyncRequest
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java
new file mode 100644
index 0000000000..489d06a3e1
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.Invocable;
+
+/**
+ * Uses a wire to return an object instance
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class WireObjectFactory<T> implements ObjectFactory<T> {
+ private Class<T> interfaze;
+ private Invocable 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, Invocable wire, ProxyFactory proxyService) {
+ this.interfaze = interfaze;
+ this.wire = wire;
+ this.proxyService = proxyService;
+ }
+
+ public T getInstance() throws ObjectCreationException {
+ return new ServiceReferenceImpl<T>(interfaze, wire, null).getProxy();
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java
new file mode 100644
index 0000000000..66b9516738
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java
@@ -0,0 +1,285 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Response;
+
+import org.apache.tuscany.sca.core.invocation.AsyncContext;
+import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler;
+
+/**
+ * A class which provides an Implementation of a Future<V> and Response<V> for use with the JAXWS defined client
+ * asynchronous APIs.
+ *
+ * This implementation class provides the interfaces for use by the client code, but also provides methods for the
+ * Tuscany system code to set the result of the asynchronous service invocation, both Regular and Fault responses.
+ *
+ * This class is constructed to be fully thread-safe
+ *
+ * @param <V> - this is the type of the response message from the invoked service.
+ */
+public class AsyncInvocationFutureImpl<V> implements Future<V>, Response<V>, AsyncContext, AsyncResponseHandler<V> {
+
+ // Lock for handling the completion of this Future
+ private final Lock lock = new ReentrantLock();
+ private final Condition isDone = lock.newCondition();
+
+ // The result
+ private volatile V response = null;
+ private volatile Throwable fault = null;
+
+ private String uniqueID = UUID.randomUUID().toString();
+
+ private Class businessInterface = null;
+ private AsyncHandler callback;
+
+ private Map<String, Object> attributes = new HashMap<String, Object>();
+
+ protected AsyncInvocationFutureImpl() {
+ super();
+ } // end constructor
+
+ /**
+ * Public constructor for AsyncInvocationFutureImpl - newInstance is necessary in order to enable the Type variable
+ * to be set for the class instances
+ * @param <V> - the type of the response from the asynchronously invoked service
+ * @param type - the type of the AsyncInvocationFutureImpl expressed as a parameter
+ * @param classLoader - the classloader used for the business interface to which this Future applies
+ * @return - an instance of AsyncInvocationFutureImpl<V>
+ */
+ public static <V> AsyncInvocationFutureImpl<V> newInstance( Class<V> type, Class businessInterface ) {
+ AsyncInvocationFutureImpl<V> future = new AsyncInvocationFutureImpl<V>();
+ future.setBusinessInterface( businessInterface );
+ return future;
+ }
+
+ /**
+ * Cancels the asynchronous process
+ * - not possible in this version, so always returns false
+ */
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ /**
+ * Gets the response value returned by the asynchronous process
+ * - waits forever
+ * @return - the response value of type V
+ * @throws InterruptedException if the get() method was interrupted while waiting for the async process to finish
+ * @throws ExecutionException if the async process threw an exception - the exception thrown is nested
+ */
+ public V get() throws InterruptedException, ExecutionException {
+ try {
+ V response = get(Long.MAX_VALUE, TimeUnit.SECONDS);
+ return response;
+ } catch (TimeoutException t) {
+ throw new InterruptedException("Timed out waiting for Future to complete");
+ } // end try
+ } // end method get()
+
+ /**
+ * Gets the response value returned by the asynchronous process
+ * @return - the response value of type V
+ * @throws InterruptedException if the get() method was interrupted while waiting for the async process to finish
+ * @throws ExecutionException if the async process threw an exception - the exception thrown is nested
+ * @throws TimeoutException if the get() method timed out waiting for the async process to finish
+ */
+ public V get(long timeout, TimeUnit unit) throws InterruptedException,
+ ExecutionException, TimeoutException {
+ lock.lock();
+ try {
+ // wait for result to be available
+ if( notSetYet() ) isDone.await( timeout, unit);
+ if( response != null ) return response;
+ if( fault != null ) throw new ExecutionException( fault );
+ throw new TimeoutException("get on this Future timed out");
+ } finally {
+ lock.unlock();
+ } // end try
+
+ } // end method get(long timeout, TimeUnit unit)
+
+ /**
+ * Indicates if the asynchronous process has been cancelled
+ * - not possible in this version so always returns false
+ */
+ public boolean isCancelled() {
+ return false;
+ }
+
+ /**
+ * Indicates if the asynchronous process is completed
+ * @return - true if the process is completed, false otherwise
+ */
+ public boolean isDone() {
+ lock.lock();
+ try {
+ return !notSetYet();
+ } finally {
+ lock.unlock();
+ } // end try
+ } // end method isDone
+
+ /**
+ * Async process completed with a Fault. Must only be invoked once.
+ * @param e - the Fault to send
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ */
+ public void setFault( Throwable e ) {
+ lock.lock();
+ try {
+ if( notSetYet() ) {
+ fault = e;
+ isDone.signalAll();
+ } else {
+ throw new IllegalStateException("setResponse() or setFault() has been called previously");
+ } // end if
+ } finally {
+ lock.unlock();
+ } // end try
+ if (callback != null) {
+ callback.handleResponse(this);
+ }
+ } // end method setFault( Throwable )
+
+ /**
+ * Async process completed with a wrapped Fault. Must only be invoked once.
+ * @param w - the wrapped Fault to send
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ */
+ public void setWrappedFault(AsyncFaultWrapper w) {
+
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Throwable e;
+ try {
+ // Set the TCCL to the classloader of the business interface
+ Thread.currentThread().setContextClassLoader(this.getBusinessInterface().getClassLoader());
+ e = w.retrieveFault();
+ } finally {
+ Thread.currentThread().setContextClassLoader(tccl);
+ } // end try
+
+ if( e == null ) throw new IllegalArgumentException("AsyncFaultWrapper did not return an Exception");
+ setFault( e );
+
+ } // end method setFault( AsyncFaultWrapper )
+
+ /**
+ * Async process completed with a response message. Must only be invoked once
+ * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously
+ * @param res - the response message, which is of type V
+ */
+ public void setResponse(V res) {
+
+ lock.lock();
+ try {
+ if( notSetYet() ) {
+ response = res;
+ isDone.signalAll();
+ } else {
+ throw new IllegalStateException("setResponse() or setFault() has been called previously");
+ }
+ } finally {
+ lock.unlock();
+ } // end try
+ if (callback != null) {
+ callback.handleResponse(this);
+ }
+
+ } // end method setResponse
+
+ /**
+ * Gets the unique ID of this future as a String
+ */
+ public String getUniqueID() { return uniqueID; }
+
+ /**
+ * Indicates that setting a response value is OK - can only set the response value or fault once
+ * @return - true if it is OK to set the response, false otherwise
+ */
+ private boolean notSetYet() {
+ return ( response == null && fault == null );
+ }
+
+ /**
+ * Returns the JAXWS context for the response
+ * @return - a Map containing the context
+ */
+ public Map<String, Object> getContext() {
+ // Intentionally returns null
+ return null;
+ }
+
+ /**
+ * Gets the business interface to which this Future relates
+ * @return the business interface
+ */
+ public Class getBusinessInterface() {
+ return businessInterface;
+ }
+
+ /**
+ * Sets the business interface to which this Future relates
+ * @param classLoader - the classloader of the business interface
+ */
+ public void setBusinessInterface(Class businessInterface) {
+ this.businessInterface = businessInterface;
+ }
+
+ /**
+ * Sets the callback handler, when the client uses the async callback method
+ * @param callback - the client's callback object
+ */
+ public void setCallback(AsyncHandler callback) {
+ this.callback = callback;
+ }
+
+ /**
+ * Look up an attribute value by name.
+ * @param name The name of the attribute
+ * @return The value of the attribute
+ */
+ public Object getAttribute(String name) {
+ return attributes.get(name);
+ }
+
+ /**
+ * Set the value of an attribute. Allows extensions to associate other data with an async response.
+ * @param name The name of the attribute
+ * @param value
+ */
+ public void setAttribute(String name, Object value) {
+ attributes.put(name, value);
+ }
+
+} // end class AsyncInvocationFutureImpl
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java
new file mode 100644
index 0000000000..dc5738af96
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java
@@ -0,0 +1,740 @@
+/*
+ * 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.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Response;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.context.CompositeContext;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory;
+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.RuntimeAssemblyFactory;
+import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseException;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseService;
+import org.apache.tuscany.sca.core.invocation.JDKAsyncResponseInvoker;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.util.FaultException;
+import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
+import org.apache.tuscany.sca.invocation.InterceptorAsync;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.provider.EndpointReferenceAsyncProvider;
+import org.apache.tuscany.sca.provider.PolicyProvider;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.work.WorkScheduler;
+import org.oasisopen.sca.ServiceReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * An InvocationHandler which deals with JAXWS-defined asynchronous client Java API method calls
+ *
+ * 2 asynchronous mappings exist for any given synchronous service operation, as shown in this example:
+ * public interface StockQuote {
+ * float getPrice(String ticker);
+ * Response<Float> getPriceAsync(String ticker);
+ * Future<?> getPriceAsync(String ticker, AsyncHandler<Float> handler);
+ * }
+ *
+ * - the second method is called the "polling method", since the returned Response<?> object permits
+ * the client to poll to see if the async call has completed
+ * - the third method is called the "async callback method", since in this case the client application can specify
+ * a callback operation that is automatically called when the async call completes
+ */
+public class AsyncJDKInvocationHandler extends JDKInvocationHandler {
+
+ private static final long serialVersionUID = 1L;
+
+ // Run the async service invocations using a WorkScheduler
+ private WorkScheduler scheduler;
+
+ public AsyncJDKInvocationHandler(ExtensionPointRegistry registry,
+ MessageFactory messageFactory,
+ ServiceReference<?> callableReference ) {
+ super(messageFactory, callableReference);
+ initWorkScheduler(registry);
+ }
+
+ public AsyncJDKInvocationHandler(ExtensionPointRegistry registry,
+ MessageFactory messageFactory,
+ Class<?> businessInterface,
+ Invocable source ) {
+ super(messageFactory, businessInterface, source);
+ initWorkScheduler(registry);
+ }
+
+ private final void initWorkScheduler(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ scheduler = utilities.getUtility(WorkScheduler.class);
+ } // end method initWorkScheduler
+
+ /**
+ * Perform the invocation of the operation
+ * - provides support for all 3 forms of client method: synchronous, polling and async callback
+ */
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+
+ if (Object.class == method.getDeclaringClass()) {
+ return invokeObjectMethod(method, args);
+ }
+
+ // force the bind of the reference so that we can look at the
+ // target contract to see if it's asynchronous
+ source.getInvocationChains();
+
+ if (isAsyncCallback(method)) {
+ return doInvokeAsyncCallback(proxy, method, args);
+ } else if (isAsyncPoll(method)) {
+ return doInvokeAsyncPoll(proxy, method, args, null);
+ } else {
+ // Regular synchronous method call
+ return doInvokeSync(proxy, method, args);
+ }
+ }
+
+ /**
+ * Indicates if a supplied method has the form of an async callback method
+ * @param method - the method
+ * @return - true if the method has the form of an async callback
+ */
+ protected boolean isAsyncCallback(Method method) {
+ if (method.getName().endsWith("Async") && (method.getReturnType() == Future.class)) {
+ if (method.getParameterTypes().length > 0) {
+ return method.getParameterTypes()[method.getParameterTypes().length - 1] == AsyncHandler.class;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Indicates is a supplied method has the form of an async polling method
+ * @param method - the method
+ * @return - true if the method has the form of an async polling method
+ */
+ protected boolean isAsyncPoll(Method method) {
+ return method.getName().endsWith("Async") && (method.getReturnType() == Response.class);
+ }
+
+ /**
+ * Invoke an async polling method
+ * @param proxy - the reference proxy
+ * @param asyncMethod - the async method to invoke
+ * @param args - array of input arguments to the method
+ * @return - the Response<?> object that is returned to the client application, typed by the
+ * type of the response
+ */
+ @SuppressWarnings("unchecked")
+ protected Response doInvokeAsyncPoll(Object proxy, Method asyncMethod, Object[] args, AsyncHandler callback) {
+ Method method = getNonAsyncMethod(asyncMethod);
+ Class<?> returnType = method.getReturnType();
+ // Allocate the Future<?> / Response<?> object - note: Response<?> is a subclass of Future<?>
+ AsyncInvocationFutureImpl future = AsyncInvocationFutureImpl.newInstance(returnType, businessInterface);
+ if (callback != null)
+ future.setCallback(callback);
+ try {
+ invokeAsync(proxy, method, args, future, asyncMethod);
+ } catch (Throwable t) {
+ // invokeAsync schedules a separate Runnable to run the request. Any exception caught here
+ // is a runtime exception, not an application exception.
+ if (!(t instanceof ServiceRuntimeException)) {
+ t = new ServiceRuntimeException("Received Throwable: " + t.getClass().getName()
+ + " when invoking: "
+ + asyncMethod.getName(), t);
+ }
+ future.setFault(t);
+ } // end try
+ return future;
+ } // end method doInvokeAsyncPoll
+
+ /**
+ * Provide a synchronous invocation of a service operation that is either synchronous or asynchronous
+ * @return
+ */
+ protected Object doInvokeSync(Object proxy, Method method, Object[] args) throws Throwable {
+ if (isAsyncInvocation(source)) {
+ // Target service is asynchronous
+ Class<?> returnType = method.getReturnType();
+ AsyncInvocationFutureImpl future =
+ AsyncInvocationFutureImpl.newInstance(returnType, businessInterface);
+ invokeAsync(proxy, method, args, future, method);
+ // Wait for some maximum time for the result - 120 seconds here
+ // Really, if the service is async, the client should use async client methods to invoke the service
+ // - and be prepared to wait a *really* long time
+ Object response = null;
+ try {
+ response = future.get(120, TimeUnit.SECONDS);
+ } catch (ExecutionException ex) {
+ throw ex.getCause();
+ }
+ return response;
+ } else {
+ // Target service is not asynchronous, so perform sync invocation
+ return super.invoke(proxy, method, args);
+ } // end if
+ } // end method doInvokeSync
+
+ /**
+ * Invoke an async callback method - note that this form of the async client API has as its final parameter
+ * an AsyncHandler method, used for callbacks to the client code
+ * @param proxy - the reference proxy
+ * @param asyncMethod - the async method to invoke
+ * @param args - array of input arguments to the method
+ * @return - the Future<?> object that is returned to the client application, typed by the type of
+ * the response
+ */
+ @SuppressWarnings("unchecked")
+ private Object doInvokeAsyncCallback(final Object proxy, final Method asyncMethod, final Object[] args)
+ throws Exception {
+
+ AsyncHandler callback = (AsyncHandler)args[args.length - 1];
+ Response response = doInvokeAsyncPoll(proxy, asyncMethod, Arrays.copyOf(args, args.length - 1), callback);
+ return response;
+
+ } // end method doInvokeAsyncCallback
+
+ /**
+ * Invoke the target (synchronous) method asynchronously
+ * @param proxy - the reference proxy object
+ * @param method - the method to invoke
+ * @param args - arguments for the call
+ * @param future - Future for handling the response
+ * @return - returns the response from the invocation
+ * @throws Throwable - if an exception is thrown during the invocation
+ */
+ @SuppressWarnings("unchecked")
+ private void invokeAsync(Object proxy,
+ Method method,
+ Object[] args,
+ AsyncInvocationFutureImpl<?> future,
+ Method asyncMethod) throws Throwable {
+ if (source == null) {
+ throw new ServiceRuntimeException("No runtime source is available");
+ }
+
+ if (source instanceof RuntimeEndpointReference) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
+ if (epr.isOutOfDate()) {
+ epr.rebuild();
+ chains.clear();
+ }
+ } // end if
+
+ InvocationChain chain = getInvocationChain(method, source);
+
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + method);
+ }
+
+ // Organize for an async service
+ RuntimeEndpoint theEndpoint = getAsyncCallback(source);
+ boolean isAsyncService = false;
+ if (theEndpoint != null) {
+ // ... the service is asynchronous but binding does not support async natively ...
+ attachFuture(theEndpoint, future);
+ } // end if
+
+ if( isAsyncInvocation((RuntimeEndpointReference)source ) ) {
+ isAsyncService = true;
+ // Get hold of the JavaAsyncResponseHandler from the chain dealing with the async response
+ Invoker theInvoker = chain.getHeadInvoker();
+ if( theInvoker instanceof InterceptorAsync ) {
+ InvokerAsyncResponse responseInvoker = ((InterceptorAsync)theInvoker).getPrevious();
+ if( responseInvoker instanceof JDKAsyncResponseInvoker ) {
+ // Register the future as the response object with its ID
+ ((JDKAsyncResponseInvoker)responseInvoker).registerAsyncResponse(future.getUniqueID(), future);
+ } // end if
+ } // end if
+ } // end if
+
+ // Perform the invocations on separate thread...
+ scheduler.scheduleWork(new SeparateThreadInvoker(chain, args, source, future, asyncMethod, isAsyncService));
+
+ return;
+ } // end method invokeAsync
+
+ /**
+ * An inner class which acts as a runnable task for invoking services asynchronously on threads that are separate from
+ * those used to execute operations of components
+ *
+ * This supports both synchronous services and asynchronous services
+ */
+ private class SeparateThreadInvoker implements Runnable {
+
+ private AsyncInvocationFutureImpl future;
+ private Method asyncMethod;
+ private InvocationChain chain;
+ private Object[] args;
+ private Invocable invocable;
+ private boolean isAsyncService;
+
+ public SeparateThreadInvoker(InvocationChain chain,
+ Object[] args,
+ Invocable invocable,
+ AsyncInvocationFutureImpl future,
+ Method asyncMethod,
+ boolean isAsyncService) {
+ super();
+ this.chain = chain;
+ this.asyncMethod = asyncMethod;
+ this.args = args;
+ this.invocable = invocable;
+ this.future = future;
+ this.isAsyncService = isAsyncService;
+ } // end constructor
+
+ public void run() {
+ Object result;
+
+ try {
+ if (isAsyncService) {
+ if( supportsNativeAsync(invocable) ) {
+ // Binding supports native async invocations
+ invokeAsync(chain, args, invocable, future.getUniqueID());
+ } else {
+ // Binding does not support native async invocations
+ invoke(asyncMethod, chain, args, invocable, future.getUniqueID());
+ } // end if
+ // The result is returned asynchronously via the future...
+ } else {
+ // ... the service is synchronous ...
+ result = invoke(asyncMethod, chain, args, invocable);
+ Type type = null;
+ if (asyncMethod.getReturnType() == Future.class) {
+ // For callback async method, where a Future is returned
+ Type[] types = asyncMethod.getGenericParameterTypes();
+ if (types.length > 0 && asyncMethod.getParameterTypes()[types.length - 1] == AsyncHandler.class) {
+ // Last parameter is AsyncHandler<T>
+ type = types[types.length - 1];
+ } // end if
+ } else if (asyncMethod.getReturnType() == Response.class) {
+ // For the polling method, Response<T>
+ type = asyncMethod.getGenericReturnType();
+ } // end if
+ if (type instanceof ParameterizedType) {
+ // Check if the parameterized type of Response<T> is a doc-lit-wrapper class
+ Class<?> wrapperClass = (Class<?>)((ParameterizedType)type).getActualTypeArguments()[0];
+ WrapperInfo wrapperInfo = chain.getSourceOperation().getOutputWrapper();
+ if (wrapperInfo != null && wrapperInfo.getWrapperClass() == wrapperClass) {
+ Object wrapper = wrapperClass.newInstance();
+ // Find the 1st matching property
+ for (PropertyDescriptor p : Introspector.getBeanInfo(wrapperClass).getPropertyDescriptors()) {
+ if (p.getWriteMethod() == null) {
+ // There is a "class" property ...
+ continue;
+ } // end if
+ if (p.getWriteMethod().getParameterTypes()[0].isInstance(result)) {
+ p.getWriteMethod().invoke(wrapper, result);
+ result = wrapper;
+ break;
+ } // end if
+ } // end for
+ } // end if
+ } // end if
+ future.setResponse(result);
+ } // end if
+ } catch (ServiceRuntimeException s) {
+ Throwable e = s.getCause();
+ if (e != null && e instanceof FaultException) {
+ if ("AsyncResponse".equals(e.getMessage())) {
+ // Do nothing...
+ } else {
+ future.setFault(s);
+ } // end if
+ } // end if
+ else {
+ future.setFault(s);
+ }
+ } catch (AsyncResponseException ar) {
+ // This exception is received in the case where the Binding does not support async invocation
+ // natively - the initial invocation is effectively synchronous with this exception thrown to
+ // indicate that the service received the request but will send the response separately - do nothing
+ } catch (Throwable t) {
+ //System.out.println("Async invoke got exception: " + t.toString());
+ // If we invoked a sync service, this might be an application exception.
+ // The databinding ensured the exception is type-compatible with the application.
+ future.setFault(t);
+ } // end try
+
+ } // end method run
+
+ } // end class SeparateThreadInvoker
+
+ /**
+ * Attaches a future to the callback endpoint - so that the Future is triggered when a response is
+ * received from the asynchronous service invocation associated with the Future
+ * @param endpoint - the async callback endpoint
+ * @param future - the async invocation future to attach
+ */
+ private void attachFuture(RuntimeEndpoint endpoint, AsyncInvocationFutureImpl<?> future) {
+ Implementation impl = endpoint.getComponent().getImplementation();
+ AsyncResponseHandlerImpl<?> asyncHandler = (AsyncResponseHandlerImpl<?>)impl;
+ asyncHandler.addFuture(future);
+ } // end method attachFuture
+
+ /**
+ * Perform an async invocation on the reference
+ * @param chain - the chain
+ * @param args - parameters for the invocation
+ * @param invocable - the reference
+ * @param msgID - a message ID
+ */
+ public void invokeAsync(InvocationChain chain, Object[] args, Invocable invocable, String msgID) {
+ Message msg = messageFactory.createMessage();
+ if (invocable instanceof RuntimeEndpointReference) {
+ msg.setFrom((RuntimeEndpointReference)invocable);
+ } // end if
+ if (target != null) {
+ msg.setTo(target);
+ } else if (source instanceof RuntimeEndpointReference) {
+ msg.setTo(((RuntimeEndpointReference)invocable).getTargetEndpoint());
+ } // end if
+
+ Operation operation = chain.getTargetOperation();
+ msg.setOperation(operation);
+ msg.setBody(args);
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ // Deal with header information that needs to be copied from the message context to the new message...
+ transferMessageHeaders( msg, msgContext);
+
+ ThreadMessageContext.setMessageContext(msg);
+
+ // If there is a supplied message ID, place its value into the Message Header under "MESSAGE_ID"
+ if( msgID != null ){
+ msg.getHeaders().put("MESSAGE_ID", msgID);
+ } // end if
+
+ try {
+ // Invoke the reference
+ invocable.invokeAsync(msg);
+ return;
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ } // end try
+ } // end method invokeAsync
+
+ /**
+ * Get the async callback endpoint - if not already created, create and start it
+ * @param source - the RuntimeEndpointReference which needs an async callback endpoint
+ * @param future
+ * @return - the RuntimeEndpoint of the async callback
+ */
+ private RuntimeEndpoint getAsyncCallback(Invocable source) {
+ if (!(source instanceof RuntimeEndpointReference))
+ return null;
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
+ if (!isAsyncInvocation(epr)) return null;
+
+ // Check to see if the binding supports async invocation natively
+ ReferenceBindingProvider eprProvider = epr.getBindingProvider();
+ if( eprProvider instanceof EndpointReferenceAsyncProvider) {
+ if( ((EndpointReferenceAsyncProvider)eprProvider).supportsNativeAsync() ) return null;
+ } // end if
+
+ RuntimeEndpoint endpoint;
+ synchronized (epr) {
+ endpoint = (RuntimeEndpoint)epr.getCallbackEndpoint();
+ // If the async callback endpoint is already created, return it...
+ if (endpoint != null)
+ return endpoint;
+ // Create the endpoint for the async callback
+ endpoint = createAsyncCallbackEndpoint(epr);
+ epr.setCallbackEndpoint(endpoint);
+ } // end synchronized
+
+ // Activate the new callback endpoint
+ startEndpoint(epr.getCompositeContext(), endpoint);
+ endpoint.getInvocationChains();
+
+ return endpoint;
+ } // end method setupAsyncCallback
+
+ /**
+ * Start the callback endpoint
+ * @param compositeContext - the composite context
+ * @param ep - the endpoint to start
+ */
+ private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep) {
+ for (PolicyProvider policyProvider : ep.getPolicyProviders()) {
+ policyProvider.start();
+ } // end for
+
+ final ServiceBindingProvider bindingProvider = ep.getBindingProvider();
+ 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;
+ }
+ });
+ compositeContext.getEndpointRegistry().addEndpoint(ep);
+ }
+ } // end method startEndpoint
+
+ /**
+ * Create the async callback endpoint for a reference that is going to invoke an asyncInvocation service
+ * @param epr - the RuntimeEndpointReference for which the callback is created
+ * @return - a RuntimeEndpoint representing the callback endpoint
+ */
+ private RuntimeEndpoint createAsyncCallbackEndpoint(RuntimeEndpointReference epr) {
+ CompositeContext compositeContext = epr.getCompositeContext();
+ RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory(compositeContext);
+ RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
+ endpoint.bind(compositeContext);
+
+ // Create a pseudo-component and pseudo-service
+ // - need to end with a chain with an invoker into the AsyncCallbackHandler class
+ RuntimeComponent fakeComponent = null;
+ try {
+ fakeComponent = (RuntimeComponent)epr.getComponent().clone();
+ applyImplementation(fakeComponent);
+ } catch (CloneNotSupportedException e2) {
+ // will not happen
+ } // end try
+ endpoint.setComponent(fakeComponent);
+
+ // Create pseudo-service
+ ComponentService service = assemblyFactory.createComponentService();
+ ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ JavaInterfaceFactory javaInterfaceFactory =
+ (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class);
+ JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ try {
+ interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseService.class));
+ } catch (InvalidInterfaceException e1) {
+ // Nothing to do here - will not happen
+ } // end try
+ service.setInterfaceContract(interfaceContract);
+ String serviceName = epr.getReference().getName() + "_asyncCallback";
+ service.setName(serviceName);
+ // MJE 06/12/2010 - fixup for JMS binding code which looks at the implementation service
+ // as well as the component service...
+ // Create a pseudo implementation service...
+ Service implService = assemblyFactory.createService();
+ implService.setName(serviceName);
+ implService.setInterfaceContract(interfaceContract);
+ service.setService(implService);
+ //
+ endpoint.setService(service);
+ // Set pseudo-service onto the pseudo-component
+ List<ComponentService> services = fakeComponent.getServices();
+ services.clear();
+ services.add(service);
+
+ // Create a binding
+ Binding binding = createMatchingBinding(epr.getBinding(), fakeComponent, service, registry);
+ endpoint.setBinding(binding);
+
+ // Need to establish policies here (binding has some...)
+ endpoint.getRequiredIntents().addAll(epr.getRequiredIntents());
+ endpoint.getPolicySets().addAll(epr.getPolicySets());
+ String epURI = epr.getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")";
+ endpoint.setURI(epURI);
+ endpoint.setUnresolved(false);
+ return endpoint;
+ }
+
+ /**
+ * Create a matching binding to a supplied binding
+ * - the matching binding has the same binding type, but is for the supplied component and service
+ * @param matchBinding - the binding to match
+ * @param component - the component
+ * @param service - the service
+ * @param registry - registry for extensions
+ * @return - the matching binding, or null if it could not be created
+ */
+ @SuppressWarnings("unchecked")
+ private Binding createMatchingBinding(Binding matchBinding,
+ RuntimeComponent component,
+ ComponentService service,
+ ExtensionPointRegistry registry) {
+ // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of
+ // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName
+ // and then read the XML using the processor for that XML...
+ QName bindingName = matchBinding.getType();
+ String bindingXML =
+ "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>";
+
+ StAXArtifactProcessorExtensionPoint processors =
+ registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName);
+
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class);
+ StreamSource source = new StreamSource(new StringReader(bindingXML));
+
+ ProcessorContext context = new ProcessorContext();
+ try {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(source);
+ reader.next();
+ Binding newBinding = (Binding)processor.read(reader, context);
+
+ // Create a URI address for the callback based on the Component_Name/Reference_Name pattern
+ String callbackURI = "/" + component.getName() + "/" + service.getName();
+ newBinding.setURI(callbackURI);
+
+ BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
+ BindingBuilder builder = builders.getBindingBuilder(newBinding.getType());
+ if (builder != null) {
+ org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
+ builder.build(component, service, newBinding, builderContext, true);
+ } // end if
+
+ return newBinding;
+ } catch (ContributionReadException e) {
+ e.printStackTrace();
+ } catch (XMLStreamException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ } // end method createMatchingBinding
+
+ /**
+ * Gets a RuntimeAssemblyFactory from the CompositeContext
+ * @param compositeContext
+ * @return the RuntimeAssemblyFactory
+ */
+ private RuntimeAssemblyFactory getAssemblyFactory(CompositeContext compositeContext) {
+ ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
+ } // end method RuntimeAssemblyFactory
+
+ /**
+ * Applies an AsyncResponseHandlerImpl as the implementation of a RuntimeComponent
+ * - the AsyncResponseHandlerImpl acts as both the implementation class and the implementation provider...
+ * @param component - the component
+ */
+ private void applyImplementation(RuntimeComponent component) {
+ AsyncResponseHandlerImpl<?> asyncHandler = new AsyncResponseHandlerImpl<Object>();
+ component.setImplementation(asyncHandler);
+ component.setImplementationProvider(asyncHandler);
+ return;
+ } // end method getImplementationProvider
+
+ private static QName ASYNC_INVOKE = new QName(Constants.SCA11_NS, "asyncInvocation");
+
+ /**
+ * Determines if the service invocation is asynchronous
+ * @param source - the EPR involved in the invocation
+ * @return - true if the invocation is async
+ */
+ private boolean isAsyncInvocation(Invocable source) {
+ if (!(source instanceof RuntimeEndpointReference))
+ return false;
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
+ // First check is to see if the EPR itself has the asyncInvocation intent marked
+ for (Intent intent : epr.getRequiredIntents()) {
+ if (intent.getName().equals(ASYNC_INVOKE))
+ return true;
+ } // end for
+
+ // Second check is to see if the target service has the asyncInvocation intent marked
+ Endpoint ep = epr.getTargetEndpoint();
+ for (Intent intent : ep.getRequiredIntents()) {
+ if (intent.getName().equals(ASYNC_INVOKE))
+ return true;
+ } // end for
+ return false;
+ } // end isAsyncInvocation
+
+ private boolean supportsNativeAsync(Invocable source) {
+ if (!(source instanceof RuntimeEndpointReference))
+ return false;
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
+
+ // TODO - need to update this once BindingProvider interface is refactored to contain
+ // supportsNativeAsync directly...
+ ReferenceBindingProvider provider = epr.getBindingProvider();
+ if( provider instanceof EndpointReferenceAsyncProvider ) {
+ return ((EndpointReferenceAsyncProvider)provider).supportsNativeAsync();
+ } else {
+ return false;
+ } // end if
+ } // end method supportsNativeAsync
+
+ /**
+ * Return the synchronous method that is the equivalent of an async method
+ * @param asyncMethod - the async method
+ * @return - the equivalent synchronous method
+ */
+ protected Method getNonAsyncMethod(Method asyncMethod) {
+ String methodName = asyncMethod.getName().substring(0, asyncMethod.getName().length() - 5);
+ for (Method m : businessInterface.getMethods()) {
+ if (methodName.equals(m.getName())) {
+ return m;
+ }
+ }
+ throw new IllegalStateException("No synchronous method matching async method " + asyncMethod.getName());
+ } // end method getNonAsyncMethod
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java
new file mode 100644
index 0000000000..7b459f3e7d
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.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.invocation.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.ws.Response;
+
+public class AsyncResponse implements Response {
+
+ private Object response;
+ private boolean isException;
+
+ public AsyncResponse(Object response, boolean isException) {
+ this.response = response;
+ this.isException = isException;
+ }
+
+ public Map getContext() {
+ return new HashMap();
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ public Object get() throws InterruptedException, ExecutionException {
+ if (isException) {
+ throw new ExecutionException((Throwable)response);
+ } else {
+ return response;
+ }
+ }
+
+ public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ return get();
+ }
+
+ public boolean isCancelled() {
+ return false;
+ }
+
+ public boolean isDone() {
+ return true;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java
new file mode 100644
index 0000000000..9de1809200
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper;
+import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler;
+import org.apache.tuscany.sca.core.invocation.Constants;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.policy.ExtensionType;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * A class intended to form the final link in the chain calling into a Future which represents
+ * the response to an asynchronous service invocation
+ *
+ * Most methods are dummies, required to fulfil the contracts for ImplementationProvider, Implementation
+ * and Invoker, since this class collapses together the functions of these separate interfaces, due to its
+ * specialized nature, where most of the function will never be used.
+ *
+ * The class acts as the implementation object that terminates the chain - and also as the provider of the implementation.
+ * The class accepts Future objects which represent individual invocations of forward operations on the async service
+ * and expects that the responses it handles as invocations will carry the unique ID of one of the Future objects in the
+ * message header. On receipt of each message, the class seeks out the Future with that unique ID and completes the future
+ * either with a response message or with a Fault.
+ *
+ * @param <V>
+ */
+public class AsyncResponseHandlerImpl<V> implements AsyncResponseHandler<V>,
+ ImplementationProvider, Implementation, Invoker {
+
+ private ConcurrentHashMap< String, AsyncInvocationFutureImpl<?> > table =
+ new ConcurrentHashMap< String, AsyncInvocationFutureImpl<?> >();
+
+ /**
+ * This class is its own invoker...
+ */
+ public Invoker createInvoker(RuntimeComponentService service,
+ Operation operation) {
+ return this;
+ }
+
+ /**
+ * Add a future to this response handler
+ * @param future - the future
+ */
+ public void addFuture( AsyncInvocationFutureImpl<?> future ) {
+ // The Future is stored in the table indexed by its unique ID
+ table.put(future.getUniqueID(), future);
+ } // end method addFuture
+
+ public boolean supportsOneWayInvocation() {
+ return true;
+ }
+
+ public void start() {}
+
+ public void stop() {}
+
+ public List<Operation> getOperations() {
+ return null;
+ }
+
+ public QName getType() {
+ return null;
+ }
+
+ public List<Property> getProperties() {
+ return null;
+ }
+
+ public Property getProperty(String name) {
+ return null;
+ }
+
+ public Reference getReference(String name) {
+ return null;
+ }
+
+ public List<Reference> getReferences() {
+ return null;
+ }
+
+ public Service getService(String name) {
+ return null;
+ }
+
+ public List<Service> getServices() {
+ return null;
+ }
+
+ public String getURI() {
+ return null;
+ }
+
+ public void setURI(String uri) {}
+
+ public boolean isUnresolved() {
+ return false;
+ }
+
+ public void setUnresolved(boolean unresolved) {}
+
+ public ExtensionType getExtensionType() {
+ return null;
+ }
+
+ public List<PolicySet> getPolicySets() {
+ return null;
+ }
+
+ public List<Intent> getRequiredIntents() {
+ return null;
+ }
+
+ public void setExtensionType(ExtensionType type) {}
+
+ public void setWrappedFault(AsyncFaultWrapper e) {}
+
+ public void setFault(Throwable e) {}
+
+ public void setResponse(V res) { }
+
+ /**
+ * Method which is the termination for the invocation chain from the callback endpoint
+ * @param msg - the Tuscany message containing the response from the async service invocation
+ * which is either the Response message or an exception of some kind
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Message invoke(Message msg) {
+ // Get the unique ID from the RELATES_TO message header
+ String idValue = (String)msg.getHeaders().get(Constants.RELATES_TO);
+
+ if( idValue == null ) {
+ System.out.println( "Async message ID not found ");
+ } else {
+ // Fetch the Future with that Unique ID
+ AsyncInvocationFutureImpl future = table.get(idValue);
+ if( future == null ) {
+ System.out.println("Future not found for id: " + idValue);
+ } else {
+ // Complete the Future with a Response message
+ Object payload = msg.getBody();
+ Object response;
+ if( payload == null ) {
+ System.out.println("Returned response message was null");
+ } else {
+ if (payload.getClass().isArray()) {
+ response = ((Object[])payload)[0];
+ } else {
+ response = payload;
+ } // end if
+ if( response.getClass().equals(AsyncFaultWrapper.class)) {
+ future.setWrappedFault((AsyncFaultWrapper) response );
+ } else {
+ future.setResponse(response);
+ } // end if
+ } // end if
+ } // end if
+ } // end if
+
+ // Prepare an empty response message
+ msg.setBody(null);
+ return msg;
+ } // end method invoke
+
+} // end class
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java
new file mode 100644
index 0000000000..0e4d4344d2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java
@@ -0,0 +1,313 @@
+/*
+ * 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.core.invocation.InterceptorAsyncImpl;
+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.InterceptorAsync;
+import org.apache.tuscany.sca.invocation.InvocationChain;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.InvokerAsyncRequest;
+import org.apache.tuscany.sca.invocation.InvokerAsyncResponse;
+import org.apache.tuscany.sca.invocation.Phase;
+import org.apache.tuscany.sca.invocation.PhasedInterceptor;
+
+/**
+ * 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>();
+
+ private final PhaseManager phaseManager;
+ private boolean forReference;
+ private boolean allowsPassByReference;
+ private boolean isAsyncInvocation;
+
+ public InvocationChainImpl(Operation sourceOperation, Operation targetOperation, boolean forReference, PhaseManager phaseManager, boolean isAsyncInvocation) {
+ this.targetOperation = targetOperation;
+ this.sourceOperation = sourceOperation;
+ this.forReference = forReference;
+ this.phaseManager = phaseManager;
+ this.isAsyncInvocation = isAsyncInvocation;
+ }
+
+ public Operation getTargetOperation() {
+ return targetOperation;
+ }
+
+ public void setTargetOperation(Operation operation) {
+ this.targetOperation = operation;
+ }
+
+ public void addInterceptor(Interceptor interceptor) {
+ if (interceptor instanceof PhasedInterceptor) {
+ PhasedInterceptor pi = (PhasedInterceptor)interceptor;
+ if (pi.getPhase() != null) {
+ addInvoker(pi.getPhase(), pi);
+ return;
+ }
+ }
+ String phase = forReference ? Phase.REFERENCE : Phase.SERVICE;
+ addInterceptor(phase, interceptor);
+ } // end method addInterceptor
+
+ public void addInvoker(Invoker invoker) {
+ if (invoker instanceof PhasedInterceptor) {
+ PhasedInterceptor pi = (PhasedInterceptor)invoker;
+ if (pi.getPhase() != null) {
+ addInvoker(pi.getPhase(), pi);
+ return;
+ }
+ }
+ 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() {
+ int nodeCount = nodes.size();
+ if( nodeCount > 0 ) {
+ return nodes.get( nodeCount - 1).getInvoker();
+ } // end if
+
+ return null;
+ } // end method getTailInvoker
+
+ public Invoker getHeadInvoker(String phase) {
+ int index = phaseManager.getAllPhases().indexOf(phase);
+ if (index == -1) {
+ throw new IllegalArgumentException("Invalid phase name: " + phase);
+ }
+ for (Node node : nodes) {
+ if (index <= node.getPhaseIndex()) {
+ return node.getInvoker();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @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(String phase, Interceptor interceptor) {
+ addInvoker(phase, interceptor);
+ }
+
+ private void addInvoker(String phase, Invoker invoker) {
+ if (isAsyncInvocation &&
+ !(invoker instanceof InvokerAsyncRequest) &&
+ !(invoker instanceof InvokerAsyncResponse) ){
+ // TODO - should raise an error but don't want to break
+ // the existing non-native async support
+/*
+ throw new IllegalArgumentException("Trying to add synchronous invoker " +
+ invoker.getClass().getName() +
+ " to asynchronous chain");
+*/
+ }
+
+ 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 ((invoker instanceof InterceptorAsync) &&
+ (before.getInvoker() instanceof InvokerAsyncResponse)) {
+ ((InterceptorAsync) invoker).setPrevious((InvokerAsyncResponse)before.getInvoker());
+ }
+ }
+ }
+ if (after != null) {
+ if (invoker instanceof Interceptor) {
+ ((Interceptor)invoker).setNext(after.getInvoker());
+ if ((after.getInvoker() instanceof InterceptorAsync) &&
+ (invoker instanceof InvokerAsyncResponse)){
+ ((InterceptorAsync) after.getInvoker()).setPrevious((InvokerAsyncResponse)invoker);
+ }
+ }
+ }
+
+ }
+
+ 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;
+ }
+ }
+
+ public boolean isAsyncInvocation() {
+ return isAsyncInvocation;
+ }
+
+ public void addHeadInterceptor(Interceptor interceptor) {
+ String phase = forReference ? Phase.REFERENCE : Phase.SERVICE_BINDING;
+ if (interceptor instanceof PhasedInterceptor) {
+ PhasedInterceptor pi = (PhasedInterceptor)interceptor;
+ if (pi.getPhase() != null) {
+ phase = pi.getPhase();
+ } // end if
+ } // end if
+
+ addHeadInterceptor(phase, interceptor);
+ } // end method addHeadInterceptor
+
+ public void addHeadInterceptor(String phase, Interceptor interceptor) {
+ // TODO Auto-generated method stub
+ Invoker invoker = (Invoker)interceptor;
+
+ int index = phaseManager.getAllPhases().indexOf(phase);
+ if (index == -1) {
+ throw new IllegalArgumentException("Invalid phase name: " + phase);
+ } // end if
+ 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();
+ // Look for the first node with a phase index equal to or greater than the one provided
+ 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 ((invoker instanceof InterceptorAsync) &&
+ (before.getInvoker() instanceof InvokerAsyncResponse)) {
+ ((InterceptorAsync) invoker).setPrevious((InvokerAsyncResponse)before.getInvoker());
+ }
+ }
+ }
+ if (after != null) {
+ if (invoker instanceof Interceptor) {
+ ((Interceptor)invoker).setNext(after.getInvoker());
+ if ((after.getInvoker() instanceof InterceptorAsync) &&
+ (invoker instanceof InvokerAsyncResponse)){
+ ((InterceptorAsync) after.getInvoker()).setPrevious((InvokerAsyncResponse)invoker);
+ }
+ }
+ }
+
+ } // end method addHeadInterceptor
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java
new file mode 100644
index 0000000000..bde3e92c27
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.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.invocation.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.Constants;
+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.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.oasisopen.sca.ServiceReference;
+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, ServiceReference<?> ref) {
+ super(messageFactory, ref);
+ this.fixedWire = false;
+ }
+
+ @Override
+ @SuppressWarnings( {"unchecked", "rawtypes"})
+ 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
+ RuntimeEndpointReference wire = ((CallbackServiceReferenceImpl)callableReference).getCallbackEPR();
+ if (wire == null) {
+ //FIXME: need better exception
+ throw new ServiceRuntimeException("No callback wire found");
+ }
+
+ setEndpoint(((CallbackServiceReferenceImpl)callableReference).getResolvedEndpoint());
+
+ InvocationChain chain = getInvocationChain(method, wire);
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + method);
+ }
+
+ try {
+ String msgID = ((CallbackServiceReferenceImpl)callableReference).getMsgID();
+ return invoke(method, chain, args, wire, msgID );
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ throw t;
+ } finally {
+ // allow the cloned wire to be reused by subsequent callbacks
+ }
+ }
+
+ /**
+ * Invoke the chain
+ * @param chain - the chain
+ * @param args - arguments to the invocation as an array of Objects
+ * @param source - the Endpoint or EndpointReference to which the chain relates
+ * @param msgID - ID of the message to which this invovation is a callback - ID ends up in "RELATES_TO" header
+ * @return - the Response message from the invocation
+ * @throws Throwable - if any exception occurs during the invocation
+ */
+ @Override
+ protected Object invoke(Method method, InvocationChain chain, Object[] args, Invocable source, String msgID)
+ throws Throwable {
+ Message msg = messageFactory.createMessage();
+ if (source instanceof RuntimeEndpointReference) {
+ msg.setFrom((RuntimeEndpointReference)source);
+ }
+ if (target != null) {
+ msg.setTo(target);
+ } else {
+ if (source instanceof RuntimeEndpointReference) {
+ msg.setTo(((RuntimeEndpointReference)source).getTargetEndpoint());
+ }
+ }
+
+ msg.getHeaders().put(Constants.CALLBACK, ((CallbackServiceReferenceImpl)callableReference).getCallbackHandler());
+
+ Invoker headInvoker = chain.getHeadInvoker();
+
+ Operation operation = null;
+ if(source instanceof RuntimeEndpoint) {
+ for (InvocationChain c : source.getInvocationChains()) {
+ Operation op = c.getTargetOperation();
+ if (method.getName().equals(op.getName())) {
+ operation = op;
+ break;
+ }
+ }
+ } else {
+ operation = chain.getTargetOperation();
+ }
+ msg.setOperation(operation);
+ msg.setBody(args);
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ // Deal with header information that needs to be copied from the message context to the new message...
+ transferMessageHeaders( msg, msgContext);
+
+ ThreadMessageContext.setMessageContext(msg);
+
+ // If there is a supplied message ID, place its value into the Message Header under "RELATES_TO"
+ if( msgID != null ){
+ msg.getHeaders().put(Constants.RELATES_TO, msgID);
+ } // end if
+
+ try {
+ // dispatch the source down the chain and get the response
+ Message resp = headInvoker.invoke(msg);
+ Object body = resp.getBody();
+ if (resp.isFault()) {
+ throw (Throwable)body;
+ }
+ return body;
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+ } // end method invoke
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java
new file mode 100644
index 0000000000..827008dc73
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java
@@ -0,0 +1,436 @@
+/*
+ * 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.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.ws.Holder;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.context.ThreadMessageContext;
+import org.apache.tuscany.sca.core.context.ServiceReferenceExt;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.ParameterMode;
+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.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+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 MessageFactory messageFactory;
+ protected Endpoint target;
+ protected Invocable source;
+ protected ServiceReferenceExt<?> callableReference;
+ protected Class<?> businessInterface;
+
+ protected boolean fixedWire = true;
+
+ protected transient Map<Method, InvocationChain> chains = new IdentityHashMap<Method, InvocationChain>();
+
+ public JDKInvocationHandler(MessageFactory messageFactory, Class<?> businessInterface, Invocable source) {
+ this.messageFactory = messageFactory;
+ this.source = source;
+ this.businessInterface = businessInterface;
+ }
+
+ public JDKInvocationHandler(MessageFactory messageFactory, ServiceReference<?> callableReference) {
+ this.messageFactory = messageFactory;
+ this.callableReference = (ServiceReferenceExt<?>)callableReference;
+ if (callableReference != null) {
+ this.businessInterface = callableReference.getBusinessInterface();
+ this.source = (RuntimeEndpointReference) this.callableReference.getEndpointReference();
+ }
+ }
+
+
+ public Class<?> getBusinessInterface() {
+ return businessInterface;
+ }
+
+ protected Object getCallbackID() {
+ return null;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (Object.class == method.getDeclaringClass()) {
+ return invokeObjectMethod(method, args);
+ }
+ if (source == null) {
+ throw new ServiceRuntimeException("No runtime source is available");
+ }
+
+ if (source instanceof RuntimeEndpointReference) {
+ RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
+ if (epr.isOutOfDate()) {
+ epr.rebuild();
+ chains.clear();
+ }
+ }
+
+ InvocationChain chain = getInvocationChain(method, source);
+
+ if (chain == null) {
+ throw new IllegalArgumentException("No matching operation is found: " + method);
+ }
+
+ // Holder pattern. Items stored in a Holder<T> are promoted to T.
+ // After the invoke, the returned data <T> are placed back in Holder<T>.
+ Object [] promotedArgs = promoteHolderArgs( args );
+
+ // Strip out OUT-only arguments. Not too sure if the presence
+ // of a sourceOperation is exactly the right check to use to
+ // know whether or not to do this, but will assume it is until
+ // learning otherwise.
+ Operation sourceOp = chain.getSourceOperation();
+ if (sourceOp != null) {
+ promotedArgs = removeOutOnlyArgs(sourceOp, promotedArgs );
+ }
+
+ Object result = invoke(method, chain, promotedArgs, source);
+
+ // TODO - Based on the code in JavaInterfaceIntrospectorImpl, it seems there are
+ // some cases involving generics that we're not taking into account.
+ boolean voidReturnType = (void.class == method.getReturnType() ? true : false);
+
+ // Returned Holder data <T> are placed back in Holder<T>.
+ boolean holderPattern = false;
+ Class [] parameters = method.getParameterTypes();
+ if ( parameters != null ) {
+ int resultIdx = (voidReturnType ? 0 : 1);
+ for ( int i = 0; i < parameters.length; i++ ) {
+ Class parameterType = parameters[ i ];
+ if ( isHolder( parameterType ) ) {
+ holderPattern = true;
+ // Pop results and place in holder (demote).
+ Holder holder = (Holder) args[ i ];
+
+ Object[] results = (Object[])result;
+ if ( result != null ) {
+ holder.value = results[resultIdx++];
+ }
+ }
+ }
+ }
+ if (holderPattern && result != null) {
+ if (voidReturnType) {
+ return null;
+ } else {
+ return ((Object[])result)[0];
+ }
+ } else {
+ 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.isInputWrapperStyle()) {
+ inputType = operation.getInputWrapper().getUnwrappedType();
+ } 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, Invocable source) {
+ if (source instanceof RuntimeEndpoint) {
+ // [rfeng] Start with the binding invocation chain
+ return source.getBindingInvocationChain();
+ }
+ if (fixedWire && chains.containsKey(method)) {
+ return chains.get(method);
+ }
+ InvocationChain found = null;
+ for (InvocationChain chain : source.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(Endpoint endpoint) {
+ this.target = endpoint;
+ }
+
+ protected Object invoke(Method method, InvocationChain chain, Object[] args, Invocable source)
+ throws Throwable {
+ return invoke( method, chain, args, source, null );
+ }
+
+ /**
+ * Invoke the chain
+ * @param chain - the chain
+ * @param args - arguments to the invocation as an array of Objects
+ * @param source - the Endpoint or EndpointReference to which the chain relates
+ * @param msgID - an ID for the message being sent, may be null
+ * @return - the Response message from the invocation
+ * @throws Throwable - if any exception occurs during the invocation
+ */
+ protected Object invoke(Method method, InvocationChain chain, Object[] args, Invocable source, String msgID)
+ throws Throwable {
+ Message msg = messageFactory.createMessage();
+ if (source instanceof RuntimeEndpointReference) {
+ msg.setFrom((RuntimeEndpointReference)source);
+ }
+ if (target != null) {
+ msg.setTo(target);
+ } else {
+ if (source instanceof RuntimeEndpointReference) {
+ msg.setTo(((RuntimeEndpointReference)source).getTargetEndpoint());
+ }
+ }
+ Invoker headInvoker = chain.getHeadInvoker();
+ Operation operation = null;
+ if(source instanceof RuntimeEndpoint) {
+ // [rfeng] We cannot use the targetOperation from the binding invocation chain.
+ // For each method, we need to find the matching operation so that we can set the operation on to the message
+ for (InvocationChain c : source.getInvocationChains()) {
+ Operation op = c.getTargetOperation();
+ if (method.getName().equals(op.getName())) {
+ operation = op;
+ break;
+ }
+ }
+ } else {
+ operation = chain.getTargetOperation();
+ }
+ msg.setOperation(operation);
+ msg.setBody(args);
+
+ Message msgContext = ThreadMessageContext.getMessageContext();
+
+ // Deal with header information that needs to be copied from the message context to the new message...
+ transferMessageHeaders( msg, msgContext);
+
+ ThreadMessageContext.setMessageContext(msg);
+
+ // If there is a supplied message ID, place its value into the Message Header under "MESSAGE_ID"
+ if( msgID != null ){
+ msg.getHeaders().put("MESSAGE_ID", msgID);
+ } // end if
+
+ try {
+ // dispatch the source down the chain and get the response
+ Message resp = headInvoker.invoke(msg);
+ Object body = resp.getBody();
+ if (resp.isFault()) {
+ throw (Throwable)body;
+ }
+ return body;
+ } finally {
+ ThreadMessageContext.setMessageContext(msgContext);
+ }
+ }
+
+ /**
+ * Transfer relevant header information from the old message (incoming) to the new message (outgoing)
+ * @param newMsg
+ * @param oldMsg
+ */
+ protected void transferMessageHeaders( Message newMsg, Message oldMsg ) {
+ if( oldMsg == null ) return;
+ // For the present, simply copy all the headers
+ if( !oldMsg.getHeaders().isEmpty() ) newMsg.getHeaders().putAll( oldMsg.getHeaders() );
+ } // end transferMessageHeaders
+
+ /**
+ * @return the callableReference
+ */
+ public ServiceReference<?> getCallableReference() {
+ return callableReference;
+ }
+
+ /**
+ * @param callableReference the callableReference to set
+ */
+ public void setCallableReference(ServiceReference<?> callableReference) {
+ this.callableReference = (ServiceReferenceExt<?>)callableReference;
+ }
+
+ /**
+ * Creates a copy of arguments. Holder<T> values are promoted to T.
+ * Note. It is essential that arg Holders not be destroyed here.
+ * PromotedArgs should not destroy holders. They are used on response return.
+ * @param args containing Holders and other objects.
+ * @return Object []
+ */
+ protected static Object [] promoteHolderArgs( Object [] args ) {
+ if ( args == null )
+ return args;
+ Object [] promotedArgs = new Object[ args.length ];
+
+ for ( int i = 0; i < args.length; i++ ) {
+ Object argument = args[ i ];
+ if ( argument != null ) {
+ if ( isHolder( argument ) ) {
+ promotedArgs[ i ] = ((Holder)argument).value;
+ } else {
+ promotedArgs[ i ] = args[ i ];
+ }
+
+ }
+ }
+ return promotedArgs;
+ }
+
+ /**
+ * Given an argument array, filters out (removes) OUT-only parameters
+ * @param sourceOp
+ * @return array of filtered arguments
+ */
+ Object[] removeOutOnlyArgs(Operation sourceOp, Object[] args) {
+ if ( args == null )
+ return args;
+ ArrayList<Object> retValList = new ArrayList<Object>();
+ List<ParameterMode> parmList = sourceOp.getParameterModes();
+ for (int i = 0; i < args.length; i++) {
+ if (parmList.get(i) != ParameterMode.OUT) {
+ retValList.add(args[i]);
+ }
+ }
+ return retValList.toArray();
+ }
+
+ /**
+ * Given a Class, tells if it is a Holder by comparing to "javax.xml.ws.Holder"
+ * @param testClass
+ * @return boolean whether class is Holder type.
+ */
+ protected static boolean isHolder( Class testClass ) {
+ if ( testClass.getName().startsWith( "javax.xml.ws.Holder" )) {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Given an Object, tells if it is a Holder by comparing to "javax.xml.ws.Holder"
+ * @param testClass
+ * @return boolean stating whether Object is a Holder type.
+ * @author DOB
+ */
+ protected static boolean isHolder( Object object ) {
+ String objectName = object.getClass().getName();
+ if ( object instanceof javax.xml.ws.Holder ) {
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java
new file mode 100644
index 0000000000..7163357042
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java
@@ -0,0 +1,248 @@
+/*
+ * 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.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Response;
+
+import org.apache.tuscany.sca.common.java.collection.LRUCache;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.LifeCycleListener;
+import org.apache.tuscany.sca.core.context.ServiceReferenceExt;
+import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl;
+import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl;
+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.Invocable;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceReference;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * the default implementation of a wire service that uses JDK dynamic proxies
+ *
+ * @version $Rev$ $Date$
+ */
+public class JDKProxyFactory implements ProxyFactory, LifeCycleListener {
+ protected ExtensionPointRegistry registry;
+ protected InterfaceContractMapper contractMapper;
+ private MessageFactory messageFactory;
+
+ public JDKProxyFactory(ExtensionPointRegistry registry,
+ MessageFactory messageFactory,
+ InterfaceContractMapper mapper) {
+ this.registry = registry;
+ 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(final Class<T> interfaze, Invocable invocable) throws ProxyCreationException {
+ if (invocable instanceof RuntimeEndpoint) {
+ InvocationHandler handler;
+ // TUSCANY-3659 - Always install a asynch handler regardless of whether ref is sync or async
+ // needs tidying
+ // if (isAsync(interfaze)) {
+ handler = new AsyncJDKInvocationHandler(registry, messageFactory, interfaze, invocable);
+ // } else {
+ // handler = new JDKInvocationHandler(messageFactory, interfaze, invocable);
+ // }
+ // Allow privileged access to class loader. Requires RuntimePermission in security policy.
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return interfaze.getClassLoader();
+ }
+ });
+ T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler));
+ return proxy;
+ }
+ ServiceReference<T> serviceReference = new ServiceReferenceImpl<T>(interfaze, invocable, null);
+ return createProxy(serviceReference);
+ }
+
+ public <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException {
+ assert callableReference != null;
+ final Class<T> interfaze = callableReference.getBusinessInterface();
+ InvocationHandler handler;
+ // TUSCANY-3659 - Always install a asynch handler regardless of whether ref is sync or async
+ // needs tidying
+ // if (isAsync(interfaze)) {
+ handler = new AsyncJDKInvocationHandler(registry, messageFactory, callableReference);
+ // } else {
+ // 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();
+ }
+ });
+ T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler));
+ ((ServiceReferenceExt<T>)callableReference).setProxy(proxy);
+ return proxy;
+ }
+
+ private boolean isAsync(Class<?> interfaze) {
+ for (Method method : interfaze.getMethods()) {
+ if (method.getName().endsWith("Async")) {
+ if (method.getReturnType().isAssignableFrom(Future.class)) {
+ if (method.getParameterTypes().length > 0) {
+ if (method.getParameterTypes()[method.getParameterTypes().length - 1]
+ .isAssignableFrom(AsyncHandler.class)) {
+ return true;
+ }
+ }
+ }
+ if (method.getReturnType().isAssignableFrom(Response.class)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public <T> T createCallbackProxy(Class<T> interfaze, List<? extends Invocable> wires) throws ProxyCreationException {
+ ServiceReferenceImpl<T> callbackReference = null;
+ try {
+ callbackReference = new CallbackServiceReferenceImpl(interfaze, wires);
+ } catch (ServiceRuntimeException e) {
+ // [rfeng] In case that the call is not from a bidirectional interface, the field should be injected with null
+ callbackReference = null;
+ }
+ return callbackReference != null ? createCallbackProxy(callbackReference) : null;
+ }
+
+ public <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException {
+ assert callbackReference != null;
+ final Class<T> interfaze = callbackReference.getBusinessInterface();
+ InvocationHandler handler = new JDKCallbackInvocationHandler(messageFactory, callbackReference);
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return interfaze.getClassLoader();
+ }
+ });
+ T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler));
+ ((ServiceReferenceExt<T>)callbackReference).setProxy(proxy);
+ return proxy;
+ }
+
+ public <B, R extends ServiceReference<B>> R cast(B target) throws IllegalArgumentException {
+ InvocationHandler handler = Proxy.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 Proxy.isProxyClass(clazz);
+ }
+
+ // 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 LRUCache<Class<?>, Constructor<?>> cache = new LRUCache<Class<?>, Constructor<?>>(512);
+
+ public Object newProxyInstance(ClassLoader classloader, Class<?> interfaces[], InvocationHandler invocationhandler)
+ throws IllegalArgumentException {
+ if (interfaces.length > 1) {
+ // We only cache the proxy constructors with one single interface which the case in SCA where
+ // one reference can have one interface
+ return Proxy.newProxyInstance(classloader, interfaces, invocationhandler);
+ }
+ try {
+ if (invocationhandler == null)
+ throw new NullPointerException("InvocationHandler is null");
+ // Lookup cached constructor. aclass[0] is the reference's business interface.
+ Constructor<?> proxyCTOR;
+ synchronized (cache) {
+ proxyCTOR = cache.get(interfaces[0]);
+ }
+ if (proxyCTOR == null) {
+ Class<?> proxyClass = Proxy.getProxyClass(classloader, interfaces);
+ proxyCTOR = proxyClass.getConstructor(InvocationHandler.class);
+ synchronized (cache) {
+ cache.put(interfaces[0], proxyCTOR);
+ }
+ }
+ return proxyCTOR.newInstance(invocationhandler);
+ } catch (Throwable e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ cache.clear();
+ }
+
+ public void removeProxiesForContribution(ClassLoader contributionClassloader){
+ try {
+ synchronized(cache) {
+ Set<Class<?>> objSet = cache.keySet();
+ List<Class<?>> toRemove = new ArrayList<Class<?>>();
+ Iterator<Class<?>> i = objSet.iterator();
+ loop:
+ while(i.hasNext()) {
+ Class<?> cls = i.next();
+ ClassLoader cl = cls.getClassLoader();
+ while (cl != null){
+ if (cl == contributionClassloader){
+ toRemove.add(cls);
+ break loop;
+ }
+ // take account of generated classes
+ cl = cl.getParent();
+ }
+ }
+ for (Class<?> cls : toRemove){
+ cache.remove(cls);
+ }
+ }
+ } catch(Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java
new file mode 100644
index 0000000000..6f3e947631
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.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.invocation.impl;
+
+import java.io.Serializable;
+
+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, Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2112289169275106977L;
+
+ public Message createMessage() {
+ return new MessageImpl();
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java
new file mode 100644
index 0000000000..cc8cb48cc5
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.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.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * The default implementation of a message flowed through a wire during an invocation
+ *
+ * @version $Rev $Date$
+ */
+public class MessageImpl implements Message {
+ private Map<String, Object> headers = new HashMap<String, Object>();
+ private Object body;
+ private Object messageID;
+ private boolean isFault;
+ private Operation operation;
+
+ private EndpointReference from;
+ private Endpoint to;
+
+ private Object bindingContext;
+
+ public MessageImpl() {
+ this.from = null;
+ this.to = null;
+ }
+
+ @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 Endpoint getTo() {
+ return to;
+ }
+
+ public void setTo(Endpoint to) {
+ this.to = to;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(Operation op) {
+ this.operation = op;
+ }
+
+ public Map<String, Object> getHeaders() {
+ return headers;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getBindingContext() {
+ return (T)bindingContext;
+ }
+
+ public <T> void setBindingContext(T bindingContext) {
+ this.bindingContext = bindingContext;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java
new file mode 100644
index 0000000000..45f4bf52bf
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java
new file mode 100644
index 0000000000..85ef79b5d7
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java
@@ -0,0 +1,313 @@
+/*
+ * 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.Collection;
+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.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+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_POLICY, REFERENCE_INTERFACE, 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_INTERFACE, SERVICE_POLICY, SERVICE};
+
+ private static final String[] SYSTEM_IMPLEMENTATION_PHASES = {IMPLEMENTATION_POLICY, IMPLEMENTATION};
+
+ private ExtensionPointRegistry registry;
+ 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;
+ }
+ }
+
+ /**
+ * @param registry
+ */
+ public PhaseManager(ExtensionPointRegistry registry) {
+ super();
+ this.registry = registry;
+ }
+
+ public static PhaseManager getInstance(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ return utilityExtensionPoint.getUtility(PhaseManager.class);
+ }
+
+ // For unit test purpose
+ PhaseManager(String pattern) {
+ super();
+ this.pattern = pattern;
+ this.registry = new DefaultExtensionPointRegistry();
+ }
+
+ 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();
+
+ Collection<ServiceDeclaration> services;
+ try {
+ services = registry.getServiceDiscovery().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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java
new file mode 100644
index 0000000000..175f3463ad
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java
new file mode 100644
index 0000000000..395d154779
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java
@@ -0,0 +1,1206 @@
+/*
+ * 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.runtime.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Callback;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.SCABinding;
+import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
+import org.apache.tuscany.sca.assembly.builder.PolicyBuilder;
+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.impl.RuntimeEndpointImpl;
+import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl;
+import org.apache.tuscany.sca.definitions.Definitions;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.interfacedef.impl.TuscanyInterfaceContractImpl;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.util.Audit;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.policy.BindingType;
+import org.apache.tuscany.sca.policy.ExtensionType;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.IntentMap;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.Qualifier;
+import org.apache.tuscany.sca.provider.EndpointReferenceAsyncProvider;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.runtime.CompositeActivator;
+import org.apache.tuscany.sca.runtime.DomainRegistry;
+import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+import org.apache.tuscany.sca.runtime.UnknownEndpointHandler;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * A builder that takes endpoint references and resolves them. It either finds local
+ * service endpoints if they are available or asks the domain. The main function here
+ * is to perform binding and policy matching.
+ *
+ * This is a separate from the builders so that the mechanism for reference/service matching
+ * can be used at runtime as well as build time and can also be replaced independently
+ *
+ * @version $Rev$ $Date$
+ */
+public class EndpointReferenceBinderImpl implements EndpointReferenceBinder {
+ private static final Logger logger = Logger.getLogger(EndpointReferenceBinderImpl.class.getName());
+
+ protected ExtensionPointRegistry extensionPoints;
+ protected AssemblyFactory assemblyFactory;
+ protected InterfaceContractMapper interfaceContractMapper;
+ protected BuilderExtensionPoint builders;
+ protected CompositeActivator compositeActivator;
+ protected Monitor monitor;
+ protected UnknownEndpointHandler unknownEndpointHandler;
+ protected CompositeBuilder policyAppliesToBuilder;
+
+
+ public EndpointReferenceBinderImpl(ExtensionPointRegistry extensionPoints) {
+ this.extensionPoints = extensionPoints;
+
+ FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+
+ UtilityExtensionPoint utils = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ this.interfaceContractMapper = utils.getUtility(InterfaceContractMapper.class);
+
+ MonitorFactory monitorFactory = utils.getUtility(MonitorFactory.class);
+ monitor = monitorFactory.createMonitor();
+
+ this.unknownEndpointHandler = utils.getUtility(UnknownEndpointHandler.class);
+
+ this.builders = extensionPoints.getExtensionPoint(BuilderExtensionPoint.class);
+
+ this.compositeActivator = extensionPoints.getExtensionPoint(CompositeActivator.class);
+ }
+
+ /**
+ * Bind a single endpoint reference at build time. Here we only expect the
+ * registry to have a record of local endpoints
+ *
+ * @param domainRegistry
+ * @param endpointReference
+ */
+ public void bindBuildTime(DomainRegistry domainRegistry,
+ EndpointReference endpointReference,
+ BuilderContext builderContext) {
+ bind(domainRegistry, endpointReference, builderContext, false);
+ }
+
+ /**
+ * Bind a single endpoint reference at run time. Here we expect the
+ * registry to be populated with endpoints from across the domain
+ *
+ * @param domainRegistry
+ * @param endpointReference
+ */
+ public void bindRunTime(DomainRegistry domainRegistry,
+ EndpointReference endpointReference) {
+ bind(domainRegistry, endpointReference, null, true);
+ }
+
+ /**
+ * Bind a reference to a service endpoint
+ *
+ * @param domainRegistry
+ * @param endpointReference
+ * @param runtime set true if called from the runtime
+ */
+ public void bind(DomainRegistry domainRegistry,
+ EndpointReference endpointReference,
+ BuilderContext builderContext,
+ boolean runtime){
+
+ logger.fine("Binding " + endpointReference.toString());
+
+ Audit matchAudit = new Audit();
+
+ // This logic does post build autowire matching but isn't actually used at the moment
+ // as problems with dependencies mean we still do this during build
+ if (endpointReference.getStatus() == EndpointReference.Status.AUTOWIRE_PLACEHOLDER){
+
+ // do autowire matching
+ // will only be called at build time at the moment
+ Multiplicity multiplicity = endpointReference.getReference().getMultiplicity();
+ for (Endpoint endpoint : domainRegistry.getEndpoints()){
+// if (endpoint is in the same composite as endpoint reference){
+ if ((multiplicity == Multiplicity.ZERO_ONE ||
+ multiplicity == Multiplicity.ONE_ONE) &&
+ (endpointReference.getReference().getEndpointReferences().size() > 1)) {
+ break;
+ }
+
+ // Prevent autowire connecting to self
+ if (endpointReference.getComponent() ==
+ endpoint.getComponent()) {
+ continue;
+ }
+
+ if (haveMatchingPolicy(endpointReference, endpoint, matchAudit, builderContext) &&
+ haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){
+ // matching service so find if this reference already has
+ // an endpoint reference for this endpoint
+ Endpoint autowireEndpoint = null;
+
+ for (EndpointReference epr : endpointReference.getReference().getEndpointReferences()){
+ if (epr.getTargetEndpoint() == endpoint){
+ autowireEndpoint = endpoint;
+ break;
+ }
+ }
+
+ if (autowireEndpoint == null){
+ // create new EPR for autowire
+ EndpointReference autowireEndpointRefrence = null;
+ try {
+ autowireEndpointRefrence = (EndpointReference)endpointReference.clone();
+ } catch (Exception ex){
+ // won't happen as clone is supported
+ }
+
+ autowireEndpointRefrence.setTargetEndpoint(endpoint);
+ autowireEndpointRefrence.setBinding(endpoint.getBinding());
+ autowireEndpointRefrence.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
+ endpointReference.getReference().getEndpointReferences().add(autowireEndpointRefrence);
+ }
+ }
+// }
+ }
+
+ if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) {
+ if (endpointReference.getReference().getEndpointReferences().size() == 1) {
+ Monitor.error(monitor,
+ this,
+ "endpoint-validation-messages",
+ "NoComponentReferenceTarget",
+ endpointReference.getReference().getName());
+ //throw new ServiceRuntimeException("Unable to bind " +
+ // monitor.getLastProblem().toString());
+ }
+ }
+
+ setSingleAutoWireTarget(endpointReference.getReference());
+
+ } else if ( endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED||
+ endpointReference.getStatus() == EndpointReference.Status.RESOLVED_BINDING ) {
+ // The endpoint reference is already resolved to either
+ // a service endpoint local to this composite or it has
+ // a remote binding. Just make sure the binding is built
+ build(endpointReference);
+
+ // still need to check that the callback endpoint is set correctly
+ if (hasCallback(endpointReference) &&
+ (endpointReference.getCallbackEndpoint() == null
+ || endpointReference.getCallbackEndpoint().isUnresolved())) {
+ selectCallbackEndpoint(endpointReference,
+ endpointReference.getReference().getCallbackService(),
+ matchAudit,
+ builderContext,
+ runtime);
+ }
+ } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING ){
+ // The endpoint reference is already resolved to either
+ // a service endpoint but no binding was specified in the
+ // target URL and/or the policies have yet to be matched.
+ // Used when $self references are resolved
+
+ selectForwardEndpoint(endpointReference,
+ endpointReference.getTargetEndpoint().getService().getEndpoints(),
+ matchAudit,
+ builderContext,
+ runtime);
+
+ if (hasCallback(endpointReference)){
+ selectCallbackEndpoint(endpointReference,
+ endpointReference.getReference().getCallbackService(),
+ matchAudit,
+ builderContext,
+ runtime);
+ }
+ } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI ||
+ endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_NOT_FOUND ||
+ endpointReference.getStatus() == EndpointReference.Status.NOT_CONFIGURED){
+ // The reference is not yet matched to a service
+
+ // find the service in the endpoint registry
+ List<Endpoint> endpoints = domainRegistry.findEndpoint(endpointReference);
+
+ if (endpoints.size() > 0){
+ selectForwardEndpoint(endpointReference,
+ endpoints,
+ matchAudit,
+ builderContext,
+ runtime);
+
+ // If the reference was matched try to match the callback
+ if (endpointReference.getStatus().equals(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED) &&
+ hasCallback(endpointReference)){
+ selectCallbackEndpoint(endpointReference,
+ endpointReference.getReference().getCallbackService(),
+ matchAudit,
+ builderContext,
+ runtime);
+ }
+ } else if (runtime) {
+ // tweak to test if this could be a resolved binding. This is the back end of the test
+ // in the builder that pulls the URI out of the binding if there are no targets
+ // on the reference. have to wait until here to see if the binding uri matches any
+ // available services. If not we assume here that it's a resolved binding
+ if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI){
+ endpointReference.getTargetEndpoint().setBinding(endpointReference.getBinding());
+ endpointReference.setStatus(EndpointReference.Status.RESOLVED_BINDING);
+ } else {
+ processUnknownEndpoint(endpointReference, matchAudit);
+
+ if (!endpointReference.getStatus().equals(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED)){
+ Monitor.error(monitor,
+ this,
+ "endpoint-validation-messages",
+ "NoEndpointsFound",
+ endpointReference.toString());
+ throw new ServiceRuntimeException(monitor.getMessageString(EndpointReferenceBinderImpl.class.getName(),
+ "endpoint-validation-messages",
+ "UnableToBind") +
+ " " +
+ monitor.getLastProblem().toString());
+ }
+ }
+ } else {
+ // it's build time so just give the UnknownEndpoint code a chance
+ // without regard for the result
+ processUnknownEndpoint(endpointReference, matchAudit);
+ }
+ }
+
+ logger.fine(matchAudit.toString());
+
+ if (endpointReference.getStatus() != EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED &&
+ endpointReference.getStatus() != EndpointReference.Status.RESOLVED_BINDING){
+
+ if (runtime){
+ Monitor.error(monitor,
+ this,
+ "endpoint-validation-messages",
+ "EndpointReferenceCantBeMatched",
+ endpointReference.toString(),
+ matchAudit);
+ throw new ServiceRuntimeException(monitor.getMessageString(EndpointReferenceBinderImpl.class.getName(),
+ "endpoint-validation-messages",
+ "UnableToBind") +
+ " " +
+ monitor.getLastProblem().toString());
+ } else {
+ Monitor.warning(monitor,
+ this,
+ "endpoint-validation-messages",
+ "ComponentReferenceTargetNotFound",
+ endpointReference.toString());
+ return;
+ }
+
+
+ }
+
+ // [rfeng] Setup the target endpoint if the reference uses an explicit binding
+ if (endpointReference.getTargetEndpoint().getBinding() == null) {
+ endpointReference.getTargetEndpoint().setBinding(endpointReference.getBinding());
+ }
+
+ // Now the endpoint reference is resolved check that the binding interfaces contract
+ // and the reference contract are compatible
+ try {
+ ((RuntimeEndpointReference)endpointReference).validateReferenceInterfaceCompatibility();
+ } catch (ServiceRuntimeException ex) {
+ // don't re-throw this exception at build time just record the
+ // error. If it's thrown here is messes up the order in which
+ // build time errors are reported and that in turn messes
+ // up the output of the compliance tests.
+ if (runtime){
+ throw ex;
+ } else {
+ Monitor.error(monitor,
+ this,
+ "endpoint-validation-messages",
+ "EndpointReferenceCantBeMatched",
+ endpointReference.toString(),
+ ex.getMessage());
+ }
+ }
+
+ // TUSCANY-3783
+ // if the reference is an async reference and the binding doesn't support
+ // async natively fluff up the response service/endpoint
+ ReferenceBindingProvider referenceBindingProvider = ((RuntimeEndpointReference)endpointReference).getBindingProvider();
+ if ( referenceBindingProvider instanceof EndpointReferenceAsyncProvider &&
+ !((EndpointReferenceAsyncProvider)referenceBindingProvider).supportsNativeAsync() &&
+ endpointReference.isAsyncInvocation() &&
+ endpointReference.getCallbackEndpoint() == null) {
+ ((RuntimeEndpointReference)endpointReference).createAsyncCallbackEndpoint();
+ }
+
+ // System.out.println("MATCH AUDIT:" + matchAudit.toString());
+ }
+
+ private void processUnknownEndpoint(EndpointReference endpointReference, Audit matchAudit){
+ Binding b = null;
+ if (unknownEndpointHandler != null) {
+ b = unknownEndpointHandler.handleUnknownEndpoint(endpointReference);
+ }
+ if (b != null) {
+ Endpoint matchedEndpoint = new RuntimeEndpointImpl(extensionPoints);
+ matchedEndpoint.setBinding(b);
+ matchedEndpoint.setRemote(true);
+ endpointReference.setTargetEndpoint(matchedEndpoint);
+ endpointReference.setBinding(b);
+ endpointReference.setUnresolved(false);
+ endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
+ matchAudit.append("Match because the UnknownEndpointHandler provided a binding: " + b.getType() + " uri: " + b.getURI());
+ matchAudit.appendSeperator();
+ }
+ }
+
+ /**
+ * Returns true if the reference has a callback
+ */
+ private boolean hasCallback(EndpointReference endpointReference){
+ if (endpointReference.getReference().getInterfaceContract() == null ||
+ endpointReference.getReference().getInterfaceContract().getCallbackInterface() == null ||
+ endpointReference.getReference().getName().startsWith("$self$.")){
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Selects a forward endpoint from a list of possible candidates
+ *
+ * @param endpointReference
+ * @param endpoints
+ */
+ private void selectForwardEndpoint(EndpointReference endpointReference, List<Endpoint> endpoints, Audit matchAudit, BuilderContext builderContext, boolean runtime) {
+
+ Endpoint matchedEndpoint = null;
+
+ if (endpointReference.getReference().getName().startsWith("$self$.")){
+ // just select the first one and don't do any policy matching
+ if (endpointReference.getTargetEndpoint() != null && !endpointReference.getTargetEndpoint().isUnresolved()) {
+ matchedEndpoint = endpointReference.getTargetEndpoint();
+ } else {
+ matchedEndpoint = endpoints.get(0);
+ }
+ } else {
+ // find the endpoints that match this endpoint reference
+ List<Endpoint> matchedEndpoints = new ArrayList<Endpoint>();
+
+ for (Endpoint endpoint : endpoints){
+ if (haveMatchingPolicy(endpointReference, endpoint, matchAudit, builderContext) &&
+ haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){
+ matchedEndpoints.add(endpoint);
+ }
+ }
+
+ // TUSCANY-4005 - raise an error if a reference target that only specifies the
+ // component name matches more than one component service
+ if (endpointReference.getTargetEndpoint().getService() == null &&
+ endpointReference.getTargetEndpoint().getBinding() == null &&
+ matchedEndpoints.size() > 1 ) {
+
+ String serviceName = null;
+ for (Endpoint endpoint : matchedEndpoints){
+ // ignore service names called "default" as these indicate dynamic services
+ // created for the likes of implementation.python
+ if (serviceName == null &&
+ !endpoint.getService().getName().equals("default")){
+ serviceName = endpoint.getService().getName();
+ }
+
+ if (serviceName != null &&
+ !endpoint.getService().getName().equals("default") &&
+ !endpoint.getService().getName().equals(serviceName)){
+ if (runtime){
+ Monitor.error(monitor,
+ this,
+ "endpoint-validation-messages",
+ "TooManyTargetServices",
+ endpointReference.toString(),
+ endpointReference.getTargetEndpoint().toString(),
+ matchAudit);
+ throw new ServiceRuntimeException("Unable to bind " +
+ monitor.getLastProblem().toString());
+ } else {
+ Monitor.warning(monitor,
+ this,
+ "endpoint-validation-messages",
+ "TooManyTargetServices",
+ endpointReference.toString(),
+ endpointReference.getTargetEndpoint().toString());
+ return;
+ }
+ }
+ }
+ }
+
+ // TUSCANY-3941 check for the case where the user has provided a
+ // binding.sca at the reference and make sure we pick
+ // a binding.sca at the service regardless of how many
+ // other bindings are provided
+ if (endpointReference.getBinding() != null &&
+ endpointReference.getBinding() instanceof SCABinding ){
+ for (Endpoint endpoint : matchedEndpoints){
+ if (endpoint.getBinding() instanceof SCABinding){
+ matchedEndpoint = endpoint;
+ break;
+ }
+ }
+ }
+
+ if (matchedEndpoint == null) {
+ // just take the first matched endpoint from the list
+ if (matchedEndpoints.size() > 0){
+ matchedEndpoint = matchedEndpoints.get(0);
+ }
+ }
+ }
+
+ if (matchedEndpoint == null){
+ return;
+ } else {
+ endpointReference.setTargetEndpoint(matchedEndpoint);
+ Binding binding = matchedEndpoint.getBinding();
+ try {
+ endpointReference.setBinding((Binding)binding.clone());
+ } catch (CloneNotSupportedException e) {
+ // shouldn't happen
+ throw new RuntimeException(e);
+ }
+ // TUSCANY-3873 - add policy from the service
+ // we don't care about intents at this stage
+ endpointReference.getPolicySets().addAll(matchedEndpoint.getPolicySets());
+
+ // TODO - we need to re-run the appliesTo processing here but there is some question about what
+ // appliesTo means. It's also difficult to get to the PolicyAppliesToBuilder from here and
+ // need a new EntensionInterface to support access. So for now I'm just cheating and looking to
+ // see if the XPath expression contains the binding type as a string while we discuss appliesTo
+ List<PolicySet> psToRemove = new ArrayList<PolicySet>();
+
+ for (PolicySet ps : endpointReference.getPolicySets() ) {
+ if (!ps.getAppliesTo().contains(endpointReference.getBinding().getType().getLocalPart())){
+ psToRemove.add(ps);
+ }
+ }
+
+ endpointReference.getPolicySets().removeAll(psToRemove);
+
+ build(endpointReference);
+ endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED);
+ endpointReference.setUnresolved(false);
+ }
+
+ }
+
+ private void build(EndpointReference endpointReference) {
+ BindingBuilder builder = builders.getBindingBuilder(endpointReference.getBinding().getType());
+ if (builder != null) {
+ builder.build(endpointReference.getComponent(),
+ endpointReference.getReference(),
+ endpointReference.getBinding(),
+ new BuilderContext(extensionPoints),
+ false);
+ }
+ }
+
+ /**
+ * This code is very similar to the code in EnpointReferenceBuilder.fixUpCallbackLinks()
+ * but here we are selecting endpoint/endpoint references at runtime.
+ *
+ * To recap the general model is as follows:
+ *
+ * Forward EPR -----------> Forward EP (target EP)
+ * | |
+ * \/ \/
+ * Callback EP <------------ Callback EPR
+ *
+ * The question then becomes how to construct this model given that
+ * target resolution can happen at runtime and EPR and EP can be
+ * distributed across the domain.
+ *
+ * The forward link is resolved by searching in the registry for an EP
+ * that matches the EPR.
+ *
+ * At build time we've made the assumption that, if the user configures
+ * a callback binding at all, they will choose the same binding as the
+ * forward call (TODO - this may be a bold assumption). So here we just
+ * assume that the callback endpoint that is set on the reference
+ * at build time matches. This may not be true if the callback bindings
+ * are configured differently on the reference and service.
+ *
+ * @param endpointReference
+ * @param endpoints
+ */
+ private void selectCallbackEndpoint(EndpointReference endpointReference, ComponentService callbackService, Audit matchAudit, BuilderContext builderContext, boolean runtime) {
+
+ // A simplifying assumption here is that the user will only specify a callback binding
+ // of the same type as the forward binding in order to specify further configuration
+ // We can then assume that if there is no callback endpoint that matches already then we have
+ // picked up binding config from the service and we can create a callback endpoint to match
+
+ // So having said this we look in three places for the callback binding.
+ // 1/ in callback endpoints at the reference
+ // - will find it here if the user has manually configured a callback binding at the reference
+ // 2/ in the service callback structure
+ // - will find it here if the user has manually configured a callback binding at the service
+ // 3/ in the service callback reference structure
+ // - will find it here if the system has constructed the callback binding based on the forward binding
+ //
+ // 2 and 3 are conflated in the distributed case as be write any derived callback bindings out into the
+ // callback structure as the endpoint is serialized across the domain
+
+ RuntimeEndpoint callbackEndpoint = null;
+
+ // 1/ look in callback endpoints at the reference
+ // - exploiting the assumption that the user will specific callback bindings of
+ // the same type as the forward binding
+ match1:
+ for(Endpoint loopCallbackEndpoint : callbackService.getEndpoints()){
+ if(loopCallbackEndpoint.getBinding().getType().equals(endpointReference.getBinding().getType())){
+ callbackEndpoint = (RuntimeEndpoint)loopCallbackEndpoint;
+ break match1;
+ }
+ }
+
+ // if no callback endpoint was found then create a new callback endpoint
+ if (callbackEndpoint == null ){
+ callbackEndpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
+ callbackEndpoint.setComponent(endpointReference.getComponent());
+ callbackEndpoint.setService(callbackService);
+
+ Binding forwardBinding = endpointReference.getBinding();
+ Binding callbackBinding = null;
+
+ // 2/ look in the service callback structure
+ Callback serviceCallback = endpointReference.getTargetEndpoint().getService().getCallback();
+
+ if (serviceCallback != null){
+ for(Binding loopCallbackBinding : serviceCallback.getBindings()){
+ if(loopCallbackBinding.getType().equals(endpointReference.getBinding().getType())){
+ callbackBinding = loopCallbackBinding;
+ break;
+ }
+ }
+ }
+
+ // 3/ look in the service endpoint callback reference structure
+ ComponentReference callbackReference = endpointReference.getTargetEndpoint().getService().getCallbackReference();
+
+ if (callbackReference != null){
+ for (EndpointReference loopEndpointReference : callbackReference.getEndpointReferences()){
+ if (loopEndpointReference.getBinding().getType().equals(endpointReference.getBinding().getType())){
+ callbackBinding = loopEndpointReference.getBinding();
+ break;
+ }
+ }
+ }
+
+ // if all else fails clone the forward binding
+ // TODO - do we ever get here?
+ if (callbackBinding == null){
+ try {
+ callbackBinding = (Binding)forwardBinding.clone();
+ } catch (CloneNotSupportedException ex){
+ }
+ }
+
+ // get the callback binding URI by looking at the SCA binding
+ // that will have been added at build time
+ callbackBinding.setURI(null);
+ for (Endpoint endpoint : callbackService.getEndpoints()){
+ if (endpoint.getBinding().getType().equals(SCABinding.TYPE)){
+ callbackBinding.setURI(endpoint.getBinding().getURI());
+ }
+ }
+
+ callbackEndpoint.setBinding(callbackBinding);
+ callbackService.getBindings().add(callbackBinding);
+
+ callbackEndpoint.setUnresolved(false);
+ callbackService.getEndpoints().add(callbackEndpoint);
+
+ // build it
+ build(callbackEndpoint);
+
+ // Only activate the callback endpoint if the bind is being done at runtime
+ // and hence everything else is running. If it's build time then the
+ // endpoint will be activated at the same time as all the other endpoints
+ if (runtime) {
+ // activate it
+ compositeActivator.activate(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(),
+ callbackEndpoint);
+
+ // start it
+ compositeActivator.start(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(),
+ callbackEndpoint);
+ }
+ }
+
+ // finally set the callback endpoint into the forward reference
+ endpointReference.setCallbackEndpoint(callbackEndpoint);
+ }
+
+ private void build(Endpoint endpoint) {
+
+ BindingBuilder builder = builders.getBindingBuilder(endpoint.getBinding().getType());
+ if (builder != null) {
+ builder.build(endpoint.getComponent(),
+ endpoint.getService(),
+ endpoint.getBinding(),
+ new BuilderContext(extensionPoints),
+ true);
+ }
+ }
+
+ /**
+ * Determine if endpoint reference and endpoint policies match. We know by this stage
+ * that
+ * - a given policy set will only contain expressions from a single language
+ * - a given endpoint or endpoint reference's policy sets will only contain
+ * expressions from a single language
+ *
+ * Matching algorithm (read from the top down):
+ * - FAIL if there are intents that are mutually exclusive between reference and service
+ * - PASS if there are no intents or policies present at reference and service
+ * - FAIL if there are unresolved intents (intents with no policy set) at the reference (service should have been checked previously)
+ * the wrinkle here is that we need to adopt policy from the service if the reference doesn't define a binding
+ * - PASS if there are no policies at reference and service (now we know all intents are resolved)
+ * - FAIL if there are some policies on one side but not on the other
+ * - PASS if the QName of the policy sets on each side match
+ * - FAIL if the policy languages on both sides are different
+ * - Perform policy specific match
+ *
+ */
+ private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit, BuilderContext builderContext){
+ matchAudit.append("Match policy of " + endpointReference.toString() + " to " + endpoint.toString() + " ");
+
+ if (!endpoint.getSpecVersion().equals(Base.SCA11_NS)){
+ // the thing we need to check here is asyncInvocation as only OASIS supports that
+ if (endpointReference.isAsyncInvocation()){
+ // this definitely won't mactch anything but OASIS so fail
+ matchAudit.append("No match because the endpoint reference is configured for asyncInvocation " +
+ "and the target endpoint is not an OASIS endpoint, specVersion = " +
+ endpoint.getSpecVersion());
+ matchAudit.appendSeperator();
+ return false;
+ } else {
+ // Assume it matches as we don't know how to do policy
+ // matching with anything but OASIS endpoints
+ matchAudit.append("Match because the target endpoint is not an OASIS endpoint, specVersion = " +
+ endpoint.getSpecVersion());
+ matchAudit.appendSeperator();
+ return true;
+ }
+ }
+
+ List<PolicySet> referencePolicySets = new ArrayList<PolicySet>();
+ Binding binding = null;
+
+ if (endpointReference.getBinding() == null){
+ binding = endpoint.getBinding();
+ } else {
+ binding = endpointReference.getBinding();
+ }
+
+ // if there are any intents that are mutually exclusive between
+ // service and reference then they don't match
+ for (Intent eprIntent : endpointReference.getRequiredIntents()){
+ for (Intent epIntent : endpoint.getRequiredIntents()){
+ if (eprIntent.getExcludedIntents().contains(epIntent) ||
+ epIntent.getExcludedIntents().contains(eprIntent) ||
+ checkQualifiedMutualExclusion(eprIntent.getExcludedIntents(), epIntent) ||
+ checkQualifiedMutualExclusion(epIntent.getExcludedIntents(), eprIntent)){
+ matchAudit.append("No match because the following intents are mutually exclusive " +
+ eprIntent.toString() +
+ " " +
+ epIntent.toString() +
+ " ");
+ matchAudit.appendSeperator();
+ return false;
+ }
+ }
+ }
+
+ // Find the set of policy sets from this reference. This includes
+ // the policy sets that are specific to the service binding and
+ // any policy sets that are not binding specific
+ for (PolicySet policySet : endpointReference.getPolicySets()){
+ PolicyBuilder policyBuilder = null;
+
+ if (policySet.getPolicies().size() > 0){
+ QName policyType = policySet.getPolicies().get(0).getName();
+ policyBuilder = builders.getPolicyBuilder(policyType);
+ }
+
+ if ((policyBuilder == null) ||
+ (policyBuilder != null && policyBuilder.getSupportedBindings() == null) ||
+ (policyBuilder != null && policyBuilder.getSupportedBindings().contains(binding.getType()))){
+ referencePolicySets.add(policySet);
+ }
+ }
+
+ // if there are no policy sets on the reference take the policy sets from the
+ // service binding we are matching against
+ if (referencePolicySets.isEmpty()) {
+ for (PolicySet policySet : endpoint.getPolicySets()){
+ PolicyBuilder policyBuilder = null;
+
+ if (policySet.getPolicies().size() > 0){
+ QName policyType = policySet.getPolicies().get(0).getName();
+ policyBuilder = builders.getPolicyBuilder(policyType);
+ }
+
+ if ((policyBuilder == null) ||
+ (policyBuilder != null && policyBuilder.getSupportedBindings() == null) ||
+ (policyBuilder != null && policyBuilder.getSupportedBindings().contains(binding.getType()))){
+ referencePolicySets.add(policySet);
+ }
+ }
+ }
+
+ // the "appliesTo" algorithm to remove any policy sets that
+ // don't apply to the service binding will already have been
+ // run during the build phase
+
+ // Determine if there are any reference policies
+ boolean noEndpointReferencePolicies = true;
+
+ for (PolicySet policySet : referencePolicySets){
+ if (policySet.getPolicies().size() > 0){
+ noEndpointReferencePolicies = false;
+ break;
+ }
+ }
+
+ // Determine of there are any service policies
+ boolean noEndpointPolicies = true;
+
+ for (PolicySet policySet : endpoint.getPolicySets()){
+ if (policySet.getPolicies().size() > 0){
+ noEndpointPolicies = false;
+ break;
+ }
+ }
+
+ // if no policy sets or intents are present then they match
+ if ((endpointReference.getRequiredIntents().size() == 0) &&
+ (endpoint.getRequiredIntents().size() == 0) &&
+ (noEndpointReferencePolicies) &&
+ (noEndpointPolicies)) {
+ matchAudit.append("Match because there are no intents or policies ");
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+ // check that the intents on the reference side are resolved
+ // can't do this until this point as the service binding
+ // may come into play. Intents may be satisfied by the default
+ // or optional intents that the binding type provides. Failing
+ // this they must be satisfied by reference policy sets
+ // Failing this the intent is unresolved and the reference and
+ // service don't match
+
+ // TODO - seems that we should do this loop on a binding by binding basis
+ // rather than each time we do matching
+ BindingType bindingType = null;
+
+ Definitions systemDefinitions = null;
+ if (builderContext != null){
+ systemDefinitions = builderContext.getDefinitions();
+ } else {
+ systemDefinitions = ((RuntimeEndpoint)endpoint).getCompositeContext().getSystemDefinitions();
+ }
+
+ bindingType = systemDefinitions.getBindingType(binding.getType());
+
+ // Before we start examining intents, remove any whose constrained
+ // types don't include the binding type
+ removeConstrainedIntents(endpointReference, bindingType);
+
+ List<Intent> eprIntents = new ArrayList<Intent>();
+ List<Intent> eprMayProvideInterationIntents = new ArrayList<Intent>();
+ eprIntents.addAll(endpointReference.getRequiredIntents());
+
+ // first check the binding type
+ for (Intent intent : endpointReference.getRequiredIntents()){
+ if (bindingType != null &&
+ bindingType.getAlwaysProvidedIntents().contains(intent)){
+ eprIntents.remove(intent);
+ } else if (bindingType != null &&
+ bindingType.getMayProvidedIntents().contains(intent)){
+ eprIntents.remove(intent);
+ if (intent.getType().equals(Intent.Type.interaction)){
+ eprMayProvideInterationIntents.add(intent);
+ }
+ } else {
+ // TODO - this code also appears in the ComponentPolicyBuilder
+ // so should rationalize
+ loop: for (PolicySet policySet : referencePolicySets){
+ if (policySet.getProvidedIntents().contains(intent)){
+ eprIntents.remove(intent);
+ break;
+ }
+
+ for (Intent psProvidedIntent : policySet.getProvidedIntents()){
+ if (isQualifiedBy(psProvidedIntent, intent)){
+ eprIntents.remove(intent);
+ break loop;
+ }
+ }
+
+ for (IntentMap map : policySet.getIntentMaps()) {
+ for (Qualifier q : map.getQualifiers()) {
+ if (intent.equals(q.getIntent())) {
+ eprIntents.remove(intent);
+ break loop;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // if there are unresolved intents the service and reference don't match
+ if (eprIntents.size() > 0){
+ matchAudit.append("No match because there are unresolved intents " + eprIntents.toString() + " ");
+ matchAudit.appendSeperator();
+ return false;
+ }
+
+ // TUSCANY-3959 - something that's not explicitly stated in the spec. mayProvides intents don't
+ // lead to policy sets as the binding natively implements the intent. So
+ // we need to check that these intents match explicitly between reference and service
+ // sides
+ if (eprMayProvideInterationIntents.size() > 0){
+ for (Intent eprIntent : eprMayProvideInterationIntents){
+ boolean match = false;
+ for (Intent epIntent : endpoint.getRequiredIntents()){
+ if (epIntent.equals(eprIntent)){
+ match = true;
+ break;
+ }
+ }
+
+ if (!match){
+ matchAudit.append("No match because the reference has a mayProvide intent that the service doesn't have " + eprIntent.getName());
+ matchAudit.appendSeperator();
+ return false;
+ }
+ }
+ }
+
+ // if there are no policies on epr or ep side then
+ // they match
+ if (noEndpointPolicies && noEndpointReferencePolicies){
+ matchAudit.append("Match because the intents are resolved and there are no policy sets ");
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+ // if there are some policies on one side and not the other then
+ // the don't match
+ if (noEndpointPolicies && !noEndpointReferencePolicies) {
+ matchAudit.append("No match because there are policy sets at the endpoint reference but not at the endpoint ");
+ matchAudit.appendSeperator();
+ return false;
+ }
+
+ if (!noEndpointPolicies && noEndpointReferencePolicies){
+ matchAudit.append("No match because there are policy sets at the endpoint but not at the endpoint reference ");
+ matchAudit.appendSeperator();
+ return false;
+ }
+
+ // If policy set QNames from epr and er match exactly then the reference and
+ // service policies are compatible
+ Set<PolicySet> referencePolicySet = new HashSet<PolicySet>(referencePolicySets);
+ Set<PolicySet> servicePolicySet = new HashSet<PolicySet>(endpoint.getPolicySets());
+ if(referencePolicySet.equals(servicePolicySet)){
+ matchAudit.append("Match because the policy sets on both sides are eactly the same ");
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+ // if policy set language at ep and epr are not the same then there is no
+ // match. We get the policy language by looking at the first expression
+ // of the first policy set. By this stage we know that all the policy sets
+ // in an endpoint or endpoint reference will use a single language and we know
+ // that there is at least one policy set with at least one policy
+ QName eprLanguage = null;
+
+ for (PolicySet policySet : referencePolicySets){
+ if (policySet.getPolicies().size() > 0){
+ eprLanguage = policySet.getPolicies().get(0).getName();
+ break;
+ }
+ }
+
+ QName epLanguage = null;
+
+ for (PolicySet policySet : endpoint.getPolicySets()){
+ if (policySet.getPolicies().size() > 0){
+ epLanguage = policySet.getPolicies().get(0).getName();
+ break;
+ }
+ }
+
+ if(!eprLanguage.getNamespaceURI().equals(epLanguage.getNamespaceURI())){
+ matchAudit.append("No match because the policy sets on either side have policies in differnt languages " +
+ eprLanguage +
+ " and " +
+ epLanguage +
+ " ");
+ matchAudit.appendSeperator();
+ return false;
+ }
+
+ // now do a policy specific language match
+ PolicyBuilder builder = builders.getPolicyBuilder(eprLanguage);
+ boolean match = false;
+
+ // switch the derived list of policy sets into the reference
+ // it will be left there if there is a match
+ List<PolicySet> originalPolicySets = endpointReference.getPolicySets();
+ endpointReference.getPolicySets().clear();
+ endpointReference.getPolicySets().addAll(referencePolicySets);
+
+ if (builder != null) {
+ if (builderContext == null){
+ builderContext = new BuilderContext(monitor);
+ }
+
+ match = builder.build(endpointReference, endpoint, builderContext);
+ }
+
+ if (!match){
+ matchAudit.append("No match because the language specific matching failed ");
+ matchAudit.appendSeperator();
+ endpointReference.getPolicySets().clear();
+ endpointReference.getPolicySets().addAll(originalPolicySets);
+ } else {
+ matchAudit.append("Match because the language specific matching succeeded ");
+ matchAudit.appendSeperator();
+ }
+
+ return match;
+ }
+
+ // Copied from ComponentPolicyBuilder, should probably be refactored
+ protected void removeConstrainedIntents(EndpointReference subject, BindingType bindingType) {
+ List<Intent> intents = subject.getRequiredIntents();
+
+ // Remove the intents whose @contrains do not include the current element
+ if(bindingType != null){
+ List<Intent> copy = new ArrayList<Intent>(intents);
+ for (Intent i : copy) {
+ List<ExtensionType> constrainedTypes = i.getConstrainedTypes();
+ if (( constrainedTypes.size() == 0 ) && ( i.getQualifiableIntent() != null ) )
+ constrainedTypes = i.getQualifiableIntent().getConstrainedTypes();
+
+ if (constrainedTypes.size() > 0){
+ boolean constraintFound = false;
+ for (ExtensionType constrainedType : constrainedTypes){
+ if (constrainedType.getType().equals(bindingType.getType()) ||
+ constrainedType.getType().equals(bindingType.getBaseType())){
+ constraintFound = true;
+ break;
+ }
+ }
+ if(!constraintFound){
+ intents.remove(i);
+ }
+ }
+ }
+ }
+ }
+
+
+ protected boolean isQualifiedBy(Intent qualifiableIntent, Intent qualifiedIntent){
+ if (qualifiedIntent.getQualifiableIntent() == qualifiableIntent){
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean checkQualifiedMutualExclusion(List<Intent> excludedIntentList, Intent intent){
+ for (Intent excludedIntent : excludedIntentList){
+ if (intent.getQualifiableIntent() != null &&
+ excludedIntent != null &&
+ intent.getQualifiableIntent().equals(excludedIntent)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine if endpoint reference and endpoint interface contracts match
+ */
+ private boolean haveMatchingInterfaceContracts(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit){
+ matchAudit.append("Match interface of " + endpointReference.toString() + " to " + endpoint.toString() + " ");
+
+ InterfaceContract endpointReferenceContract = endpointReference.getReference().getInterfaceContract();
+ InterfaceContract endpointContract = endpoint.getComponentServiceInterfaceContract();
+
+ if (endpointReferenceContract == null){
+ matchAudit.append("Match because there is no interface contract on the reference ");
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+ if (!endpoint.getSpecVersion().equals(Base.SCA11_NS)){
+ // Assume it matches as we don't know how to do interface
+ // matching with anything but OASIS endpoint
+ matchAudit.append("Match because the target endpoint is not an OASIS endpoint, specVersion = " +
+ endpoint.getSpecVersion());
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+/* For testing this code turns off remote interface matching completely
+ if (endpoint.isRemote()){
+ matchAudit.append("Match because endpoint is remote");
+ matchAudit.appendSeperator();
+ return true;
+ }
+*/
+
+ // If the remote interface was not retrieved successfully from the registry for whatever reason
+ // then assume the interfaces match and leave the checking until runtime. We looking for an interface
+ // with no operations defined to tell us this.
+ if ((endpointContract.getInterface().getOperations().size() == 0 &&
+ endpointContract.getNormalizedWSDLContract() == null) ||
+ (endpointContract.getNormalizedWSDLContract() != null &&
+ endpointContract.getNormalizedWSDLContract().getInterface().getOperations().size() == 0)){
+ matchAudit.append("Match because the endpoint is remote and we don't have a copy of it's interface contract ");
+ matchAudit.appendSeperator();
+ return true;
+ }
+
+ // TUSCANY-4033
+ // Detect the case where the interfaces are both Java but the Endpoint is remote in which case
+ // we have to match the local Java interface with the remote Tuscany interface. But we can do this
+ // without running WSDLGen
+ if (endpointReferenceContract.getClass() == endpointContract.getClass() &&
+ endpointReferenceContract instanceof JavaInterfaceContract &&
+ endpointContract.getNormalizedWSDLContract() != null &&
+ endpointContract.getNormalizedWSDLContract() instanceof TuscanyInterfaceContractImpl){
+ // use the TuscanyInterfaceContractImpl to compare against the Java contract
+ endpointContract = endpointContract.getNormalizedWSDLContract();
+ } else if (endpointReferenceContract.getClass() != endpointContract.getClass() ||
+ endpointReferenceContract.getNormalizedWSDLContract() != null ||
+ endpointContract.getNormalizedWSDLContract() != null) {
+ // If the contracts are not of the same type use normailized interfaces
+ endpointReferenceContract = ((RuntimeEndpointReference)endpointReference).getGeneratedWSDLContract(endpointReferenceContract);
+ endpointContract = ((RuntimeEndpoint)endpoint).getGeneratedWSDLContract(endpointContract);
+ }
+
+ boolean match = false;
+ match = interfaceContractMapper.isCompatibleSubset(endpointReferenceContract,
+ endpointContract,
+ matchAudit);
+
+ if (!match){
+ matchAudit.append("Match failed because the interface contract mapper failed ");
+ } else {
+ matchAudit.append("Match because the interface contract mapper succeeded ");
+ }
+
+ matchAudit.appendSeperator();
+
+ return match;
+ }
+
+ /**
+ * Checks to see if the registry has been updated since the reference was last matched
+ *
+ * @return true is the registry has changed
+ */
+ public boolean isOutOfDate(DomainRegistry domainRegistry, EndpointReference endpointReference) {
+ Endpoint te = endpointReference.getTargetEndpoint();
+ if (te != null && !te.isUnresolved()
+ && te.getURI() != null
+ && endpointReference.getStatus() != EndpointReference.Status.RESOLVED_BINDING) {
+ return domainRegistry.isOutOfDate(endpointReference);
+ }
+ return false;
+ }
+
+ /**
+ * ASM_5021: where a <reference/> of a <component/> has @autowire=true
+ * and where the <reference/> has a <binding/> child element which
+ * declares a single target service, the reference is wired only to
+ * the single service identified by the <wire/> element
+ */
+ private void setSingleAutoWireTarget(ComponentReference reference) {
+ if (reference.getEndpointReferences().size() > 1 && reference.getBindings() != null
+ && reference.getBindings().size() == 1) {
+ String uri = reference.getBindings().get(0).getURI();
+ if (uri != null) {
+ if (uri.indexOf('/') > -1) {
+ // TODO: must be a way to avoid this fiddling
+ int i = uri.indexOf('/');
+ String c = uri.substring(0, i);
+ String s = uri.substring(i + 1);
+ uri = c + "#service(" + s + ")";
+ }
+ for (EndpointReference er : reference.getEndpointReferences()) {
+ if (er.getTargetEndpoint() != null && uri.equals(er.getTargetEndpoint().getURI())) {
+ reference.getEndpointReferences().clear();
+ reference.getEndpointReferences().add(er);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java
new file mode 100644
index 0000000000..cd8bc936af
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java
@@ -0,0 +1,38 @@
+/*
+ * 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.runtime.impl;
+
+import java.util.Properties;
+
+import org.apache.tuscany.sca.runtime.RuntimeProperties;
+
+public class RuntimePropertiesImpl implements RuntimeProperties {
+
+ private Properties properties = new Properties();
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java
new file mode 100644
index 0000000000..a1bb91faec
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java
@@ -0,0 +1,181 @@
+/*
+ * 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;
+
+ private static String scopeStateStrings[] = {"CONFIG_ERROR",
+ "UNINITIALIZED",
+ "INITIALIZING",
+ "INITIALIZED",
+ "NOT USED",
+ "RUNNING",
+ "STOPPING",
+ "STOPPED",
+ "ERROR"};
+
+ 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. Current state is [" +
+ scopeStateStrings[getLifecycleState() + 1] +
+ "]");
+ }
+ }
+
+ /**
+ * 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 but the current state is [" +
+ scopeStateStrings[lifecycleState + 1] +
+ "]. Did you try to start the same node twice?");
+ }
+ 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. Current state is [" +
+ scopeStateStrings[lifecycleState + 1] +
+ "]");
+ }
+ setLifecycleState(STOPPED);
+ }
+
+ public void stopContext(KEY contextId) {
+ wrappers.remove(contextId);
+ }
+
+ @Override
+ public String toString() {
+ return "In state [" + scopeStateStrings[lifecycleState + 1] + ']';
+ }
+
+ 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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java
new file mode 100644
index 0000000000..2ea724ccf6
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.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.core.scope.impl.CompositeScopeContainerFactory;
+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()};
+ for (ScopeContainerFactory f : factories) {
+ register(f);
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java
new file mode 100644
index 0000000000..35da433af0
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.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.scope;
+
+/**
+ * The default implementation scopes supported by assemblies.
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+public class Scope {
+ public static final Scope STATELESS = new Scope("STATELESS");
+ public static final Scope COMPOSITE = new Scope("COMPOSITE");
+ public static final Scope INVALID = new Scope("INVALID");
+
+ 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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java
new file mode 100644
index 0000000000..7d34a0144b
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ *
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java
new file mode 100644
index 0000000000..b19c14b3e0
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java
new file mode 100644
index 0000000000..842ed4c547
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java
new file mode 100644
index 0000000000..ee55917f2f
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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$
+ * @tuscany.spi.extension.inheritfrom
+ */
+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();
+
+ /**
+ * Create a wrapper for the component instance for the scope management
+ *
+ * @return A wrapper for the component instance
+ */
+ InstanceWrapper createInstanceWrapper();
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java
new file mode 100644
index 0000000000..98c5f84c71
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java
@@ -0,0 +1,41 @@
+/*
+ * 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$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java
new file mode 100644
index 0000000000..5c85fead2c
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.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.scope;
+
+/**
+ * Denotes an error destroying a target
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java
new file mode 100644
index 0000000000..89ddd7e538
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.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.scope;
+
+/**
+ * Denotes an error initializing a target
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java
new file mode 100644
index 0000000000..bb46a2499b
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java
new file mode 100644
index 0000000000..17afd36219
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.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.scope;
+
+/**
+ * Denotes an error retrieving a target instance
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.asclient
+ */
+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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java
new file mode 100644
index 0000000000..efe7c94b54
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java
@@ -0,0 +1,89 @@
+/*
+ * 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;
+import org.oasisopen.sca.ServiceUnavailableException;
+
+/**
+ * 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) {
+ wrapper = null;
+ throw new IllegalStateException(e);
+ }
+ }
+ wrapper = null;
+ }
+
+ @Override
+ public synchronized InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException {
+ if (wrapper == null) {
+ try {
+ wrapper = createInstanceWrapper();
+ wrapper.start();
+ } catch (Exception e) {
+ wrapper = null;
+ throw new ServiceUnavailableException(e);
+ }
+ }
+ 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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java
new file mode 100644
index 0000000000..f61e70a598
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java
new file mode 100644
index 0000000000..9884c5f053
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.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.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;
+ } else if (scope.equals(Scope.INVALID)) {
+ return null;
+ }
+ ScopeContainerFactory factory = scopeCache.get(scope);
+ ScopeContainer container = factory.createScopeContainer(component);
+ component.setScopeContainer(container);
+ return container;
+ }
+ return null;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java
new file mode 100644
index 0000000000..1235fd2a67
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java
@@ -0,0 +1,61 @@
+/*
+ * 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 {
+ if (lifecycleState != RUNNING) {
+ throw new TargetResolutionException("scope container not running, lifecycleState=" + lifecycleState);
+ }
+ 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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java
new file mode 100644
index 0000000000..5bf20a6a5f
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java
new file mode 100644
index 0000000000..dd4abf0cd2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java
@@ -0,0 +1,210 @@
+/*
+ * 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 java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.LifeCycleListener;
+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, LifeCycleListener {
+
+ /**
+ * Underlying JSR-237 work manager
+ */
+ private ThreadPoolWorkManager jsr237WorkManager;
+ private int maxThreads = 0;
+
+ /**
+ * Initializes the JSR 237 work manager.
+ *
+ * @param jsr237WorkManager JSR 237 work manager.
+ */
+ public DefaultWorkScheduler(ExtensionPointRegistry registry, Map<String, String> attributes) {
+ if (attributes != null) {
+ String value = attributes.get("maxThreads");
+ if (value != null) {
+ maxThreads = Integer.parseInt(value.trim());
+ }
+ }
+ }
+
+ 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(maxThreads);
+ }
+ 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 start() {
+ }
+
+ public void stop() {
+ 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;
+ }
+
+ }
+
+ @Override
+ public ExecutorService getExecutorService() {
+ return getWorkManager().getExecutorService();
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java
new file mode 100644
index 0000000000..7e116655e1
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java
@@ -0,0 +1,232 @@
+/*
+ * 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.Collection;
+import java.util.Map;
+import java.util.UUID;
+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;
+
+/**
+ * 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
+ protected ExecutorService executor;
+
+ /**
+ * Initializes the thread-pool.
+ *
+ * @param threadPoolSize Thread-pool size. If the size <1, then a cached pool is created
+ */
+ public ThreadPoolWorkManager(int threadPoolSize) {
+ ThreadFactory factory = new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r);
+ thread.setDaemon(true);
+ return thread;
+ }
+ };
+ if (threadPoolSize <= 0) {
+
+ // Creates a new Executor, use a custom ThreadFactory that
+ // creates daemon threads.
+ executor = Executors.newCachedThreadPool(factory);
+ } else {
+ executor = Executors.newFixedThreadPool(threadPoolSize, factory);
+ }
+ }
+
+ /**
+ * 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(UUID.randomUUID().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 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 waitForAny(Collection 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));
+ }
+ }
+
+ }
+
+ public void destroy() {
+ executor.shutdown();
+ }
+
+ public ExecutorService getExecutorService() {
+ return executor;
+ }
+
+}
+
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java
new file mode 100644
index 0000000000..ca06d0e854
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java
new file mode 100644
index 0000000000..4580011806
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java
new file mode 100644
index 0000000000..0fc104d0fc
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java b/sca-java-2.x/tags/2.0.1-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java
new file mode 100644
index 0000000000..38bbaeebe0
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/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);
+
+}