diff options
Diffstat (limited to 'branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder')
37 files changed, 6619 insertions, 0 deletions
diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/AutomaticBinding.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/AutomaticBinding.java new file mode 100644 index 0000000000..97708f9ef5 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/AutomaticBinding.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.builder; + +/** + * Represent a binding that has been added automatically to the model rather + * than being specified by the user through the composite file + * + * @version $Rev$ $Date$ + * + */ +public interface AutomaticBinding extends Cloneable { + + /** + * @param isAutomatic + */ + void setIsAutomatic(boolean isAutomatic); + + /** + * @return isAutomatic + */ + boolean getIsAutomatic(); +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilder.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilder.java new file mode 100644 index 0000000000..7bac630d5b --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilder.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +import org.apache.tuscany.sca.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A builder that handles any build-time configuration needed by bindings. + * + * @version $Rev$ $Date$ + */ +public interface BindingBuilder { + + /** + * Configure a binding. + * + * @param component The component for the binding's service or reference + * @param contract The binding's service or reference + */ + void build(Component component, AbstractContract contract, Binding binding, Monitor monitor); + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilderExtension.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilderExtension.java new file mode 100644 index 0000000000..37ad8af0b3 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/BindingBuilderExtension.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +/** + * An extension that can be implemented by bindings to provide a binding builder. + * + * @version $Rev$ $Date$ + */ +public interface BindingBuilderExtension { + + /** + * Returns the binding builder. + * + * @return the binding builder + */ + BindingBuilder getBuilder(); + + /** + * Sets the binding builder. + * + * @param builder the binding builder + */ + void setBuilder(BindingBuilder builder); + +} + diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java new file mode 100644 index 0000000000..d2fae4d24a --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java @@ -0,0 +1,33 @@ +/* + * 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; + +import org.apache.tuscany.sca.assembly.Component; + +/** + * Interface for Component Pre Processors. + * + * @version $Rev$ $Date$ + */ +public interface ComponentPreProcessor { + + void preProcess(Component component); + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java new file mode 100644 index 0000000000..cf38894702 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +import org.apache.tuscany.sca.assembly.Composite; + +/** + * A builder that handles the configuration of the components inside a + * composite and the wiring of component references to component services. + * + * @version $Rev$ $Date$ + */ +public interface CompositeBuilder { + + /** + * Build a composite. + * + * @param composite + * @throws CompositeBuilderException + */ + void build(Composite composite) throws CompositeBuilderException; + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java new file mode 100644 index 0000000000..5a2015f55e --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +/** + * Reports a composite builder exception. + * + * @version $Rev$ $Date$ + */ +public class CompositeBuilderException extends Exception { + private static final long serialVersionUID = -8916323176803443856L; + + public CompositeBuilderException() { + } + + public CompositeBuilderException(String message) { + super(message); + } + + public CompositeBuilderException(Throwable cause) { + super(cause); + } + + public CompositeBuilderException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DefaultEndpointBuilder.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DefaultEndpointBuilder.java new file mode 100644 index 0000000000..9743117174 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DefaultEndpointBuilder.java @@ -0,0 +1,34 @@ +/* + * 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; + +import org.apache.tuscany.sca.assembly.builder.impl.EndpointBuilderImpl; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A default builder. + * + * @version $Rev$ $Date$ + */ +public class DefaultEndpointBuilder extends EndpointBuilderImpl { + public DefaultEndpointBuilder (Monitor monitor){ + super(monitor); + } +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java new file mode 100644 index 0000000000..20a17e1bd0 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java @@ -0,0 +1,80 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.assembly.builder;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Service;
+
+/**
+ * A builder that handles the configuration of the components inside a
+ * composite and the wiring of component references to component services.
+ *
+ * @version $Rev: 563358 $ $Date: 2007-08-07 01:26:27 +0100 (Tue, 07 Aug 2007) $
+ */
+public interface DomainBuilder {
+
+ /**
+ * Wire up the references and service in a domain returning a list
+ * of the composites that have changed
+ *
+ * @param domainLevelCompsite
+ * @return a list of change composites
+ * @throws CompositeBuilderException
+ */
+ List<Composite> wireDomain(Composite domainLevelComposite);
+
+ /**
+ * Locates the referenced service and updates the URI on the identified binding
+ *
+ * @param domainLevelComposite
+ * @param referenceName
+ * @param bindingClassName
+ * @param URI
+ */
+ void updateDomainLevelServiceURI(Composite domainLevelComposite, String referenceName, String bindingClassName, String URI);
+
+ /**
+ * Get the component name out of the reference name that might look like Component/Service
+ *
+ * @param referenceName
+ * @return
+ */
+ String getComponentNameFromReference(String referenceName);
+
+ /**
+ * Get the service name out of the reference name that might look like Component/Service
+ *
+ * @param referenceName
+ * @return
+ */
+ String getServiceNameFromReference(String referenceName);
+
+ /**
+ * Find the service object given a reference name
+ *
+ * @param composite
+ * @param referenceName
+ * @return
+ */
+ Service findServiceForReference(Composite composite, String referenceName);
+
+}
diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/EndpointBuilder.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/EndpointBuilder.java new file mode 100644 index 0000000000..eb2977d87a --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/EndpointBuilder.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +import org.apache.tuscany.sca.assembly.Endpoint; + +/** + * A builder that handles the configuration of reference endpoints + * It collects together the logic so that it can be used at build time + * or later on during late binding scenarios + * + * @version $Rev$ $Date$ + */ +public interface EndpointBuilder { + + /** + * Build an endpoint. + * + * @param endpoint + */ + void build(Endpoint endpoint); + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseConfigurationBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseConfigurationBuilderImpl.java new file mode 100644 index 0000000000..b6e404a2a5 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseConfigurationBuilderImpl.java @@ -0,0 +1,1334 @@ +/* + * 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.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.Composite; +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.OptimizableBinding; +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.AutomaticBinding; +import org.apache.tuscany.sca.assembly.builder.ComponentPreProcessor; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; + +/** + * Base class for Builder implementations that handles configuration. + * + * @version $Rev$ $Date$ + */ +public abstract class BaseConfigurationBuilderImpl { + private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + private static final String BINDING_SCA = "binding.sca"; + private static final QName BINDING_SCA_QNAME = new QName(SCA10_NS, BINDING_SCA); + + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory; + private Monitor monitor; + private InterfaceContractMapper interfaceContractMapper; + private SCADefinitions policyDefinitions; + + protected BaseConfigurationBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper interfaceContractMapper, + SCADefinitions policyDefinitions, + Monitor monitor) { + this.assemblyFactory = assemblyFactory; + this.scaBindingFactory = scaBindingFactory; + this.interfaceContractMapper = interfaceContractMapper; + this.policyDefinitions = policyDefinitions; + this.monitor = monitor; + } + + /** + * Configure components in the composite. + * + * @param composite + * @param problems + */ + protected void configureComponents(Composite composite) throws CompositeBuilderException { + configureComponents(composite, null); + configureSourcedProperties(composite, null); + //configureBindingURIs(composite, null, null); + } + + /** + * Configure components in the composite. + * + * @param composite + * @param uri + * @param problems + */ + private void configureComponents(Composite composite, String uri) { + String parentURI = uri; + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + + // Initialize component URI + String componentURI; + if (parentURI == null) { + componentURI = component.getName(); + } else { + componentURI = URI.create(parentURI + '/').resolve(component.getName()).toString(); + } + component.setURI(componentURI); + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // Process nested composite + configureComponents((Composite)implementation, componentURI); + } + } + + // Initialize service bindings + List<Service> compositeServices = composite.getServices(); + for (Service service : compositeServices) { + // Set default binding names + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } +/* + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + + // Binding name defaults to the service name + if (binding.getName() == null) { + binding.setName(service.getName()); + } + } + + if (service.getCallback() != null) { + for (Binding binding : service.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(service.getName()); + } + } + } +*/ + } + + // Initialize reference bindings + for (Reference reference : composite.getReferences()) { + // Create default SCA binding + if (reference.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + reference.getBindings().add(scaBinding); + } +/* + // Set binding names + for (Binding binding : reference.getBindings()) { + if (binding.getName() == null) { + binding.setName(reference.getName()); + } + } + + if (reference.getCallback() != null) { + for (Binding binding : reference.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(reference.getName()); + } + } + } +*/ + } + + // Initialize all component services and references + Map<String, Component> components = new HashMap<String, Component>(); + for (Component component : composite.getComponents()) { + + // Index all components and check for duplicates + if (components.containsKey(component.getName())) { + warning("DuplicateComponentName", component, composite.getName().toString(), component.getName()); + } else { + components.put(component.getName(), component); + } + + // Propagate the autowire flag from the composite to components + if (component.getAutowire() == null) { + component.setAutowire(composite.getAutowire()); + } + + if (component.getImplementation() instanceof ComponentPreProcessor) { + ((ComponentPreProcessor)component.getImplementation()).preProcess(component); + } + + // Index properties, services and references + Map<String, Service> services = new HashMap<String, Service>(); + Map<String, Reference> references = new HashMap<String, Reference>(); + Map<String, Property> properties = new HashMap<String, Property>(); + indexImplementationPropertiesServicesAndReferences(component, + services, + references, + properties); + + // Index component services, references and properties + // Also check for duplicates + Map<String, ComponentService> componentServices = + new HashMap<String, ComponentService>(); + Map<String, ComponentReference> componentReferences = + new HashMap<String, ComponentReference>(); + Map<String, ComponentProperty> componentProperties = + new HashMap<String, ComponentProperty>(); + indexComponentPropertiesServicesAndReferences(component, + componentServices, + componentReferences, + componentProperties); + + // Reconcile component services/references/properties and + // implementation services/references and create component + // services/references/properties for the services/references + // declared by the implementation + reconcileServices(component, services, componentServices); + reconcileReferences(component, references, componentReferences); + reconcileProperties(component, properties, componentProperties); + + // Configure or create callback services for component's references + // with callbacks + configureCallbackServices(component, componentServices); + + // Configure or create callback references for component's services + // with callbacks + configureCallbackReferences(component, componentReferences); + + // Create self references to the component's services +// if (!(component.getImplementation() instanceof Composite)) { +// createSelfReferences(component); +// } + + // Initialize service bindings + for (ComponentService componentService : component.getServices()) { + + // Create default SCA binding + if (componentService.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + componentService.getBindings().add(scaBinding); + } +/* + // Set binding names + for (Binding binding : componentService.getBindings()) { + + // Binding name defaults to the service name + if (binding.getName() == null) { + binding.setName(componentService.getName()); + } + } + if (componentService.getCallback() != null) { + for (Binding binding : componentService.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(componentService.getName()); + } + } + } +*/ + } + + // Initialize reference bindings + for (ComponentReference componentReference : component.getReferences()) { + + // Create default SCA binding + if (componentReference.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + componentReference.getBindings().add(scaBinding); + } +/* + // Set binding names + for (Binding binding : componentReference.getBindings()) { + if (binding.getName() == null) { + binding.setName(componentReference.getName()); + } + } + if (componentReference.getCallback() != null) { + for (Binding binding : componentReference.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(componentReference.getName()); + } + } + } +*/ + } + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model, String... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, String... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Reconcile component properties and the properties defined by the + * component type. + * + * @param component + * @param properties + * @param componentProperties + * @param problems + */ + private void reconcileProperties(Component component, + Map<String, Property> properties, + Map<String, ComponentProperty> componentProperties) { + + // Connect component properties to their properties + for (ComponentProperty componentProperty : component.getProperties()) { + Property property = properties.get(componentProperty.getName()); + if (property != null) { + componentProperty.setProperty(property); + } else { + warning("PropertyNotFound", component, component.getName(), componentProperty.getName()); + } + } + + // Create component properties for all properties + if (component.getImplementation() != null) { + for (Property property : component.getImplementation().getProperties()) { + if (!componentProperties.containsKey(property.getName())) { + ComponentProperty componentProperty = assemblyFactory.createComponentProperty(); + componentProperty.setName(property.getName()); + componentProperty.setMany(property.isMany()); + componentProperty.setXSDElement(property.getXSDElement()); + componentProperty.setXSDType(property.getXSDType()); + componentProperty.setProperty(property); + component.getProperties().add(componentProperty); + } + } + } + + // Reconcile component properties and their properties + for (ComponentProperty componentProperty : component.getProperties()) { + Property property = componentProperty.getProperty(); + if (property != null) { + + // Check that a component property does not override the + // mustSupply attribute + if (!property.isMustSupply() && componentProperty.isMustSupply()) { + warning("PropertyMustSupplyIncompatible", component, component.getName(), componentProperty.getName()); + } + + // Default to the mustSupply attribute specified on the property + if (!componentProperty.isMustSupply()) + componentProperty.setMustSupply(property.isMustSupply()); + + // Default to the value specified on the property + if (componentProperty.getValue() == null) { + componentProperty.setValue(property.getValue()); + } + + // Override the property value for the composite + if(component.getImplementation() instanceof Composite) { + property.setValue(componentProperty.getValue()); + } + + // Check that a value is supplied + if (componentProperty.getValue() == null && property.isMustSupply()) { + warning("PropertyMustSupplyNull", component, component.getName(), componentProperty.getName()); + } + + // Check that a a component property does not override the + // many attribute + if (!property.isMany() && componentProperty.isMany()) { + + warning("PropertyOverrideManyAttribute", component, component.getName(), componentProperty.getName()); + } + + // Default to the many attribute defined on the property + componentProperty.setMany(property.isMany()); + + // Default to the type and element defined on the property + if (componentProperty.getXSDType() == null) { + componentProperty.setXSDType(property.getXSDType()); + } + if (componentProperty.getXSDElement() == null) { + componentProperty.setXSDElement(property.getXSDElement()); + } + + // Check that a type or element are specified + if (componentProperty.getXSDElement() == null && componentProperty.getXSDType() == null) { + warning("NoTypeForComponentProperty", component, component.getName(), componentProperty.getName()); + } + } + } + } + + /** + * Reconcile component references with the references defined on the + * component type. + * + * @param component + * @param references + * @param componentReferences + * @param problems + */ + private void reconcileReferences(Component component, + Map<String, Reference> references, + Map<String, ComponentReference> componentReferences) { + + // Connect each component reference to the corresponding reference + for (ComponentReference componentReference : component.getReferences()) { + if (componentReference.getReference() != null || componentReference.isCallback()) { + continue; + } + Reference reference = references.get(componentReference.getName()); + if (reference != null) { + componentReference.setReference(reference); + } else { + if (!componentReference.getName().startsWith("$self$.")) { + error("ReferenceNotFound", component, component.getName(), componentReference.getName()); + } + } + } + + // Create a component reference for each reference + if (component.getImplementation() != null) { + for (Reference reference : component.getImplementation().getReferences()) { + if (!componentReferences.containsKey(reference.getName())) { + ComponentReference componentReference = + assemblyFactory.createComponentReference(); + componentReference.setIsCallback(reference.isCallback()); + componentReference.setName(reference.getName()); + componentReference.setReference(reference); + component.getReferences().add(componentReference); + } + } + } + + // Reconcile each component reference with its reference + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + // Reconcile multiplicity + if (componentReference.getMultiplicity() != null) { + if (!ReferenceConfigurationUtil.isValidMultiplicityOverride(reference.getMultiplicity(), + componentReference + .getMultiplicity())) { + warning("ReferenceIncompatibleMultiplicity", component, component.getName(), componentReference.getName()); + } + } else { + componentReference.setMultiplicity(reference.getMultiplicity()); + } + + // Reconcile interface + InterfaceContract interfaceContract = reference.getInterfaceContract(); + if (componentReference.getInterfaceContract() != null) { + if (interfaceContract != null && !componentReference.getInterfaceContract().equals(reference + .getInterfaceContract())) { + if (!interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), + interfaceContract)) { + warning("ReferenceIncompatibleComponentInterface", component, component.getName(), componentReference.getName()); + } + } + } else { + componentReference.setInterfaceContract(interfaceContract); + } + + // Reconcile bindings + if (componentReference.getBindings().isEmpty()) { + componentReference.getBindings().addAll(reference.getBindings()); + } + + // Reconcile callback bindings + if (componentReference.getCallback() == null) { + componentReference.setCallback(reference.getCallback()); + if (componentReference.getCallback() == null) { + // Create an empty callback to avoid null check + componentReference.setCallback(assemblyFactory.createCallback()); + } + + } else if (componentReference.getCallback().getBindings().isEmpty() && reference + .getCallback() != null) { + componentReference.getCallback().getBindings().addAll(reference.getCallback() + .getBindings()); + } + + // Propagate autowire setting from the component + if (componentReference.getAutowire() == null) { + componentReference.setAutowire(component.getAutowire()); + } + + // Reconcile targets + if (componentReference.getTargets().isEmpty()) { + componentReference.getTargets().addAll(reference.getTargets()); + } + } + } + } + + /** + * Reconcile component services and services defined on the component type. + * + * @param component + * @param services + * @param componentServices + * @param problems + */ + private void reconcileServices(Component component, + Map<String, Service> services, + Map<String, ComponentService> componentServices) { + + // Connect each component service to the corresponding service + for (ComponentService componentService : component.getServices()) { + if (componentService.getService() != null || componentService.isCallback()) { + continue; + } + Service service = services.get(componentService.getName()); + if (service != null) { + componentService.setService(service); + } else { + warning("ServiceNotFoundForComponentService", component, component.getName(), componentService.getName()); + } + } + + // Create a component service for each service + if (component.getImplementation() != null) { + for (Service service : component.getImplementation().getServices()) { + if (!componentServices.containsKey(service.getName())) { + ComponentService componentService = assemblyFactory.createComponentService(); + componentService.setIsCallback(service.isCallback()); + String name = service.getName(); + componentService.setName(name); + componentService.setService(service); + component.getServices().add(componentService); + componentServices.put(name, componentService); + } + } + } + + //Reconcile each component service with its service + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + // Reconcile interface + InterfaceContract interfaceContract = service.getInterfaceContract(); + if (componentService.getInterfaceContract() != null) { + if (interfaceContract != null && !componentService.getInterfaceContract().equals(interfaceContract)) { + if (!interfaceContractMapper.isCompatible(componentService.getInterfaceContract(), + interfaceContract)) { + warning("ServiceIncompatibleComponentInterface", component, component.getName(), componentService.getName()); + } + } + } else { + componentService.setInterfaceContract(interfaceContract); + } + + // Reconcile bindings + if (componentService.getBindings().isEmpty()) { + componentService.getBindings().addAll(service.getBindings()); + } + + // Reconcile callback bindings + if (componentService.getCallback() == null) { + componentService.setCallback(service.getCallback()); + if (componentService.getCallback() == null) { + // Create an empty callback to avoid null check + componentService.setCallback(assemblyFactory.createCallback()); + } + } else if (componentService.getCallback().getBindings().isEmpty() && service + .getCallback() != null) { + componentService.getCallback().getBindings().addAll(service.getCallback() + .getBindings()); + } + } + } + } + + private void indexComponentPropertiesServicesAndReferences(Component component, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences, + Map<String, ComponentProperty> componentProperties) { + for (ComponentService componentService : component.getServices()) { + if (componentServices.containsKey(componentService.getName())) { + warning("DuplicateComponentServiceName", component, component.getName(), componentService.getName()); + } else { + componentServices.put(componentService.getName(), componentService); + } + } + for (ComponentReference componentReference : component.getReferences()) { + if (componentReferences.containsKey(componentReference.getName())) { + warning("DuplicateComponentReferenceName", component, component.getName(), componentReference.getName()); + } else { + componentReferences.put(componentReference.getName(), componentReference); + } + } + for (ComponentProperty componentProperty : component.getProperties()) { + if (componentProperties.containsKey(componentProperty.getName())) { + warning("DuplicateComponentPropertyName", component, component.getName(), componentProperty.getName()); + } else { + componentProperties.put(componentProperty.getName(), componentProperty); + } + } + + } + + private void indexImplementationPropertiesServicesAndReferences(Component component, + Map<String, Service> services, + Map<String, Reference> references, + Map<String, Property> properties) { + // First check that the component has a resolved implementation + Implementation implementation = component.getImplementation(); + if (implementation == null) { + // A component must have an implementation + warning("NoComponentImplementation", component, component.getName()); + + } else if (implementation.isUnresolved()) { + + // The implementation must be fully resolved + warning("UnresolvedComponentImplementation", component, component.getName(), implementation.getURI()); + + } else { + + // Index properties, services and references, also check for + // duplicates + for (Property property : implementation.getProperties()) { + if (properties.containsKey(property.getName())) { + warning("DuplicateImplementationPropertyName", component, component.getName(), property.getName()); + } else { + properties.put(property.getName(), property); + } + } + for (Service service : implementation.getServices()) { + if (services.containsKey(service.getName())) { + warning("DuplicateImplementationServiceName", component, component.getName(), service.getName()); + } else { + services.put(service.getName(), service); + } + } + for (Reference reference : implementation.getReferences()) { + if (references.containsKey(reference.getName())) { + warning("DuplicateImplementationReferenceName", component, component.getName(), reference.getName()); + } else { + references.put(reference.getName(), reference); + } + } + } + + } + + /** + * For all the references with callbacks, create a corresponding callback + * service. + * + * @param component + */ + private void configureCallbackServices(Component component, + Map<String, ComponentService> componentServices) { + for (ComponentReference reference : component.getReferences()) { + if (reference.getInterfaceContract() != null && // can be null in + // unit tests + reference.getInterfaceContract().getCallbackInterface() != null) { + ComponentService service = + componentServices.get(reference.getName()); + if (service == null) { + service = createCallbackService(component, reference); + } + if (reference.getCallback() != null) { + if (service.getBindings().isEmpty()) { + service.getBindings().addAll(reference.getCallback().getBindings()); + } + } + reference.setCallbackService(service); + } + } + } + + /** + * Create a callback service for a component reference + * + * @param component + * @param reference + */ + private ComponentService createCallbackService(Component component, ComponentReference reference) { + ComponentService componentService = assemblyFactory.createComponentService(); + componentService.setIsCallback(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) { + Service implService = assemblyFactory.createService(); + 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); + return componentService; + } + + /** + * For all the services with callbacks, create a corresponding callback + * reference. + * + * @param component + */ + private void configureCallbackReferences(Component component, + Map<String, ComponentReference> componentReferences) { + for (ComponentService service : component.getServices()) { + if (service.getInterfaceContract() != null && // can be null in + // unit tests + service.getInterfaceContract().getCallbackInterface() != null) { + ComponentReference reference = + componentReferences.get(service.getName()); + if (reference == null) { + reference = createCallbackReference(component, service); + } + if (service.getCallback() != null) { + if (reference.getBindings().isEmpty()) { + reference.getBindings().addAll(service.getCallback().getBindings()); + } + } + service.setCallbackReference(reference); + } + } + } + + /** + * Create a callback reference for a component service + * + * @param component + * @param service + */ + private ComponentReference createCallbackReference(Component component, ComponentService service) { + ComponentReference componentReference = assemblyFactory.createComponentReference(); + componentReference.setIsCallback(true); + componentReference.setName(service.getName()); + try { + InterfaceContract contract = (InterfaceContract)service.getInterfaceContract().clone(); + contract.setInterface(contract.getCallbackInterface()); + contract.setCallbackInterface(null); + componentReference.setInterfaceContract(contract); + } catch (CloneNotSupportedException e) { + // will not happen + } + Service implService = service.getService(); + if (implService != null) { + Reference implReference = assemblyFactory.createReference(); + implReference.setName(implService.getName()); + try { + InterfaceContract implContract = + (InterfaceContract)implService.getInterfaceContract().clone(); + implContract.setInterface(implContract.getCallbackInterface()); + implContract.setCallbackInterface(null); + implReference.setInterfaceContract(implContract); + } catch (CloneNotSupportedException e) { + // will not happen + } + componentReference.setReference(implReference); + } + component.getReferences().add(componentReference); + return componentReference; + } + + /** + * @param composite + */ + private void configureSourcedProperties(Composite composite, List<ComponentProperty> propertySettings) { + // Resolve properties + Map<String, Property> compositeProperties = new HashMap<String, Property>(); + ComponentProperty componentProperty = null; + for (Property p : composite.getProperties()) { + componentProperty = getComponentPropertyByName(p.getName(), propertySettings); + if (componentProperty != null) { + compositeProperties.put(p.getName(), componentProperty); + } else { + compositeProperties.put(p.getName(), p); + } + } + + for (Component component : composite.getComponents()) { + try { + PropertyConfigurationUtil.sourceComponentProperties(compositeProperties, component); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Implementation impl = component.getImplementation(); + if (impl instanceof Composite) { + configureSourcedProperties((Composite)impl, component.getProperties()); + } + } + } + + private ComponentProperty getComponentPropertyByName(String propertyName, List<ComponentProperty> properties) { + if (properties != null) { + for (ComponentProperty aProperty : properties) { + if (aProperty.getName().equals(propertyName)) { + return aProperty; + } + } + } + return null; + } + + private SCABinding createSCABinding() { + SCABinding scaBinding = scaBindingFactory.createSCABinding(); + + // mark the bindings that are added automatically so that they can + // be disregarded for overriding purposes + if (scaBinding instanceof AutomaticBinding){ + ((AutomaticBinding)scaBinding).setIsAutomatic(true); + } + + if ( policyDefinitions != null ) { + for ( IntentAttachPointType attachPointType : policyDefinitions.getBindingTypes() ) { + if ( attachPointType.getName().equals(BINDING_SCA_QNAME)) { + ((IntentAttachPoint)scaBinding).setType(attachPointType); + } + } + } + + return scaBinding; + } + + /** + * Called by CompositeBindingURIBuilderImpl + * + * @param composite the composite to be configured + */ + protected void configureBindingURIsAndNames(Composite composite) throws CompositeBuilderException { + configureBindingURIs(composite, null, null); + configureBindingNames(composite); + } + + /** + * 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, List<Binding> defaultBindings) throws CompositeBuilderException { + configureBindingURIs(composite, null, defaultBindings); + } + + /** + * 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, List<Binding> defaultBindings) throws CompositeBuilderException { + + String parentComponentURI = uri; + + // 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, defaultBindings); + } + } + + // Initialize composite service binding URIs + List<Service> compositeServices = composite.getServices(); + for (Service service : compositeServices) { + // Set default binding names + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } + + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + constructBindingName(service, binding); + constructBindingURI(parentComponentURI, composite, service, binding, defaultBindings); + } + } + + // Initialize component service binding URIs + for (Component component : composite.getComponents()) { + + // Index properties, services and references + Map<String, Service> services = new HashMap<String, Service>(); + Map<String, Reference> references = new HashMap<String, Reference>(); + Map<String, Property> properties = new HashMap<String, Property>(); + indexImplementationPropertiesServicesAndReferences(component, + services, + references, + properties); + + // Index component services, references and properties + // Also check for duplicates + Map<String, ComponentService> componentServices = + new HashMap<String, ComponentService>(); + Map<String, ComponentReference> componentReferences = + new HashMap<String, ComponentReference>(); + Map<String, ComponentProperty> componentProperties = + new HashMap<String, ComponentProperty>(); + indexComponentPropertiesServicesAndReferences(component, + componentServices, + componentReferences, + componentProperties); + + // Reconcile component services/references/properties and + // implementation services/references and create component + // services/references/properties for the services/references + // declared by the implementation + reconcileServices(component, services, componentServices); + reconcileReferences(component, references, componentReferences); + reconcileProperties(component, properties, componentProperties); + + for (ComponentService service : component.getServices()) { + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } + + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + + constructBindingName(service, binding); + constructBindingURI(component, service, binding, defaultBindings); + } + } + } + } + + /** + * 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) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // Process nested composite + configureBindingNames((Composite)implementation); + } + } + + // Initialize composite service callback binding names + for (Service service : composite.getServices()) { + + if (service.getCallback() != null) { + for (Binding binding : service.getCallback().getBindings()) { + constructBindingName(service, binding); + } + } + } + + // Initialize composite reference binding names + for (Reference reference : composite.getReferences()) { + + for (Binding binding : reference.getBindings()) { + constructBindingName(reference, binding); + } + + if (reference.getCallback() != null) { + for (Binding binding : reference.getCallback().getBindings()) { + constructBindingName(reference, binding); + } + } + } + + // Initialize component service and reference binding names + for (Component component : composite.getComponents()) { + + // Initialize component service callback binding names + for (ComponentService service : component.getServices()) { + + if (service.getCallback() != null) { + for (Binding binding : service.getCallback().getBindings()) { + constructBindingName(service, binding); + } + } + } + + // Initialize component reference binding names + for (ComponentReference reference : component.getReferences()) { + + // Initialize binding names + for (Binding binding : reference.getBindings()) { + constructBindingName(reference, binding); + } + + if (reference.getCallback() != null) { + for (Binding binding : reference.getCallback().getBindings()) { + constructBindingName(reference, binding); + } + } + } + } + } + + /** + * 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 + * @param binding + */ + private void constructBindingName(Contract contract, Binding binding) { + + // 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()); + } + + // Check that multiple bindings do not have the same name + for (Binding otherBinding : contract.getBindings()) { + if (otherBinding == binding) { + // Skip the current binding + continue; + } + if (binding.getClass() != otherBinding.getClass()) { + // Look for a binding of the same type + continue; + } + if (binding.getName().equals(otherBinding.getName())) { + warning(contract instanceof Service ? "MultipleBindingsForService" : "MultipleBindingsForReference", + binding, 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, List<Binding> defaultBindings) + 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. + boolean includeBindingName = composite.getServices().size() != 1; + constructBindingURI(parentComponentURI, service, binding, includeBindingName, defaultBindings); + } + + /** + * 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, List<Binding> defaultBindings) + throws CompositeBuilderException{ + boolean includeBindingName = component.getServices().size() != 1; + constructBindingURI(component.getURI(), service, binding, includeBindingName, defaultBindings); + } + + /** + * 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, boolean includeBindingName, List<Binding> defaultBindings) + throws CompositeBuilderException{ + + try { + // 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; + } + + // Get the service binding name + URI bindingName; + if (binding.getName() != null) { + bindingName = new URI(binding.getName()); + } else { + bindingName = new URI(""); + } + + // 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, includeBindingName, bindingName)); + return; + } + + // calculate the base URI + + // get the protocol for this binding/URI +/* some code that allows binding specific code to run. Being discussed on ML + BindingURICalculator uriCalculator = bindingURICalcualtorExtensionPoint.getBindingURICalculator(binding); + + if (uriCalculator != null){ + String protocol = uriCalculator.getProtocol(binding); + + // find the default binding with the right protocol + Binding defaultBinding = nodeInfo.getBindingDefault(binding, protocol); + + if (defaultBinding != null){ + baseURI = new URI(defaultBinding.getURI()); + } else { + baseURI = null; + } + + } else { + baseURI = null; + } +*/ + // as a simpler alternative to the above commented out code. + URI baseURI = null; + if (defaultBindings != null) { + for (Binding defaultBinding : defaultBindings){ + if (binding.getClass() == defaultBinding.getClass()){ + baseURI = new URI(addSlashToPath(defaultBinding.getURI())); + break; + } + } + } + + binding.setURI(constructBindingURI(baseURI, componentURI, bindingURI, includeBindingName, bindingName)); + } catch (URISyntaxException ex) { + error("URLSyntaxException", binding, 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, boolean includeBindingName, URI bindingName){ + String uriString; + + if (baseURI == null) { + if (componentURI == null){ + if (bindingURI != null ) { + uriString = bindingURI.toString(); + } else { + uriString = bindingName.toString(); + } + } else { + if (bindingURI != null ) { + uriString = componentURI.resolve(bindingURI).toString(); + } else { + if (includeBindingName) { + uriString = componentURI.resolve(bindingName).toString(); + } else { + uriString = componentURI.toString(); + } + } + } + } else { + if (componentURI == null) { + if (bindingURI != null ) { + uriString = basedURI(baseURI, bindingURI).toString(); + } else { + if (includeBindingName) { + uriString = basedURI(baseURI, bindingName).toString(); + } else { + uriString = baseURI.toString(); + } + } + } else { + if (bindingURI != null ) { + uriString = basedURI(baseURI, componentURI.resolve(bindingURI)).toString(); + } else { + if (includeBindingName) { + uriString = basedURI(baseURI, componentURI.resolve(bindingName)).toString(); + } else { + uriString = basedURI(baseURI, componentURI).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/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseWireBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseWireBuilderImpl.java new file mode 100644 index 0000000000..0c2d02ab48 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BaseWireBuilderImpl.java @@ -0,0 +1,1149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.CompositeService; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.Wire; +import org.apache.tuscany.sca.assembly.builder.DefaultEndpointBuilder; +import org.apache.tuscany.sca.assembly.builder.EndpointBuilder; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.policy.util.PolicyComputationUtils; + +/** + * A composite builder that handles wiring inside a composite. + * + * @version $Rev$ $Date$ + */ +class BaseWireBuilderImpl { + + private Monitor monitor; + private AssemblyFactory assemblyFactory; + private EndpointFactory endpointFactory; + private InterfaceContractMapper interfaceContractMapper; + private EndpointBuilder endpointBuilder; + + + protected BaseWireBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, InterfaceContractMapper interfaceContractMapper, Monitor monitor) { + this.assemblyFactory = assemblyFactory; + this.endpointFactory = endpointFactory; + this.interfaceContractMapper = interfaceContractMapper; + this.monitor = monitor; + this.endpointBuilder = new DefaultEndpointBuilder(monitor); + + } + + /** + * Wire component references to component services and connect promoted + * services/references to component services/references inside a composite. + * + * @param composite + */ + protected void wireComponentReferences(Composite composite) { + + // Wire nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + wireComponentReferences((Composite)implementation); + } + } + + // Index components, services and references + Map<String, Component> components = new HashMap<String, Component>(); + Map<String, ComponentService> componentServices = new HashMap<String, ComponentService>(); + Map<String, ComponentReference> componentReferences = new HashMap<String, ComponentReference>(); + indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences); + + // Connect composite services and references to the component + // services and references that they promote + //connectCompositeServices(composite, components, componentServices); + //connectCompositeReferences(composite, componentReferences); + + // Compute the policies before connecting component references + //computePolicies(composite); + + // Connect component references as described in wires + connectWires(composite, componentServices, componentReferences); + + // Connect component references to their targets + connectComponentReferences(composite, components, componentServices, componentReferences); + + // Validate that references are wired or promoted, according + // to their multiplicity + for (ComponentReference componentReference : componentReferences.values()) { + if (!ReferenceConfigurationUtil.validateMultiplicityAndTargets(componentReference.getMultiplicity(), componentReference + .getTargets(), componentReference.getBindings())) { + if (componentReference.getTargets().isEmpty()) { + + // No warning if the reference is promoted out of the current composite + boolean promoted = false; + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + if (compositeReference.getPromotedReferences().contains(componentReference)) { + promoted = true; + break; + } + } + if (!promoted && !componentReference.isCallback()) { + warning("ReferenceWithoutTargets", composite, composite.getName().toString(), componentReference.getName()); + } + } else { + warning("TooManyReferenceTargets", composite, componentReference.getName()); + } + } + } + + // Finally clear the original reference target lists as we now have + // bindings to represent the targets + for (ComponentReference componentReference : componentReferences.values()) { + componentReference.getTargets().clear(); + } + } + + /** + * Index components, services and references inside a composite. + * @param composite + * @param components + * @param componentServices + * @param componentReferences + */ + private void indexComponentsServicesAndReferences(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences) { + + for (Component component : composite.getComponents()) { + + // Index components by name + components.put(component.getName(), component); + + ComponentService nonCallbackService = null; + int nonCallbackServices = 0; + for (ComponentService componentService : component.getServices()) { + + // Index component services by component name / service name + String uri = component.getName() + '/' + componentService.getName(); + componentServices.put(uri, componentService); + + boolean promotedService = false; + if (componentService.getName() != null && componentService.getName().indexOf("$promoted$") > -1) { + promotedService = true; + } + + // count how many non-callback, non-promoted services there are + // if there is only one the component name also acts as the service name + if ((!componentService.isCallback()) && (!promotedService)) { + + // Check how many non callback non-promoted services we have + if (nonCallbackServices == 0) { + nonCallbackService = componentService; + } + nonCallbackServices++; + } + + } + + if (nonCallbackServices == 1) { + // If we have a single non callback service, index it by + // component name as well + componentServices.put(component.getName(), nonCallbackService); + } + + // Index references by component name / reference name + for (ComponentReference componentReference : component.getReferences()) { + String uri = component.getName() + '/' + componentReference.getName(); + componentReferences.put(uri, componentReference); + } + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model, String... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = null; + problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + /** + * Connect composite references and services to the reference and services that they promote. + * + * @param composite + * @param componentServices + * @param problems + */ + protected void connectCompositeReferencesAndServices(Composite composite){ + // Wire nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + connectCompositeReferencesAndServices((Composite)implementation); + } + } + + // Index components, services and references + Map<String, Component> components = new HashMap<String, Component>(); + Map<String, ComponentService> componentServices = new HashMap<String, ComponentService>(); + Map<String, ComponentReference> componentReferences = new HashMap<String, ComponentReference>(); + indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences); + + // Connect composite services and references to the component + // services and references that they promote + connectCompositeServices(composite, components, componentServices); + connectCompositeReferences(composite, componentReferences); + } + + /** + * Connect composite services to the component services that they promote. + * + * @param composite + * @param componentServices + * @param problems + */ + private void connectCompositeServices(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices) { + + // Propagate interfaces from inner composite components' services to + // their component services + for (Component component : composite.getComponents()) { + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + if (componentService.getInterfaceContract() == null) { + componentService.setInterfaceContract(service.getInterfaceContract()); + } + } + } + } + } + + // Connect composite services to the component services that they + // promote + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null && componentService.isUnresolved()) { + + String promotedComponentName = compositeService.getPromotedComponent().getName(); + String promotedServiceName; + if (componentService.getName() != null) { + promotedServiceName = promotedComponentName + '/' + componentService.getName(); + } else { + promotedServiceName = promotedComponentName; + } + ComponentService promotedService = componentServices.get(promotedServiceName); + if (promotedService != null) { + + // Point to the resolved component + Component promotedComponent = components.get(promotedComponentName); + compositeService.setPromotedComponent(promotedComponent); + + // Point to the resolved component service + compositeService.setPromotedService(promotedService); + + // Use the interface contract from the component service if + // none is specified on the composite service + InterfaceContract compositeServiceInterfaceContract = compositeService.getInterfaceContract(); + InterfaceContract promotedServiceInterfaceContract = promotedService.getInterfaceContract(); + if (compositeServiceInterfaceContract == null) { + compositeService.setInterfaceContract(promotedServiceInterfaceContract); + } else if (promotedServiceInterfaceContract != null) { + // Check the compositeServiceInterfaceContract and promotedServiceInterfaceContract + boolean isCompatible = interfaceContractMapper.isCompatible(compositeServiceInterfaceContract, promotedServiceInterfaceContract); + if(!isCompatible){ + warning("ServiceInterfaceNotSubSet", compositeService, promotedServiceName); + } + } + + } else { + warning("PromotedServiceNotFound", composite, composite.getName().toString(), promotedServiceName); + } + } + } + + } + + /** + * Resolves promoted references. + * + * @param composite + * @param componentReferences + * @param problems + */ + private void connectCompositeReferences(Composite composite, Map<String, ComponentReference> componentReferences) { + + // Propagate interfaces from inner composite components' references to + // their component references + for (Component component : composite.getComponents()) { + if (component.getImplementation() instanceof Composite) { + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + if (componentReference.getInterfaceContract() == null) { + componentReference.setInterfaceContract(reference.getInterfaceContract()); + } + } + } + } + } + + // Connect composite references to the component references + // that they promote + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + List<ComponentReference> promotedReferences = compositeReference.getPromotedReferences(); + for (int i = 0, n = promotedReferences.size(); i < n; i++) { + ComponentReference componentReference = promotedReferences.get(i); + if (componentReference.isUnresolved()) { + String componentReferenceName = componentReference.getName(); + componentReference = componentReferences.get(componentReferenceName); + if (componentReference != null) { + + // Point to the resolved component reference + promotedReferences.set(i, componentReference); + + // Use the interface contract from the component + // reference if none + // is specified on the composite reference + + InterfaceContract compositeReferenceInterfaceContract = compositeReference.getInterfaceContract(); + InterfaceContract componentReferenceInterfaceContract = componentReference.getInterfaceContract(); + if (compositeReferenceInterfaceContract == null) { + compositeReference.setInterfaceContract(componentReferenceInterfaceContract); + } else if (componentReferenceInterfaceContract != null) { + // Check the compositeInterfaceContract and componentInterfaceContract + boolean isCompatible = interfaceContractMapper.isCompatible(compositeReferenceInterfaceContract, componentReferenceInterfaceContract); + if (!isCompatible) { + warning("ReferenceInterfaceNotSubSet", compositeReference, componentReferenceName); + } + } + } else { + warning("PromotedReferenceNotFound", composite, composite.getName().toString(), componentReferenceName); + } + } + } + } + } + + private List<Endpoint> createComponentReferenceTargets(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices, + ComponentReference componentReference) { + + List<Endpoint> endpoints = new ArrayList<Endpoint>(); + + if (componentReference.getAutowire() == Boolean.TRUE) { + + // Find suitable targets in the current composite for an + // autowired reference + Multiplicity multiplicity = componentReference.getMultiplicity(); + for (Component targetComponent : composite.getComponents()) { + // prevent autowire connecting to self + boolean skipSelf = false; + for (ComponentReference targetComponentReference : targetComponent.getReferences()) { + if (componentReference == targetComponentReference){ + skipSelf = true; + } + } + + if (!skipSelf){ + for (ComponentService targetComponentService : targetComponent.getServices()) { + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint.setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll(componentReference.getBindings()); + endpoints.add(endpoint); + + if (multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) { + break; + } + } + } + } + } + + if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) { + if (endpoints.size() == 0) { + warning("NoComponentReferenceTarget", componentReference, componentReference.getName()); + } + } + + } else if (!componentReference.getTargets().isEmpty()) { + + // Check if the component reference does not mix the use of endpoints specified via + // binding elements with target endpoints specified via the target attribute + for (Binding binding : componentReference.getBindings()) { + if (binding.getURI() != null) { + warning("ReferenceEndPointMixWithTarget", composite, componentReference.getName()); + } + } + + // Resolve targets specified on the component reference + for (ComponentService componentService : componentReference.getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices.get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint.setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll(componentReference.getBindings()); + endpoints.add(endpoint); + + // mark the reference target as resolved. Used later when we are looking to + // see if an sca binding is associated with a resolved target or not + componentService.setUnresolved(false); + } else { + warning("ReferenceIncompatibleInterface", composite, composite.getName().toString(), + componentReference.getName(), componentService.getName()); + } + } else { + // add all the reference bindings into the target so that they + // can be used for comparison when the target is resolved at runtime + componentService.getBindings().addAll(componentReference.getBindings()); + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(name); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.getCandidateBindings().addAll(componentReference.getBindings()); + endpoints.add(endpoint); + + // The bindings will be cloned back into the reference when the + // target is finally resolved. + warning("ComponentReferenceTargetNotFound", composite, + composite.getName().toString(), componentService.getName()); + } + } + } else if (componentReference.getReference() != null) { + + // Resolve targets from the corresponding reference in the + // componentType + for (ComponentService componentService : componentReference.getReference().getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices.get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of + // the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint.setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().addAll(componentReference.getBindings()); + endpoints.add(endpoint); + + // mark the reference target as resolved. Used later when we are looking to + // see if an sca binding is associated with a resolved target or not + componentService.setUnresolved(false); + } else { + warning("ComponentIncompatibleInterface", composite, + componentReference.getName(), componentService.getName()); + } + } else { + // add all the reference bindings into the target so that they + // can be used for comparison when the target is resolved at runtime + componentService.getBindings().addAll(componentReference.getBindings()); + + // The bindings will be cloned back into the reference when the + // target is finally resolved. + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(name); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.getCandidateBindings().addAll(componentReference.getBindings()); + endpoints.add(endpoint); + + warning("ComponentReferenceTargetNotFound", composite, + composite.getName().toString(), componentService.getName()); + } + } + } + + + // if no endpoints have found so far retrieve any target names that are in binding URIs + if (endpoints.isEmpty()){ + for (Binding binding : componentReference.getBindings()) { + + String uri = binding.getURI(); + + // user hasn't put a uri on the binding so it's not a target name + if (uri == null) { + continue; + } + + // user might have put a local target name in the uri so get + // the path part and see if it refers to a target we know about + // - if it does the reference binding will be matched with a service binding + // - if it doesn't it is assumed to be an external reference + Component targetComponent = null; + ComponentService targetComponentService = null; + String path = null; + + try { + path = URI.create(uri).getPath(); + } catch(Exception ex){ + // just assume that no target is identified if + // a URI related exception is thrown + } + + if (path != null) { + if (path.startsWith("/")) { + path = path.substring(1); + } + + // Resolve the target component and service + targetComponentService = componentServices.get(path); + int s = path.indexOf('/'); + if (s == -1) { + targetComponent = components.get(path); + } else { + targetComponent = components.get(path.substring(0, s)); + } + } + + // if the path of the binding URI matches a component in the + // composite then configure an endpoint with this component as the target + // if not then the binding URI will be assumed to reference an external service + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(targetComponent.getName()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.setTargetComponent(targetComponent); + endpoint.setTargetComponentService(targetComponentService); + endpoint.getCandidateBindings().add(binding); + endpoints.add(endpoint); + } else { + warning("ReferenceIncompatibleInterface", + composite, + composite.getName().toString(), + componentReference.getName(), + uri); + } + } else { + + // create endpoints for manually configured bindings + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(uri); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(componentReference); + endpoint.setInterfaceContract(componentReference.getInterfaceContract()); + endpoint.setSourceBinding(binding); + endpoints.add(endpoint); + } + } + } + + return endpoints; + } + + + /** + * Connect references to their targets. + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectComponentReferences(Composite composite, + Map<String, Component> components, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences){ + + for (ComponentReference componentReference : componentReferences.values()) { + + List<Endpoint> endpoints = createComponentReferenceTargets(composite, + components, + componentServices, + componentReference); + + componentReference.getEndpoints().addAll(endpoints); + + // the result of calculating the endpoints is either that bindings have been + // configured manually using a URI or that targets have been provided and the + // endpoint remains unresolved. So all endpoints should be either resved or uresolved. + boolean endpointsRequireAutomaticResolution = false; + for(Endpoint endpoint : endpoints){ + endpointsRequireAutomaticResolution = endpoint.isUnresolved(); + } + + // build each endpoint + if (endpointsRequireAutomaticResolution) { + + for(Endpoint endpoint : endpoints){ + endpointBuilder.build(endpoint); + } + + // TODO - The following step ensures that the reference binding list remains + // as the record of resolved targets for now. This needs fixing so + // that the endpoint takes on this responsibility. + componentReference.getBindings().clear(); + + if (componentReference.getCallback() != null){ + componentReference.getCallback().getBindings().clear(); + } + + for(Endpoint endpoint : endpoints){ + if (endpoint.isUnresolved() == false){ + componentReference.getBindings().add(endpoint.getSourceBinding()); + + if (componentReference.getCallback() != null){ + componentReference.getCallback().getBindings().add(endpoint.getSourceCallbackBinding()); + } + } + } + + } else { + // do nothing as no targets have been specified so the bindings + // in the reference binding list are assumed to be manually configured + } + + +/* + // Select the reference bindings matching the target service bindings + List<Binding> selectedBindings = new ArrayList<Binding>(); + List<Binding> selectedCallbackBindings = null; + + // Handle callback + boolean bidirectional = false; + + if (componentReference.getInterfaceContract() != null && componentReference.getInterfaceContract().getCallbackInterface() != null) { + bidirectional = true; + selectedCallbackBindings = new ArrayList<Binding>(); + } + + for (Target target : targets) { + + Component targetComponent = target.getComponent(); + ComponentService targetComponentService = target.getService(); + if (targetComponentService.getService() instanceof CompositeService) { + CompositeService compositeService = (CompositeService) targetComponentService.getService(); + // Find the promoted component service + targetComponentService = ServiceConfigurationUtil.getPromotedComponentService(compositeService); + } + + try { + PolicyConfigurationUtil.determineApplicableBindingPolicySets(componentReference, targetComponentService); + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + + // Match the binding against the bindings of the target service + Binding selected = BindingConfigurationUtil.resolveBindings(componentReference, targetComponent, targetComponentService); + if (selected == null) { + warning("NoMatchingBinding", componentReference, componentReference.getName(), targetComponentService.getName()); + } else { + selectedBindings.add(selected); + } + if (bidirectional) { + Binding selectedCallback = BindingConfigurationUtil.resolveCallbackBindings(componentReference, targetComponent, targetComponentService); + if (selectedCallback != null) { + selectedCallbackBindings.add(selectedCallback); + } + } + } +*/ + + // Need to tidy up the reference binding list and add in the bindings that + // have been selected above. The situation so far... + // Wired reference (1 or more targets are specified) + // Binding.uri = null - remove as it's left over from target resolution + // the binding will have been moved to the target from where + // it will be resolved later + // Binding.uri != null - the selected and resolved reference binding + // Unwired reference (0 targets) + // Binding.uri = null - Either a callback reference or the reference is yet to be wired + // by the implementation so leave the binding where it is + // Binding.uri != null - from the composite file so leave it +/* + if ((componentReference.getTargets().size() > 0) || + (!targets.isEmpty())) { + + // Add all the effective bindings + componentReference.getBindings().clear(); + componentReference.getBindings().addAll(selectedBindings); + if (bidirectional) { + componentReference.getCallback().getBindings().clear(); + componentReference.getCallback().getBindings().addAll(selectedCallbackBindings); + } + + // add in sca bindings to represent all unresolved targets. The sca binding + // will try to resolve the target at a later date. + for (ComponentService service : componentReference.getTargets()) { + if (service.isUnresolved()) { + SCABinding scaBinding = null; + + // find the sca binding amongst the candidate binding list. We want to + // find this one and clone it as it may have been configured with + // policies + for (Binding binding : service.getBindings()) { + + if (binding instanceof SCABinding) { + try { + scaBinding = (SCABinding)((OptimizableBinding)binding).clone(); + } catch (CloneNotSupportedException ex){ + // we know it is supported on the SCA binding + } + break; + } + } + + if (scaBinding != null) { + // configure the cloned SCA binding for this reference target + scaBinding.setName(service.getName()); + + // this service object holds the list of candidate bindings which + // can be used for later matching + ((OptimizableBinding)scaBinding).setTargetComponentService(service); + componentReference.getBindings().add(scaBinding); + } else { + // not sure we need to raise a warning here as a warning will already been + // thrown previously to indicate the reason why there is no sca binding + // warning("NoSCABindingAvailableForUnresolvedService", componentReference, componentReference.getName(), service.getName()); + } + } + } + } + +*/ + // Connect the optimizable bindings to their target component and + // service +/* + for (Binding binding : componentReference.getBindings()) { + if (!(binding instanceof OptimizableBinding)) { + continue; + } + OptimizableBinding optimizableBinding = (OptimizableBinding)binding; + if (optimizableBinding.getTargetComponentService() != null) { + continue; + } + String uri = optimizableBinding.getURI(); + if (uri == null) { + continue; + } + uri = URI.create(uri).getPath(); + if (uri.startsWith("/")) { + uri = uri.substring(1); + } + + // Resolve the target component and service + ComponentService targetComponentService = componentServices.get(uri); + Component targetComponent; + int s = uri.indexOf('/'); + if (s == -1) { + targetComponent = components.get(uri); + } else { + targetComponent = components.get(uri.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + } else { + warning("ReferenceIncompatibleInterface", + composite, + composite.getName().toString(), + componentReference.getName(), + uri); + } + optimizableBinding.setTargetComponent(targetComponent); + optimizableBinding.setTargetComponentService(targetComponentService); + optimizableBinding.setTargetBinding(targetComponentService.getBinding(optimizableBinding.getClass())); + } + } +*/ + } + } + + /** + * Resolve wires and connect the sources to their targets + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectWires(Composite composite, + Map<String, ComponentService> componentServices, + Map<String, ComponentReference> componentReferences) { + + // For each wire, resolve the source reference, the target service, and + // add it to the list of targets of the reference + List<Wire> wires = composite.getWires(); + for (int i = 0, n = wires.size(); i < n; i++) { + Wire wire = wires.get(i); + + ComponentReference resolvedReference; + ComponentService resolvedService; + + // Resolve the source reference + ComponentReference source = wire.getSource(); + if (source != null && source.isUnresolved()) { + resolvedReference = componentReferences.get(source.getName()); + if (resolvedReference != null) { + wire.setSource(resolvedReference); + } else { + warning("WireSourceNotFound", composite, source.getName()); + } + } else { + resolvedReference = wire.getSource(); + } + + // Resolve the target service + ComponentService target = wire.getTarget(); + if (target != null && target.isUnresolved()) { + resolvedService = componentServices.get(target.getName()); + if (resolvedService != null) { + wire.setTarget(target); + } else { + warning("WireTargetNotFound", composite, source.getName()); + } + } else { + resolvedService = wire.getTarget(); + } + + // Add the target service to the list of targets of the + // reference + if (resolvedReference != null && resolvedService != null) { + // Check that the target component service provides + // a superset of + // the component reference interface + if (resolvedReference.getInterfaceContract() == null || interfaceContractMapper + .isCompatible(resolvedReference.getInterfaceContract(), resolvedService.getInterfaceContract())) { + + //resolvedReference.getTargets().add(resolvedService); + resolvedReference.getTargets().add(wire.getTarget()); + } else { + warning("WireIncompatibleInterface", composite, source.getName(), target.getName()); + } + } + } + + // Clear the list of wires + composite.getWires().clear(); + } + + private void addPoliciesFromPromotedService(CompositeService compositeService) { + //inherit intents and policies from promoted service + PolicyComputationUtils.addInheritedIntents(compositeService.getPromotedService().getRequiredIntents(), + compositeService.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(compositeService.getPromotedService().getPolicySets(), + compositeService.getPolicySets(), true); + addInheritedOperationConfigurations(compositeService.getPromotedService(), compositeService); + } + + private void addPoliciesFromPromotedReference(CompositeReference compositeReference) { + for ( Reference promotedReference : compositeReference.getPromotedReferences() ) { + PolicyComputationUtils.addInheritedIntents(promotedReference.getRequiredIntents(), + compositeReference.getRequiredIntents()); + + PolicyComputationUtils.addInheritedPolicySets(promotedReference.getPolicySets(), + compositeReference.getPolicySets(), true); + addInheritedOperationConfigurations(promotedReference, compositeReference); + } + } + + + protected void computePolicies(Composite composite) { + + // compute policies recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + computePolicies((Composite)implementation); + } + } + + for (Component component : composite.getComponents()) { + + // Inherit default policies from the component to component-level contracts. + // This must be done BEFORE computing implementation policies because the + // implementation policy computer removes from the component any + // intents and policy sets that don't apply to implementations. + PolicyConfigurationUtil.inheritDefaultPolicies(component, component.getServices()); + PolicyConfigurationUtil.inheritDefaultPolicies(component, component.getReferences()); + + Implementation implemenation = component.getImplementation(); + try { + PolicyConfigurationUtil.computeImplementationIntentsAndPolicySets(implemenation, component); + } catch ( Exception e ) { + error("PolicyRelatedException", implemenation, e); + //throw new RuntimeException(e); + } + + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + // reconcile intents and policysets from componentType + PolicyComputationUtils.addInheritedIntents(service.getRequiredIntents(), componentService.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(service.getPolicySets(), componentService.getPolicySets(), true); + + //reconcile intents and policysets for operations + boolean notFound; + List<ConfiguredOperation> opsFromComponentType = new ArrayList<ConfiguredOperation>(); + for ( ConfiguredOperation ctsConfOp : service.getConfiguredOperations() ) { + notFound = true; + for ( ConfiguredOperation csConfOp : componentService.getConfiguredOperations() ) { + if ( csConfOp.getName().equals(ctsConfOp.getName()) ) { + PolicyComputationUtils.addInheritedIntents(ctsConfOp.getRequiredIntents(), csConfOp.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(ctsConfOp.getPolicySets(), csConfOp.getPolicySets(), true); + notFound = false; + } + } + + if ( notFound ) { + opsFromComponentType.add(ctsConfOp); + } + } + componentService.getConfiguredOperations().addAll(opsFromComponentType); + } + + try { + //compute the intents for operations under service element + PolicyConfigurationUtil.computeIntentsForOperations(componentService); + //compute intents and policyset for each binding + //addInheritedOpConfOnBindings(componentService); + PolicyConfigurationUtil.computeBindingIntentsAndPolicySets(componentService); + PolicyConfigurationUtil.determineApplicableBindingPolicySets(componentService, null); + + } catch ( Exception e ) { + error("PolicyRelatedException", componentService, e); + //throw new RuntimeException(e); + } + } + + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + // reconcile intents and policysets + PolicyComputationUtils.addInheritedIntents(reference.getRequiredIntents(), componentReference.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(reference.getPolicySets(), componentReference.getPolicySets(), true); + } + + + try { + //compute the intents for operations under reference element + PolicyConfigurationUtil.computeIntentsForOperations(componentReference); + //compute intents and policyset for each binding + //addInheritedOpConfOnBindings(componentReference); + PolicyConfigurationUtil.computeBindingIntentsAndPolicySets(componentReference); + PolicyConfigurationUtil.determineApplicableBindingPolicySets(componentReference, null); + + + if ( componentReference.getCallback() != null ) { + PolicyComputationUtils.addInheritedIntents(componentReference.getRequiredIntents(), + componentReference.getCallback().getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(componentReference.getPolicySets(), + componentReference.getCallback().getPolicySets(), + false); + } + } catch ( Exception e ) { + error("PolicyRelatedException", componentReference, e); + //throw new RuntimeException(e); + } + } + } + + PolicyConfigurationUtil.inheritDefaultPolicies(composite, composite.getServices()); + PolicyConfigurationUtil.inheritDefaultPolicies(composite, composite.getReferences()); + + //compute policies for composite service bindings + for (Service service : composite.getServices()) { + addPoliciesFromPromotedService((CompositeService)service); + try { + //compute the intents for operations under service element + PolicyConfigurationUtil.computeIntentsForOperations(service); + //add or merge service operations to the binding + //addInheritedOpConfOnBindings(service); + PolicyConfigurationUtil.computeBindingIntentsAndPolicySets(service); + PolicyConfigurationUtil.determineApplicableBindingPolicySets(service, null); + } catch ( Exception e ) { + error("PolicyRelatedException", service, e); + //throw new RuntimeException(e); + } + + } + + for (Reference reference : composite.getReferences()) { + CompositeReference compReference = (CompositeReference)reference; + addPoliciesFromPromotedReference(compReference); + try { + //compute the intents for operations under service element + PolicyConfigurationUtil.computeIntentsForOperations(reference); + //addInheritedOpConfOnBindings(reference); + + if (compReference.getCallback() != null) { + PolicyComputationUtils.addInheritedIntents(compReference.getRequiredIntents(), + compReference.getCallback().getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(compReference.getPolicySets(), + compReference.getCallback().getPolicySets(), + false); + } + + PolicyConfigurationUtil.computeBindingIntentsAndPolicySets(reference); + PolicyConfigurationUtil.determineApplicableBindingPolicySets(reference, null); + } catch ( Exception e ) { + error("PolicyRelatedException", reference, e); + //throw new RuntimeException(e); + } + } + + } + + private void addInheritedOperationConfigurations(OperationsConfigurator source, + OperationsConfigurator target) { + boolean found = false; + + List<ConfiguredOperation> additionalOperations = new ArrayList<ConfiguredOperation>(); + for ( ConfiguredOperation sourceConfOp : source.getConfiguredOperations() ) { + for ( ConfiguredOperation targetConfOp : target.getConfiguredOperations() ) { + if ( sourceConfOp.getName().equals(targetConfOp.getName())) { + PolicyComputationUtils.addInheritedIntents(sourceConfOp.getRequiredIntents(), + targetConfOp.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(sourceConfOp.getPolicySets(), + targetConfOp.getPolicySets(), true); + found = true; + break; + } + } + + if ( !found ) { + additionalOperations.add(sourceConfOp); + } + } + + if ( !additionalOperations.isEmpty() ) { + target.getConfiguredOperations().addAll(additionalOperations); + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingConfigurationUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingConfigurationUtil.java new file mode 100644 index 0000000000..4016d02a36 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingConfigurationUtil.java @@ -0,0 +1,146 @@ +/* + * 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.ArrayList; +import java.util.List; + +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.OptimizableBinding; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * This class encapsulates utility methods to deal with binding definitions + * + * @version $Rev$ $Date$ + */ +abstract class BindingConfigurationUtil { + private static boolean hasCompatiblePolicySets(Binding refBinding, Binding svcBinding) { + boolean isCompatible = true; + if ( refBinding instanceof PolicySetAttachPoint && svcBinding instanceof PolicySetAttachPoint ) { + //TODO : need to add more compatibility checks at the policy attachment levels + for ( PolicySet svcPolicySet : ((PolicySetAttachPoint)svcBinding).getPolicySets() ) { + isCompatible = false; + for ( PolicySet refPolicySet : ((PolicySetAttachPoint)refBinding).getPolicySets() ) { + if ( svcPolicySet.equals(refPolicySet) ) { + isCompatible = true; + break; + } + } + //if there exists no matching policy set in the reference binding + if ( !isCompatible ) { + return isCompatible; + } + } + } + return isCompatible; + } + + + static Binding matchBinding(Component targetComponent, ComponentService targetComponentService, List<Binding> source, List<Binding> target) { + List<Binding> matched = new ArrayList<Binding>(); + // Find the corresponding bindings from the service side + for (Binding binding : source) { + for (Binding serviceBinding : target) { + if (binding.getClass() == serviceBinding.getClass() && + hasCompatiblePolicySets(binding, serviceBinding)) { + + try { + Binding cloned = (Binding)binding.clone(); + + //Customise the binding name to make it unique + // regardless of how many bindings or targets there are + if ( targetComponent != null){ + cloned.setName(binding.getName() + "#" + targetComponent.getName() + "/" + serviceBinding.getName()); + } else { + cloned.setName(binding.getName() + "#" + serviceBinding.getName()); + } + + // Set the binding URI to the URI of the target service + // that has been matched + if (binding.getURI() == null) { + cloned.setURI(serviceBinding.getURI()); + } + + if (binding instanceof OptimizableBinding) { + OptimizableBinding endpoint = ((OptimizableBinding)cloned); + endpoint.setTargetComponent(targetComponent); + endpoint.setTargetComponentService(targetComponentService); + endpoint.setTargetBinding(serviceBinding); + } + + matched.add(cloned); + break; + } catch (Exception ex) { + // do nothing + } + } + } + } + if (matched.isEmpty()) { + // No matching binding + return null; + } else { + for (Binding binding : matched) { + // If binding.sca is present, use it + if (SCABinding.class.isInstance(binding)) { + return binding; + } + } + // Use the first one + return matched.get(0); + } + } + + /** + * Choose a binding for the reference based on the bindings available on the + * service + * + * @param reference The component reference + * @param service The component service + * @return Resolved binding + */ + static Binding resolveBindings(ComponentReference reference, Component component, ComponentService service) { + List<Binding> source = reference.getBindings(); + List<Binding> target = service.getBindings(); + + return matchBinding(component, service, source, target); + + } + + + /** + * @param reference + * @param service + * @return + */ + static Binding resolveCallbackBindings(ComponentReference reference, Component component, ComponentService service) { + List<Binding> source = reference.getCallback().getBindings(); + List<Binding> target = service.getCallback().getBindings(); + + return matchBinding(component, service, source, target); + } + + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentConfigurationBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentConfigurationBuilderImpl.java new file mode 100644 index 0000000000..8dd585f92b --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentConfigurationBuilderImpl.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that handles the configuration of components. + * + * @version $Rev$ $Date$ + */ +public class ComponentConfigurationBuilderImpl extends BaseConfigurationBuilderImpl implements CompositeBuilder { + + public ComponentConfigurationBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper interfaceContractMapper, + SCADefinitions policyDefinitions, + Monitor monitor) { + super(assemblyFactory, scaBindingFactory, interfaceContractMapper, policyDefinitions, monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + configureComponents(composite); + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceBindingBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceBindingBuilderImpl.java new file mode 100644 index 0000000000..1769e7eee9 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceBindingBuilderImpl.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + + +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.Composite; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.BindingBuilderExtension; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that performs any additional building steps that + * component reference bindings may need. Used for WSDL generation. + * + * @version $Rev$ $Date$ + */ +public class ComponentReferenceBindingBuilderImpl implements CompositeBuilder { + private Monitor monitor; + + public ComponentReferenceBindingBuilderImpl(Monitor monitor) { + this.monitor = monitor; + } + + public void build(Composite composite) throws CompositeBuilderException { + buildReferenceBindings(composite); + } + + private void buildReferenceBindings(Composite composite) { + + // find all the component reference bindings (starting at top level) + for (Component component : composite.getComponents()) { + for (ComponentReference componentReference : component.getReferences()) { + for (Binding binding : componentReference.getBindings()) { + if (binding instanceof BindingBuilderExtension) { + ((BindingBuilderExtension)binding).getBuilder().build(component, componentReference, binding, monitor); + } + } + } + } + + // build bindings recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + buildReferenceBindings((Composite)implementation); + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferencePromotionWireBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferencePromotionWireBuilderImpl.java new file mode 100644 index 0000000000..c0702c87b3 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferencePromotionWireBuilderImpl.java @@ -0,0 +1,165 @@ +/* + * 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 org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that handles the creation of promoted composite services. + * + * @version $Rev$ $Date$ + */ +public class ComponentReferencePromotionWireBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + private EndpointFactory endpointFactory; + private Monitor monitor; + + public ComponentReferencePromotionWireBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, Monitor monitor) { + this.assemblyFactory = assemblyFactory; + this.endpointFactory = endpointFactory; + this.monitor = monitor; + } + + public void build(Composite composite) throws CompositeBuilderException { + wireCompositeReferences(composite); + } + + /** + * Wire composite references in nested composites. + * + * @param composite + * @param problems + */ + private void wireCompositeReferences(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + wireCompositeReferences((Composite)implementation); + } + } + + // Process component references declared on components in this composite + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + for (ComponentReference componentReference : component.getReferences()) { + Reference implReference = componentReference.getReference(); + if (implReference != null && implReference instanceof CompositeReference) { + + // If the component reference is wired, it is a promotion override + if (!componentReference.getEndpoints().isEmpty()) { + componentReference.setPromotionOverride(true); + } + + // If the component reference is a promotion override, override the + // configuration of the promoted reference + if (componentReference.isPromotionOverride()) { + CompositeReference compositeReference = (CompositeReference)implReference; + List<ComponentReference> promotedReferences = + ReferenceConfigurationUtil.getPromotedComponentReferences(compositeReference); + for (ComponentReference promotedReference : promotedReferences) { + ReferenceConfigurationUtil.reconcileReferenceBindings( + componentReference, promotedReference, assemblyFactory, endpointFactory, monitor); + if (componentReference.getInterfaceContract() != null && // can be null in unit tests + componentReference.getInterfaceContract().getCallbackInterface() != null) { + SCABinding scaCallbackBinding = promotedReference.getCallbackBinding(SCABinding.class); + if (promotedReference.getCallback() != null) { + promotedReference.getCallback().getBindings().clear(); + } else { + promotedReference.setCallback(assemblyFactory.createCallback()); + } + if (scaCallbackBinding != null) { + promotedReference.getCallback().getBindings().add(scaCallbackBinding); + } + if (componentReference.getCallback() != null) { + promotedReference.getCallback().getBindings().addAll(componentReference + .getCallback().getBindings()); + } + } + + // Wire the promoted reference to the actual non-composite component services + if (promotedReference.getMultiplicity() == Multiplicity.ONE_ONE) { + // promotedReference.getTargets().clear(); + } + for (ComponentService target : componentReference.getTargets()) { + if (target.getService() instanceof CompositeService) { + + // Wire to the actual component service + // promoted by a composite service + CompositeService compositeService = (CompositeService)target.getService(); + // Find the promoted component service + ComponentService componentService = + ServiceConfigurationUtil.getPromotedComponentService(compositeService); + if (componentService != null) { + promotedReference.getTargets().add(componentService); + } + } else { + + // Wire to a non-composite target service + promotedReference.getTargets().add(target); + } + } + } + } + } + } + } else { + for (ComponentReference componentReference : component.getReferences()) { + + // Wire the component reference to the actual + // non-composite component services + List<ComponentService> targets = componentReference.getTargets(); + for (int i = 0, n = targets.size(); i < n; i++) { + ComponentService target = targets.get(i); + if (target.getService() instanceof CompositeService) { + + // Wire to the actual component service + // promoted by a composite service + CompositeService compositeService = (CompositeService)target.getService(); + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + targets.set(i, componentService); + } + } + } + } + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java new file mode 100644 index 0000000000..927330b139 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentReferenceWireBuilderImpl.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that wires component references. + * + * @version $Rev$ $Date$ + */ +public class ComponentReferenceWireBuilderImpl extends BaseWireBuilderImpl implements CompositeBuilder { + + public ComponentReferenceWireBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, InterfaceContractMapper interfaceContractMapper, Monitor monitor) { + super(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + wireComponentReferences(composite); + } +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServiceBindingBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServiceBindingBuilderImpl.java new file mode 100644 index 0000000000..c4c6462c60 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServiceBindingBuilderImpl.java @@ -0,0 +1,73 @@ +/* + * 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 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.Implementation; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilderExtension; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that performs any additional building steps that + * component service bindings may need. Used for WSDL generation. + * + * @version $Rev$ $Date$ + */ +public class ComponentServiceBindingBuilderImpl implements CompositeBuilder { + private Monitor monitor; + + public ComponentServiceBindingBuilderImpl(Monitor monitor) { + this.monitor = monitor; + } + + public void build(Composite composite) throws CompositeBuilderException { + buildServiceBindings(composite); + } + + private void buildServiceBindings(Composite composite) { + + // build bindings recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + buildServiceBindings((Composite)implementation); + } + } + + // find all the component service bindings + for (Component component : composite.getComponents()) { + for (ComponentService componentService : component.getServices()) { + for (Binding binding : componentService.getBindings()) { + if (binding instanceof BindingBuilderExtension) { + ((BindingBuilderExtension)binding).getBuilder().build(component, componentService, binding, monitor); + } + } + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServicePromotionBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServicePromotionBuilderImpl.java new file mode 100644 index 0000000000..d73286f7ab --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ComponentServicePromotionBuilderImpl.java @@ -0,0 +1,99 @@ +/* + * 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 org.apache.tuscany.sca.assembly.AssemblyFactory; +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.Service; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; + +/** + * A composite builder that handles the creation of promoted services. + * + * @version $Rev$ $Date$ + */ +public class ComponentServicePromotionBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + + public ComponentServicePromotionBuilderImpl(AssemblyFactory assemblyFactory) { + this.assemblyFactory = assemblyFactory; + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Process nested composites recursively + configureNestedCompositeServices(composite); + } + + private void configureNestedCompositeServices(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // First process nested composites + configureNestedCompositeServices((Composite)implementation); + + // Process the component services declared on components in this composite + for (ComponentService componentService : component.getServices()) { + Service implService = componentService.getService(); + if (implService != null && implService instanceof CompositeService) { + CompositeService compositeService = (CompositeService)implService; + + // Get the innermost promoted service + ComponentService promotedService = + ServiceConfigurationUtil.getPromotedComponentService(compositeService); + if (promotedService != null) { + Component promotedComponent = ServiceConfigurationUtil.getPromotedComponent(compositeService); + + // Create a new component service to represent this + // component service on the promoted component + ComponentService newComponentService = assemblyFactory.createComponentService(); + newComponentService.setName("$promoted$" + component.getName() + "$slash$" + componentService.getName()); + promotedComponent.getServices().add(newComponentService); + newComponentService.setService(promotedService.getService()); + newComponentService.getBindings().addAll(componentService.getBindings()); + newComponentService.setInterfaceContract(componentService.getInterfaceContract()); + + if (componentService.getInterfaceContract() != null && + componentService.getInterfaceContract().getCallbackInterface() != null) { + newComponentService.setCallback(assemblyFactory.createCallback()); + newComponentService.getCallback().getBindings() + .addAll(componentService.getCallback().getBindings()); + } + + // Change the composite service to now promote the + // newly created component service directly + compositeService.setPromotedComponent(promotedComponent); + compositeService.setPromotedService(newComponentService); + } + } + } + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBindingURIBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBindingURIBuilderImpl.java new file mode 100644 index 0000000000..4c2c369f3e --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBindingURIBuilderImpl.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that handles the configuration of binding URIs. + * + * @version $Rev$ $Date$ + */ +public class CompositeBindingURIBuilderImpl extends BaseConfigurationBuilderImpl implements CompositeBuilder { + + public CompositeBindingURIBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper interfaceContractMapper, + SCADefinitions policyDefinitions, + Monitor monitor) { + super(assemblyFactory, scaBindingFactory, interfaceContractMapper, policyDefinitions, monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + configureBindingURIsAndNames(composite); + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java new file mode 100644 index 0000000000..fd1c3d2a8f --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java @@ -0,0 +1,169 @@ +/* + * 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.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.DefaultEndpointFactory; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +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.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; + +/** + * A builder that handles the configuration of the components inside a composite + * and the wiring of component references to component services. + * + * @version $Rev$ $Date$ + */ +public class CompositeBuilderImpl implements CompositeBuilder { + private static final Logger logger = Logger.getLogger(CompositeBuilderImpl.class.getName()); + private CompositeBuilder compositeIncludeBuilder; + private CompositeBuilder componentReferenceWireBuilder; + private CompositeBuilder componentReferencePromotionWireBuilder; + private CompositeBuilder compositeReferenceWireBuilder; + private CompositeBuilder compositeCloneBuilder; + private CompositeBuilder componentConfigurationBuilder; + private CompositeBuilder compositeServiceConfigurationBuilder; + private CompositeBuilder compositeReferenceConfigurationBuilder; + private CompositeBuilder compositeBindingURIBuilder; + private CompositeBuilder componentServicePromotionBuilder; + private CompositeBuilder compositeServicePromotionBuilder; + private CompositeBuilder compositePromotionBuilder; + private CompositeBuilder compositePolicyBuilder; + private CompositeBuilder componentServiceBindingBuilder; + private CompositeBuilder componentReferenceBindingBuilder; + + /** + * Constructs a new composite builder. + * + * @param assemblyFactory + * @param scaBindingFactory + * @param intentAttachPointTypeFactory + * @param interfaceContractMapper + * @param monitor + */ + public CompositeBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + Monitor monitor) { + this(assemblyFactory, null, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, null, monitor); + } + + /** + * Constructs a new composite builder. + * + * @param assemblyFactory + * @param scaBindingFactory + * @param endpointFactory + * @param intentAttachPointTypeFactory + * @param interfaceContractMapper + * @param policyDefinitions + * @param monitor + */ + public CompositeBuilderImpl(AssemblyFactory assemblyFactory, + EndpointFactory endpointFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + SCADefinitions policyDefinitions, + Monitor monitor) { + + if (endpointFactory == null){ + endpointFactory = new DefaultEndpointFactory(); + } + + compositeIncludeBuilder = new CompositeIncludeBuilderImpl(monitor); + componentReferenceWireBuilder = new ComponentReferenceWireBuilderImpl(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + componentReferencePromotionWireBuilder = new ComponentReferencePromotionWireBuilderImpl(assemblyFactory, endpointFactory, monitor); + compositeReferenceWireBuilder = new CompositeReferenceWireBuilderImpl(assemblyFactory, endpointFactory, monitor); + compositeCloneBuilder = new CompositeCloneBuilderImpl(monitor); + componentConfigurationBuilder = new ComponentConfigurationBuilderImpl(assemblyFactory, scaBindingFactory, interfaceContractMapper, policyDefinitions, monitor); + compositeServiceConfigurationBuilder = new CompositeServiceConfigurationBuilderImpl(assemblyFactory); + compositeReferenceConfigurationBuilder = new CompositeReferenceConfigurationBuilderImpl(assemblyFactory); + compositeBindingURIBuilder = new CompositeBindingURIBuilderImpl(assemblyFactory, scaBindingFactory, interfaceContractMapper, policyDefinitions, monitor); + componentServicePromotionBuilder = new ComponentServicePromotionBuilderImpl(assemblyFactory); + compositeServicePromotionBuilder = new CompositeServicePromotionBuilderImpl(assemblyFactory); + compositePromotionBuilder = new CompositePromotionBuilderImpl(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + compositePolicyBuilder = new CompositePolicyBuilderImpl(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + componentServiceBindingBuilder = new ComponentServiceBindingBuilderImpl(monitor); + componentReferenceBindingBuilder = new ComponentReferenceBindingBuilderImpl(monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Collect and fuse includes + compositeIncludeBuilder.build(composite); + + // Expand nested composites + compositeCloneBuilder.build(composite); + + // Configure all components + componentConfigurationBuilder.build(composite); + + // Connect composite services/references to promoted services/references + compositePromotionBuilder.build(composite); + + // Compute the policies across the model hierarchy + compositePolicyBuilder.build(composite); + + // Configure composite services + compositeServiceConfigurationBuilder.build(composite); + + // Configure composite references + compositeReferenceConfigurationBuilder.build(composite); + + // Configure binding URIs + compositeBindingURIBuilder.build(composite); + + // Create promoted component services + componentServicePromotionBuilder.build(composite); + + // Create promoted composite services + compositeServicePromotionBuilder.build(composite); + + // Build component service binding-related information + componentServiceBindingBuilder.build(composite); + + // Wire the components + componentReferenceWireBuilder.build(composite); + + // Wire the promoted component references + componentReferencePromotionWireBuilder.build(composite); + + // Wire the composite references + compositeReferenceWireBuilder.build(composite); + + // Build component reference binding-related information + componentReferenceBindingBuilder.build(composite); + + // Fuse nested composites + //FIXME do this later + //cloneBuilder.fuseCompositeImplementations(composite); + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java new file mode 100644 index 0000000000..5779ddbc78 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java @@ -0,0 +1,118 @@ +/* + * 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.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that clones nested composites. + * + * @version $Rev$ $Date$ + */ +public class CompositeCloneBuilderImpl implements CompositeBuilder { + + public CompositeCloneBuilderImpl(Monitor monitor) { + } + + public void build(Composite composite) throws CompositeBuilderException { + expandCompositeImplementations(composite); + } + + /** + * Expand composite component implementations. + * + * @param composite + * @param problems + */ + private void expandCompositeImplementations(Composite composite) { + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + Composite compositeImplementation = (Composite)implementation; + Composite clone; + try { + clone = (Composite)compositeImplementation.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + component.setImplementation(clone); + expandCompositeImplementations(clone); + } + } + } + + /** + * Collect all nested composite implementations in a graph of composites. + * + * @param composite + * @param nested + */ + private void collectNestedComposites(Composite composite, List<Composite> nested) { + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + Composite nestedComposite = (Composite)implementation; + nested.add(nestedComposite); + collectNestedComposites(nestedComposite, nested); + } + } + } + + /** + * Fuse nested composites into a top level composite. + * + * @param composite + */ + private void fuseCompositeImplementations(Composite composite) { + + // First collect all nested composites + List<Composite> nested = new ArrayList<Composite>(); + collectNestedComposites(composite, nested); + + // Then add all the non-composite components they contain + for (Composite nestedComposite : nested) { + for (Component component: nestedComposite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (!(implementation instanceof Composite)) { + composite.getComponents().add(component); + } + } + } + + // Clear the initial list of composite components + for (Iterator<Component> i = composite.getComponents().iterator(); i.hasNext();) { + Component component = i.next(); + if (component.getImplementation() instanceof Composite) { + i.remove(); + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java new file mode 100644 index 0000000000..539ad8d137 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java @@ -0,0 +1,110 @@ +/* + * 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.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * Implementation of a CompositeBuilder. + * + * @version $Rev$ $Date$ + */ +public class CompositeIncludeBuilderImpl implements CompositeBuilder { + + private Monitor monitor; + + public CompositeIncludeBuilderImpl(Monitor monitor) { + this.monitor = monitor; + } + + public void build(Composite composite) throws CompositeBuilderException { + fuseIncludes(composite); + } + + private void warning(String message, Object model, String... messageParameters) { + if (monitor != null){ + Problem problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Collect all includes in a graph of includes. + * + * @param composite + * @param includes + */ + private void collectIncludes(Composite composite, List<Composite> includes, Set<Composite> visited) { + for (Composite include : composite.getIncludes()) { + if (visited.contains(include)) { + warning("CompositeAlreadyIncluded", composite, include.getName().toString()); + continue; + } + + includes.add(include); + visited.add(include); + collectIncludes(include, includes, visited); + } + } + + /** + * Copy a list of includes into a composite. + * + * @param composite + */ + private void fuseIncludes(Composite composite) { + + // First collect all includes + List<Composite> includes = new ArrayList<Composite>(); + Set<Composite> visited = new HashSet<Composite>(); + visited.add(composite); + collectIncludes(composite, includes, visited); + // Then clone them + for (Composite include : includes) { + Composite clone; + try { + clone = (Composite)include.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + composite.getComponents().addAll(clone.getComponents()); + composite.getServices().addAll(clone.getServices()); + composite.getReferences().addAll(clone.getReferences()); + composite.getProperties().addAll(clone.getProperties()); + composite.getWires().addAll(clone.getWires()); + composite.getPolicySets().addAll(clone.getPolicySets()); + composite.getRequiredIntents().addAll(clone.getRequiredIntents()); + } + + // Clear the list of includes + composite.getIncludes().clear(); + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePolicyBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePolicyBuilderImpl.java new file mode 100644 index 0000000000..76ed861167 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePolicyBuilderImpl.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that computes policy sets based on attached intents and policy sets. + * Useful if you want to build the model without making any runtime decisions such as + * reference/services matching + * + * @version $Rev$ $Date$ + */ +public class CompositePolicyBuilderImpl extends BaseWireBuilderImpl implements CompositeBuilder { + + public CompositePolicyBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, InterfaceContractMapper interfaceContractMapper, Monitor monitor) { + super(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + computePolicies(composite); + } +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePromotionBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePromotionBuilderImpl.java new file mode 100644 index 0000000000..5a6437b3a3 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositePromotionBuilderImpl.java @@ -0,0 +1,46 @@ +/* + * 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 org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that makes the connections between composite services and references + * and the services and references that they promote + * + * @version $Rev$ $Date$ + */ +public class CompositePromotionBuilderImpl extends BaseWireBuilderImpl implements CompositeBuilder { + + public CompositePromotionBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, InterfaceContractMapper interfaceContractMapper, Monitor monitor) { + super(assemblyFactory, endpointFactory, interfaceContractMapper, monitor); + } + + public void build(Composite composite) throws CompositeBuilderException { + connectCompositeReferencesAndServices(composite); + } +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceConfigurationBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceConfigurationBuilderImpl.java new file mode 100644 index 0000000000..41462b151d --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceConfigurationBuilderImpl.java @@ -0,0 +1,224 @@ +/* + * 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 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.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.AutomaticBinding; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; + +/** + * A composite builder that handles the configuration of composite references. + * + * @version $Rev: 651179 $ $Date: 2008-04-24 08:21:13 +0100 (Thu, 24 Apr 2008) $ + */ +public class CompositeReferenceConfigurationBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + + public CompositeReferenceConfigurationBuilderImpl(AssemblyFactory assemblyFactory) { + this.assemblyFactory = assemblyFactory; + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Process nested composites recursively + configureNestedCompositeReferences(composite); + + // Process top level composite references + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + + // Get the next lower level promoted reference + List<ComponentReference> promotedRefs = compositeReference.getPromotedReferences(); + if (!promotedRefs.isEmpty()) { + if (promotedRefs.size() == 1) { + ComponentReference promotedReference = promotedRefs.get(0); + + // Set the bindings using the top level bindings to override the lower level bindings + if (bindingsSpecifiedManually(compositeReference.getBindings())) { + compositeReference.setPromotionOverride(true); + } else if (bindingsSpecifiedManually(promotedReference.getBindings()) ) { + compositeReference.getBindings().clear(); + for (Binding binding : promotedReference.getBindings()) { + try { + compositeReference.getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted reference + } + } + } + if (compositeReference.getInterfaceContract() != null && + compositeReference.getInterfaceContract().getCallbackInterface() != null) { + if (compositeReference.getCallback() != null && + bindingsSpecifiedManually(compositeReference.getCallback().getBindings())) { + compositeReference.setPromotionOverride(true); + } else if (promotedReference.getCallback() != null && + bindingsSpecifiedManually(promotedReference.getCallback().getBindings())) { + if (compositeReference.getCallback() != null) { + compositeReference.getCallback().getBindings().clear(); + } else { + compositeReference.setCallback(assemblyFactory.createCallback()); + } + for (Binding binding : promotedReference.getCallback().getBindings()) { + try { + compositeReference.getCallback().getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted reference + } + } + } + } + } else { + // This composite reference promotes multiple component references. + // Because the component reference bindings can all be different, we don't + // copy any of them up to this composite reference, which will therefore always + // have its own binding, even if it's only the default SCA binding. + if (bindingsSpecifiedManually(compositeReference.getBindings()) || + (compositeReference.getCallback() != null && + bindingsSpecifiedManually(compositeReference.getCallback().getBindings()))) { + compositeReference.setPromotionOverride(true); + } + } + } + } + } + + private void configureNestedCompositeReferences(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // First process nested composites + configureNestedCompositeReferences((Composite)implementation); + + // Process the component references declared on components in this composite + for (ComponentReference componentReference : component.getReferences()) { + Reference implReference = componentReference.getReference(); + if (implReference != null && implReference instanceof CompositeReference) { + CompositeReference compositeReference = (CompositeReference)implReference; + + // Get the next lower level promoted reference + List<ComponentReference> promotedRefs = compositeReference.getPromotedReferences(); + if (!promotedRefs.isEmpty()) { + if (promotedRefs.size() == 1) { + ComponentReference promotedReference = promotedRefs.get(0); + + // Set the bindings using the top level bindings to override the lower level bindings + if (!bindingsSpecifiedManually(compositeReference.getBindings()) && + bindingsSpecifiedManually(promotedReference.getBindings()) ) { + compositeReference.getBindings().clear(); + for (Binding binding : promotedReference.getBindings()) { + try { + compositeReference.getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted reference + } + } + } + if (bindingsSpecifiedManually(componentReference.getBindings())) { + componentReference.setPromotionOverride(true); + } else if (bindingsSpecifiedManually(compositeReference.getBindings()) ) { + componentReference.getBindings().clear(); + componentReference.getBindings().addAll(compositeReference.getBindings()); + } + if (componentReference.getInterfaceContract() != null && + componentReference.getInterfaceContract().getCallbackInterface() != null) { + if (!(compositeReference.getCallback() != null && + bindingsSpecifiedManually(compositeReference.getCallback().getBindings())) && + promotedReference.getCallback() != null && + bindingsSpecifiedManually(promotedReference.getCallback().getBindings())) { + if (compositeReference.getCallback() != null) { + compositeReference.getCallback().getBindings().clear(); + } else { + compositeReference.setCallback(assemblyFactory.createCallback()); + } + compositeReference.getCallback().getBindings().addAll( + promotedReference.getCallback().getBindings()); + } + if (componentReference.getCallback() != null && + bindingsSpecifiedManually(componentReference.getCallback().getBindings())) { + componentReference.setPromotionOverride(true); + } else if (compositeReference.getCallback() != null && + bindingsSpecifiedManually(compositeReference.getCallback().getBindings())) { + if (componentReference.getCallback() != null) { + componentReference.getCallback().getBindings().clear(); + } else { + componentReference.setCallback(assemblyFactory.createCallback()); + } + for (Binding binding : compositeReference.getCallback().getBindings()) { + try { + componentReference.getCallback().getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted reference + } + } + } + } + } else { + // This component reference promotes multiple lower-level component references. + // Because the lower-level component reference bindings can all be different, + // we don't copy any of them up to this component reference, which will therefore + // always have its own binding, even if it's only the default SCA binding. + if (bindingsSpecifiedManually(componentReference.getBindings()) || + (componentReference.getCallback() != null && + bindingsSpecifiedManually(componentReference.getCallback().getBindings()))) { + componentReference.setPromotionOverride(true); + } + } + } + } + } + } + } + } + + /** + * If the bindings are specified in the composite file return true as they should + * otherwise return false + * + * @param bindings + * @return true if the bindings were specified manually + */ + private boolean bindingsSpecifiedManually(List<Binding> bindings) { + + if (bindings.size() > 1) { + return true; + } else if (bindings.size() == 1 && + bindings.get(0) instanceof AutomaticBinding && + ((AutomaticBinding)bindings.get(0)).getIsAutomatic()) { + return false; + } else if (bindings.size() == 1) { + return true; + } else { + return false; + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceWireBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceWireBuilderImpl.java new file mode 100644 index 0000000000..8aa1897311 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeReferenceWireBuilderImpl.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that wires composite references. + * + * @version $Rev$ $Date$ + */ +public class CompositeReferenceWireBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + private EndpointFactory endpointFactory; + private Monitor monitor; + + public CompositeReferenceWireBuilderImpl(AssemblyFactory assemblyFactory, EndpointFactory endpointFactory, Monitor monitor) { + this.assemblyFactory = assemblyFactory; + this.endpointFactory = endpointFactory; + this.monitor = monitor; + } + + /** + * Wire composite references in a deployment composite. + * + * @param composite + */ + public void build(Composite composite) throws CompositeBuilderException { + + // Process composite references declared in this composite + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + + // If the composite reference is a promotion override, override the + // configuration of the promoted reference. + //FIXME: Policy configuration or wiring of domain-level composite references + // doesn't cause a promotion override, unless the composite reference has + // additional bindings. Do we need to detect this and force an override? + if (compositeReference.isPromotionOverride()) { + List<ComponentReference> promotedReferences = + ReferenceConfigurationUtil.getPromotedComponentReferences(compositeReference); + for (ComponentReference promotedReference : promotedReferences) { + ReferenceConfigurationUtil.reconcileReferenceBindings( + compositeReference, promotedReference, assemblyFactory, endpointFactory, monitor); + if (compositeReference.getInterfaceContract() != null && // can be null in unit tests + compositeReference.getInterfaceContract().getCallbackInterface() != null) { + SCABinding scaCallbackBinding = promotedReference.getCallbackBinding(SCABinding.class); + if (promotedReference.getCallback() != null) { + promotedReference.getCallback().getBindings().clear(); + } else { + promotedReference.setCallback(assemblyFactory.createCallback()); + } + if (scaCallbackBinding != null) { + promotedReference.getCallback().getBindings().add(scaCallbackBinding); + } + if (compositeReference.getCallback() != null) { + promotedReference.getCallback().getBindings().addAll(compositeReference.getCallback() + .getBindings()); + } + } + } + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceBindingBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceBindingBuilderImpl.java new file mode 100644 index 0000000000..51e2da2d64 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceBindingBuilderImpl.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilderExtension; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.monitor.Monitor; + +/** + * A composite builder that performs any additional building steps that + * composite service bindings may need. Used for WSDL generation. + * + * @version $Rev$ $Date$ + */ +public class CompositeServiceBindingBuilderImpl implements CompositeBuilder { + private Monitor monitor; + + public CompositeServiceBindingBuilderImpl(Monitor monitor) { + this.monitor = monitor; + } + + public void build(Composite composite) throws CompositeBuilderException { + buildServiceBindings(composite); + } + + private void buildServiceBindings(Composite composite) { + + // build bindings recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + buildServiceBindings((Composite)implementation); + } + } + + // find all the composite service bindings + for (Service service : composite.getServices()) { + for (Binding binding : service.getBindings()) { + if (binding instanceof BindingBuilderExtension) { + Component component = ServiceConfigurationUtil.getPromotedComponent((CompositeService)service); + ((BindingBuilderExtension)binding).getBuilder().build(component, service, binding, monitor); + } + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceConfigurationBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceConfigurationBuilderImpl.java new file mode 100644 index 0000000000..a3f31ea2fa --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServiceConfigurationBuilderImpl.java @@ -0,0 +1,194 @@ +/* + * 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 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.Service; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.AutomaticBinding; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; + +/** + * A composite builder that handles the configuration of composite services. + * + * @version $Rev$ $Date$ + */ +public class CompositeServiceConfigurationBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + + public CompositeServiceConfigurationBuilderImpl(AssemblyFactory assemblyFactory) { + this.assemblyFactory = assemblyFactory; + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Process nested composites recursively + configureNestedCompositeServices(composite); + + // Process top level composite services + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + + // Get the next lower level promoted service + ComponentService promotedService = compositeService.getPromotedService(); + if (promotedService != null) { + + // Set the bindings using the top level bindings to override the lower level bindings + if (!bindingsSpecifiedManually(compositeService.getBindings()) && + bindingsSpecifiedManually(promotedService.getBindings())) { + compositeService.getBindings().clear(); + for (Binding binding : promotedService.getBindings()) { + try { + compositeService.getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted service + } + } + } + if (compositeService.getInterfaceContract() != null && + compositeService.getInterfaceContract().getCallbackInterface() != null) { + if (!(compositeService.getCallback() != null && + bindingsSpecifiedManually(compositeService.getCallback().getBindings())) && + promotedService.getCallback() != null && + bindingsSpecifiedManually(promotedService.getCallback().getBindings())) { + if (compositeService.getCallback() != null) { + compositeService.getCallback().getBindings().clear(); + } else { + compositeService.setCallback(assemblyFactory.createCallback()); + } + for (Binding binding : promotedService.getCallback().getBindings()) { + try { + compositeService.getCallback().getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted service + } + } + } + } + } + } + } + + private void configureNestedCompositeServices(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // First process nested composites + configureNestedCompositeServices((Composite)implementation); + + // Process the component services declared on components in this composite + for (ComponentService componentService : component.getServices()) { + Service implService = componentService.getService(); + if (implService != null && implService instanceof CompositeService) { + CompositeService compositeService = (CompositeService)implService; + + // Get the next lower level promoted service + ComponentService promotedService = compositeService.getPromotedService(); + if (promotedService != null) { + + // Set the bindings using the top level bindings to override the lower level bindings + if (!bindingsSpecifiedManually(compositeService.getBindings()) && + bindingsSpecifiedManually(promotedService.getBindings()) ) { + compositeService.getBindings().clear(); + for (Binding binding : promotedService.getBindings()) { + try { + compositeService.getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted service + } + } + } + if (!bindingsSpecifiedManually(componentService.getBindings()) && + bindingsSpecifiedManually(compositeService.getBindings()) ) { + componentService.getBindings().clear(); + componentService.getBindings().addAll(compositeService.getBindings()); + } + if (componentService.getInterfaceContract() != null && + componentService.getInterfaceContract().getCallbackInterface() != null) { + if (!(compositeService.getCallback() != null && + bindingsSpecifiedManually(compositeService.getCallback().getBindings())) && + promotedService.getCallback() != null && + bindingsSpecifiedManually(promotedService.getCallback().getBindings())) { + if (compositeService.getCallback() != null) { + compositeService.getCallback().getBindings().clear(); + } else { + compositeService.setCallback(assemblyFactory.createCallback()); + } + for (Binding binding : promotedService.getCallback().getBindings()) { + try { + compositeService.getCallback().getBindings().add((Binding)binding.clone()); + } catch (CloneNotSupportedException ex) { + // this binding can't be used in the promoted service + } + } + } + if (!(componentService.getCallback() != null && + bindingsSpecifiedManually(componentService.getCallback().getBindings())) && + compositeService.getCallback() != null && + bindingsSpecifiedManually(compositeService.getCallback().getBindings())) { + if (componentService.getCallback() != null) { + componentService.getCallback().getBindings().clear(); + } else { + componentService.setCallback(assemblyFactory.createCallback()); + } + componentService.getCallback().getBindings().addAll( + compositeService.getCallback().getBindings()); + } + } + } + } + } + } + } + } + + /** + * If the bindings are specified in the composite file return true as they should + * otherwise return false + * + * @param bindings + * @return true if the bindings were specified manually + */ + private boolean bindingsSpecifiedManually(List<Binding> bindings) { + + if (bindings.size() > 1) { + return true; + } else if (bindings.size() == 1 && + bindings.get(0) instanceof AutomaticBinding && + ((AutomaticBinding)bindings.get(0)).getIsAutomatic()) { + return false; + } else if (bindings.size() == 1) { + return true; + } else { + return false; + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServicePromotionBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServicePromotionBuilderImpl.java new file mode 100644 index 0000000000..ea0e88ac24 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeServicePromotionBuilderImpl.java @@ -0,0 +1,77 @@ +/* + * 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 org.apache.tuscany.sca.assembly.AssemblyFactory; +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.Service; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; + +/** + * A composite builder that handles the creation of promoted composite services. + * + * @version $Rev$ $Date$ + */ +public class CompositeServicePromotionBuilderImpl implements CompositeBuilder { + private AssemblyFactory assemblyFactory; + + public CompositeServicePromotionBuilderImpl(AssemblyFactory assemblyFactory) { + this.assemblyFactory = assemblyFactory; + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Process top level composite services + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + + // Get the innermost promoted service + ComponentService promotedService = ServiceConfigurationUtil.getPromotedComponentService(compositeService); + if (promotedService != null) { + Component promotedComponent = ServiceConfigurationUtil.getPromotedComponent(compositeService); + + // Create a new component service to represent this composite + // service on the promoted component + ComponentService newComponentService = assemblyFactory.createComponentService(); + newComponentService.setName("$promoted$" + compositeService.getName()); + promotedComponent.getServices().add(newComponentService); + newComponentService.setService(promotedService.getService()); + newComponentService.getBindings().addAll(compositeService.getBindings()); + newComponentService.setInterfaceContract(compositeService.getInterfaceContract()); + if (compositeService.getInterfaceContract() != null && + compositeService.getInterfaceContract().getCallbackInterface() != null) { + newComponentService.setCallback(assemblyFactory.createCallback()); + newComponentService.getCallback().getBindings() + .addAll(compositeService.getCallback().getBindings()); + } + + // Change the composite service to now promote the newly + // created component service directly + compositeService.setPromotedComponent(promotedComponent); + compositeService.setPromotedService(newComponentService); + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java new file mode 100644 index 0000000000..1698b1a9c7 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/EndpointBuilderImpl.java @@ -0,0 +1,127 @@ +/* + * 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 org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.builder.EndpointBuilder; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * A factory for the Endpoint model. + * + * @version $Rev$ $Date$ + */ +public abstract class EndpointBuilderImpl implements EndpointBuilder { + + private Monitor monitor; + + public EndpointBuilderImpl (Monitor monitor){ + this.monitor = monitor; + } + + private void warning(String message, Object model, String... messageParameters) { + if (monitor != null){ + Problem problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + private void error(String message, Object model, Exception ex) { + if (monitor != null){ + Problem problem = null; + problem = new ProblemImpl(this.getClass().getName(), "assembly-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + /** + * Resolve an endpoint against the provided target information and the + * set of candidate bindings. + */ + public void build(Endpoint endpoint) { + + // If this endpoint is not fully configured then don't try and resolve it + if (endpoint.getTargetComponentService() == null){ + return; + } + + // Does the reference expect callbacks + boolean bidirectional = false; + + if (endpoint.getSourceComponentReference().getInterfaceContract() != null && + endpoint.getSourceComponentReference().getInterfaceContract().getCallbackInterface() != null) { + bidirectional = true; + } + + // if the target service is a promoted service then find the + // service it promotes + if (endpoint.getTargetComponentService().getService() instanceof CompositeService) { + CompositeService compositeService = (CompositeService) endpoint.getTargetComponentService().getService(); + // Find the promoted component service + ComponentService promotedComponentService = ServiceConfigurationUtil.getPromotedComponentService(compositeService); + if (promotedComponentService != null && !promotedComponentService.isUnresolved()) { + endpoint.setTargetComponentService(promotedComponentService); + } + } + + try { + PolicyConfigurationUtil.determineApplicableBindingPolicySets(endpoint.getSourceComponentReference(), + endpoint.getTargetComponentService()); + } catch ( Exception e ) { + error("PolicyRelatedException", endpoint, e); + } + + + // Match the binding against the bindings of the target service + Binding resolvedBinding = BindingConfigurationUtil.matchBinding(endpoint.getTargetComponent(), + endpoint.getTargetComponentService(), + endpoint.getCandidateBindings(), + endpoint.getTargetComponentService().getBindings()); + if (resolvedBinding == null) { + warning("NoMatchingBinding", + endpoint.getSourceComponentReference(), + endpoint.getSourceComponentReference().getName(), + endpoint.getTargetComponentService().getName()); + } else { + endpoint.setSourceBinding(resolvedBinding); + } + + if (bidirectional) { + Binding resolvedCallbackBinding = BindingConfigurationUtil.matchBinding(endpoint.getTargetComponent(), + endpoint.getTargetComponentService(), + endpoint.getSourceComponentReference().getCallback().getBindings(), + endpoint.getTargetComponentService().getCallback().getBindings()); + if (resolvedBinding == null) { + warning("NoMatchingCallbackBinding", + endpoint.getSourceComponentReference(), + endpoint.getSourceComponentReference().getName(), + endpoint.getTargetComponentService().getName()); + } else { + endpoint.setSourceCallbackBinding(resolvedCallbackBinding); + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationException.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationException.java new file mode 100644 index 0000000000..944cf2cf36 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationException.java @@ -0,0 +1,38 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.assembly.builder.impl;
+
+/**
+ * Exception to be throw for invalid policy intents / policysets
+ *
+ * @version $Rev$ $Date$
+ */
+public class PolicyConfigurationException extends Exception {
+ private static final long serialVersionUID = 506979037642587755L;
+
+ public PolicyConfigurationException(String message) {
+ super(message);
+ }
+
+ public PolicyConfigurationException(Throwable e) {
+ super(e);
+ }
+
+}
diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationUtil.java new file mode 100644 index 0000000000..c0bc18dfaf --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyConfigurationUtil.java @@ -0,0 +1,752 @@ +/*
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ConfiguredOperation;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.OperationsConfigurator;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.IntentAttachPoint;
+import org.apache.tuscany.sca.policy.IntentAttachPointType;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
+import org.apache.tuscany.sca.policy.QualifiedIntent;
+import org.apache.tuscany.sca.policy.util.PolicyComputationUtils;
+import org.apache.tuscany.sca.policy.util.PolicyValidationException;
+import org.apache.tuscany.sca.policy.util.PolicyValidationUtils;
+
+/**
+ * This class contains policy computation methods common to computing implementation and binding policies
+ *
+ * @version $Rev$ $Date$
+ */
+abstract class PolicyConfigurationUtil {
+
+ private static List<Intent> computeInheritableIntents(IntentAttachPointType attachPointType,
+ List<Intent> inheritableIntents) throws PolicyValidationException {
+ List<Intent> validInheritableIntents = new ArrayList<Intent>();
+
+ //expand profile intents in inherited intents
+ PolicyComputationUtils.expandProfileIntents(inheritableIntents);
+
+ //validate if inherited intent applies to the attachpoint (binding / implementation) and
+ //only add such intents to the attachpoint (binding / implementation)
+ for (Intent intent : inheritableIntents) {
+ if ( !intent.isUnresolved() ) {
+ for (QName constrained : intent.getConstrains()) {
+ if ( PolicyValidationUtils.isConstrained(constrained, attachPointType)) {
+ validInheritableIntents.add(intent);
+ break;
+ }
+ }
+ } else {
+ throw new PolicyValidationException("Policy Intent '" + intent.getName() + "' is not defined in this domain");
+ }
+ }
+
+ return validInheritableIntents;
+ }
+
+ private static void normalizeIntents(IntentAttachPoint intentAttachPoint) {
+ //expand profile intents specified in the attachpoint (binding / implementation)
+ PolicyComputationUtils.expandProfileIntents(intentAttachPoint.getRequiredIntents());
+
+ //remove duplicates and ...
+ //where qualified form of intent exists retain it and remove the qualifiable intent
+ filterDuplicatesAndQualifiableIntents(intentAttachPoint);
+ }
+
+ private static void trimInherentlyProvidedIntents(IntentAttachPointType attachPointType, List<Intent>intents) {
+ //exclude intents that are inherently supported by the
+ //attachpoint-type (binding-type / implementation-type)
+ List<Intent> requiredIntents = new ArrayList<Intent>(intents);
+ for ( Intent intent : requiredIntents ) {
+ if ( isProvidedInherently(attachPointType, intent) ) {
+ intents.remove(intent);
+ }
+ }
+ }
+
+
+ static void computeIntentsForOperations(IntentAttachPoint intentAttachPoint) throws PolicyValidationException {
+ if ( intentAttachPoint instanceof OperationsConfigurator ) {
+ computeIntentsForOperations((OperationsConfigurator)intentAttachPoint,
+ intentAttachPoint,
+ intentAttachPoint.getRequiredIntents());
+ }
+ }
+
+ private static void computeIntentsForOperations(OperationsConfigurator opConfigurator,
+ IntentAttachPoint intentAttachPoint,
+ List<Intent> parentIntents) throws PolicyValidationException {
+ IntentAttachPointType attachPointType = intentAttachPoint.getType();
+
+ boolean found = false;
+ for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) {
+ //expand profile intents specified on operations
+ PolicyComputationUtils.expandProfileIntents(confOp.getRequiredIntents());
+
+ //validateIntents(confOp, attachPointType);
+
+ //add intents specified for parent intent attach point (binding / implementation)
+ //wherever its not overridden in the operation
+ Intent tempIntent = null;
+ List<Intent> attachPointOpIntents = new ArrayList<Intent>();
+ for (Intent anIntent : parentIntents) {
+ found = false;
+
+ tempIntent = anIntent;
+ while ( tempIntent instanceof QualifiedIntent ) {
+ tempIntent = ((QualifiedIntent)tempIntent).getQualifiableIntent();
+ }
+
+ for ( Intent opIntent : confOp.getRequiredIntents() ) {
+ if ( opIntent.getName().getLocalPart().startsWith(tempIntent.getName().getLocalPart())) {
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found ) {
+ boolean conflict = false;
+ for (Intent excluded : anIntent.getExcludedIntents()) {
+ if (confOp.getRequiredIntents().contains(excluded)) {
+ conflict = true;
+ break;
+ }
+ }
+ if (!conflict) {
+ attachPointOpIntents.add(anIntent);
+ }
+ }
+ }
+
+ confOp.getRequiredIntents().addAll(attachPointOpIntents);
+
+ //remove duplicates and ...
+ //where qualified form of intent exists retain it and remove the qualifiable intent
+ filterDuplicatesAndQualifiableIntents(confOp);
+
+ //exclude intents that are inherently supported by the parent
+ //attachpoint-type (binding-type / implementation-type)
+ if ( attachPointType != null ) {
+ List<Intent> requiredIntents = new ArrayList<Intent>(confOp.getRequiredIntents());
+ for ( Intent intent : requiredIntents ) {
+ if ( isProvidedInherently(attachPointType, intent) ) {
+ confOp.getRequiredIntents().remove(intent);
+ }
+ }
+ }
+ }
+ }
+
+ private static List<PolicySet> computeInheritablePolicySets(List<PolicySet> inheritablePolicySets,
+ List<PolicySet> applicablePolicySets)
+ throws PolicyValidationException {
+ List<PolicySet> validInheritablePolicySets = new ArrayList<PolicySet>();
+ for (PolicySet policySet : inheritablePolicySets) {
+ if ( !policySet.isUnresolved() ) {
+ if ( applicablePolicySets.contains(policySet) ) {
+ validInheritablePolicySets.add(policySet);
+ }
+ } else {
+ throw new PolicyValidationException("Policy Set '" + policySet.getName()
+ + "' is not defined in this domain ");
+ }
+ }
+
+ return validInheritablePolicySets;
+ }
+
+ private static void normalizePolicySets(PolicySetAttachPoint policySetAttachPoint ) {
+ //get rid of duplicate entries
+ HashMap<QName, PolicySet> policySetTable = new HashMap<QName, PolicySet>();
+ for ( PolicySet policySet : policySetAttachPoint.getPolicySets() ) {
+ policySetTable.put(policySet.getName(), policySet);
+ }
+
+ policySetAttachPoint.getPolicySets().clear();
+ policySetAttachPoint.getPolicySets().addAll(policySetTable.values());
+
+ //expand profile intents
+ for ( PolicySet policySet : policySetAttachPoint.getPolicySets() ) {
+ PolicyComputationUtils.expandProfileIntents(policySet.getProvidedIntents());
+ }
+ }
+
+ private static void computePolicySetsForOperations(List<PolicySet> applicablePolicySets,
+ PolicySetAttachPoint policySetAttachPoint)
+ throws PolicyValidationException {
+ if ( policySetAttachPoint instanceof OperationsConfigurator ) {
+ computePolicySetsForOperations(applicablePolicySets,
+ (OperationsConfigurator)policySetAttachPoint,
+ policySetAttachPoint);
+ }
+
+ }
+
+ private static void computePolicySetsForOperations(List<PolicySet> applicablePolicySets,
+ OperationsConfigurator opConfigurator,
+ PolicySetAttachPoint policySetAttachPoint)
+ throws PolicyValidationException {
+ //String appliesTo = null;
+ //String scdlFragment = "";
+ HashMap<QName, PolicySet> policySetTable = new HashMap<QName, PolicySet>();
+ IntentAttachPointType attachPointType = policySetAttachPoint.getType();
+
+ for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) {
+ //validate policysets specified for the attachPoint
+ for (PolicySet policySet : confOp.getPolicySets()) {
+ if ( !policySet.isUnresolved() ) {
+ //appliesTo = policySet.getAppliesTo();
+
+ //if (!PolicyValidationUtils.isPolicySetApplicable(scdlFragment, appliesTo, attachPointType)) {
+ if (!applicablePolicySets.contains(policySet)) {
+ throw new PolicyValidationException("Policy Set '" + policySet.getName()
+ + " specified for operation " + confOp.getName()
+ + "' does not constrain extension type "
+ + attachPointType.getName());
+
+ }
+ } else {
+ throw new PolicyValidationException("Policy Set '" + policySet.getName()
+ + " specified for operation " + confOp.getName()
+ + "' is not defined in this domain ");
+ }
+ }
+
+ //get rid of duplicate entries
+ for ( PolicySet policySet : confOp.getPolicySets() ) {
+ policySetTable.put(policySet.getName(), policySet);
+ }
+
+ confOp.getPolicySets().clear();
+ confOp.getPolicySets().addAll(policySetTable.values());
+ policySetTable.clear();
+
+ //expand profile intents
+ for ( PolicySet policySet : confOp.getPolicySets() ) {
+ PolicyComputationUtils.expandProfileIntents(policySet.getProvidedIntents());
+ }
+ }
+ }
+
+
+ private static void trimProvidedIntents(List<Intent> requiredIntents, List<PolicySet> policySets) {
+ for ( PolicySet policySet : policySets ) {
+ trimProvidedIntents(requiredIntents, policySet);
+ }
+ }
+
+ private static void determineApplicableDomainPolicySets(List<PolicySet> applicablePolicySets,
+ PolicySetAttachPoint policySetAttachPoint,
+ IntentAttachPointType intentAttachPointType) {
+
+ if (policySetAttachPoint.getRequiredIntents().size() > 0) {
+
+ // form a list of all intents required by the attach point
+ List<Intent> combinedTargetIntents = new ArrayList<Intent>();
+ combinedTargetIntents.addAll(policySetAttachPoint.getRequiredIntents());
+ for (PolicySet targetPolicySet : policySetAttachPoint.getPolicySets()) {
+ combinedTargetIntents.addAll(PolicyComputationUtils.findAndExpandProfileIntents(targetPolicySet.getProvidedIntents()));
+ }
+
+ //since the set of applicable policysets for this attachpoint is known
+ //we only need to check in that list if there is a policyset that matches
+ for (PolicySet policySet : applicablePolicySets) {
+ // do not use the policy set if it provides intents that conflict with required intents
+ boolean conflict = false;
+ List<Intent> providedIntents = PolicyComputationUtils.findAndExpandProfileIntents(policySet.getProvidedIntents());
+ checkConflict: for (Intent intent : providedIntents) {
+ for (Intent excluded : intent.getExcludedIntents()) {
+ if (combinedTargetIntents.contains(excluded)) {
+ conflict = true;
+ break checkConflict;
+ }
+ }
+ }
+ if (conflict)
+ continue;
+ int prevSize = policySetAttachPoint.getRequiredIntents().size();
+ trimProvidedIntents(policySetAttachPoint.getRequiredIntents(), policySet);
+ // if any intent was trimmed off, then this policyset must
+ // be attached to the intent attachpoint's policyset
+ if (prevSize != policySetAttachPoint.getRequiredIntents().size()) {
+ policySetAttachPoint.getPolicySets().add(policySet);
+ }
+ }
+ }
+ }
+
+ private static boolean isProvidedInherently(IntentAttachPointType attachPointType, Intent intent) {
+ return ( attachPointType != null &&
+ (( attachPointType.getAlwaysProvidedIntents() != null &&
+ attachPointType.getAlwaysProvidedIntents().contains(intent) ) ||
+ ( attachPointType.getMayProvideIntents() != null &&
+ attachPointType.getMayProvideIntents().contains(intent) )
+ ) );
+ }
+
+ private static void trimProvidedIntents(List<Intent> requiredIntents, PolicySet policySet) {
+ for ( Intent providedIntent : policySet.getProvidedIntents() ) {
+ if ( requiredIntents.contains(providedIntent) ) {
+ requiredIntents.remove(providedIntent);
+ }
+ }
+
+ for ( Intent mappedIntent : policySet.getMappedPolicies().keySet() ) {
+ if ( requiredIntents.contains(mappedIntent) ) {
+ requiredIntents.remove(mappedIntent);
+ }
+ }
+ }
+
+ private static void filterDuplicatesAndQualifiableIntents(IntentAttachPoint intentAttachPoint) {
+ //remove duplicates
+ Map<QName, Intent> intentsTable = new HashMap<QName, Intent>();
+ for ( Intent intent : intentAttachPoint.getRequiredIntents() ) {
+ intentsTable.put(intent.getName(), intent);
+ }
+
+ //where qualified form of intent exists retain it and remove the qualifiable intent
+ Map<QName, Intent> intentsTableCopy = new HashMap<QName, Intent>(intentsTable);
+ //if qualified form of intent exists remove the unqualified form
+ for ( Intent intent : intentsTableCopy.values() ) {
+ if ( intent instanceof QualifiedIntent ) {
+ QualifiedIntent qualifiedIntent = (QualifiedIntent)intent;
+ if ( intentsTable.get(qualifiedIntent.getQualifiableIntent().getName()) != null ) {
+ intentsTable.remove(qualifiedIntent.getQualifiableIntent().getName());
+ }
+ }
+ }
+ intentAttachPoint.getRequiredIntents().clear();
+ intentAttachPoint.getRequiredIntents().addAll(intentsTable.values());
+ }
+
+ private static void validateIntents(ConfiguredOperation confOp, IntentAttachPointType attachPointType) throws PolicyValidationException {
+ boolean found = false;
+ if ( attachPointType != null ) {
+ //validate intents specified against the parent (binding / implementation)
+ found = false;
+ for (Intent intent : confOp.getRequiredIntents()) {
+ if ( !intent.isUnresolved() ) {
+ for (QName constrained : intent.getConstrains()) {
+ if (PolicyValidationUtils.isConstrained(constrained, attachPointType)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ throw new PolicyValidationException("Policy Intent '" + intent.getName()
+ + " specified for operation " + confOp.getName()
+ + "' does not constrain extension type "
+ + attachPointType.getName());
+ }
+ } else {
+ throw new PolicyValidationException("Policy Intent '" + intent.getName()
+ + " specified for operation " + confOp.getName()
+ + "' is not defined in this domain ");
+ }
+ }
+ }
+ }
+
+ static void computeBindingIntentsAndPolicySets(Contract contract) throws PolicyValidationException {
+ for (Binding binding : contract.getBindings()) {
+ if (binding instanceof PolicySetAttachPoint) {
+ PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)binding;
+ computeIntents((IntentAttachPoint)binding, contract.getRequiredIntents());
+
+ aggregateAndPruneApplicablePolicySets(contract.getApplicablePolicySets(),
+ policiedBinding.getApplicablePolicySets());
+
+ computePolicySets(policiedBinding, contract.getPolicySets());
+
+ PolicyComputationUtils.checkForMutuallyExclusiveIntents(
+ policiedBinding.getRequiredIntents(),
+ policiedBinding.getPolicySets(),
+ policiedBinding.getType(),
+ contract.getName());
+
+ if ( binding instanceof OperationsConfigurator &&
+ contract instanceof OperationsConfigurator ) {
+ //add or merge service operations to the binding
+ addInheritedOpConfOnBindings((OperationsConfigurator)contract,
+ (OperationsConfigurator)binding,
+ (PolicySetAttachPoint)binding);
+
+ computeIntentsForOperations((IntentAttachPoint)binding);
+ computePolicySetsForOperations(contract.getApplicablePolicySets(),
+ policiedBinding);
+
+ for ( ConfiguredOperation confOp : ((OperationsConfigurator)binding).getConfiguredOperations() ) {
+ PolicyComputationUtils.checkForMutuallyExclusiveIntents(
+ confOp.getRequiredIntents(),
+ confOp.getPolicySets(),
+ policiedBinding.getType(),
+ contract.getName() + "." + confOp.getName());
+ }
+
+ }
+ }
+ }
+
+ if ( contract.getCallback() != null ) {
+ for (Binding binding : contract.getCallback().getBindings()) {
+ if (binding instanceof PolicySetAttachPoint) {
+ PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)binding;
+ computeIntents((IntentAttachPoint)binding, contract.getCallback().getRequiredIntents());
+
+ aggregateAndPruneApplicablePolicySets(contract.getApplicablePolicySets(),
+ policiedBinding.getApplicablePolicySets());
+
+ computePolicySets(policiedBinding, contract.getCallback().getPolicySets());
+
+ PolicyComputationUtils.checkForMutuallyExclusiveIntents(
+ policiedBinding.getRequiredIntents(),
+ policiedBinding.getPolicySets(),
+ policiedBinding.getType(),
+ contract.getName() + " callback");
+
+ }
+ }
+ }
+ }
+
+ private static void computeIntents(IntentAttachPoint policiedBinding, List<Intent> inheritedIntents)
+ throws PolicyValidationException {
+ //since the parent component could also contain intents that apply to implementation
+ //and binding elements within, we filter out only those that apply to this binding type
+ List<Intent> prunedIntents = computeInheritableIntents(policiedBinding.getType(),
+ inheritedIntents);
+ policiedBinding.getRequiredIntents().addAll(prunedIntents);
+
+ normalizeIntents(policiedBinding);
+ }
+
+ private static void computePolicySets(PolicySetAttachPoint policiedBinding,
+ List<PolicySet> inheritedPolicySets) throws PolicyValidationException {
+
+ List<PolicySet> prunedPolicySets = computeInheritablePolicySets(inheritedPolicySets,
+ policiedBinding.getApplicablePolicySets());
+ policiedBinding.getPolicySets().addAll(prunedPolicySets);
+ normalizePolicySets(policiedBinding);
+ }
+
+ static void determineApplicableBindingPolicySets(Contract source, Contract target) throws PolicyConfigurationException {
+ List<Intent> intentsCopy = null;
+ for (Binding aBinding : source.getBindings()) {
+ if (aBinding instanceof PolicySetAttachPoint) {
+ PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)aBinding;
+ IntentAttachPointType bindingType = policiedBinding.getType();
+
+
+ intentsCopy = new ArrayList<Intent>(policiedBinding.getRequiredIntents());
+ // add the target component's intents to the reference binding
+ if (target != null) {
+ for (Intent intent : target.getRequiredIntents()) {
+ if (!policiedBinding.getRequiredIntents().contains(intent)) {
+ for (QName constrained : intent.getConstrains()) {
+ if (bindingType != null && bindingType.getName().getNamespaceURI()
+ .equals(constrained.getNamespaceURI())
+ && bindingType.getName().getLocalPart().startsWith(constrained
+ .getLocalPart())) {
+ policiedBinding.getRequiredIntents().add(intent);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //trim intents specified in operations. First check for policysets specified on the operation
+ //and then in the parent implementation
+ if ( aBinding instanceof OperationsConfigurator ) {
+ OperationsConfigurator opConfigurator = (OperationsConfigurator)aBinding;
+
+ for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) {
+ List<Intent> opsIntentsCopy = new ArrayList<Intent>(confOp.getRequiredIntents());
+
+ trimInherentlyProvidedIntents(policiedBinding.getType(),
+ confOp.getRequiredIntents());
+ trimProvidedIntents(confOp.getRequiredIntents(), confOp.getPolicySets());
+ trimProvidedIntents(confOp.getRequiredIntents(), policiedBinding.getPolicySets());
+
+ determineApplicableDomainPolicySets(policiedBinding.getApplicablePolicySets(),
+ confOp,
+ policiedBinding.getType());
+
+ if (confOp.getRequiredIntents().size() > 0) {
+ throw new PolicyConfigurationException("The following are unfulfilled intents for operations configured in "
+ + "binding - " + aBinding.getName() + "\nUnfulfilled Intents = " +
+ confOp.getRequiredIntents());
+ }
+
+ //the intents list could have been trimmed when matching for policysets
+ //since the bindings may need the original set of intents we copy that back
+ confOp.getRequiredIntents().clear();
+ confOp.getRequiredIntents().addAll(opsIntentsCopy);
+
+ }
+ }
+
+ trimInherentlyProvidedIntents(policiedBinding.getType(),
+ policiedBinding.getRequiredIntents());
+ trimProvidedIntents(policiedBinding.getRequiredIntents(), policiedBinding
+ .getPolicySets());
+
+ // determine additional policysets that match remaining intents
+ // TODO: resolved to domain policy registry and attach suitable
+ // policy sets to the binding
+ // for now using the SCA Definitions instead of registry
+ // if there are intents that are not provided by any policy set
+ // throw a warning
+ determineApplicableDomainPolicySets(source, policiedBinding);
+
+ //the intents list could have been trimmed when matching for policysets
+ //since the bindings may need the original set of intents we copy that back
+ policiedBinding.getRequiredIntents().clear();
+ policiedBinding.getRequiredIntents().addAll(intentsCopy);
+
+ }
+ }
+ }
+
+ private static void determineApplicableDomainPolicySets(Contract contract,
+ PolicySetAttachPoint policiedBinding)
+ throws PolicyConfigurationException {
+ //if ( domainPolicySets != null) {
+ determineApplicableDomainPolicySets(policiedBinding.getApplicablePolicySets(),
+ policiedBinding,
+ policiedBinding.getType());
+
+ if ( policiedBinding.getRequiredIntents().size() > 0 ) {
+ if ( contract instanceof Service ) {
+ throw new PolicyConfigurationException("The following are unfulfilled intents for " +
+ "binding in service - " + contract.getName() + "\nUnfulfilled Intents = " +
+ policiedBinding.getRequiredIntents());
+ } else {
+ throw new PolicyConfigurationException("The are unfulfilled intents for " +
+ "binding in reference - " + contract.getName() + "\nUnfulfilled Intents = " +
+ policiedBinding.getRequiredIntents());
+ }
+ }
+ //}
+ }
+
+ private static void addInheritedOpConfOnBindings(OperationsConfigurator source,
+ OperationsConfigurator target,
+ PolicySetAttachPoint attachPoint) throws PolicyValidationException {
+ boolean found = false;
+
+ List<ConfiguredOperation> additionalOperations = new ArrayList<ConfiguredOperation>();
+ for ( ConfiguredOperation sourceConfOp : source.getConfiguredOperations() ) {
+ for ( ConfiguredOperation targetConfOp : target.getConfiguredOperations() ) {
+ if ( sourceConfOp.getName().equals(targetConfOp.getName())) {
+ List<Intent> prunedIntents = computeInheritableIntents(attachPoint.getType(),
+ sourceConfOp.getRequiredIntents());
+ PolicyComputationUtils.addInheritedIntents(prunedIntents,
+ targetConfOp.getRequiredIntents());
+
+ List<PolicySet> prunedPolicySets = computeInheritablePolicySets(sourceConfOp.getPolicySets(),
+ attachPoint.getApplicablePolicySets());
+ PolicyComputationUtils.addInheritedPolicySets(prunedPolicySets, targetConfOp.getPolicySets(), true);
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found ) {
+ additionalOperations.add(sourceConfOp);
+ }
+ }
+
+ if ( !additionalOperations.isEmpty() ) {
+ target.getConfiguredOperations().addAll(additionalOperations);
+ }
+ }
+
+ private static void aggregateAndPruneApplicablePolicySets(List<PolicySet> source, List<PolicySet> target) {
+ target.addAll(source);
+ //strip duplicates
+ Hashtable<QName, PolicySet> policySetTable = new Hashtable<QName, PolicySet>();
+ for ( PolicySet policySet : target ) {
+ policySetTable.put(policySet.getName(), policySet);
+ }
+
+ target.clear();
+ target.addAll(policySetTable.values());
+ }
+
+ static <C extends Contract> void inheritDefaultPolicies(Base parent, List<C> contracts) {
+
+ for (Contract contract : contracts) {
+
+ // The contract inherits default policies from the parent composite/component.
+ if ( parent instanceof PolicySetAttachPoint ) {
+ PolicyComputationUtils.addDefaultPolicies(
+ ((PolicySetAttachPoint)parent).getRequiredIntents(),
+ ((PolicySetAttachPoint)parent).getPolicySets(),
+ contract.getRequiredIntents(),
+ contract.getPolicySets());
+ }
+
+ // The contract's configured operations inherit default policies from the contract.
+ for ( ConfiguredOperation confOp : contract.getConfiguredOperations() ) {
+ PolicyComputationUtils.addDefaultPolicies(
+ contract.getRequiredIntents(),
+ contract.getPolicySets(),
+ confOp.getRequiredIntents(),
+ confOp.getPolicySets());
+ }
+
+ // The contract's callback inherits default policies from the contract.
+ if (contract.getCallback() != null) {
+ PolicyComputationUtils.addDefaultPolicies(
+ contract.getRequiredIntents(),
+ contract.getPolicySets(),
+ contract.getCallback().getRequiredIntents(),
+ contract.getCallback().getPolicySets());
+ }
+
+ }
+ }
+
+ static void computeImplementationIntentsAndPolicySets(Implementation implementation, Component parent)
+ throws PolicyValidationException, PolicyConfigurationException {
+ if ( implementation instanceof PolicySetAttachPoint ) {
+ PolicySetAttachPoint policiedImplementation = (PolicySetAttachPoint)implementation;
+ //since for an implementation the component has its policy intents and policysets its possible
+ //that there are some intents there that does not constrain the implementation.. so prune
+ List<Intent> prunedIntents = computeInheritableIntents(policiedImplementation.getType(),
+ parent.getRequiredIntents());
+ parent.getRequiredIntents().clear();
+ parent.getRequiredIntents().addAll(prunedIntents);
+ normalizeIntents(parent);
+
+ computeIntentsForOperations((OperationsConfigurator)parent,
+ (IntentAttachPoint)implementation,
+ parent.getRequiredIntents());
+
+
+ List<PolicySet> prunedPolicySets = computeInheritablePolicySets(parent.getPolicySets(),
+ parent.getApplicablePolicySets());
+ parent.getPolicySets().clear();
+ parent.getPolicySets().addAll(prunedPolicySets);
+ normalizePolicySets(parent);
+
+ PolicyComputationUtils.checkForMutuallyExclusiveIntents(
+ parent.getRequiredIntents(),
+ parent.getPolicySets(),
+ policiedImplementation.getType(),
+ parent.getName());
+
+ computePolicySetsForOperations(parent.getApplicablePolicySets(),
+ (OperationsConfigurator)parent,
+ (PolicySetAttachPoint)implementation);
+
+ for ( ConfiguredOperation confOp : ((OperationsConfigurator)parent).getConfiguredOperations() ) {
+ PolicyComputationUtils.checkForMutuallyExclusiveIntents(
+ confOp.getRequiredIntents(),
+ confOp.getPolicySets(),
+ policiedImplementation.getType(),
+ parent.getName() + "." + confOp.getName());
+ }
+
+ determineApplicableImplementationPolicySets(parent);
+
+ }
+ }
+
+ private static void determineApplicableImplementationPolicySets(Component component) throws PolicyConfigurationException {
+ List<Intent> intentsCopy = null;
+ if ( component.getImplementation() instanceof PolicySetAttachPoint ) {
+ PolicySetAttachPoint policiedImplementation = (PolicySetAttachPoint)component.getImplementation();
+
+ //trim intents specified in operations. First check for policysets specified on the operation
+ //and then in the parent implementation
+ if ( component instanceof OperationsConfigurator ) {
+ OperationsConfigurator opConfigurator = (OperationsConfigurator)component;
+
+ for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) {
+ intentsCopy = new ArrayList<Intent>(confOp.getRequiredIntents());
+ trimInherentlyProvidedIntents(policiedImplementation.getType(),
+ confOp.getRequiredIntents());
+ trimProvidedIntents(confOp.getRequiredIntents(), confOp.getPolicySets());
+ trimProvidedIntents(confOp.getRequiredIntents(), component.getPolicySets());
+
+ determineApplicableDomainPolicySets(component.getApplicablePolicySets(),
+ confOp,
+ policiedImplementation.getType());
+
+ if (confOp.getRequiredIntents().size() > 0) {
+ throw new PolicyConfigurationException("The following are unfulfilled intents for operations configured in "
+ + "component implementation - " + component.getName() + "\nUnfulfilled Intents = " +
+ confOp.getRequiredIntents());
+ }
+
+ //the intents list could have been trimmed when matching for policysets
+ //since the implementation may need the original set of intents we copy that back
+ confOp.getRequiredIntents().clear();
+ confOp.getRequiredIntents().addAll(intentsCopy);
+ }
+ }
+
+ intentsCopy = new ArrayList<Intent>(component.getRequiredIntents());
+ trimInherentlyProvidedIntents(policiedImplementation.getType(),
+ component.getRequiredIntents());
+ trimProvidedIntents(component.getRequiredIntents(), component.getPolicySets());
+
+ //determine additional policysets that match remaining intents
+ //if there are intents that are not provided by any policy set throw a warning
+ //TODO: resolved to domain policy registry and attach suitable policy sets to the implementation
+ //...for now using the SCA Definitions instead of registry
+ //if ( domainPolicySets != null) {
+ determineApplicableDomainPolicySets(component.getApplicablePolicySets(),
+ component,
+ policiedImplementation.getType());
+
+ if (component.getRequiredIntents().size() > 0) {
+ throw new PolicyConfigurationException("The following are unfulfilled intents for component implementation - " + component
+ .getName() + "\nUnfulfilled Intents = " + component.getRequiredIntents());
+ }
+ //}
+
+ //the intents list could have been trimmed when matching for policysets
+ //since the bindings may need the original set of intents we copy that back
+ component.getRequiredIntents().clear();
+ component.getRequiredIntents().addAll(intentsCopy);
+ }
+ }
+}
diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java new file mode 100644 index 0000000000..e85aec8cea --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java @@ -0,0 +1,273 @@ +/* + * 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.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.w3c.dom.Node; + +/** + * A simple print utility class to help print model instances. + * + * @version $Rev$ $Date$ + */ +class PrintUtil { + private boolean useGetters = false; + private PrintWriter out; + private int indent; + + public PrintUtil(PrintWriter out, boolean useGetters) { + this.out = out; + this.useGetters = useGetters; + } + + public PrintUtil(OutputStream out) { + this.out = new PrintWriter(new OutputStreamWriter(out), true); + } + + void indent() { + for (int i = 0; i < indent; i++) { + out.print(" "); + } + } + + /** + * Print an object. + * + * @param object + */ + public void print(Object object) { + Set<Integer> objects = new HashSet<Integer>(); + print(object, objects); + } + + /** + * Print an object. + * + * @param object + */ + private void print(Object object, Set<Integer> printed) { + if (object == null) { + return; + } + int id = System.identityHashCode(object); + if (printed.contains(id)) { + + // If we've already printed an object, print just it's HashCode + indent(); + out.println(object.getClass().getName() + "@" + id); + } else { + printed.add(id); + try { + + // Print the object class name + indent(); + out.println(object.getClass().getSimpleName() + " {"); + + // Get the object's properties + ValueAccessor accessor = useGetters ? new PropertyAccessor(object) : new FieldAccessor(object); + for (int i = 0; i < accessor.size(); i++) { + try { + + // Get the value of each property + Object value = accessor.getValue(i); + if (value != null) { + + // Convert array value into a list + if (value.getClass().isArray()) { + value = Arrays.asList((Object[])value); + } + + // Print elements in a list + if (value instanceof List) { + if (!((List)value).isEmpty()) { + indent++; + indent(); + out.println(accessor.getName(i) + "= ["); + + // Print each element, recursively + for (Object element : (List)value) { + indent++; + print(element, printed); + indent--; + } + indent(); + out.println(" ]"); + indent--; + } + } else { + Class<?> valueClass = value.getClass(); + + // Print a primitive, java built in type or + // enum, using toString() + if (valueClass.isPrimitive() || valueClass.getName().startsWith("java.") + || valueClass.getName().startsWith("javax.") + || valueClass.isEnum()) { + if (!accessor.getName(i).equals("class")) { + if (!(Boolean.FALSE.equals(value))) { + indent++; + indent(); + out.println(accessor.getName(i) + "=" + value.toString()); + indent--; + } + } + } else if (value instanceof Node) { + indent++; + indent(); + out.println(accessor.getName(i) + "=" + value.toString()); + indent--; + } else { + + // Print an object, recursively + indent++; + indent(); + out.println(accessor.getName(i) + "= {"); + indent++; + print(value, printed); + indent--; + indent(); + out.println("}"); + indent--; + } + } + } + } catch (Exception e) { + } + } + indent(); + out.println("}"); + } catch (Exception e) { + indent(); + out.println(e); + } + } + } + + public static interface ValueAccessor { + int size(); + + String getName(int i); + + Object getValue(int i) throws Exception; + } + + /** + * Java field reflection based value accessor + */ + private static class FieldAccessor implements ValueAccessor { + + private Object object; + private List<Field> fields; + + public FieldAccessor(Object object) { + this.fields = getAllFields(object.getClass()); + this.object = object; + } + + public String getName(int i) { + return fields.get(i).getName(); + } + + public Object getValue(int i) throws Exception { + return fields.get(i).get(object); + } + + public int size() { + return fields.size(); + } + + } + + /** + * JavaBean-based value accessor + */ + private static class PropertyAccessor implements ValueAccessor { + + private Object object; + private PropertyDescriptor[] fields; + + public PropertyAccessor(Object object) throws IntrospectionException { + BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass()); + this.fields = beanInfo.getPropertyDescriptors(); + this.object = object; + } + + public String getName(int i) { + return fields[i].getName(); + } + + public Object getValue(int i) throws Exception { + Method getter = fields[i].getReadMethod(); + if (getter != null) { + return getter.invoke(object); + } + return null; + } + + public int size() { + return fields.length; + } + + } + + /** + * Returns a collection of fields declared by a class + * or one of its supertypes + */ + private static List<Field> getAllFields(Class<?> clazz) { + return getAllFields(clazz, new ArrayList<Field>()); + } + + /** + * Recursively evaluates the type hierarchy to return all fields + */ + private static List<Field> getAllFields(Class<?> clazz, List<Field> fields) { + if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) { + return fields; + } + fields = getAllFields(clazz.getSuperclass(), fields); + Field[] declaredFields = clazz.getDeclaredFields(); + for (final Field field : declaredFields) { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + field.setAccessible(true); // ignore Java accessibility + return null; + } + }); + fields.add(field); + } + return fields; + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java new file mode 100644 index 0000000000..03f24dfae8 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java @@ -0,0 +1,132 @@ +/* + * 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.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; + +import org.apache.tuscany.sca.monitor.Problem; + +/** + * Reports a composite assembly problem. + * + * @version $Rev$ $Date$ + */ +public class ProblemImpl implements Problem { + + private String sourceClassName; + private String bundleName; + private Severity severity; + private Object problemObject; + private String messageId; + private Object[] messageParams; + private Exception cause; + + /** + * Construct a new problem + * + * @param sourceClassName the class name reporting the problem + * @param bundleName the name of the message bundle to use + * @param severity the severity of the problem + * @param problemObject the model object for which the problem is being reported + * @param messageId the id of the problem message + * @param messageParams the parameters of the problem message + */ + public ProblemImpl(String sourceClassName, String bundleName, Severity severity, Object problemObject, String messageId, Object... messageParams ) { + this.sourceClassName = sourceClassName; + this.bundleName = bundleName; + this.severity = severity; + this.problemObject = problemObject; + this.messageId = messageId; + this.messageParams = messageParams; + } + + /** + * Construct a new problem + * + * @param sourceClassName the class name reporting the problem + * @param bundleName the name of the message bundle to use + * @param severity the severity of the problem + * @param problemObject the model object for which the problem is being reported + * @param messageId the id of the problem message + * @param cause the exception which caused the problem + */ + public ProblemImpl(String sourceClassName, String bundleName, Severity severity, Object problemObject, String messageId, Exception cause) { + this.sourceClassName = sourceClassName; + this.bundleName = bundleName; + this.severity = severity; + this.problemObject = problemObject; + this.messageId = messageId; + this.cause = cause; + } + + public String getSourceClassName() { + return sourceClassName; + } + + public String getBundleName() { + return bundleName; + } + + public Severity getSeverity() { + return severity; + } + + public Object getProblemObject() { + return problemObject; + } + + public String getMessageId() { + return messageId; + } + + public Object[] getMessageParams() { + return messageParams; + } + + public Exception getCause() { + return cause; + } + + @Override + public String toString() { + Logger logger = Logger.getLogger(sourceClassName, bundleName); + + LogRecord record = new LogRecord(Level.INFO, messageId); + + if (cause == null){ + record.setParameters(messageParams); + + } else { + Object[] params = new String[1]; + params[0] = cause.toString(); + record.setParameters(params); + } + record.setResourceBundle(logger.getResourceBundle()); + record.setSourceClassName(sourceClassName); + + Formatter formatter = new SimpleFormatter(); + + return formatter.formatMessage(record); + } +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyConfigurationUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyConfigurationUtil.java new file mode 100644 index 0000000000..71971ef5a4 --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyConfigurationUtil.java @@ -0,0 +1,213 @@ +/* + * 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.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +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.Component; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Utility class to deal with processing of component properties that are taking values from the parent + * composite's properties or an external file. + * + * @version $Rev$ $Date$ + */ +abstract class PropertyConfigurationUtil { + private static final DocumentBuilderFactory DOC_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); + + private static Document evaluate(Document node, XPathExpression expression) + throws XPathExpressionException, ParserConfigurationException { + + Node value = node.getDocumentElement(); + Node result = (Node)expression.evaluate(value, XPathConstants.NODE); + if (result == null) { + return null; + } + + // TODO: How to wrap the result into a Document? + Document document = DOC_BUILDER_FACTORY.newDocumentBuilder().newDocument(); + if (result instanceof Document) { + return (Document)result; + } else { + //Element root = document.createElementNS(null, "value"); + //document.appendChild(root); + document.appendChild(document.importNode(result, true)); + return document; + } + } + + private static Document loadFromFile(String file) throws MalformedURLException, IOException, + TransformerException, ParserConfigurationException { + 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(); + + Source streamSource = new SAXSource(new InputSource(is)); + DOMResult result = new DOMResult(); + javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.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); + return document; + } finally { + if (is != null) { + is.close(); + } + } + } + + static void sourceComponentProperties(Map<String, Property> compositeProperties, + Component componentDefinition) throws CompositeBuilderException, + ParserConfigurationException, + XPathExpressionException, + TransformerException, + IOException { + + List<ComponentProperty> componentProperties = componentDefinition.getProperties(); + for (ComponentProperty aProperty : componentProperties) { + String source = aProperty.getSource(); + String file = aProperty.getFile(); + 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 = compositeProperties.get(name); + if (compositeProp == null) { + throw new CompositeBuilderException("The 'source' cannot be resolved to a composite property: " + source); + } + + Document compositePropDefValues = (Document)compositeProp.getValue(); + + // FIXME: How to deal with namespaces? + Document node = evaluate(compositePropDefValues, aProperty.getSourceXPathExpression()); + + if (node != null) { + aProperty.setValue(node); + } + } else { + throw new CompositeBuilderException("The 'source' has an invalid value: " + source); + } + } else if (file != null) { + aProperty.setValue(loadFromFile(aProperty.getFile())); + + } + } + } + + private static class DOMNamespaceContext implements NamespaceContext { + private Node node; + + /** + * @param node + */ + public DOMNamespaceContext(Node node) { + super(); + this.node = node; + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Prefix is null"); + } else if (XMLConstants.XML_NS_PREFIX.equals(prefix)) { + return XMLConstants.XML_NS_URI; + } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } + String ns = node.lookupNamespaceURI(prefix); + return ns == null ? XMLConstants.NULL_NS_URI : ns; + } + + public String getPrefix(String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace URI is null"); + } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { + return XMLConstants.XML_NS_PREFIX; + } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { + return XMLConstants.XMLNS_ATTRIBUTE; + } + return node.lookupPrefix(namespaceURI); + } + + public Iterator<?> getPrefixes(String namespaceURI) { + // Not implemented + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace URI is null"); + } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { + return Arrays.asList(XMLConstants.XML_NS_PREFIX).iterator(); + } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { + return Arrays.asList(XMLConstants.XMLNS_ATTRIBUTE).iterator(); + } + String prefix = getPrefix(namespaceURI); + if (prefix == null) { + return Collections.emptyList().iterator(); + } + return Arrays.asList(prefix).iterator(); + } + + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceConfigurationUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceConfigurationUtil.java new file mode 100644 index 0000000000..23d547efaf --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceConfigurationUtil.java @@ -0,0 +1,264 @@ +/* + * 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.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * This class encapsulates utility methods to deal with reference definitions + * + * @version $Rev$ $Date$ + */ +abstract class ReferenceConfigurationUtil { + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private static void warning(Monitor monitor, String message, Object model, String... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(ReferenceConfigurationUtil.class.getName(), "assembly-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + static boolean isValidMultiplicityOverride(Multiplicity definedMul, Multiplicity overridenMul) { + if (definedMul != overridenMul) { + switch (definedMul) { + case ZERO_N: + return overridenMul == Multiplicity.ZERO_ONE; + case ONE_N: + return overridenMul == Multiplicity.ONE_ONE; + default: + return false; + } + } else { + return true; + } + } + + static boolean validateMultiplicityAndTargets(Multiplicity multiplicity, + List<?> targets, List<Binding> bindings) { + + // Count targets + int count = targets.size(); + + //FIXME workaround, this validation is sometimes invoked too early + // before we get a chance to init the multiplicity attribute + if (multiplicity == null) { + return true; + } + + switch (multiplicity) { + case ZERO_N: + break; + case ZERO_ONE: + if (count > 1) { + return false; + } + break; + case ONE_ONE: + if (count != 1) { + if (count == 0) { + for (Binding binding: bindings) { + if (!(binding instanceof OptimizableBinding) || binding.getURI()!=null) { + return true; + } + } + } + return false; + } + break; + case ONE_N: + if (count < 1) { + if (count == 0) { + for (Binding binding: bindings) { + if (!(binding instanceof OptimizableBinding) || binding.getURI()!=null) { + return true; + } + } + } + return false; + } + break; + } + return true; + } + + /** + * Follow a reference promotion chain down to the innermost (non composite) + * component references. + * + * @param compositeReference + * @return + */ + static List<ComponentReference> getPromotedComponentReferences(CompositeReference compositeReference) { + List<ComponentReference> componentReferences = new ArrayList<ComponentReference>(); + collectPromotedComponentReferences(compositeReference, componentReferences); + return componentReferences; + } + + /** + * Follow a reference promotion chain down to the innermost (non composite) + * component references. + * + * @param compositeReference + * @param componentReferences + * @return + */ + private static void collectPromotedComponentReferences(CompositeReference compositeReference, + List<ComponentReference> componentReferences) { + for (ComponentReference componentReference : compositeReference.getPromotedReferences()) { + Reference reference = componentReference.getReference(); + if (reference instanceof CompositeReference) { + + // Continue to follow the reference promotion chain + collectPromotedComponentReferences((CompositeReference)reference, componentReferences); + + } else if (reference != null) { + + // Found a non-composite reference + componentReferences.add(componentReference); + } + } + } + + /** + * Override the bindings for a promoted reference from an outer component + * reference + * + * @param reference + * @param promotedReference + */ + static void reconcileReferenceBindings(Reference reference, + ComponentReference promotedReference, + AssemblyFactory assemblyFactory, + EndpointFactory endpointFactory, + Monitor monitor) { + + if (promotedReference.getMultiplicity() == Multiplicity.ONE_ONE || + promotedReference.getMultiplicity() == Multiplicity.ZERO_ONE) { + + // if necessary override the promoted endpoints (and bindings) with the top level bindings + if (reference.getBindings().size() > 0 ){ + + List<Binding> bindingsToCopyDown = new ArrayList<Binding>(); + List<Endpoint> endpointsToCopyDown = new ArrayList<Endpoint>(); + + for (Binding binding : reference.getBindings()) { + if ((!(binding instanceof OptimizableBinding)) || binding.getURI() != null) { + bindingsToCopyDown.add(binding); + + if (reference instanceof ComponentReference){ + for (Endpoint endpoint : ((ComponentReference)reference).getEndpoints()){ + if ( endpoint.getSourceBinding() == binding){ + endpointsToCopyDown.add(endpoint); + break; + } + } + } else { + // create a new endpoint to represent this promoted binding + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(binding.getURI()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(promotedReference); + endpoint.setInterfaceContract(reference.getInterfaceContract()); + endpoint.setSourceBinding(binding); + endpointsToCopyDown.add(endpoint); + } + } + } + + if (bindingsToCopyDown.size() > 0) { + promotedReference.getBindings().clear(); + promotedReference.getBindings().addAll(bindingsToCopyDown); + + promotedReference.getEndpoints().clear(); + promotedReference.getEndpoints().addAll(endpointsToCopyDown); + } + } + + if (promotedReference.getBindings().size() > 1) { + warning(monitor, "ComponentReferenceMoreWire", promotedReference, promotedReference.getName()); + } + } else { + // if necessary merge the promoted endpoints (and bindings) with the top level bindings + if (reference.getBindings().size() > 0 ){ + + for (Binding binding : reference.getBindings()) { + if ((!(binding instanceof OptimizableBinding)) || binding.getURI() != null) { + promotedReference.getBindings().add(binding); + + if (reference instanceof ComponentReference){ + for (Endpoint endpoint : ((ComponentReference)reference).getEndpoints()){ + if ( endpoint.getSourceBinding() == binding){ + promotedReference.getEndpoints().add(endpoint); + break; + } + } + } else { + // create a new endpoint to represent this promoted binding + Endpoint endpoint = endpointFactory.createEndpoint(); + endpoint.setTargetName(binding.getURI()); + endpoint.setSourceComponent(null); // TODO - fixed up at start + endpoint.setSourceComponentReference(promotedReference); + endpoint.setInterfaceContract(reference.getInterfaceContract()); + endpoint.setSourceBinding(binding); + promotedReference.getEndpoints().add(endpoint); + } + } + } + } + } + + Set<Binding> callbackBindings = new HashSet<Binding>(); + if (promotedReference.getCallback() != null) { + callbackBindings.addAll(promotedReference.getCallback().getBindings()); + } + if (reference.getCallback() != null) { + callbackBindings.addAll(reference.getCallback().getBindings()); + } + promotedReference.setCallback(assemblyFactory.createCallback()); + for (Binding binding : callbackBindings) { + if ((!(binding instanceof OptimizableBinding)) || binding.getURI() != null) { + promotedReference.getCallback().getBindings().add(binding); + } + } + } + +} diff --git a/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ServiceConfigurationUtil.java b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ServiceConfigurationUtil.java new file mode 100644 index 0000000000..41a8b3f8ba --- /dev/null +++ b/branches/sca-java-1.3.3/modules/assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ServiceConfigurationUtil.java @@ -0,0 +1,88 @@ +/* + * 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 org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Service; + +/** + * This class encapsulates utility methods to deal with service definitions. + * + * @version $Rev$ $Date$ + */ +abstract class ServiceConfigurationUtil { + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + static ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + /** + * Follow a service promotion chain down to the innermost (non-composite) component. + * + * @param compositeService + * @return + */ + static Component getPromotedComponent(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponent((CompositeService)service); + + } else { + + // Found a non-composite service + return compositeService.getPromotedComponent(); + } + } else { + + // No promoted service + return null; + } + } + +} |