summaryrefslogtreecommitdiffstats
path: root/java/sca
diff options
context:
space:
mode:
Diffstat (limited to 'java/sca')
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingURIBuilderImpl.java518
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentBuilderImpl.java663
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeComponentTypeBuilderImpl.java (renamed from java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentTypeBuilderImpl.java)87
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java108
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointReferenceBuilderImpl.java731
-rw-r--r--java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ModelBuilderImpl.java156
6 files changed, 2025 insertions, 238 deletions
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingURIBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingURIBuilderImpl.java
new file mode 100644
index 0000000000..cb4c549b7d
--- /dev/null
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingURIBuilderImpl.java
@@ -0,0 +1,518 @@
+/*
+ * 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.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.assembly.ComponentReference;
+import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
+import org.apache.tuscany.sca.assembly.builder.DeployedCompositeBuilder;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.definitions.Definitions;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+
+/**
+ * Configuration of binding URIs.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BindingURIBuilderImpl {
+
+ private Monitor monitor;
+
+ public BindingURIBuilderImpl(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ monitor = monitorFactory.createMonitor();
+ }
+
+
+ /**
+ * Called by CompositeBindingURIBuilderImpl
+ *
+ * @param composite the composite to be configured
+ */
+ protected void configureBindingURIsAndNames(Composite composite, Definitions definitions, Monitor monitor)
+ throws CompositeBuilderException {
+ configureBindingURIs(composite, null, definitions, null, monitor);
+ configureBindingNames(composite, monitor);
+ }
+
+ /**
+ * Fully resolve the binding URIs based on available information. This includes information
+ * from the ".composite" files, from resources associated with the binding, e.g. WSDL files,
+ * from any associated policies and from the default information for each binding type.
+ *
+ * @param composite the composite to be configured
+ * @param defaultBindings list of default binding configurations
+ */
+ protected void configureBindingURIs(Composite composite,
+ Definitions definitions,
+ Map<QName, List<String>> defaultBindings,
+ Monitor monitor) throws CompositeBuilderException {
+ configureBindingURIs(composite, null, definitions, defaultBindings, monitor);
+ }
+
+ /**
+ * Fully resolve the binding URIs based on available information. This includes information
+ * from the ".composite" files, from resources associated with the binding, e.g. WSDL files,
+ * from any associated policies and from the default information for each binding type.
+ *
+ * NOTE: This method repeats some of the processing performed by the configureComponents()
+ * method above. The duplication is needed because NodeConfigurationServiceImpl
+ * calls this method without previously calling configureComponents(). In the
+ * normal builder sequence used by CompositeBuilderImpl, both of these methods
+ * are called.
+ *
+ * TODO: Share the URL calculation algorithm with the configureComponents() method above
+ * although keeping the configureComponents() methods signature as is because when
+ * a composite is actually build in a node the node default information is currently
+ * available
+ *
+ * @param composite the composite to be configured
+ * @param uri the path to the composite provided through any nested composite component implementations
+ * @param defaultBindings list of default binding configurations
+ */
+ private void configureBindingURIs(Composite composite,
+ String uri,
+ Definitions definitions,
+ Map<QName, List<String>> defaultBindings,
+ Monitor monitor) throws CompositeBuilderException {
+
+ String parentComponentURI = uri;
+
+ monitor.pushContext("Composite: " + composite.getName().toString());
+ try {
+ // Process nested composites recursively
+ for (Component component : composite.getComponents()) {
+
+ // Initialize component URI
+ String componentURI;
+ if (parentComponentURI == null) {
+ componentURI = component.getName();
+ } else {
+ componentURI = URI.create(parentComponentURI + '/').resolve(component.getName()).toString();
+ }
+ component.setURI(componentURI);
+
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ // Process nested composite
+ configureBindingURIs((Composite)implementation, componentURI, definitions, defaultBindings, monitor);
+ }
+ }
+
+ // Initialize composite service binding URIs
+ List<Service> compositeServices = composite.getServices();
+ for (Service service : compositeServices) {
+
+ constructBindingNames(service, monitor);
+
+ // Initialize binding names and URIs
+ for (Binding binding : service.getBindings()) {
+ constructBindingURI(parentComponentURI, composite, service, binding, defaultBindings, monitor);
+ }
+ }
+
+ // Initialize component service binding URIs
+ for (Component component : composite.getComponents()) {
+
+ monitor.pushContext("Component: " + component.getName());
+
+ try {
+
+ for (ComponentService service : component.getServices()) {
+
+ constructBindingNames(service, monitor);
+
+ // Initialize binding names and URIs
+ for (Binding binding : service.getBindings()) {
+ constructBindingURI(component, service, binding, defaultBindings, monitor);
+ }
+ }
+ } finally {
+ monitor.popContext();
+ }
+ }
+ } finally {
+ monitor.popContext();
+ }
+ }
+
+ /**
+ * Add default names for callback bindings and reference bindings. Needs to be
+ * separate from configureBindingURIs() because configureBindingURIs() is called
+ * by NodeConfigurationServiceImpl as well as by CompositeBuilderImpl.
+ */
+ private void configureBindingNames(Composite composite, Monitor monitor) {
+
+ // Process nested composites recursively
+ for (Component component : composite.getComponents()) {
+
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+
+ // Process nested composite
+ configureBindingNames((Composite)implementation, monitor);
+ }
+ }
+
+ // Initialize composite service callback binding names
+ for (Service service : composite.getServices()) {
+ constructBindingNames(service, monitor);
+ }
+
+ // Initialize composite reference binding names
+ for (Reference reference : composite.getReferences()) {
+ constructBindingNames(reference, monitor);
+ }
+
+ // Initialize component service and reference binding names
+ for (Component component : composite.getComponents()) {
+
+ // Initialize component service callback binding names
+ for (ComponentService service : component.getServices()) {
+ constructBindingNames(service, monitor);
+ }
+
+ // Initialize component reference binding names
+ for (ComponentReference reference : component.getReferences()) {
+ // Initialize binding names
+ constructBindingNames(reference, monitor);
+ }
+ }
+ }
+
+ /**
+ * If a binding name is not provided by the user, construct it based on the service
+ * or reference name
+ *
+ * @param contract the service or reference
+ */
+ private void constructBindingNames(Contract contract, Monitor monitor) {
+ List<Binding> bindings = contract.getBindings();
+ Map<String, Binding> bindingMap = new HashMap<String, Binding>();
+ for (Binding binding : bindings) {
+ // set the default binding name if one is required
+ // if there is no name on the binding then set it to the service or reference name
+ if (binding.getName() == null) {
+ binding.setName(contract.getName());
+ }
+ Binding existed = bindingMap.put(binding.getName(), binding);
+ // Check that multiple bindings do not have the same name
+ if (existed != null && existed != binding) {
+ if (contract instanceof Service){
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "MultipleBindingsForService",
+ contract.getName(),
+ binding.getName());
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "MultipleBindingsForReference",
+ contract.getName(),
+ binding.getName());
+ }
+ }
+ }
+
+ if (contract.getCallback() != null) {
+ bindings = contract.getCallback().getBindings();
+ bindingMap.clear();
+ for (Binding binding : bindings) {
+ // set the default binding name if one is required
+ // if there is no name on the binding then set it to the service or reference name
+ if (binding.getName() == null) {
+ binding.setName(contract.getName());
+ }
+ Binding existed = bindingMap.put(binding.getName(), binding);
+ // Check that multiple bindings do not have the same name
+ if (existed != null && existed != binding) {
+ if (contract instanceof Service){
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "MultipleBindingsForServiceCallback",
+ contract.getName(),
+ binding.getName());
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "MultipleBindingsForReferenceCallback",
+ contract.getName(),
+ binding.getName());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * URI construction for composite bindings based on Assembly Specification section 1.7.2, This method
+ * assumes that the component URI part of the binding URI is formed from the part to the
+ * composite in question and just calls the generic constructBindingURI method with this
+ * information
+ *
+ * @param parentComponentURI
+ * @param composite
+ * @param service
+ * @param binding
+ * @param defaultBindings
+ */
+ private void constructBindingURI(String parentComponentURI,
+ Composite composite,
+ Service service,
+ Binding binding,
+ Map<QName, List<String>> defaultBindings,
+ Monitor monitor) throws CompositeBuilderException {
+ // This is a composite service so there is no component to provide a component URI
+ // The path to this composite (through nested composites) is used.
+ constructBindingURI(parentComponentURI, service, binding, defaultBindings, monitor);
+ }
+
+ /**
+ * URI construction for component bindings based on Assembly Specification section 1.7.2. This method
+ * calculates the component URI part based on component information before calling the generic
+ * constructBindingURI method
+ *
+ * @param component the component that holds the service
+ * @param service the service that holds the binding
+ * @param binding the binding for which the URI is being constructed
+ * @param defaultBindings the list of default binding configurations
+ */
+ private void constructBindingURI(Component component,
+ Service service,
+ Binding binding,
+ Map<QName, List<String>> defaultBindings,
+ Monitor monitor) throws CompositeBuilderException {
+ constructBindingURI(component.getURI(), service, binding, defaultBindings, monitor);
+ }
+
+ /**
+ * Generic URI construction for bindings based on Assembly Specification section 1.7.2
+ *
+ * @param componentURIString the string version of the URI part that comes from the component name
+ * @param service the service in question
+ * @param binding the binding for which the URI is being constructed
+ * @param includeBindingName when set true the serviceBindingURI part should be used
+ * @param defaultBindings the list of default binding configurations
+ * @throws CompositeBuilderException
+ */
+ private void constructBindingURI(String componentURIString,
+ Service service,
+ Binding binding,
+ Map<QName, List<String>> defaultBindings,
+ Monitor monitor) throws CompositeBuilderException {
+
+ try {
+
+ boolean includeBindingName = !service.getName().equals(binding.getName());
+
+ // calculate the service binding URI
+ URI bindingURI;
+ if (binding.getURI() != null) {
+ bindingURI = new URI(binding.getURI());
+
+ // if the user has provided an absolute binding URI then use it
+ if (bindingURI.isAbsolute()) {
+ binding.setURI(bindingURI.toString());
+ return;
+ }
+ } else {
+ bindingURI = null;
+ }
+
+ String serviceName = service.getName();
+ // Get the service binding name
+ String bindingName;
+ if (binding.getName() != null) {
+ bindingName = binding.getName();
+ } else {
+ bindingName = serviceName;
+ }
+
+ // calculate the component URI
+ URI componentURI;
+ if (componentURIString != null) {
+ componentURI = new URI(addSlashToPath(componentURIString));
+ } else {
+ componentURI = null;
+ }
+
+ // if the user has provided an absolute component URI then use it
+ if (componentURI != null && componentURI.isAbsolute()) {
+ binding.setURI(constructBindingURI(null,
+ componentURI,
+ bindingURI,
+ serviceName,
+ includeBindingName,
+ bindingName));
+ return;
+ }
+
+ // calculate the base URI
+ URI baseURI = null;
+ if (defaultBindings != null) {
+ List<String> uris = defaultBindings.get(binding.getType());
+ if (uris != null && uris.size() > 0) {
+ baseURI = new URI(addSlashToPath(uris.get(0)));
+ }
+ }
+
+ binding.setURI(constructBindingURI(baseURI,
+ componentURI,
+ bindingURI,
+ serviceName,
+ includeBindingName,
+ bindingName));
+ } catch (URISyntaxException ex) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "URLSyntaxException",
+ componentURIString,
+ service.getName(),
+ binding.getName());
+ }
+ }
+
+ /**
+ * Use to ensure that URI paths end in "/" as here we want to maintain the
+ * last path element of an base URI when other URI are resolved against it. This is
+ * not the default behaviour of URI resolution as defined in RFC 2369
+ *
+ * @param path the path string to which the "/" is to be added
+ * @return the resulting path with a "/" added if it not already there
+ */
+ private static String addSlashToPath(String path) {
+ if (path.endsWith("/") || path.endsWith("#")) {
+ return path;
+ } else {
+ return path + "/";
+ }
+ }
+
+ /**
+ * Concatenate binding URI parts together based on Assembly Specification section 1.7.2
+ *
+ * @param baseURI the base of the binding URI
+ * @param componentURI the middle part of the binding URI derived from the component name
+ * @param bindingURI the end part of the binding URI
+ * @param includeBindingName when set true the binding name part should be used
+ * @param bindingName the binding name
+ * @return the resulting URI as a string
+ */
+ private static String constructBindingURI(URI baseURI,
+ URI componentURI,
+ URI bindingURI,
+ String serviceName,
+ boolean includeBindingName,
+ String bindingName) {
+ String name = includeBindingName ? serviceName + "/" + bindingName : serviceName;
+ String uriString;
+
+ if (baseURI == null) {
+ if (componentURI == null) {
+ if (bindingURI != null) {
+ uriString = name + "/" + bindingURI.toString();
+ } else {
+ uriString = name;
+ }
+ } else {
+ if (bindingURI != null) {
+ if (bindingURI.toString().startsWith("/")) {
+ uriString = componentURI.resolve(bindingURI).toString();
+ } else {
+ uriString = componentURI.resolve(name + "/" + bindingURI).toString();
+ }
+ } else {
+ uriString = componentURI.resolve(name).toString();
+ }
+ }
+ } else {
+ if (componentURI == null) {
+ if (bindingURI != null) {
+ uriString = basedURI(baseURI, bindingURI).toString();
+ } else {
+ uriString = basedURI(baseURI, URI.create(name)).toString();
+ }
+ } else {
+ if (bindingURI != null) {
+ uriString = basedURI(baseURI, componentURI.resolve(bindingURI)).toString();
+ } else {
+ uriString = basedURI(baseURI, componentURI.resolve(name)).toString();
+ }
+ }
+ }
+
+ // tidy up by removing any trailing "/"
+ if (uriString.endsWith("/")) {
+ uriString = uriString.substring(0, uriString.length() - 1);
+ }
+
+ URI uri = URI.create(uriString);
+ if (!uri.isAbsolute()) {
+ uri = URI.create("/").resolve(uri);
+ }
+ return uri.toString();
+ }
+
+ /**
+ * Combine a URI with a base URI.
+ *
+ * @param baseURI
+ * @param uri
+ * @return
+ */
+ private static URI basedURI(URI baseURI, URI uri) {
+ if (uri.getScheme() != null) {
+ return uri;
+ }
+ String str = uri.toString();
+ if (str.startsWith("/")) {
+ str = str.substring(1);
+ }
+ return URI.create(baseURI.toString() + str).normalize();
+ }
+
+}
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentBuilderImpl.java
index 54475253a2..09e9d95724 100644
--- a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentBuilderImpl.java
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentBuilderImpl.java
@@ -18,24 +18,46 @@
*/
package org.apache.tuscany.sca.assembly.builder.impl;
+import static org.apache.tuscany.sca.assembly.Base.SCA11_NS;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentProperty;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
+import org.apache.tuscany.sca.assembly.ComponentType;
import org.apache.tuscany.sca.assembly.Composite;
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.Implementation;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.Property;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.SCABindingFactory;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
import org.apache.tuscany.sca.assembly.builder.ImplementationBuilder;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
@@ -47,6 +69,10 @@ import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.MonitorFactory;
import org.apache.tuscany.sca.policy.ExtensionType;
import org.apache.tuscany.sca.policy.PolicySubject;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
/**
* @version $Rev$ $Date$
@@ -58,12 +84,15 @@ public class ComponentBuilderImpl {
protected static final String BINDING_SCA = "binding.sca";
protected static final QName BINDING_SCA_QNAME = new QName(SCA11_NS, BINDING_SCA);
- private ComponentTypeBuilderImpl componentTypeBuilder;
+ private CompositeComponentTypeBuilderImpl componentTypeBuilder;
private Monitor monitor;
private AssemblyFactory assemblyFactory;
private SCABindingFactory scaBindingFactory;
+ private DocumentBuilderFactory documentBuilderFactory;
+ protected TransformerFactory transformerFactory;
private InterfaceContractMapper interfaceContractMapper;
private BuilderExtensionPoint builders;
+
public ComponentBuilderImpl(ExtensionPointRegistry registry) {
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
@@ -73,25 +102,32 @@ public class ComponentBuilderImpl {
FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
scaBindingFactory = modelFactories.getFactory(SCABindingFactory.class);
+ documentBuilderFactory = modelFactories.getFactory(DocumentBuilderFactory.class);
+ transformerFactory = modelFactories.getFactory(TransformerFactory.class);
interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
}
- public void setComponentTypeBuilder(ComponentTypeBuilderImpl componentTypeBuilder){
+ public void setComponentTypeBuilder(CompositeComponentTypeBuilderImpl componentTypeBuilder){
this.componentTypeBuilder = componentTypeBuilder;
}
/**
* Configure the component based on its component type using OASIS rules
*
- * @param component
+ * @Param parentComposite the composite that contains the component being configured. Required for property processing
+ * @param component the component to be configured
*/
- public void configureComponentFromComponentType(Component component){
+ public void configureComponentFromComponentType(Composite parentComposite,
+ Component component){
- // do any required pre-processing on the implementation
- // what does this do?
+ // do any work we need to do before we calculate the component type
+ // for this component. Anything that needs to be pushed down the promotion
+ // hierarchy must be done before we calculate the component type
+
+ // first carry out any implementation specific builder processing
Implementation impl = component.getImplementation();
if (impl != null) {
ImplementationBuilder builder = builders.getImplementationBuilder(impl.getClass());
@@ -100,19 +136,22 @@ public class ComponentBuilderImpl {
}
}
+ // Properties on the composite component type are not affected by the components
+ // that the composite contains. Instead the child components might source
+ // composite level property values. Hence we have to calculate whether the component
+ // type property value should be overridden by this component's property value
+ // before we go ahead and calculate the component type
+ configureProperties(parentComposite, component);
+
// create the component type for this component
// taking any nested composites into account
createComponentType(component);
-
- // services
+
+ // configure services based on the calculated component type
configureServices(component);
- // references
+ // configure services based on the calculated component type
configureReferences(component);
-
- // properties
- //configureProperties(component);
-
}
/**
@@ -194,21 +233,26 @@ public class ComponentBuilderImpl {
// configuration based on OASIS rules
for (ComponentReference componentReference : component.getReferences()) {
Reference componentTypeReference = componentReference.getReference();
+
+ // reference multiplicity
+ reconcileReferenceMultiplicity(component,
+ componentReference,
+ componentTypeReference);
// interface contracts
calculateInterfaceContract(componentReference,
componentTypeReference);
// bindings
- // We don've to do anything with reference bindings. You've either
+ // We don't have to do anything with reference bindings. You've either
// specified one or you haven't
//calculateBindings(componentService,
// componentTypeService);
// add callback service model objects
- //createCallbackService(component,
- // componentReference);
+ createCallbackService(component,
+ componentReference);
// intents - done later in CompositePolicyBuilder - discuss with RF
@@ -218,9 +262,53 @@ public class ComponentBuilderImpl {
// policy sets - done later in CompositePolicyBuilder - discuss with RF
// calculatePolicySets(componentService,
// componentTypeService);
+
+ // Propagate autowire setting from the component down the structural
+ // hierarchy
+ if (componentReference.getAutowire() == null) {
+ componentReference.setAutowire(component.getAutowire());
+ }
+
+ // Reconcile targets copying then up the promotion hierarchy
+ if (componentReference.getTargets().isEmpty()) {
+ componentReference.getTargets().addAll(componentTypeReference.getTargets());
+ }
}
- }
+ }
+
+ /**
+ * Configure this component's properties based on the properties in its
+ * component type and the configuration from the composite file
+ *
+ * @param component
+ */
+ private void configureProperties(Composite parentComposite, Component component){
+ // If the component type has properties that are not described in this
+ // component then create properties for this component
+ addPropertiesFromComponentType(component);
+
+ // Connect this component's properties to the
+ // properties from its component type
+ connectReferencesToComponentType(component);
+
+ // Reconcile component properties and their component type properties
+ for (ComponentProperty componentProperty : component.getProperties()) {
+ reconcileComponentPropertyWithComponentType(component,
+ componentProperty);
+
+ // configure the property value based on the @source attribute
+ // At the moment this is done in the parent composite component
+ // type calculation a
+ processPropertySourceAttribute(parentComposite,
+ component,
+ componentProperty);
+
+ // configure the property value based on the @file attribute
+ processPropertyFileAttribute(component,
+ componentProperty);
+ }
+ }
private void addServicesFromComponentType(Component component){
@@ -262,7 +350,32 @@ public class ComponentBuilderImpl {
}
}
}
- }
+ }
+
+ private void addPropertiesFromComponentType(Component component){
+
+ // Create component property for each property
+ if (component.getImplementation() != null) {
+ for (Property property : component.getImplementation().getProperties()) {
+ ComponentProperty componentProperty =
+ (ComponentProperty)component.getProperty(property.getName());
+
+ // if the component doesn't have a property with the same name as
+ // the component type property then create one
+ if (componentProperty == null) {
+ componentProperty = assemblyFactory.createComponentProperty();
+ componentProperty.setName(property.getName());
+ componentProperty.setValue(property.getValue());
+ componentProperty.setMany(property.isMany());
+ componentProperty.setMustSupply(property.isMustSupply());
+ componentProperty.setXSDElement(property.getXSDElement());
+ componentProperty.setXSDType(property.getXSDType());
+ componentProperty.setProperty(property);
+ component.getProperties().add(componentProperty);
+ }
+ }
+ }
+ }
private void connectServicesToComponentType(Component component){
@@ -308,76 +421,289 @@ public class ComponentBuilderImpl {
componentReference.getName());
}
}
- }
-
+ }
+
+ private void connectPropertiesToComponentType(Component component){
+ // Connect each component property to the corresponding component type property
+ for (ComponentProperty componentProperty : component.getProperties()) {
+ Property property = component.getImplementation().getProperty(componentProperty.getName());
+ if (property != null) {
+ componentProperty.setProperty(property);
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertyNotFound",
+ component.getName(),
+ componentProperty.getName());
+ }
+ }
+ }
+
+ private void reconcileReferenceMultiplicity(Component component,
+ Reference componentReference,
+ Reference componentTypeReference){
+ if (componentReference.getMultiplicity() != null) {
+ if (!isValidMultiplicityOverride(componentTypeReference.getMultiplicity(),
+ componentReference.getMultiplicity())) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceIncompatibleMultiplicity",
+ component.getName(),
+ componentReference.getName());
+ }
+ } else {
+ componentReference.setMultiplicity(componentTypeReference.getMultiplicity());
+ }
+ }
+
+ private void reconcileComponentPropertyWithComponentType(Component component,
+ ComponentProperty componentProperty){
+ Property componentTypeProperty = componentProperty.getProperty();
+ if (componentTypeProperty != null) {
+
+ // Check that a component property does not override the
+ // mustSupply attribute
+ if (!componentTypeProperty.isMustSupply() &&
+ componentProperty.isMustSupply()) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertyMustSupplyIncompatible",
+ component.getName(),
+ componentProperty.getName());
+ }
+
+ // Default to the mustSupply attribute specified on the property
+ if (!componentProperty.isMustSupply())
+ componentProperty.setMustSupply(componentTypeProperty.isMustSupply());
+
+ // Default to the value specified on the component type property
+ if (!isPropertyValueSet(componentProperty)) {
+ componentProperty.setValue(componentTypeProperty.getValue());
+ }
+
+ // Override the property value for the composite
+ if (component.getImplementation() instanceof Composite) {
+ componentTypeProperty.setValue(componentProperty.getValue());
+ }
+
+ // Check that a value is supplied
+ if (!isPropertyValueSet(componentProperty) &&
+ componentTypeProperty.isMustSupply()) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertyMustSupplyNull",
+ component.getName(),
+ componentProperty.getName());
+ }
+
+ // Check that a component property does not override the
+ // many attribute
+ if (!componentTypeProperty.isMany() &&
+ componentProperty.isMany()) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertyOverrideManyAttribute",
+ component.getName(),
+ componentProperty.getName());
+ }
+
+ // Default to the many attribute defined on the property
+ componentProperty.setMany(componentTypeProperty.isMany());
+
+ // Default to the type and element defined on the property
+ if (componentProperty.getXSDType() == null) {
+ componentProperty.setXSDType(componentTypeProperty.getXSDType());
+ }
+ if (componentProperty.getXSDElement() == null) {
+ componentProperty.setXSDElement(componentTypeProperty.getXSDElement());
+ }
+
+ // Check that a type or element are specified
+ if (componentProperty.getXSDElement() == null &&
+ componentProperty.getXSDType() == null) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "NoTypeForComponentProperty",
+ component.getName(),
+ componentProperty.getName());
+ }
+ }
+ }
+
/**
- * OASIS RULE: Interface contract from higher in the implementation hierarchy takes precedence
+ * If the property has a source attribute use this to retrieve the value from a
+ * property in the parent composite
+
*
- * @param topContract the top contract
- * @param bottomContract the bottom contract
- */
- private void calculateInterfaceContract(Contract topContract,
- Contract bottomContract) {
- // Use the interface contract from the bottom level contract if
- // none is specified on the top level contract
- InterfaceContract topInterfaceContract = topContract.getInterfaceContract();
- InterfaceContract bottomInterfaceContract = bottomContract.getInterfaceContract();
-
- if (topInterfaceContract == null) {
- topContract.setInterfaceContract(bottomInterfaceContract);
- } else if (bottomInterfaceContract != null) {
- // Check that the top and bottom interface contracts are compatible
- boolean isCompatible = interfaceContractMapper.isCompatible(topInterfaceContract,
- bottomInterfaceContract);
- if (!isCompatible) {
- if (topContract instanceof Reference) {
+ * @param parentCompoent the composite that contains the component
+ * @param component
+ * @param componentProperty
+ */
+ private void processPropertySourceAttribute(Composite parentComposite,
+ Component component,
+ ComponentProperty componentProperty){
+ String source = componentProperty.getSource();
+
+ if (source != null) {
+ // $<name>/...
+ int index = source.indexOf('/');
+ if (index == -1) {
+ // Tolerating $prop
+ source = source + "/";
+ index = source.length() - 1;
+ }
+ if (source.charAt(0) == '$') {
+ String name = source.substring(1, index);
+ Property compositeProp = parentComposite.getProperty(name);
+ if (compositeProp == null) {
Monitor.error(monitor,
- this,
- "assembly-validation-messages",
- "ReferenceInterfaceNotSubSet",
- topContract.getName());
- } else {
+ this,
+ "assembly-validation-messages",
+ "PropertySourceNotFound",
+ source,
+ componentProperty.getName(),
+ component.getName());
+ }
+
+ Document compositePropDefValues = (Document)compositeProp.getValue();
+
+ try {
+ // FIXME: How to deal with namespaces?
+ Document node = evaluateXPath(compositePropDefValues,
+ componentProperty.getSourceXPathExpression(),
+ documentBuilderFactory);
+
+ if (node != null) {
+ componentProperty.setValue(node);
+ }
+ } catch (Exception ex){
Monitor.error(monitor,
- this,
- "assembly-validation-messages",
- "ServiceInterfaceNotSubSet",
- topContract.getName());
+ this,
+ "assembly-validation-messages",
+ "PropertySourceXpathInvalid",
+ source,
+ componentProperty.getName(),
+ component.getName(),
+ ex.toString());
}
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertySourceValueInvalid",
+ source,
+ componentProperty.getName(),
+ component.getName());
}
}
- }
+ }
/**
- * OASIS RULE: Bindings from higher in the hierarchy take precedence
+ * If the property has a file attribute use this to retrieve the value from a
+ * local file
+
*
- * @param componentService the top service
- * @param componentTypeService the bottom service
- */
- private void calculateBindings(Service componentService,
- Service componentTypeService){
- // forward bindings
- if (componentService.getBindings().isEmpty()) {
- componentService.getBindings().addAll(componentTypeService.getBindings());
- }
+ * @param parentCompoent the composite that contains the component
+ * @param component
+ */
+ private void processPropertyFileAttribute(Component component,
+ ComponentProperty componentProperty){
+ String file = componentProperty.getFile();
+ if (file != null) {
+ try{
+ URI uri = URI.create(file);
+ // URI resolution for relative URIs is done when the composite is resolved.
+ URL url = uri.toURL();
+ URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ InputStream is = null;
+ try {
+ is = connection.getInputStream();
- if (componentService.getBindings().isEmpty()) {
- createSCABinding(componentService, null);
- }
-
- // callback bindings
- if (componentService.getCallback() == null) {
- componentService.setCallback(componentTypeService.getCallback());
- if (componentService.getCallback() == null) {
- // Create an empty callback to avoid null check
- componentService.setCallback(assemblyFactory.createCallback());
+ Source streamSource = new SAXSource(new InputSource(is));
+ DOMResult result = new DOMResult();
+ javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+ transformer.transform(streamSource, result);
+
+ Document document = (Document)result.getNode();
+
+ // TUSCANY-2377, Add a fake value element so it's consistent with
+ // the DOM tree loaded from inside SCDL
+ Element root = document.createElementNS(null, "value");
+ root.appendChild(document.getDocumentElement());
+ document.appendChild(root);
+ componentProperty.setValue(document);
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ } catch (Exception ex){
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "PropertyFileValueInvalid",
+ file,
+ componentProperty.getName(),
+ component.getName(),
+ ex.toString());
}
- } else if (componentService.getCallback().getBindings().isEmpty() && componentTypeService.getCallback() != null) {
- componentService.getCallback().getBindings().addAll(componentTypeService.getCallback().getBindings());
}
}
/**
+ * Evaluate an XPath expression against a Property value, returning the result as a Property value
+ * @param node - the document root element of a Property value
+ * @param expression - the XPath expression
+ * @param documentBuilderFactory - a DOM document builder factory
+ * @return - a DOM Document representing the result of the evaluation as a Property value
+ * @throws XPathExpressionException
+ * @throws ParserConfigurationException
+ */
+ private Document evaluateXPath(Document node,
+ XPathExpression expression,
+ DocumentBuilderFactory documentBuilderFactory)
+ throws XPathExpressionException, ParserConfigurationException {
+
+ // The document element is a <sca:property/> element
+ Node property = node.getDocumentElement();
+ // The first child of the <property/> element is a <value/> element
+ Node value = property.getFirstChild();
+
+ Node result = (Node)expression.evaluate(value, XPathConstants.NODE);
+ if (result == null) {
+ return null;
+ }
+
+ if (result instanceof Document) {
+ return (Document)result;
+ } else {
+ Document document = documentBuilderFactory.newDocumentBuilder().newDocument();
+ Element newProperty = document.createElementNS(SCA11_NS, "property");
+
+ if (result.getNodeType() == Node.ELEMENT_NODE) {
+ // If the result is a <value/> element, use it directly in the result
+ newProperty.appendChild(document.importNode(result, true));
+ } else {
+ // If the result is not a <value/> element, create a <value/> element to contain the result
+ Element newValue = document.createElementNS(SCA11_NS, "value");
+ newValue.appendChild(document.importNode(result, true));
+ newProperty.appendChild(newValue);
+ } // end if
+ document.appendChild(newProperty);
+
+ return document;
+ }
+ }
+
+ /**
* Create a callback reference for a component service
*
* @param component
@@ -453,9 +779,84 @@ public class ComponentBuilderImpl {
callbackReference.getBindings().addAll(service.getBindings());
} // end if
} // end if
- service.setCallbackReference(callbackReference);
+ service.setCallbackReference(callbackReference);
}
- }
+ }
+
+ /**
+ * Create a callback service for a component reference
+ *
+ * @param component
+ * @param service
+ */
+ private void createCallbackService(Component component, ComponentReference reference) {
+ if (reference.getInterfaceContract() != null && // can be null in unit tests
+ reference.getInterfaceContract().getCallbackInterface() != null) {
+ ComponentService componentService = assemblyFactory.createComponentService();
+ componentService.setForCallback(true);
+ componentService.setName(reference.getName());
+ try {
+ InterfaceContract contract = (InterfaceContract)reference.getInterfaceContract().clone();
+ contract.setInterface(contract.getCallbackInterface());
+ contract.setCallbackInterface(null);
+ componentService.setInterfaceContract(contract);
+ } catch (CloneNotSupportedException e) {
+ // will not happen
+ }
+ Reference implReference = reference.getReference();
+ if (implReference != null) {
+ // If the implementation reference is a CompositeReference, ensure that the Service that is
+ // created is a CompositeService, otherwise create a Service
+ Service implService;
+ if (implReference instanceof CompositeReference) {
+ CompositeService implCompService = assemblyFactory.createCompositeService();
+ // TODO The reality here is that the composite reference which has the callback COULD promote more than
+ // one component reference - and there must be a separate composite callback service for each of these component
+ // references
+ // Set the promoted component from the promoted component of the composite reference
+ implCompService
+ .setPromotedComponent(((CompositeReference)implReference).getPromotedComponents().get(0));
+ implCompService.setForCallback(true);
+ // Set the promoted service
+ ComponentService promotedService = assemblyFactory.createComponentService();
+ promotedService.setName(((CompositeReference)implReference).getPromotedReferences().get(0).getName());
+ promotedService.setUnresolved(true);
+ promotedService.setForCallback(true);
+ implCompService.setPromotedService(promotedService);
+ implService = implCompService;
+ // Add the composite service to the composite implementation artifact
+ Implementation implementation = component.getImplementation();
+ if (implementation != null && implementation instanceof Composite) {
+ ((Composite)implementation).getServices().add(implCompService);
+ } // end if
+ //
+ } else {
+ implService = assemblyFactory.createService();
+ } // end if
+ //
+ implService.setName(implReference.getName());
+ try {
+ InterfaceContract implContract = (InterfaceContract)implReference.getInterfaceContract().clone();
+ implContract.setInterface(implContract.getCallbackInterface());
+ implContract.setCallbackInterface(null);
+ implService.setInterfaceContract(implContract);
+ } catch (CloneNotSupportedException e) {
+ // will not happen
+ }
+ componentService.setService(implService);
+ }
+ component.getServices().add(componentService);
+
+ // set bindings of the callback service
+ if (reference.getCallback() != null) {
+ if (componentService.getBindings().isEmpty()) {
+ componentService.getBindings().addAll(reference.getCallback().getBindings());
+ }
+ }
+
+ reference.setCallbackService(componentService);
+ }
+ }
/**
* Create a default SCA binding in the case that no binding
@@ -478,6 +879,122 @@ public class ComponentBuilderImpl {
contract.getBindings().add(scaBinding);
contract.setOverridingBindings(false);
+ }
+
+ /**
+ * Look to see if any value elements have been set into the property
+ * A bit involved as the value is stored as a DOM Document
+ *
+ * @param property the property to be tested
+ * @return true is values are present
+ */
+ private boolean isPropertyValueSet(Property property){
+ Document value = (Document)property.getValue();
+
+ if (value == null){
+ return false;
+ }
+
+ if (value.getFirstChild() == null){
+ return false;
+ }
+
+ if (value.getFirstChild().getChildNodes().getLength() == 0){
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean isValidMultiplicityOverride(Multiplicity definedMul,
+ Multiplicity overridenMul) {
+ if (definedMul != overridenMul) {
+ switch (definedMul) {
+ case ZERO_N:
+ return overridenMul == Multiplicity.ZERO_ONE || overridenMul == Multiplicity.ONE_ONE || overridenMul == Multiplicity.ONE_N;
+ case ONE_N:
+ return overridenMul == Multiplicity.ONE_ONE;
+ case ZERO_ONE:
+ return overridenMul == Multiplicity.ONE_ONE;
+ default:
+ return false;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * The following methods implement rules that the OASIS specification defined explicitly
+ * to control how configuration from a component type is inherited by a component
+ */
+
+ /**
+ * OASIS RULE: Interface contract from higher in the implementation hierarchy takes precedence
+ *
+ * @param topContract the top contract
+ * @param bottomContract the bottom contract
+ */
+ private void calculateInterfaceContract(Contract topContract,
+ Contract bottomContract) {
+
+ // Use the interface contract from the bottom level contract if
+ // none is specified on the top level contract
+ InterfaceContract topInterfaceContract = topContract.getInterfaceContract();
+ InterfaceContract bottomInterfaceContract = bottomContract.getInterfaceContract();
+
+ if (topInterfaceContract == null) {
+ topContract.setInterfaceContract(bottomInterfaceContract);
+ } else if (bottomInterfaceContract != null) {
+ // Check that the top and bottom interface contracts are compatible
+ boolean isCompatible = interfaceContractMapper.isCompatible(topInterfaceContract,
+ bottomInterfaceContract);
+ if (!isCompatible) {
+ if (topContract instanceof Reference) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceInterfaceNotSubSet",
+ topContract.getName());
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "ServiceInterfaceNotSubSet",
+ topContract.getName());
+ }
+ }
+ }
+ }
+
+ /**
+ * OASIS RULE: Bindings from higher in the hierarchy take precedence
+ *
+ * @param componentService the top service
+ * @param componentTypeService the bottom service
+ */
+ private void calculateBindings(Service componentService,
+ Service componentTypeService){
+ // forward bindings
+ if (componentService.getBindings().isEmpty()) {
+ componentService.getBindings().addAll(componentTypeService.getBindings());
+ }
+
+ if (componentService.getBindings().isEmpty()) {
+ createSCABinding(componentService, null);
+ }
+
+ // callback bindings
+ if (componentService.getCallback() == null) {
+ componentService.setCallback(componentTypeService.getCallback());
+ if (componentService.getCallback() == null) {
+ // Create an empty callback to avoid null check
+ componentService.setCallback(assemblyFactory.createCallback());
+ }
+ } else if (componentService.getCallback().getBindings().isEmpty() && componentTypeService.getCallback() != null) {
+ componentService.getCallback().getBindings().addAll(componentTypeService.getCallback().getBindings());
+ }
+
}
}
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentTypeBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeComponentTypeBuilderImpl.java
index 68db5bdb72..4d0f37d36d 100644
--- a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentTypeBuilderImpl.java
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeComponentTypeBuilderImpl.java
@@ -28,6 +28,7 @@ import javax.xml.namespace.QName;
import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentProperty;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.ComponentType;
@@ -36,11 +37,13 @@ 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.Implementation;
+import org.apache.tuscany.sca.assembly.Property;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.SCABindingFactory;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
@@ -51,15 +54,16 @@ import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.MonitorFactory;
import org.apache.tuscany.sca.policy.ExtensionType;
import org.apache.tuscany.sca.policy.PolicySubject;
+import org.w3c.dom.Document;
/**
* @version $Rev$ $Date$
*/
-// TODO - really implementation.composite component type builder
+// TODO - really implementation.composite component type builder - CompositeComponentTypeBuilder?
-public class ComponentTypeBuilderImpl {
- private static final Logger logger = Logger.getLogger(ComponentTypeBuilderImpl.class.getName());
+public class CompositeComponentTypeBuilderImpl {
+ private static final Logger logger = Logger.getLogger(CompositeComponentTypeBuilderImpl.class.getName());
protected static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
protected static final String BINDING_SCA = "binding.sca";
@@ -73,7 +77,7 @@ public class ComponentTypeBuilderImpl {
private BuilderExtensionPoint builders;
- public ComponentTypeBuilderImpl(ExtensionPointRegistry registry) {
+ public CompositeComponentTypeBuilderImpl(ExtensionPointRegistry registry){
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
monitor = monitorFactory.createMonitor();
@@ -120,14 +124,17 @@ public class ComponentTypeBuilderImpl {
component.getName());
}
+ // do any work we need to do before we configure the component
+ // Anything that needs to be pushed down the promotion
+ // hierarchy must be done before we configure the component
+
// Push down the autowire flag from the composite to components
- // TODO - Is this the right place to do this structural inheritance
if (component.getAutowire() == null) {
component.setAutowire(composite.getAutowire());
}
// configure the component from its component type
- componentBuilder.configureComponentFromComponentType(component);
+ componentBuilder.configureComponentFromComponentType(composite, component);
}
// create the composite component type based on the promoted artifacts
@@ -147,10 +154,11 @@ public class ComponentTypeBuilderImpl {
calculateReferences(composite, components, componentReferences);
// properties
- //calculateProperties(composite);
+ // Properties on the composite component are unaffected by properties
+ // on child components. Instead child component properties might take their
+ // values from component properties. Hence there is nothing to do here.
+ //calculateProperties(composite, components);
- // autowire
- //calculateAutowire(composite);
}
@@ -163,9 +171,9 @@ public class ComponentTypeBuilderImpl {
* @param componentReferences
*/
private void indexComponentsServicesAndReferences(Composite composite,
- Map<String, Component> components,
- Map<String, ComponentService> componentServices,
- Map<String, ComponentReference> componentReferences) {
+ Map<String, Component> components,
+ Map<String, ComponentService> componentServices,
+ Map<String, ComponentReference> componentReferences) {
for (Component component : composite.getComponents()) {
@@ -284,7 +292,7 @@ public class ComponentTypeBuilderImpl {
// calculatePromotedPolicySets(compositeService, promotedComponentService);
}
}
- }
+ }
/**
* Connect the services in the component type to the component services that
@@ -384,6 +392,34 @@ public class ComponentTypeBuilderImpl {
}
/**
+ * Create a default SCA binding in the case that no binding
+ * is specified by the user
+ *
+ * @param contract
+ * @param definitions
+ */
+ protected void createSCABinding(Contract contract, Definitions definitions) {
+
+ SCABinding scaBinding = scaBindingFactory.createSCABinding();
+
+ if (definitions != null) {
+ for (ExtensionType attachPointType : definitions.getBindingTypes()) {
+ if (attachPointType.getType().equals(BINDING_SCA_QNAME)) {
+ ((PolicySubject)scaBinding).setExtensionType(attachPointType);
+ }
+ }
+ }
+
+ contract.getBindings().add(scaBinding);
+ contract.setOverridingBindings(false);
+ }
+
+ /**
+ * The following methods implement rules that the OASIS specification defined explicitly
+ * to control how configuration from a component type is inherited by a component
+ */
+
+ /**
* OASIS RULE: Interface contract from higher in the implementation hierarchy takes precedence
*
* @param topContract the top contract
@@ -459,30 +495,7 @@ public class ComponentTypeBuilderImpl {
}
}
}
- }
-
- /**
- * Create a default SCA binding in the case that no binding
- * is specified by the user
- *
- * @param contract
- * @param definitions
- */
- protected void createSCABinding(Contract contract, Definitions definitions) {
-
- SCABinding scaBinding = scaBindingFactory.createSCABinding();
-
- if (definitions != null) {
- for (ExtensionType attachPointType : definitions.getBindingTypes()) {
- if (attachPointType.getType().equals(BINDING_SCA_QNAME)) {
- ((PolicySubject)scaBinding).setExtensionType(attachPointType);
- }
- }
- }
-
- contract.getBindings().add(scaBinding);
- contract.setOverridingBindings(false);
- }
+ }
} //end class
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java
new file mode 100644
index 0000000000..c749782b90
--- /dev/null
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java
@@ -0,0 +1,108 @@
+/*
+ * 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.util.List;
+import java.util.Vector;
+
+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.ComponentService;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.CompositeService;
+import org.apache.tuscany.sca.assembly.Endpoint;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.definitions.Definitions;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicySet;
+
+/**
+ * creates endpoint models for component services.
+ */
+public class EndpointBuilderImpl {
+ private AssemblyFactory assemblyFactory;
+
+ public EndpointBuilderImpl(ExtensionPointRegistry registry) {
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ }
+
+ /**
+ * Create endpoint models for all component services.
+ *
+ * @param composite - the top-level composite to build the models for
+ * @param definitions
+ * @param monitor - a Monitor for logging errors
+ */
+ public void build(Composite composite, Definitions definitions, Monitor monitor) throws CompositeBuilderException {
+
+ processComponentServices(composite);
+
+ } // end method build
+
+ private void processComponentServices(Composite composite) {
+
+ for (Component component : composite.getComponents()) {
+
+ // recurse for composite implementations
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ processComponentServices((Composite)implementation);
+ }
+
+ // create an endpoint for each component service binding
+ for (ComponentService service : component.getServices()) {
+
+ /* change to finding the promoted component and service
+ * when the wire is created as storing them here leads to
+ * the wrong URI being calculated
+ Component endpointComponent = component;
+ ComponentService endpointService = service;
+
+ // TODO - EPR - We maintain all endpoints at the right level now
+ // but endpoints for promoting services must point down
+ // to the services they promote.
+ if (service.getService() instanceof CompositeService) {
+ CompositeService compositeService = (CompositeService)service.getService();
+ endpointService = ServiceConfigurationUtil.getPromotedComponentService(compositeService);
+ endpointComponent = ServiceConfigurationUtil.getPromotedComponent(compositeService);
+ } // end if
+ */
+
+ for (Binding binding : service.getBindings()) {
+ Endpoint endpoint = assemblyFactory.createEndpoint();
+ endpoint.setComponent(component);
+ endpoint.setService(service);
+ endpoint.setBinding(binding);
+ endpoint.setUnresolved(false);
+ service.getEndpoints().add(endpoint);
+ } // end for
+ }
+ }
+ }
+}
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointReferenceBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointReferenceBuilderImpl.java
new file mode 100644
index 0000000000..fe800200ca
--- /dev/null
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointReferenceBuilderImpl.java
@@ -0,0 +1,731 @@
+/*
+ * 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.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.EndpointReference;
+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.SCABinding;
+import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException;
+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.definitions.Definitions;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+
+/**
+ * Creates endpoint reference models.
+ */
+public class EndpointReferenceBuilderImpl {
+
+ private Monitor monitor;
+ private AssemblyFactory assemblyFactory;
+ private InterfaceContractMapper interfaceContractMapper;
+
+
+ public EndpointReferenceBuilderImpl(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ monitor = monitorFactory.createMonitor();
+ interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ }
+
+
+ /**
+ * Create endpoint references for all component references.
+ *
+ * @param composite
+ */
+ public void build(Composite composite, Definitions definitions, Monitor monitor) throws CompositeBuilderException {
+ this.monitor = monitor;
+
+ // process component services
+ processComponentReferences(composite);
+ }
+
+ private void processComponentReferences(Composite composite) {
+
+ monitor.pushContext("Composite: " + composite.getName().toString());
+ try {
+ // index all of the components in the composite
+ Map<String, Component> components = new HashMap<String, Component>();
+ indexComponents(composite, components);
+
+ // index all of the services in the composite
+ Map<String, ComponentService> componentServices = new HashMap<String, ComponentService>();
+ indexServices(composite, componentServices);
+
+ // create endpoint references for each component's references
+ for (Component component : composite.getComponents()) {
+ monitor.pushContext("Component: " + component.getName());
+
+ try {
+
+ // recurse for composite implementations
+ Implementation implementation = component.getImplementation();
+ if (implementation instanceof Composite) {
+ processComponentReferences((Composite)implementation);
+ }
+
+ // create endpoint references to represent the component reference
+ for (ComponentReference reference : component.getReferences()) {
+ createReferenceEndpointReferences(composite, component, reference, components, componentServices);
+
+ // fix up links between endpoints and endpoint references that represent callbacks
+ for (ComponentService service : component.getServices()) {
+ if ((service.getInterfaceContract() != null) && (service.getInterfaceContract()
+ .getCallbackInterface() != null)) {
+ if (reference.getName().equals(service.getName())) {
+ for (Endpoint endpoint : service.getEndpoints()) {
+ endpoint.getCallbackEndpointReferences().addAll(reference.getEndpointReferences());
+ }
+ break;
+ } // end if
+ } // end if
+ } // end for
+ } // end for
+
+ // Validate that references are wired or promoted, according
+ // to their multiplicity
+ validateReferenceMultiplicity(composite, component);
+
+ } finally {
+ monitor.popContext();
+ }
+ } // end for
+
+ } finally {
+ monitor.popContext();
+ }
+
+ } // end method processCompoenntReferences
+
+ private void indexComponents(Composite composite, Map<String, Component> components) {
+ for (Component component : composite.getComponents()) {
+ // Index components by name
+ components.put(component.getName(), component);
+ }
+ }
+
+ protected void indexServices(Composite composite, Map<String, ComponentService> componentServices) {
+
+ for (Component component : composite.getComponents()) {
+
+ ComponentService nonCallbackService = null;
+ int nonCallbackServiceCount = 0;
+
+ for (ComponentService componentService : component.getServices()) {
+ // Index component services by component name / service name
+ String uri = component.getName() + '/' + componentService.getName();
+ componentServices.put(uri, componentService);
+
+ // count how many non-callback there are
+ if (!componentService.isForCallback()) {
+
+ if (nonCallbackServiceCount == 0) {
+ nonCallbackService = componentService;
+ }
+ nonCallbackServiceCount++;
+ }
+ }
+ if (nonCallbackServiceCount == 1) {
+ // If we have a single non callback service, index it by
+ // component name as well
+ componentServices.put(component.getName(), nonCallbackService);
+ }
+ }
+ }
+
+ private void createReferenceEndpointReferences(Composite composite,
+ Component component,
+ ComponentReference reference,
+ Map<String, Component> components,
+ Map<String, ComponentService> componentServices) {
+
+ monitor.pushContext("Reference: " + reference.getName());
+
+ // Get reference targets
+ List<ComponentService> refTargets = getReferenceTargets(reference);
+ if (reference.getAutowire() == Boolean.TRUE && reference.getTargets().isEmpty()) {
+
+ // Find suitable targets in the current composite for an
+ // autowired reference
+ Multiplicity multiplicity = reference.getMultiplicity();
+ for (Component targetComponent : composite.getComponents()) {
+
+ // Tuscany specific selection of the first autowire reference
+ // when there are more than one (ASM_60025)
+ if ((multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) &&
+ (reference.getEndpointReferences().size() != 0) ) {
+ break;
+ }
+
+ // Prevent autowire connecting to self
+ if (targetComponent == component)
+ continue;
+
+ for (ComponentService targetComponentService : targetComponent.getServices()) {
+ if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatible(reference
+ .getInterfaceContract(), targetComponentService.getInterfaceContract())) {
+
+ EndpointReference endpointRef = createEndpointRef(component, reference, false);
+ endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
+ reference.getEndpointReferences().add(endpointRef);
+
+ // Stop with the first match for 0..1 and 1..1 references
+ if (multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) {
+ break;
+ } // end if
+ } // end if
+ } // end for
+ } // end for
+
+ if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) {
+ if (reference.getEndpointReferences().size() == 0) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "NoComponentReferenceTarget",
+ reference.getName());
+ }
+ }
+
+ setSingleAutoWireTarget(reference);
+
+ } 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(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceEndPointMixWithTarget",
+ composite.getName().toString(),
+ component.getName(),
+ reference.getName());
+ }
+
+ // Resolve targets specified on the component reference
+ for (ComponentService target : refTargets) {
+
+ String targetName = getComponentServiceName(target.getName());
+ String bindingName = getBindingName(target.getName());
+ ComponentService targetComponentService = componentServices.get(targetName);
+
+ Component targetComponent = getComponentFromTargetName(components, targetName);
+
+ if (targetComponentService != null) {
+ // Check that target component service provides a superset of the component reference interface
+ if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatible(reference
+ .getInterfaceContract(), targetComponentService.getInterfaceContract())) {
+
+ if (bindingName != null){
+ // the user has selected a binding as part of the target name
+ Binding targetBinding = null;
+
+ for (Binding tmp : targetComponentService.getBindings()){
+ if (tmp.getName().equals(bindingName)){
+ targetBinding = tmp;
+ continue;
+ }
+ }
+
+ if (targetBinding != null){
+ EndpointReference endpointRef = createEndpointRef(component, reference, false);
+ endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, targetBinding, true));
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND);
+ // relying on the registry here to resolve the real endpoint
+ reference.getEndpointReferences().add(endpointRef);
+
+ } else {
+ EndpointReference endpointRef = createEndpointRef(component, reference, true);
+ endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
+ endpointRef.setRemote(true);
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND);
+ reference.getEndpointReferences().add(endpointRef);
+ Monitor.warning(monitor,
+ this,
+ "assembly-validation-messages",
+ "ComponentReferenceTargetNotFound",
+ composite.getName().toString(),
+ targetName);
+ }
+
+ } else {
+ // the user hasn't selected a binding as part of the target name
+
+ EndpointReference endpointRef = createEndpointRef(component, reference, false);
+ endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
+ reference.getEndpointReferences().add(endpointRef);
+ }
+ } else {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceIncompatibleInterface",
+ composite.getName().toString(),
+ component.getName() + "." + reference.getName(),
+ targetName);
+ }
+ } else {
+ // add an unresolved endpoint reference with an unresolved endpoint to go with it
+ EndpointReference endpointRef = createEndpointRef(component, reference, true);
+ endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
+ endpointRef.setRemote(true);
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND);
+ reference.getEndpointReferences().add(endpointRef);
+ Monitor.warning(monitor,
+ this,
+ "assembly-validation-messages",
+ "ComponentReferenceTargetNotFound",
+ composite.getName().toString(),
+ targetName);
+ } // end if
+ } // end for
+ } // end if
+
+ // if no endpoints have 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 with a service binding
+ // - if it doesn't it is assumed to be an external reference
+ if (uri.startsWith("/")) {
+ uri = uri.substring(1);
+ }
+
+ String targetName = getComponentServiceName(uri);
+ String bindingName = getBindingName(uri);
+
+ // Resolve the target component and service
+ ComponentService targetComponentService = componentServices.get(targetName);
+ Component targetComponent = getComponentFromTargetName(components, targetName);
+
+ // If the binding URI matches a component in the composite, configure an endpoint reference with
+ // this component as the target.
+ // If not, the binding URI is assumed to reference an external service
+ if (targetComponentService != null) {
+
+ // Check that the target component service provides
+ // a superset of the component reference interface
+ if (reference.getInterfaceContract() == null || interfaceContractMapper.isCompatible(reference
+ .getInterfaceContract(), targetComponentService.getInterfaceContract())) {
+ if (bindingName != null){
+ // the user has selected a binding as part of the target name
+ Binding targetBinding = null;
+
+ for (Binding tmp : targetComponentService.getBindings()){
+ if (tmp.getName().equals(bindingName)){
+ targetBinding = tmp;
+ continue;
+ }
+ }
+
+ if (targetBinding != null){
+ EndpointReference endpointRef = createEndpointRef(component, reference, false);
+ endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, targetBinding, true));
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND);
+ // relying on the registry here to resolve the real endpoint
+ reference.getEndpointReferences().add(endpointRef);
+
+ } else {
+ EndpointReference endpointRef = createEndpointRef(component, reference, true);
+ endpointRef.setTargetEndpoint(createEndpoint(component, targetName));
+ endpointRef.setRemote(true);
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_NOT_FOUND);
+ reference.getEndpointReferences().add(endpointRef);
+ Monitor.warning(monitor,
+ this,
+ "assembly-validation-messages",
+ "ComponentReferenceTargetNotFound",
+ composite.getName().toString(),
+ targetName);
+ }
+
+ } else {
+ // create endpoint reference with dummy endpoint which will be replaced when policies
+ // are matched and bindings are configured later
+ EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false);
+ endpointRef.setTargetEndpoint(createEndpoint(targetComponent, targetComponentService, true));
+ endpointRef.setStatus(EndpointReference.WIRED_TARGET_FOUND_READY_FOR_MATCHING);
+ reference.getEndpointReferences().add(endpointRef);
+ }
+ } else {
+ Monitor.warning(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceIncompatibleInterface",
+ composite.getName().toString(),
+ reference.getName(),
+ uri);
+ }
+ } else {
+ // create endpoint reference for manually configured bindings with resolved endpoint
+ // to signify that this reference is pointing at some unwired endpoint. The endpoint
+ // is given the configured binding as a representation of the endpoint configuration.
+ EndpointReference endpointRef = createEndpointRef(component, reference, binding, null, false);
+ Endpoint endpoint = createEndpoint(false);
+ endpoint.setBinding(binding);
+ endpointRef.setTargetEndpoint(endpoint);
+ endpointRef.setRemote(true);
+ endpointRef.setStatus(EndpointReference.RESOLVED_BINDING);
+ reference.getEndpointReferences().add(endpointRef);
+ } // end if
+ }
+ }
+
+ monitor.popContext();
+
+ } // end method
+
+ private void validateReferenceMultiplicity(Composite composite, Component component){
+ for (ComponentReference componentReference : component.getReferences()) {
+ if (!ReferenceConfigurationUtil.validateMultiplicityAndTargets(componentReference.getMultiplicity(),
+ componentReference.getEndpointReferences())) {
+ if (componentReference.getEndpointReferences().isEmpty()) {
+
+ // No error 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.isForCallback() && !componentReference.isWiredByImpl()) {
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "ReferenceWithoutTargets",
+ composite.getName().toString(),
+ componentReference.getName());
+ }
+ } else {
+ // no error if reference is autowire and more targets
+ // than multiplicity have been found
+ if (componentReference.getAutowire() == Boolean.TRUE){
+ break;
+ }
+
+ Monitor.error(monitor,
+ this,
+ "assembly-validation-messages",
+ "TooManyReferenceTargets",
+ componentReference.getName());
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Evaluates whether the bindings attached to a reference identify one or more target services.
+ * @param reference - the reference
+ * @return true if the bindings identify a target, false otherwise
+ */
+ private boolean bindingsIdentifyTargets(ComponentReference reference) {
+ for (Binding binding : reference.getBindings()) {
+ // <binding.sca without a URI does not identify a target
+ if ((binding instanceof SCABinding) && (binding.getURI() == null))
+ continue;
+ // any other binding implies a target
+ // TODO Processing for other binding types
+ return true;
+ } // end for
+ return false;
+ } // end bindingsIdentifyTargets
+
+ /**
+ * Helper method which obtains a list of targets for a reference
+ * @param reference - Component reference
+ * @return - the list of targets, which will be empty if there are no targets
+ */
+ private List<ComponentService> getReferenceTargets(ComponentReference reference) {
+ List<ComponentService> theTargets = reference.getTargets();
+ if (theTargets.isEmpty()) {
+ // Component reference list of targets is empty, try the implementation reference
+ if (reference.getReference() != null) {
+ theTargets = reference.getReference().getTargets();
+ } // end if
+ } // end if
+ return theTargets;
+ } // end method getReferenceTargets
+
+ /**
+ * Target names can take the form
+ * component/service/binding
+ * This extracts the component/service part
+ *
+ * @param targetName
+ * @return String the component/service name
+ */
+ private String getComponentServiceName(String targetName) {
+ String[] parts = targetName.split("/");
+
+ if (parts.length > 1){
+ return parts[0] + "/" + parts[1];
+ } else {
+ return parts[0];
+ }
+ }
+
+ /**
+ * Target names can take the form
+ * component/service/binding
+ * This extracts the binding part and returns
+ * it. If there is no binding part it returns null
+ *
+ * @param targetName
+ * @return String the binding name or null if there is no binding name
+ */
+ private String getBindingName(String targetName) {
+ String[] parts = targetName.split("/");
+
+ if (parts.length == 3){
+ return parts[2];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Helper method that finds the Component given a target name
+ * @param components
+ * @param targetName
+ * @return the component
+ */
+ private Component getComponentFromTargetName(Map<String, Component> components, String targetName) {
+ Component theComponent;
+ int s = targetName.indexOf('/');
+ if (s == -1) {
+ theComponent = components.get(targetName);
+ } else {
+ theComponent = components.get(targetName.substring(0, s));
+ }
+ return theComponent;
+ } // end method getComponentFromTargetName
+
+ /**
+ * Helper method to create an Endpoint Reference
+ * @param component
+ * @param reference
+ * @param binding
+ * @param endpoint
+ * @param unresolved
+ * @return the endpoint reference
+ */
+ private EndpointReference createEndpointRef(Component component,
+ ComponentReference reference,
+ Binding binding,
+ Endpoint endpoint,
+ boolean unresolved) {
+ EndpointReference endpointRef = createEndpointRef(component, reference, unresolved);
+ endpointRef.setBinding(binding);
+ endpointRef.setTargetEndpoint(endpoint);
+ return endpointRef;
+ } // end method
+
+ /**
+ * Helper method to create an Endpoint Reference
+ * @param component
+ * @param reference
+ * @param unresolved
+ * @return the endpoint reference
+ */
+ private EndpointReference createEndpointRef(Component component, ComponentReference reference, boolean unresolved) {
+ EndpointReference endpointRef = assemblyFactory.createEndpointReference();
+ endpointRef.setComponent(component);
+ endpointRef.setReference(reference);
+ endpointRef.setUnresolved(unresolved);
+ return endpointRef;
+ } // end method createEndpointRef
+
+ /**
+ * Helper method to create an endpoint
+ * @param component
+ * @param service
+ * @param unresolved
+ * @return the endpoint
+ */
+ private Endpoint createEndpoint(Component component, ComponentService service, boolean unresolved) {
+ Endpoint endpoint = createEndpoint(unresolved);
+ endpoint.setComponent(component);
+ endpoint.setService(service);
+ endpoint.setUnresolved(unresolved);
+ return endpoint;
+ } // end method createEndpoint
+
+ /**
+ * Helper method to create an endpoint
+ * @param component
+ * @param service
+ * @param binding
+ * @param unresolved
+ * @return the endpoint
+ */
+ private Endpoint createEndpoint(Component component, ComponentService service, Binding binding, boolean unresolved) {
+ Endpoint endpoint = createEndpoint(unresolved);
+ endpoint.setComponent(component);
+ endpoint.setService(service);
+ endpoint.setBinding(binding);
+ endpoint.setUnresolved(unresolved);
+ return endpoint;
+ } // end method createEndpoint
+
+ /**
+ * Helper method to create an Endpoint
+ * @param unresolved
+ * @return the endpoint
+ */
+ private Endpoint createEndpoint(boolean unresolved) {
+ Endpoint endpoint = assemblyFactory.createEndpoint();
+ endpoint.setUnresolved(unresolved);
+ return endpoint;
+ } // end method createEndpoint
+
+ /**
+ * Helper method to create an Endpoint
+ *
+ * @param component The component that owns the reference
+ * @param targetName It can be one of the following formats
+ * <ul>
+ * <li>componentName
+ * <li>componentName/serviceName
+ * <li>componentName/serviceName/bindingName
+ * </ul>
+ * @return the endpoint
+ */
+ private Endpoint createEndpoint(Component component, String targetName) {
+ String[] parts = targetName.split("/");
+ if (parts.length < 1 || parts.length > 3) {
+ throw new IllegalArgumentException("Invalid target URI: " + targetName);
+ }
+
+ // Find the parent uri
+ String uri = component.getURI();
+ int index = uri.lastIndexOf('/');
+ if (index == -1) {
+ uri = "";
+ } else {
+ uri = uri.substring(0, index);
+ }
+
+ if (parts.length >= 1) {
+ // Append the target component name
+ if (uri.length() == 0) {
+ uri = parts[0];
+ } else {
+ uri = uri + "/" + parts[0];
+ }
+ }
+ if (parts.length == 3) {
+ // <componentURI>#service-binding(serviceName/bindingName)
+ uri = uri + "#service-binding(" + parts[1] + "/" + parts[2] + ")";
+ } else if (parts.length == 2) {
+ // <componentURI>#service(serviceName)
+ uri = uri + "#service(" + parts[1] + ")";
+ }
+
+ Endpoint endpoint = assemblyFactory.createEndpoint();
+ endpoint.setUnresolved(true);
+ endpoint.setURI(uri);
+ return endpoint;
+ } // end method createEndpoint
+
+ /**
+ * ASM_5021: where a <reference/> of a <component/> has @autowire=true
+ * and where the <reference/> has a <binding/> child element which
+ * declares a single target service, the reference is wired only to
+ * the single service identified by the <wire/> element
+ */
+ private void setSingleAutoWireTarget(ComponentReference reference) {
+ if (reference.getEndpointReferences().size() > 1 && reference.getBindings() != null && reference.getBindings().size() == 1) {
+ String uri = reference.getBindings().get(0).getURI();
+ if (uri != null) {
+ if (uri.indexOf('/') > -1) {
+ // TODO: must be a way to avoid this fiddling
+ int i = uri.indexOf('/');
+ String c = uri.substring(0, i);
+ String s = uri.substring(i+1);
+ uri = c + "#service(" + s + ")";
+ }
+ for (EndpointReference er : reference.getEndpointReferences()) {
+ if (er.getTargetEndpoint() != null && uri.equals(er.getTargetEndpoint().getURI())) {
+ reference.getEndpointReferences().clear();
+ reference.getEndpointReferences().add(er);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+} // end class
diff --git a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ModelBuilderImpl.java b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ModelBuilderImpl.java
index 2376e414ff..ccca010775 100644
--- a/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ModelBuilderImpl.java
+++ b/java/sca/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ModelBuilderImpl.java
@@ -40,78 +40,34 @@ public class ModelBuilderImpl implements CompositeBuilder, DeployedCompositeBuil
private static final Logger logger = Logger.getLogger(ModelBuilderImpl.class.getName());
private CompositeBuilder compositeIncludeBuilder;
private CompositeBuilder compositeCloneBuilder;
- private ComponentTypeBuilderImpl componentTypeBuilder;
+ private CompositeComponentTypeBuilderImpl compositeComponentTypeBuilder;
private ComponentBuilderImpl componentBuilder;
-
-/*
- private CompositeBuilder componentConfigurationBuilder;
- private CompositeBuilder compositePromotionBuilder;
- private CompositeBuilder componentReferenceWireBuilder;
- private CompositeBuilder componentReferencePromotionBuilder;
- private CompositeBuilder compositeServiceConfigurationBuilder;
- private CompositeBuilder compositeReferenceConfigurationBuilder;
- private CompositeBuilder compositeBindingURIBuilder;
- private CompositeBuilder compositePolicyBuilder;
- private CompositeBuilder componentServiceBindingBuilder;
- private CompositeBuilder componentReferenceBindingBuilder;
- private CompositeBuilder componentReferenceEndpointReferenceBuilder;
- private CompositeBuilder componentServiceEndpointBuilder;
-*/
-
-
-
+ private BindingURIBuilderImpl bindingURIBuilder;
+ private EndpointBuilderImpl endpointBuilder;
+ private EndpointReferenceBuilderImpl endpointReferenceBuilder;
+ private CompositePolicyBuilderImpl compositePolicyBuilder;
+
/**
* Constructs a new composite builder.
*
- * @param assemblyFactory
- * @param scaBindingFactory
- * @param endpointFactory
- * @param intentAttachPointTypeFactory
- * @param interfaceContractMapper
- * @param policyDefinitions
- * @param monitor
+ * @param registry the extension point registry
*/
public ModelBuilderImpl(ExtensionPointRegistry registry) {
- FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
- AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
-
- UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
- MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
- Monitor monitor = monitorFactory.createMonitor();
-
compositeIncludeBuilder = new CompositeIncludeBuilderImpl();
compositeCloneBuilder = new CompositeCloneBuilderImpl();
- componentTypeBuilder = new ComponentTypeBuilderImpl(registry);
+ compositeComponentTypeBuilder = new CompositeComponentTypeBuilderImpl(registry);
componentBuilder = new ComponentBuilderImpl(registry);
- componentTypeBuilder.setComponentBuilder(componentBuilder);
- componentBuilder.setComponentTypeBuilder(componentTypeBuilder);
+ compositeComponentTypeBuilder.setComponentBuilder(componentBuilder);
+ componentBuilder.setComponentTypeBuilder(compositeComponentTypeBuilder);
-
-/*
- compositePromotionBuilder = new CompositePromotionBuilderImpl(assemblyFactory, interfaceContractMapper);
- componentConfigurationBuilder =
- new ComponentConfigurationBuilderImpl(assemblyFactory, scaBindingFactory, documentBuilderFactory,
- transformerFactory, interfaceContractMapper);
- componentReferenceWireBuilder = new ComponentReferenceWireBuilderImpl(assemblyFactory, interfaceContractMapper);
- componentReferencePromotionBuilder = new ComponentReferencePromotionBuilderImpl(assemblyFactory);
-
- compositeServiceConfigurationBuilder = new CompositeServiceConfigurationBuilderImpl(assemblyFactory);
- compositeReferenceConfigurationBuilder = new CompositeReferenceConfigurationBuilderImpl(assemblyFactory);
- compositeBindingURIBuilder =
- new CompositeBindingURIBuilderImpl(assemblyFactory, scaBindingFactory, documentBuilderFactory,
- transformerFactory, interfaceContractMapper);
-
- compositePolicyBuilder = new CompositePolicyBuilderImpl(assemblyFactory, interfaceContractMapper);
- componentServiceBindingBuilder = new ComponentServiceBindingBuilderImpl();
- componentReferenceBindingBuilder = new ComponentReferenceBindingBuilderImpl();
+ bindingURIBuilder = new BindingURIBuilderImpl(registry);
+ endpointBuilder = new EndpointBuilderImpl(registry);
+ endpointReferenceBuilder = new EndpointReferenceBuilderImpl(registry);
+ compositePolicyBuilder = new CompositePolicyBuilderImpl(registry);
- componentReferenceEndpointReferenceBuilder =
- new ComponentReferenceEndpointReferenceBuilderImpl(assemblyFactory, interfaceContractMapper);
- componentServiceEndpointBuilder = new ComponentServiceEndpointBuilderImpl(assemblyFactory);
-*/
}
public String getID() {
@@ -142,83 +98,27 @@ public class ModelBuilderImpl implements CompositeBuilder, DeployedCompositeBuil
// for the top level implementation (composite). This has the effect of
// recursively calculating component types and configuring the
// components that depend on them
- componentTypeBuilder.createComponentType(composite);
-
+ compositeComponentTypeBuilder.createComponentType(composite);
+
// create the runtime model by updating the static model we have just
// created. This involves things like creating
// component URIs
// binding URIs
- // callback references
- // callback services
+ // callback references - currently done in static pass
+ // callback services - currently done in static pass
// Endpoints
// Endoint References
- // runtimeBuilder.build(composite);
-
- // Compute the policies across the model hierarchy
- //compositePolicyBuilder.build(composite, definitions, monitor);
-
-
-
-/*
- // Configure all components. Created any derived model elements that
- // are required. Specifically
- // Component name
- // autowire flags
- // callback references
- // callback services
- // default bindings
- componentConfigurationBuilder.build(composite, definitions, monitor);
-
- // Connect composite services/references to promoted services/references
- // so that subsequent processing can navigate down the hierarchy
- compositePromotionBuilder.build(composite, definitions, monitor);
-
- // calculate the component type for the composite that was passed in
- // this involves
-
-
- // Configure composite services by copying bindings up the promotion
- // hierarchy overwriting automatic bindings with those added manually
- compositeServiceConfigurationBuilder.build(composite, definitions, monitor);
-
- // Configure composite references by copying bindings down promotion
- // hierarchy overwriting automatic bindings with those added manually
- compositeReferenceConfigurationBuilder.build(composite, definitions, monitor);
-
- // Configure service binding URIs and names. Creates an SCA defined URI based
- // on the scheme base URI, the component name and the binding name
- ((CompositeBuilderTmp)compositeBindingURIBuilder).build(composite, definitions, bindingBaseURIs, monitor);
-
- // Perform and service binding related build activities. The binding
- // will provide the builder.
- componentServiceBindingBuilder.build(composite, definitions, monitor);
-
- // create endpoints on component services.
- componentServiceEndpointBuilder.build(composite, definitions, monitor);
-
- // Apply any wires in the composite to create new component reference targets
- componentReferenceWireBuilder.build(composite, definitions, monitor);
-
- // create reference endpoint reference models
- componentReferenceEndpointReferenceBuilder.build(composite, definitions, monitor);
-
- // Push down configuration from promoted references to the
- // references they promote
- componentReferencePromotionBuilder.build(composite, definitions, monitor);
-
-
- // Perform and reference binding related build activities. The binding
- // will provide the builder.
- componentReferenceBindingBuilder.build(composite, definitions, monitor);
-
- // Compute the policies across the model hierarchy
+ // Policies
+ // TODO - called here at the moment but we could have a separate build phase
+ // to call these. Also we could re-org the builders themselves
+ bindingURIBuilder.configureBindingURIsAndNames(composite, definitions, monitor);
+ endpointBuilder.build(composite, definitions, monitor);
+ endpointReferenceBuilder.build(composite, definitions, monitor);
compositePolicyBuilder.build(composite, definitions, monitor);
-*/
+
} catch (Exception e) {
throw new CompositeBuilderException("Exception while building model " + composite.getName(), e);
- } // end try
-
- } // end method build
-
-} //end class
+ }
+ }
+}