From 07ea3bbe7e438fc985c2b7832fb4955543ae218f Mon Sep 17 00:00:00 2001 From: slaws Date: Tue, 30 Nov 2010 09:11:10 +0000 Subject: TUSCANY-3788, TUSCANY-3786 - Allow build time resolvable references to be resolved then so that async response services can be established at that point. In a reliable situation the response service is then available as soon as reference is resolved and doesn't depend on the reference actually being used. Also start adding interfaces to allow the implementation provider to make an async invocation explicitly. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1040444 13f79535-47bb-0310-9956-ffa450edef68 --- .../sca/assembly/impl/EndpointReferenceImpl.java | 6 + .../testing/service/mocks/TestRuntimeWire.java | 5 +- .../builder/impl/EndpointReferenceBuilderImpl.java | 72 +----------- .../trunk/modules/core-spi/META-INF/MANIFEST.MF | 1 + .../tuscany/sca/invocation/InvokerAsync.java | 39 +++++++ .../tuscany/sca/runtime/BaseEndpointRegistry.java | 1 + .../sca/runtime/EndpointReferenceBinder.java | 3 +- .../org/apache/tuscany/sca/runtime/Invocable.java | 9 ++ .../sca/runtime/RuntimeEndpointReference.java | 8 ++ .../core/assembly/impl/RuntimeEndpointImpl.java | 9 +- .../impl/RuntimeEndpointReferenceImpl.java | 81 ++++++++++++- .../tuscany/sca/core/invocation/Constants.java | 30 +++++ .../sca/core/invocation/RuntimeInvoker.java | 60 +++++++++- .../runtime/impl/EndpointReferenceBinderImpl.java | 128 ++++++++++++++------- .../endpoint-validation-messages.properties | 2 +- .../trunk/modules/deployment/META-INF/MANIFEST.MF | 1 + sca-java-2.x/trunk/modules/deployment/pom.xml | 20 ++-- .../tuscany/sca/deployment/impl/DeployerImpl.java | 115 +++++++++++++++++- 18 files changed, 461 insertions(+), 129 deletions(-) create mode 100644 sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvokerAsync.java create mode 100644 sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/EndpointReferenceImpl.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/EndpointReferenceImpl.java index d5ba25f04b..96af9373cd 100644 --- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/EndpointReferenceImpl.java +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/EndpointReferenceImpl.java @@ -232,6 +232,12 @@ public class EndpointReferenceImpl implements EndpointReference { } public boolean isAsyncInvocation() { + if (reference.getName().endsWith("_asyncCallback")){ + // this is a response reference at the service component so don't create a + // response service. The response service will be at the reference component + return false; + } + for(Intent intent : getRequiredIntents()){ if (intent.getName().getLocalPart().equals("asyncInvocation")){ return true; diff --git a/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeWire.java b/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeWire.java index 2896114775..d109b74e34 100644 --- a/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeWire.java +++ b/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeWire.java @@ -204,7 +204,10 @@ public class TestRuntimeWire implements RuntimeEndpoint { // TODO Auto-generated method stub return null; } - + + public void invokeAsync(Operation operation, Message msg) { + return; + } public void unbind() { // TODO Auto-generated method stub diff --git a/sca-java-2.x/trunk/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/EndpointReferenceBuilderImpl.java b/sca-java-2.x/trunk/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/EndpointReferenceBuilderImpl.java index 7af1451f68..9daaad8737 100644 --- a/sca-java-2.x/trunk/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/EndpointReferenceBuilderImpl.java +++ b/sca-java-2.x/trunk/modules/builder/src/main/java/org/apache/tuscany/sca/builder/impl/EndpointReferenceBuilderImpl.java @@ -58,9 +58,6 @@ public class EndpointReferenceBuilderImpl { private AssemblyFactory assemblyFactory; private InterfaceContractMapper interfaceContractMapper; - - // causes dependency between builders and core - //private EndpointReferenceBinder endpointReferenceBinder; public EndpointReferenceBuilderImpl(ExtensionPointRegistry registry) { UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); @@ -68,9 +65,6 @@ public class EndpointReferenceBuilderImpl { FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); - - // causes dependency between builders and core - //endpointReferenceBinder = registry.getExtensionPoint(EndpointReferenceBinder.class); } /** @@ -88,20 +82,6 @@ public class EndpointReferenceBuilderImpl { // left until this stage, after all endpoints have been created, // to to catch more complex cases caused by reference promotion validateComponentReferences(composite, context.getMonitor()); - - // TODO - move the following buld time matching code - // to somewhere else because of - // the dependency between builders and core - - // create temporary local registry for all available local endpoints - //EndpointRegistry registry = new EndpointRegistryImpl(); - - // populate the registry with all the endpoints that are present in the model - //populateLocalRegistry(composite, registry, context); - - // match all local services against the endpoint references - // we've just created - //matchEndpointReferences(composite, registry, context); return composite; } @@ -270,7 +250,7 @@ public class EndpointReferenceBuilderImpl { // non-targetted, i.e. no URI, binding.sca in order to control the // intended QoS of the wire when matching takes place. If any other // bindings are specified then the test later on will complain about - // mixing targts with bindings + // mixing targets with bindings if (reference.getBindings().size() == 1){ Binding binding = reference.getBindings().get(0); if ((binding instanceof SCABinding) && (binding.getURI() == null)){ @@ -327,7 +307,7 @@ public class EndpointReferenceBuilderImpl { } } catch (Exception ex){ // do nothing and go to the next bit of code - // which assumes that the URI is an SCA usi + // which assumes that the URI is an SCA URI } // The user has put something in the binding uri but we don't know if it's @@ -832,52 +812,6 @@ public class EndpointReferenceBuilderImpl { } } } - } - - //========================================================================= - // methods below related to build time matching which is currently disabled -/* - private void populateLocalRegistry(Composite composite, EndpointRegistry registry, BuilderContext context){ - for (Component component : composite.getComponents()) { - // recurse for composite implementations - Implementation implementation = component.getImplementation(); - if (implementation instanceof Composite) { - populateLocalRegistry((Composite)implementation, registry, context); - } - - for (ComponentService service : component.getServices()) { - for (Endpoint endpoint : service.getEndpoints()){ - registry.addEndpoint(endpoint); - } - } - - - for (ComponentReference reference : component.getReferences()) { - for (EndpointReference epr : reference.getEndpointReferences()){ - registry.addEndpointReference(epr); - } - } - - // remove all autowire place holders so they don't cause wires to be created - // have to pass in reference as we don't have access to the registry in - // the builders - for (EndpointReference epr : registry.getEndpointReferences()){ - if (epr.getStatus() == EndpointReference.Status.AUTOWIRE_PLACEHOLDER){ - epr.getReference().getEndpointReferences().remove(epr); - } - } - } - } - - private void matchEndpointReferences(Composite composite, EndpointRegistry registry, BuilderContext context){ - - // look at all the endpoint references and try to match them to - // endpoints - for (EndpointReference endpointReference : registry.getEndpointReferences()){ - endpointReferenceBinder.bindBuildTime(registry, endpointReference); - } - } -*/ - + } } \ No newline at end of file diff --git a/sca-java-2.x/trunk/modules/core-spi/META-INF/MANIFEST.MF b/sca-java-2.x/trunk/modules/core-spi/META-INF/MANIFEST.MF index 1ae10356d5..baae06d53a 100644 --- a/sca-java-2.x/trunk/modules/core-spi/META-INF/MANIFEST.MF +++ b/sca-java-2.x/trunk/modules/core-spi/META-INF/MANIFEST.MF @@ -31,6 +31,7 @@ Bundle-ManifestVersion: 2 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-Description: Apache Tuscany SCA Core SPI Import-Package: org.apache.tuscany.sca.assembly;version="2.0.0", + org.apache.tuscany.sca.assembly.builder;version="2.0.0", org.apache.tuscany.sca.context;version="2.0.0", org.apache.tuscany.sca.core;version="2.0.0", org.apache.tuscany.sca.definitions;version="2.0.0", diff --git a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvokerAsync.java b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvokerAsync.java new file mode 100644 index 0000000000..624e8fdab4 --- /dev/null +++ b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvokerAsync.java @@ -0,0 +1,39 @@ +/* + * 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.invocation; + +/** + * TUSCANY-3786 - Possibly temporary interface to describe an + * async invocation. Need to make it work end to + * end before committing to this. + * + * Asynchronous mediation associated with a client- or target- side wire. + * + */ +public interface InvokerAsync { + + /** + * Process an asynchronous wire + * + * @param msg The request Message for the wire + * + */ + void invokeAsync(Message msg); + +} diff --git a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java index 0b6b93edc0..65c1f8815b 100644 --- a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java +++ b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java @@ -60,6 +60,7 @@ public abstract class BaseEndpointRegistry implements EndpointRegistry, LifeCycl public void addEndpointReference(EndpointReference endpointReference) { endpointreferences.add(endpointReference); + ((RuntimeEndpointReference)endpointReference).bind(registry, this); logger.fine("Add endpoint reference - " + endpointReference); } diff --git a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java index b2ce3f5b7b..60f8a5c5a0 100644 --- a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java +++ b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java @@ -20,6 +20,7 @@ package org.apache.tuscany.sca.runtime; import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; /** * A utility responsible for resolving the endpoint reference against a matching endpoint published @@ -32,7 +33,7 @@ public interface EndpointReferenceBinder { * @param endpointReference * @return */ - void bindBuildTime(EndpointRegistry endpointRegistry, EndpointReference endpointReference); + void bindBuildTime(EndpointRegistry endpointRegistry, EndpointReference endpointReference, BuilderContext builderContext); /** diff --git a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java index 2df1761aec..31260f1afa 100644 --- a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java +++ b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java @@ -128,6 +128,15 @@ public interface Invocable { * @throws InvocationTargetException */ Message invoke(Operation operation, Message msg); + + /** + * Asynchronously invoke an operation with a context message + * @param operation The operation + * @param msg The request message + * @return The ticket that can be used to identify this invocation + * @throws InvocationTargetException + */ + void invokeAsync(Operation operation, Message msg); /** * Get a list of policy providers diff --git a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java index 42e7328c0a..81ef1acd9e 100644 --- a/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java +++ b/sca-java-2.x/trunk/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java @@ -77,4 +77,12 @@ public interface RuntimeEndpointReference extends EndpointReference, Invocable, * @return */ public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract); + + /** + * Create the endpoint which will be the target of and asynchronous response to a + * message sent through this reference. We have the code here as this can't be done + * in the builders in the same was as callbacks are because we don't know the details + * of the endpoint until the endpoint reference has been resolved. + */ + public void createAsyncCallbackEndpoint(); } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java index 4cae8d0085..31738c3a5d 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java @@ -182,7 +182,7 @@ public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); - this.invoker = new RuntimeInvoker(this.messageFactory, this); + this.invoker = new RuntimeInvoker(registry, this); this.phaseManager = utilities.getUtility(PhaseManager.class); this.serializer = utilities.getUtility(EndpointSerializer.class); @@ -285,6 +285,11 @@ public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint 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); + } /** * Navigate the component/componentType inheritence chain to find the leaf contract @@ -647,7 +652,7 @@ public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint @Override public Object clone() throws CloneNotSupportedException { RuntimeEndpointImpl copy = (RuntimeEndpointImpl)super.clone(); - copy.invoker = new RuntimeInvoker(copy.messageFactory, copy); + copy.invoker = new RuntimeInvoker(registry, copy); return copy; } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java index 36480f3435..b18af33a39 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java @@ -31,18 +31,24 @@ 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.FactoryExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; import org.apache.tuscany.sca.core.invocation.RuntimeInvoker; @@ -51,8 +57,10 @@ 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.invocation.Interceptor; import org.apache.tuscany.sca.invocation.InvocationChain; import org.apache.tuscany.sca.invocation.Invoker; @@ -68,7 +76,9 @@ import org.apache.tuscany.sca.provider.ReferenceBindingProvider; import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; import org.apache.tuscany.sca.runtime.EndpointRegistry; import org.apache.tuscany.sca.runtime.EndpointSerializer; +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; @@ -169,7 +179,7 @@ public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implemen new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); - this.invoker = new RuntimeInvoker(this.messageFactory, this); + this.invoker = new RuntimeInvoker(registry, this); this.phaseManager = utilities.getUtility(PhaseManager.class); this.serializer = utilities.getUtility(EndpointSerializer.class); @@ -227,6 +237,11 @@ public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implemen 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); + } /** * Navigate the component/componentType inheritence chain to find the leaf contract @@ -472,7 +487,7 @@ public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implemen @Override public Object clone() throws CloneNotSupportedException { RuntimeEndpointReferenceImpl copy = (RuntimeEndpointReferenceImpl)super.clone(); - copy.invoker = new RuntimeInvoker(copy.messageFactory, copy); + copy.invoker = new RuntimeInvoker(registry, copy); return copy; } @@ -615,5 +630,65 @@ public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implemen } 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(AsyncResponseHandler.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); + + // 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); + } } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java new file mode 100644 index 0000000000..3e2a71027d --- /dev/null +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/Constants.java @@ -0,0 +1,30 @@ +/* + * 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 { + String MESSAGE_ID = "MESSAGE_ID"; + +} diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java index 0751fd631b..b5e3eec282 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java @@ -20,28 +20,45 @@ 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.InvokerAsync; 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; /** * Invoker for a endpoint or endpoint reference * @version $Rev$ $Date$ */ -public class RuntimeInvoker implements Invoker { +public class RuntimeInvoker implements Invoker, InvokerAsync { + protected ExtensionPointRegistry registry; protected MessageFactory messageFactory; protected Invocable invocable; + + // Run async service invocations using a ThreadPoolExecutor + private ExecutorService theExecutor; - public RuntimeInvoker(MessageFactory messageFactory, Invocable invocable) { - this.messageFactory = messageFactory; + 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) { @@ -93,5 +110,42 @@ public class RuntimeInvoker implements Invoker { ThreadMessageContext.setMessageContext(msgContext); } } + + public void invokeAsync(Message msg) { + if (invocable instanceof Endpoint) { + msg.setTo((Endpoint)invocable); + } else if (invocable instanceof EndpointReference) { + RuntimeEndpointReference epr = (RuntimeEndpointReference)invocable; + if (epr.isOutOfDate()) { + epr.rebuild(); + } + msg.setFrom((EndpointReference)invocable); + } + + 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 + InvokerAsync headInvoker = (InvokerAsync)chain.getHeadInvoker(); + + Message msgContext = ThreadMessageContext.setMessageContext(msg); + try { + // TODO - is this the way we'll pass async messages down the chain? + headInvoker.invokeAsync(msg); + } finally { + ThreadMessageContext.setMessageContext(msgContext); + } + + return; + } } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java index 905fed4e01..ffe48005ea 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java @@ -107,8 +107,9 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { * @param endpointReference */ public void bindBuildTime(EndpointRegistry endpointRegistry, - EndpointReference endpointReference) { - bind(endpointRegistry, endpointReference, false); + EndpointReference endpointReference, + BuilderContext builderContext) { + bind(endpointRegistry, endpointReference, builderContext, false); } /** @@ -120,7 +121,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { */ public void bindRunTime(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { - bind(endpointRegistry, endpointReference, true); + bind(endpointRegistry, endpointReference, null, true); } /** @@ -132,6 +133,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { */ public void bind(EndpointRegistry endpointRegistry, EndpointReference endpointReference, + BuilderContext builderContext, boolean runtime){ logger.fine("Binding " + endpointReference.toString()); @@ -159,7 +161,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { continue; } - if (haveMatchingPolicy(endpointReference, endpoint, matchAudit) && + 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 @@ -216,7 +218,9 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { || endpointReference.getCallbackEndpoint().isUnresolved())) { selectCallbackEndpoint(endpointReference, endpointReference.getReference().getCallbackService(), - matchAudit); + matchAudit, + builderContext, + runtime); } } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING ){ // The endpoint reference is already resolved to either @@ -226,12 +230,15 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { selectForwardEndpoint(endpointReference, endpointReference.getTargetEndpoint().getService().getEndpoints(), - matchAudit); + matchAudit, + builderContext); if (hasCallback(endpointReference)){ selectCallbackEndpoint(endpointReference, endpointReference.getReference().getCallbackService(), - matchAudit); + matchAudit, + builderContext, + runtime); } } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI || endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_NOT_FOUND || @@ -241,10 +248,23 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { // find the service in the endpoint registry List endpoints = endpointRegistry.findEndpoint(endpointReference); - if ((endpoints.size() == 0) && - (runtime == true) ) { - - // tweak to test if this could be a resolve binding. This is the back end of the test + if (endpoints.size() > 0){ + selectForwardEndpoint(endpointReference, + endpoints, + matchAudit, + builderContext); + + // 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 @@ -260,16 +280,6 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { throw new ServiceRuntimeException("Unable to bind " + monitor.getLastProblem().toString()); } - } - - selectForwardEndpoint(endpointReference, - endpoints, - matchAudit); - - if (hasCallback(endpointReference)){ - selectCallbackEndpoint(endpointReference, - endpointReference.getReference().getCallbackService(), - matchAudit); } } @@ -285,21 +295,46 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { "EndpointReferenceCantBeMatched", endpointReference.toString(), matchAudit); + throw new ServiceRuntimeException("Unable to bind " + + monitor.getLastProblem().toString()); } else { Monitor.warning(monitor, this, "endpoint-validation-messages", "ComponentReferenceTargetNotFound", endpointReference.toString()); + return; } - throw new ServiceRuntimeException("Unable to bind " + - monitor.getLastProblem().toString()); + } // Now the endpoint reference is resolved check that the binding interfaces contract // and the reference contract are compatible - ((RuntimeEndpointReference)endpointReference).validateReferenceInterfaceCompatibility(); + 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()); + } + } + + // if the reference is an async reference fluff up the + // response service/endpoint + if (endpointReference.isAsyncInvocation()){ + ((RuntimeEndpointReference)endpointReference).createAsyncCallbackEndpoint(); + } // System.out.println("MATCH AUDIT:" + matchAudit.toString()); } @@ -323,7 +358,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { * @param endpointReference * @param endpoints */ - private void selectForwardEndpoint(EndpointReference endpointReference, List endpoints, Audit matchAudit) { + private void selectForwardEndpoint(EndpointReference endpointReference, List endpoints, Audit matchAudit, BuilderContext builderContext) { Endpoint matchedEndpoint = null; @@ -337,7 +372,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { } else { // find the first endpoint that matches this endpoint reference for (Endpoint endpoint : endpoints){ - if (haveMatchingPolicy(endpointReference, endpoint, matchAudit) && + if (haveMatchingPolicy(endpointReference, endpoint, matchAudit, builderContext) && haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){ matchedEndpoint = endpoint; break; @@ -374,7 +409,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { * @param endpointReference * @param endpoints */ - private void selectCallbackEndpoint(EndpointReference endpointReference, ComponentService callbackService, Audit matchAudit) { + private void selectCallbackEndpoint(EndpointReference endpointReference, ComponentService callbackService, Audit matchAudit, BuilderContext builderContext, boolean runtime) { // find the first callback endpoint that matches a callback endpoint reference // at the service @@ -382,7 +417,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { match: for ( EndpointReference callbackEndpointReference : endpointReference.getTargetEndpoint().getCallbackEndpointReferences()){ for (Endpoint endpoint : callbackService.getEndpoints()){ - if (haveMatchingPolicy(callbackEndpointReference, endpoint, matchAudit) && + if (haveMatchingPolicy(callbackEndpointReference, endpoint, matchAudit, builderContext) && haveMatchingInterfaceContracts(callbackEndpointReference, endpoint, matchAudit)){ callbackEndpoint = (RuntimeEndpoint)endpoint; break match; @@ -435,13 +470,18 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { // build it build(callbackEndpoint); - // activate it - compositeActivator.activate(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(), - callbackEndpoint); - - // start it - compositeActivator.start(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(), - callbackEndpoint); + // Only activate the callback endpoint if the bind is being done at runtime + // and hence everthing else is running. If we don't activate here then the + // endpoint will be activate 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); + } } endpointReference.setCallbackEndpoint(callbackEndpoint); @@ -477,7 +517,7 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { * - Perform policy specific match * */ - private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit){ + private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit, BuilderContext builderContext){ matchAudit.append("Match policy of " + endpointReference.toString() + " to " + endpoint.toString() + " "); List referencePolicySets = new ArrayList(); @@ -568,12 +608,17 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { // 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 = ((RuntimeEndpoint)endpoint).getCompositeContext().getSystemDefinitions(); + + Definitions systemDefinitions = null; + if (builderContext != null){ + systemDefinitions = builderContext.getDefinitions(); + } else { + systemDefinitions = ((RuntimeEndpoint)endpoint).getCompositeContext().getSystemDefinitions(); + } + for (BindingType loopBindingType : systemDefinitions.getBindingTypes()){ if (loopBindingType.getType().equals(binding.getType())){ bindingType = loopBindingType; @@ -707,8 +752,9 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { endpointReference.getPolicySets().addAll(referencePolicySets); if (builder != null) { - // TODO - where to get builder context from? - BuilderContext builderContext = new BuilderContext(monitor); + if (builderContext == null){ + builderContext = new BuilderContext(monitor); + } match = builder.build(endpointReference, endpoint, builderContext); } diff --git a/sca-java-2.x/trunk/modules/core/src/main/resources/endpoint-validation-messages.properties b/sca-java-2.x/trunk/modules/core/src/main/resources/endpoint-validation-messages.properties index 6e12d11d68..75f635fb1a 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/resources/endpoint-validation-messages.properties +++ b/sca-java-2.x/trunk/modules/core/src/main/resources/endpoint-validation-messages.properties @@ -20,4 +20,4 @@ # NoEndpointsFound = No endpoints found in the domain that match the reference {0} EndpointReferenceCantBeMatched = = Unable to match the endpoint reference {0} with the policy of the service to which it refers, matching process was {1} -ComponentReferenceTargetNotFound = Component reference target not found, it might be a remote service running elsewhere in the SCA Domain: {1} +ComponentReferenceTargetNotFound = Component reference target not found at deployment time, it might be a remote service elsewhere in the SCA Domain so we'll try and resolve it again at runtime: {1} diff --git a/sca-java-2.x/trunk/modules/deployment/META-INF/MANIFEST.MF b/sca-java-2.x/trunk/modules/deployment/META-INF/MANIFEST.MF index 58d085ce87..65f35c59b0 100644 --- a/sca-java-2.x/trunk/modules/deployment/META-INF/MANIFEST.MF +++ b/sca-java-2.x/trunk/modules/deployment/META-INF/MANIFEST.MF @@ -45,6 +45,7 @@ Import-Package: javax.xml.namespace, org.apache.tuscany.sca.deployment;version="2.0.0", org.apache.tuscany.sca.monitor;version="2.0.0", org.apache.tuscany.sca.xsd;version="2.0.0", + org.apache.tuscany.sca.runtime;version="2.0.0", org.oasisopen.sca.annotation;version="2.0.0";resolution:=optional Bundle-SymbolicName: org.apache.tuscany.sca.deployment Bundle-DocURL: http://www.apache.org/ diff --git a/sca-java-2.x/trunk/modules/deployment/pom.xml b/sca-java-2.x/trunk/modules/deployment/pom.xml index 68205135a2..31e380eaea 100644 --- a/sca-java-2.x/trunk/modules/deployment/pom.xml +++ b/sca-java-2.x/trunk/modules/deployment/pom.xml @@ -37,24 +37,30 @@ tuscany-assembly 2.0-SNAPSHOT + + + org.apache.tuscany.sca + tuscany-assembly-xml + 2.0-SNAPSHOT + - + org.apache.tuscany.sca - tuscany-contribution + tuscany-assembly-xsd 2.0-SNAPSHOT org.apache.tuscany.sca - tuscany-assembly-xml + tuscany-contribution 2.0-SNAPSHOT - + - + org.apache.tuscany.sca - tuscany-assembly-xsd + tuscany-core 2.0-SNAPSHOT - + org.apache.tuscany.sca diff --git a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java index cf94c5a8b7..c3e680bd4d 100644 --- a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java +++ b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java @@ -24,6 +24,7 @@ import java.io.Writer; import java.net.URI; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -38,7 +39,13 @@ import javax.xml.stream.XMLStreamWriter; import org.apache.tuscany.sca.assembly.AssemblyFactory; import org.apache.tuscany.sca.assembly.Base; +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.builder.BuilderContext; import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; @@ -72,6 +79,7 @@ import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.core.ModuleActivatorExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.impl.EndpointRegistryImpl; import org.apache.tuscany.sca.definitions.Definitions; import org.apache.tuscany.sca.definitions.DefinitionsFactory; import org.apache.tuscany.sca.definitions.util.DefinitionsUtil; @@ -79,6 +87,9 @@ import org.apache.tuscany.sca.definitions.xml.DefinitionsExtensionPoint; import org.apache.tuscany.sca.deployment.Deployer; import org.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.runtime.BaseEndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; import org.apache.tuscany.sca.xsd.XSDFactory; import org.apache.tuscany.sca.xsd.XSDefinition; @@ -103,6 +114,7 @@ public class DeployerImpl implements Deployer { protected ExtensibleURLArtifactProcessor artifactProcessor; protected ExtensibleStAXArtifactProcessor staxProcessor; protected ValidationSchemaExtensionPoint validationSchema; + protected EndpointReferenceBinder endpointReferenceBinder; protected MonitorFactory monitorFactory; @@ -310,11 +322,13 @@ public class DeployerImpl implements Deployer { // get the validation schema validationSchema = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class); + + // Get the reference binder + endpointReferenceBinder = registry.getExtensionPoint(EndpointReferenceBinder.class); loadSystemContribution(new ProcessorContext(monitorFactory.createMonitor())); inited = true; - } protected void loadSystemContribution(ProcessorContext context) { @@ -546,6 +560,9 @@ public class DeployerImpl implements Deployer { BuilderContext builderContext = new BuilderContext(systemDefinitions, bindingMap, monitor); compositeBuilder.build(domainComposite, builderContext); // analyzeProblems(monitor); + + // do build time reference binding + buildTimeReferenceBind(domainComposite, builderContext); return domainComposite; } @@ -717,5 +734,101 @@ public class DeployerImpl implements Deployer { init(); return systemDefinitions; } + + // The following operations gives references a chance to bind to + // services at deployment time. + + private void buildTimeReferenceBind(Composite domainComposite, BuilderContext context){ + // create temporary local registry for all available local endpoints + EndpointRegistry endpointRegistry = new LocalEndpointRegistry(registry); + + // populate the registry with all the endpoints that are present in the model + populateLocalRegistry(domainComposite, endpointRegistry, context); + + // match all local services against the endpoint references + // we've just created + matchEndpointReferences(domainComposite, endpointRegistry, context); + } + + private void populateLocalRegistry(Composite composite, EndpointRegistry registry, BuilderContext context){ + for (Component component : composite.getComponents()) { + // recurse for composite implementations + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + populateLocalRegistry((Composite)implementation, registry, context); + } + + // add all endpoints to the local registry + for (ComponentService service : component.getServices()) { + for (Endpoint endpoint : service.getEndpoints()){ + registry.addEndpoint(endpoint); + } + } + + // add endpoint references that we want to match to the registry + for (ComponentReference reference : component.getReferences()) { + for (EndpointReference epr : reference.getEndpointReferences()){ + if (epr.getStatus().equals(EndpointReference.Status.WIRED_TARGET_NOT_FOUND)|| + epr.getStatus().equals(EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI)){ + registry.addEndpointReference(epr); + } + } + } + } + } + + private void matchEndpointReferences(Composite composite, EndpointRegistry registry, BuilderContext builderContext){ + + // look at all the endpoint references and try to match them to + // endpoints + for (EndpointReference endpointReference : registry.getEndpointReferences()){ + endpointReferenceBinder.bindBuildTime(registry, endpointReference, builderContext); + } + } + + // A minimal endpoint registry implementation used to store the Endpoints/EndpointReferences + // for build time local reference resolution. We don't rely on the endpoint registry + // factory here as we specifically just want to do simple local resolution + class LocalEndpointRegistry extends BaseEndpointRegistry { + + private List endpoints = new ArrayList(); + + public LocalEndpointRegistry(ExtensionPointRegistry registry){ + super(registry, null, "", ""); + } + + public void addEndpoint(Endpoint endpoint) { + endpoints.add(endpoint); + endpointAdded(endpoint); + } + + public void removeEndpoint(Endpoint endpoint) { + } + + public Collection getEndpoints() { + return endpoints; + } + + public Endpoint getEndpoint(String uri) { + return null; + } + + public List findEndpoint(String uri) { + List foundEndpoints = new ArrayList(); + 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 void start() { + } + public void stop() { + } + } } -- cgit v1.2.3