diff options
Diffstat (limited to 'sandbox/ant/sca/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java')
-rw-r--r-- | sandbox/ant/sca/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/sandbox/ant/sca/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java b/sandbox/ant/sca/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java new file mode 100644 index 0000000000..99d4defb21 --- /dev/null +++ b/sandbox/ant/sca/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java @@ -0,0 +1,672 @@ +/* + * 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.assembly.builder.impl; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Wire; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.DefaultEndpointBuilder; +import org.apache.tuscany.sca.assembly.builder.EndpointBuilder; +import org.apache.tuscany.sca.definitions.Definitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that wires component references. + * + * @version $Rev$ $Date$ + */ +public class ComponentReferenceWireBuilderImpl extends BaseBuilderImpl implements CompositeBuilder { + + protected EndpointFactory endpointFactory; + private EndpointBuilder endpointBuilder; + + public ComponentReferenceWireBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, InterfaceContractMapper interfaceContractMapper) { + super(assemblyFactory, null, null, null, interfaceContractMapper); + this.endpointFactory = endpointFactory; + this.endpointBuilder = new DefaultEndpointBuilder(); + } + + public String getID() { + return "org.apache.tuscany.sca.assembly.builder.ComponentReferenceWireBuilder"; + } + + public void build(Composite composite, Definitions definitions, Monitor monitor) throws CompositeBuilderException { + wireComponentReferences(composite, monitor); + } + + /** + * Wire component references to component services and connect promoted + * services/references to component services/references inside a composite. + * + * @param composite + */ + protected void wireComponentReferences(Composite composite, Monitor monitor) { + + // Wire nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + wireComponentReferences((Composite)implementation, monitor); + } + } + + // Index components, services and references + Map<String, Component> components = new HashMap<String, Component>(); + Map<String, ComponentService> componentServices = new HashMap<String, ComponentService>(); + Map<String, ComponentReference> componentReferences = new HashMap<String, ComponentReference>(); + indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences); + + // Connect composite services and references to the component + // services and references that they promote + //connectCompositeServices(composite, components, componentServices); + //connectCompositeReferences(composite, componentReferences); + + // Compute the policies before connecting component references + //computePolicies(composite); + + // Connect component references as described in wires + connectWires(composite, componentServices, componentReferences, monitor); + + // Connect component references to their targets +// connectComponentReferences(composite, components, componentServices, componentReferences, monitor); + + // Validate that references are wired or promoted, according + // to their multiplicity + for (ComponentReference componentReference : componentReferences.values()) { + if (!ReferenceConfigurationUtil.validateMultiplicityAndTargets(componentReference.getMultiplicity(), componentReference + .getTargets(), componentReference.getBindings())) { + if (componentReference.getTargets().isEmpty()) { + + // No warning if the reference is promoted out of the current composite + boolean promoted = false; + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + if (compositeReference.getPromotedReferences().contains(componentReference)) { + promoted = true; + break; + } + } + if (!promoted && !componentReference.isCallback()) { + warning(monitor, "ReferenceWithoutTargets", composite, composite.getName().toString(), componentReference.getName()); + } + } else { + warning(monitor, "TooManyReferenceTargets", composite, componentReference.getName()); + } + } + } + + // Finally clear the original reference target lists as we now have + // bindings to represent the targets + // for (ComponentReference componentReference : componentReferences.values()) { + // componentReference.getTargets().clear(); + // } + } + + /** + * Resolve wires and connect the sources to their targets + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectWires(Composite composite, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences, + Monitor monitor) { + + // For each wire, resolve the source reference, the target service, and + // add it to the list of targets of the reference + List<Wire> wires = composite.getWires(); + for (int i = 0, n = wires.size(); i < n; i++) { + Wire wire = wires.get(i); + + ComponentReference resolvedReference; + ComponentService resolvedService; + + // Resolve the source reference + ComponentReference source = wire.getSource(); + if (source != null && source.isUnresolved()) { + resolvedReference = componentReferences.get(source.getName()); + if (resolvedReference != null) { + wire.setSource(resolvedReference); + } else { + warning(monitor, "WireSourceNotFound", composite, source.getName()); + } + } else { + resolvedReference = wire.getSource(); + } + + // Resolve the target service + ComponentService target = wire.getTarget(); + if (target != null && target.isUnresolved()) { + resolvedService = componentServices.get(target.getName()); + if (resolvedService != null) { + wire.setTarget(target); + } else { + warning(monitor, "WireTargetNotFound", composite, source.getName()); + } + } else { + resolvedService = wire.getTarget(); + } + + // Add the target service to the list of targets of the + // reference + if (resolvedReference != null && resolvedService != null) { + // Check that the target component service provides + // a superset of + // the component reference interface + if (resolvedReference.getInterfaceContract() == null || interfaceContractMapper + .isCompatible(resolvedReference.getInterfaceContract(), resolvedService.getInterfaceContract())) { + + //resolvedReference.getTargets().add(resolvedService); + resolvedReference.getTargets().add(wire.getTarget()); + } else { + warning(monitor, "WireIncompatibleInterface", composite, source.getName(), target.getName()); + } + } + } + + // Clear the list of wires + composite.getWires().clear(); + } + + private List<Endpoint> createComponentReferenceTargets(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices, + ComponentReference componentReference, Monitor monitor) { + + List<Endpoint> endpoints = new ArrayList<Endpoint>(); + + if (componentReference.getAutowire() == Boolean.TRUE + && componentReference.getTargets().isEmpty()) { + + // Find suitable targets in the current composite for an + // autowired reference + Multiplicity multiplicity = componentReference.getMultiplicity(); + for (Component targetComponent : composite.getComponents()) { + // prevent autowire connecting to self + boolean skipSelf = false; + for (ComponentReference targetComponentReference : targetComponent + .getReferences()) { + if (componentReference == targetComponentReference) { + skipSelf = true; + } + } + + if (!skipSelf) { + for (ComponentService targetComponentService : targetComponent + .getServices()) { + if (componentReference.getInterfaceContract() == null + || interfaceContractMapper.isCompatible( + componentReference + .getInterfaceContract(), + targetComponentService + .getInterfaceContract())) { + + Endpoint endpoint = endpointFactory + .createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed + // up at start + endpoint + .setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint + .setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + if (multiplicity == Multiplicity.ZERO_ONE + || multiplicity == Multiplicity.ONE_ONE) { + break; + } + } + } + } + } + + if (multiplicity == Multiplicity.ONE_N + || multiplicity == Multiplicity.ONE_ONE) { + if (endpoints.size() == 0) { + warning(monitor, "NoComponentReferenceTarget", + componentReference, componentReference.getName()); + } + } + + } else if (!componentReference.getTargets().isEmpty()) { + + // Check if the component reference does not mix the use of + // endpoints specified via + // binding elements with target endpoints specified via the target + // attribute + for (Binding binding : componentReference.getBindings()) { + if (binding.getURI() != null) { + warning(monitor, "ReferenceEndPointMixWithTarget", + composite, componentReference.getName()); + } + } + + // Resolve targets specified on the component reference + for (ComponentService componentService : componentReference + .getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices + .get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null + || interfaceContractMapper.isCompatible( + componentReference.getInterfaceContract(), + targetComponentService + .getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint + .setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint + .setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + // mark the reference target as resolved. Used later + // when we are looking to + // see if an sca binding is associated with a resolved + // target or not + componentService.setUnresolved(false); + } else { + warning(monitor, "ReferenceIncompatibleInterface", + composite, composite.getName().toString(), + componentReference.getName(), componentService + .getName()); + } + } else { + // add all the reference bindings into the target so that + // they + // can be used for comparison when the target is resolved at + // runtime + componentService.getBindings().addAll( + componentReference.getBindings()); + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(name); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + // The bindings will be cloned back into the reference when + // the + // target is finally resolved. + warning(monitor, "ComponentReferenceTargetNotFound", + composite, composite.getName().toString(), + componentService.getName()); + } + } + } else if ((componentReference.getReference() != null) + && (!componentReference.getReference().getTargets().isEmpty())) { + + // Resolve targets from the corresponding reference in the + // componentType + for (ComponentService componentService : componentReference + .getReference().getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices + .get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of + // the component reference interface + if (componentReference.getInterfaceContract() == null + || interfaceContractMapper.isCompatible( + componentReference.getInterfaceContract(), + targetComponentService + .getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint + .setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint + .setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + // mark the reference target as resolved. Used later + // when we are looking to + // see if an sca binding is associated with a resolved + // target or not + componentService.setUnresolved(false); + } else { + warning(monitor, "ComponentIncompatibleInterface", + composite, componentReference.getName(), + componentService.getName()); + } + } else { + // add all the reference bindings into the target so that + // they + // can be used for comparison when the target is resolved at + // runtime + componentService.getBindings().addAll( + componentReference.getBindings()); + + // The bindings will be cloned back into the reference when + // the + // target is finally resolved. + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(name); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + warning(monitor, "ComponentReferenceTargetNotFound", + composite, composite.getName().toString(), + componentService.getName()); + } + } + } else if (componentReference.getAutowire() == Boolean.TRUE) { + + // Find suitable targets in the current composite for an + // autowired reference + Multiplicity multiplicity = componentReference.getMultiplicity(); + for (Component targetComponent : composite.getComponents()) { + // prevent autowire connecting to self + boolean skipSelf = false; + for (ComponentReference targetComponentReference : targetComponent + .getReferences()) { + if (componentReference == targetComponentReference) { + skipSelf = true; + } + } + + if (!skipSelf) { + for (ComponentService targetComponentService : targetComponent + .getServices()) { + if (componentReference.getInterfaceContract() == null + || interfaceContractMapper.isCompatible( + componentReference + .getInterfaceContract(), + targetComponentService + .getInterfaceContract())) { + + Endpoint endpoint = endpointFactory + .createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed + // up at start + endpoint + .setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint + .setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll( + componentReference.getBindings()); + endpoints.add(endpoint); + + if (multiplicity == Multiplicity.ZERO_ONE + || multiplicity == Multiplicity.ONE_ONE) { + break; + } + } + } + } + } + + if (multiplicity == Multiplicity.ONE_N + || multiplicity == Multiplicity.ONE_ONE) { + if (endpoints.size() == 0) { + warning(monitor, "NoComponentReferenceTarget", + componentReference, componentReference.getName()); + } + } + } + + // if no endpoints have found so far retrieve any target names that are + // in binding URIs + if (endpoints.isEmpty()) { + for (Binding binding : componentReference.getBindings()) { + + String uri = binding.getURI(); + + // user hasn't put a uri on the binding so it's not a target + // name + if (uri == null) { + continue; + } + + // user might have put a local target name in the uri so get + // the path part and see if it refers to a target we know about + // - if it does the reference binding will be matched with a + // service binding + // - if it doesn't it is assumed to be an external reference + Component targetComponent = null; + ComponentService targetComponentService = null; + String path = null; + + try { + path = URI.create(uri).getPath(); + } catch (Exception ex) { + // just assume that no target is identified if + // a URI related exception is thrown + } + + if (path != null) { + if (path.startsWith("/")) { + path = path.substring(1); + } + + // Resolve the target component and service + targetComponentService = componentServices.get(path); + int s = path.indexOf('/'); + if (s == -1) { + targetComponent = components.get(path); + } else { + targetComponent = components.get(path.substring(0, s)); + } + } + + // if the path of the binding URI matches a component in the + // composite then configure an endpoint with this component as + // the target + // if not then the binding URI will be assumed to reference an + // external service + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null + || interfaceContractMapper.isCompatible( + componentReference.getInterfaceContract(), + targetComponentService + .getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint + .setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint + .setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().add(binding); + endpoints.add(endpoint); + } else { + warning(monitor, "ReferenceIncompatibleInterface", + composite, composite.getName().toString(), + componentReference.getName(), uri); + } + } else { + + // create endpoints for manually configured bindings + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(uri); + endpoint.setSourceComponent(null); // TODO - fixed up at + // start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference + .getInterfaceContract()); + endpoint.setSourceBinding(binding); + endpoints.add(endpoint); + } + } + } + + return endpoints; + } + + /** + * Connect references to their targets. + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectComponentReferences(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences, + Monitor monitor){ + + for (ComponentReference componentReference : componentReferences.values()) { + + List<Endpoint> endpoints = createComponentReferenceTargets(composite, + components, + componentServices, + componentReference, + monitor); + + componentReference.getEndpoints().addAll(endpoints); + + // the result of calculating the endpoints is either that bindings have been + // configured manually using a URI or that targets have been provided and the + // endpoint remains unresolved. So all endpoints should be either resved or uresolved. + boolean endpointsRequireAutomaticResolution = false; + for(Endpoint endpoint : endpoints){ + endpointsRequireAutomaticResolution = endpoint.isUnresolved(); + } + + // build each endpoint + if (endpointsRequireAutomaticResolution) { + + for(Endpoint endpoint : endpoints){ + endpointBuilder.build(endpoint, monitor); + } + + // TODO - The following step ensures that the reference binding list remains + // as the record of resolved targets for now. This needs fixing so + // that the endpoint takes on this responsibility. + componentReference.getBindings().clear(); + + if (componentReference.getCallback() != null){ + componentReference.getCallback().getBindings().clear(); + } + + for(Endpoint endpoint : endpoints){ + if (endpoint.isUnresolved() == false){ + componentReference.getBindings().add(endpoint.getSourceBinding()); + + if (componentReference.getCallback() != null){ + componentReference.getCallback().getBindings().add(endpoint.getSourceCallbackBinding()); + } + } + } + + } else { + // do nothing as no targets have been specified so the bindings + // in the reference binding list are assumed to be manually configured + } + } + } + +} |