diff options
5 files changed, 389 insertions, 20 deletions
diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/EndpointReference.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/EndpointReference.java index 793a07d55a..be900ed589 100644 --- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/EndpointReference.java +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/EndpointReference.java @@ -34,9 +34,12 @@ public interface EndpointReference extends Base, PolicySubject, Cloneable, Seria public static final int NOT_CONFIGURED = 0; public static final int RESOLVED_BINDING = 1; - public static final int WIRED_TARGET_NOT_FOUND = 2; - public static final int WIRED_TARGET_FOUND_READY_FOR_MATCHING = 3; - public static final int WIRED_TARGET_FOUND_AND_MATCHED = 4; + public static final int AUTOWIRE_PLACEHOLDER = 2; + public static final int WIRED_TARGET_NOT_FOUND = 3; + public static final int WIRED_TARGET_FOUND_READY_FOR_MATCHING = 4; + public static final int WIRED_TARGET_FOUND_AND_MATCHED = 5; + public static final int WIRED_TARGET_FOUND = 4; // to replace previous two? + /** * Get the structural URI of the reference binding 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 b39e27683d..049ca24e3c 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 @@ -183,12 +183,15 @@ public class EndpointReferenceImpl implements EndpointReference { output += " RESOLVED_BINDING "; break; case 2: + output += " AUTOWIRE_PLACEHOLDER "; + break; + case 3: output += " WIRED_TARGET_NOT_FOUND "; break; - case 3: + case 4: output += " WIRED_TARGET_FOUND_READY_FOR_MATCHING "; break; - case 4: + case 5: output += " WIRED_TARGET_FOUND_AND_MATCHED "; break; } 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 336fa05a2c..56a009e0a5 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 @@ -49,6 +49,9 @@ import org.apache.tuscany.sca.core.UtilityExtensionPoint; import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; import org.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.runtime.DomainRegistryFactory; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; /** * Creates endpoint reference models. @@ -57,20 +60,25 @@ public class EndpointReferenceBuilderImpl { private AssemblyFactory assemblyFactory; private InterfaceContractMapper interfaceContractMapper; - + private DomainRegistryFactory domainRegistryFactory; + private EndpointReferenceBinder endpointReferenceBinder; + public EndpointReferenceBuilderImpl(ExtensionPointRegistry registry) { UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + + domainRegistryFactory = registry.getExtensionPoint(DomainRegistryFactory.class); + endpointReferenceBinder = registry.getExtensionPoint(EndpointReferenceBinder.class); } /** * Create endpoint references for all component references. * * @param composite - */ + */ public Composite build(Composite composite, BuilderContext context) throws CompositeBuilderException { Monitor monitor = context.getMonitor(); @@ -82,7 +90,36 @@ public class EndpointReferenceBuilderImpl { validateComponentReferences(composite, monitor); return composite; - } + } +/* + // Moving toward a consistent matching model between build and runtime + // endpoint reference matching + public Composite build(Composite composite, BuilderContext context) + throws CompositeBuilderException { + // create temporary local registry for all available local endpoints + // TODO - need a better way of getting a local registry + EndpointRegistry registry = domainRegistryFactory.getEndpointRegistry("vm://tmp", "local"); + + // populate the registry with all the endpoints that are present in the model + populateLocalRegistry(composite, registry, context); + + // create endpoint references for each reference + createEndpointReferences(composite, registry, context); + + // match all local services against the endpoint references + // we've just created + matchEndpointReferences(composite, registry, context); + + // remove the local registry + domainRegistryFactory.getEndpointRegistries().remove(registry); + + // validate component references + // TODO - do we really need to leave this until this point? + validateComponentReferences(composite, monitor); + + return composite; + } +*/ private void processComponentReferences(Composite composite, Monitor monitor) { @@ -792,6 +829,7 @@ public class EndpointReferenceBuilderImpl { * @param reference - the reference * @return true if the bindings identify a target, false otherwise */ + // TODO - don't think we need this private boolean bindingsIdentifyTargets(ComponentReference reference) { for (Binding binding : reference.getBindings()) { // <binding.sca without a URI does not identify a target @@ -1029,5 +1067,162 @@ public class EndpointReferenceBuilderImpl { } } } + + // ======================================================================== + // methods below in support of reference matching consolidation + + + 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); + } + } + } + } + + private void createEndpointReferences(Composite composite, EndpointRegistry registry, BuilderContext context){ + for (Component component : composite.getComponents()) { + // recurse for composite implementations + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + createEndpointReferences((Composite)implementation, registry, context); + } + + for (ComponentReference reference : component.getReferences()) { + processComponentReference(composite, + component, + reference, + registry, + context); + + // add all the endpoint references to the local registry so that they're + // easily accessible during the matching stage + for (EndpointReference epr : reference.getEndpointReferences()){ + registry.addEndpointReference(epr); + } + } + } + } + + private void processComponentReference(Composite composite, + Component component, + ComponentReference reference, + EndpointRegistry registry, + BuilderContext context){ + + // Get reference targets + List<ComponentService> refTargets = getReferenceTargets(reference); + + if (reference.getAutowire() == Boolean.TRUE && reference.getTargets().isEmpty()) { + // for autowire references we create a place holder + // endpoint reference. This is not used itself but + // marks out the reference for special attention + // later in the matching process + EndpointReference endpointRef = createEndpointRef(component, reference, false); + endpointRef.setStatus(EndpointReference.AUTOWIRE_PLACEHOLDER); + reference.getEndpointReferences().add(endpointRef); + + } else if (!refTargets.isEmpty()) { + // Check that the component reference does not mix the use of endpoint references + // specified via the target attribute with the presence of binding elements + if (bindingsIdentifyTargets(reference)) { + Monitor.error(context.getMonitor(), + this, + Messages.ASSEMBLY_VALIDATION, + "ReferenceEndPointMixWithTarget", + composite.getName().toString(), + component.getName(), + reference.getName()); + } + + // create endpoint references for targets + for (ComponentService target : refTargets) { + + EndpointReference endpointRef = createEndpointRef(component, reference, true); + endpointRef.setTargetEndpoint(createEndpoint(component, target.getName())); + endpointRef.setRemote(true); + endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND); + reference.getEndpointReferences().add(endpointRef); + } + } -} // end class + // if no endpoints have been found so far the bindings hold the targets. + if (reference.getEndpointReferences().isEmpty()) { + for (Binding binding : reference.getBindings()) { + + String uri = binding.getURI(); + + // user hasn't put a uri on the binding so it's not a target name and the assumption is that + // the target is established via configuration of the binding element itself + if (uri == null) { + // Regular forward references are UNWIRED with no endpoint if they have an SCABinding with NO targets + // and NO URI set - but Callbacks with an SCABinding are wired and need an endpoint + if (!reference.isForCallback() && (binding instanceof SCABinding)) + continue; + + // create endpoint reference for manually configured bindings with a resolved endpoint to + // signify that this reference is pointing at some unwired endpoint + EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false); + if (binding instanceof SCABinding) { + // Assume that the system needs to resolve this binding later as + // it's the SCA binding + endpointRef.setTargetEndpoint(createEndpoint(true)); + endpointRef.setStatus(EndpointReference.NOT_CONFIGURED); + } else { + // The user has configured a binding so assume they know what + // they are doing and mark in as already resolved. + endpointRef.setTargetEndpoint(createEndpoint(false)); + endpointRef.setStatus(EndpointReference.RESOLVED_BINDING); + } + endpointRef.setRemote(true); + reference.getEndpointReferences().add(endpointRef); + continue; + } // end if + + // user might have put a local target name in the uri - see if it refers to a target we know about + // - if it does the reference binding will be matched later on + // - if it doesn't it is assumed to be an external reference + if (uri.startsWith("/")) { + uri = uri.substring(1); + } + + EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false); + + if (registry.findEndpoint(endpointRef).size() > 0){ + // it do refer to an endpoint so we'll match it for real later on + endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND); + } else { + // it's a manually configured binding + Endpoint endpoint = createEndpoint(false); + endpoint.setBinding(binding); + endpointRef.setTargetEndpoint(endpoint); + endpointRef.setRemote(true); + endpointRef.setStatus(EndpointReference.RESOLVED_BINDING); + } + + // TODO - there is a hole in this logic if the uri of the binding represents + // a target to a service elsewhere in the domain we won't know about it + // with this local registry. Should test the real regsitry here also. + + reference.getEndpointReferences().add(endpointRef); + } + } + } + + 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.match(registry, endpointReference); + } + } +}
\ No newline at end of file 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 78a0e19f10..cd435b8321 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 @@ -19,6 +19,8 @@ package org.apache.tuscany.sca.runtime; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.assembly.EndpointReference; /** @@ -26,12 +28,22 @@ import org.apache.tuscany.sca.assembly.EndpointReference; * to the EndpointRegistry */ public interface EndpointReferenceBinder { + + /** + * @param endpointRegistry + * @param endpointReference + * @return + */ + boolean match(EndpointRegistry endpointRegistry, EndpointReference endpointReference); + + /** * @param endpointRegistry * @param endpointReference * @return */ boolean bind(EndpointRegistry endpointRegistry, EndpointReference endpointReference); + /** * * @param endpointRegistry 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 da5abeb728..d5b9eaaf16 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 @@ -22,8 +22,15 @@ package org.apache.tuscany.sca.core.runtime.impl; 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.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.Messages; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; @@ -35,11 +42,12 @@ import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; import org.apache.tuscany.sca.runtime.EndpointRegistry; /** - * An builder that takes endpoint references and resolves them. It either finds local + * 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 builder in case it is required by undresolved endpoints - * once the runtime has started. + * + * This is a separate builder so that the mechanism for reference/service matching + * can be replaced independently * * @version $Rev$ $Date$ */ @@ -63,7 +71,138 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { monitor = monitorFactory.createMonitor(); } + /** + * Match a reference with a service endpoint + * + * Taking a look a consolidating the match logic that used to be in the + * EndpointReferenceBuilder with the match logic that is in the bind() + * method below + */ + public boolean match(EndpointRegistry endpointRegistry, + EndpointReference endpointReference){ + + Problem problem = null; + + if (endpointReference.getStatus() == EndpointReference.AUTOWIRE_PLACEHOLDER){ + // do autowire matching + Multiplicity multiplicity = endpointReference.getReference().getMultiplicity(); + for (Endpoint endpoint : endpointRegistry.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) && + haveMatchingInterfaceContracts(endpointReference, endpoint)){ + // 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(autowireEndpoint); + autowireEndpointRefrence.setStatus(EndpointReference.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, + Messages.ASSEMBLY_VALIDATION, + "NoComponentReferenceTarget", + endpointReference.getReference().getName()); + } + } + } else if ( endpointReference.getStatus() == EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED|| + endpointReference.getStatus() == EndpointReference.RESOLVED_BINDING ) { + // The endpoint reference is already resolved to either + // a service endpoint local to this composite or it has + // a remote binding + + // still need to check that the callback endpoint is set correctly + if (hasCallback(endpointReference) && + endpointReference.getCallbackEndpoint() != null && + endpointReference.getCallbackEndpoint().isUnresolved() == true ){ + problem = selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService().getEndpoints()); + } + } else if (endpointReference.getStatus() == EndpointReference.WIRED_TARGET_NOT_FOUND || + endpointReference.getStatus() == EndpointReference.NOT_CONFIGURED){ + // The reference is not yet matched to a service + + // find the service in the endpoint registry + List<Endpoint> endpoints = endpointRegistry.findEndpoint(endpointReference); + + problem = selectForwardEndpoint(endpointReference, + endpoints); + + if (problem == null && hasCallback(endpointReference)){ + problem = selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService().getEndpoints()); + } + } + + if (problem != null){ + monitor.problem(problem); + return false; + } + if (endpointReference.getStatus() != EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED && + endpointReference.getStatus() != EndpointReference.RESOLVED_BINDING){ + + // how to tell between runtime and build time + boolean runtime = false; + + if (runtime){ + problem = monitor.createProblem(this.getClass().getName(), + "endpoint-validation-messages", + Problem.Severity.ERROR, + this, + "EndpointReferenceCantBeMatched", + endpointReference.toString()); + } else { + problem = monitor.createProblem(this.getClass().getName(), + Messages.ASSEMBLY_VALIDATION, + Problem.Severity.WARNING, + this, + "ComponentReferenceTargetNotFound", + "NEED COMPOSITE NAME", + endpointReference.toString()); + } + + monitor.problem(problem); + return false; + } + + return true; + } /** * Build a single endpoint reference @@ -71,7 +210,8 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { * @param invocable * @param monitor */ - public boolean bind(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { + public boolean bind(EndpointRegistry endpointRegistry, + EndpointReference endpointReference) { Problem problem = null; if ( endpointReference.getStatus() == EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED || endpointReference.getStatus() == EndpointReference.RESOLVED_BINDING ) { @@ -155,7 +295,8 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { } else { // find the first endpoint that matches this endpoint reference for (Endpoint endpoint : endpoints){ - if (haveMatchingPolicy(endpointReference, endpoint)){ + if (haveMatchingPolicy(endpointReference, endpoint) && + haveMatchingInterfaceContracts(endpointReference, endpoint)){ matchedEndpoint = endpoint; break; } @@ -194,7 +335,8 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { match: for ( EndpointReference callbackEndpointReference : endpointReference.getTargetEndpoint().getCallbackEndpointReferences()){ for (Endpoint endpoint : endpoints){ - if (haveMatchingPolicy(callbackEndpointReference, endpoint)){ + if (haveMatchingPolicy(callbackEndpointReference, endpoint) && + haveMatchingInterfaceContracts(endpointReference, endpoint)){ matchedEndpoint = endpoint; break match; } @@ -210,11 +352,9 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { return problem; } - // FIXME: [rfeng] This implementation is wrong. It is the responsibility of the policy language - // to compare the reference and service side setting to determine if they are compatible. Some of - // policies apply to the reference side only, some of the policies apply to the service side only, - // while others apply to both sides. Even for those policies that apply to both side, they can be - // independent or related. + /** + * Determine in endpoint reference and endpoint policies match + */ private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint){ /* @@ -286,6 +426,22 @@ public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { return true; } + + /** + * Determine in endpoint reference and endpoint interface contracts match + */ + private boolean haveMatchingInterfaceContracts(EndpointReference endpointReference, Endpoint endpoint){ + return true; +/* this breaks the existing matching code + if (endpointReference.getReference().getInterfaceContract() == null){ + return true; + } + + return interfaceContractMapper.isCompatible(endpointReference.getReference().getInterfaceContract(), + endpoint.getComponentServiceInterfaceContract()); +*/ + } + public boolean isOutOfDate(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { Endpoint te = endpointReference.getTargetEndpoint(); |