/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sca.core.context; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import javax.xml.namespace.QName; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; 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.Multiplicity; import org.apache.tuscany.sca.assembly.OptimizableBinding; import org.apache.tuscany.sca.assembly.Reference; import org.apache.tuscany.sca.assembly.Service; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; import org.apache.tuscany.sca.contribution.resolver.ModelResolver; import org.apache.tuscany.sca.core.assembly.CompositeActivator; import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; import org.apache.tuscany.sca.interfacedef.Interface; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; import org.apache.tuscany.sca.invocation.Message; import org.apache.tuscany.sca.runtime.EndpointReference; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeComponentReference; import org.apache.tuscany.sca.runtime.RuntimeComponentService; import org.osoa.sca.ServiceRuntimeException; /** * @version $Rev$ $Date$ */ public class ComponentContextHelper { private final AssemblyFactory assemblyFactory; private final JavaInterfaceFactory javaInterfaceFactory; private final StAXArtifactProcessorExtensionPoint staxProcessors; /** * @param assemblyFactory The factory to create assembly models * @param processors The extension point for StAX artifact processors */ public ComponentContextHelper(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaInterfaceFactory, StAXArtifactProcessorExtensionPoint processors) { this.assemblyFactory = assemblyFactory; this.javaInterfaceFactory = javaInterfaceFactory; this.staxProcessors = processors; } /** * Create a self-reference for a component service * @param component * @param service * @throws CloneNotSupportedException * @throws InvalidInterfaceException */ public ComponentReference createSelfReference(Component component, ComponentService service, Class businessInterface) throws CloneNotSupportedException, InvalidInterfaceException { ComponentReference componentReference = assemblyFactory.createComponentReference(); componentReference.setName("$self$." + service.getName()); for (Binding binding : service.getBindings()) { if (binding instanceof OptimizableBinding) { OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone(); optimizableBinding.setTargetBinding(binding); optimizableBinding.setTargetComponent(component); optimizableBinding.setTargetComponentService(service); componentReference.getBindings().add(optimizableBinding); } else { componentReference.getBindings().add(binding); } } componentReference.setCallback(service.getCallback()); componentReference.getTargets().add(service); componentReference.getPolicySets().addAll(service.getPolicySets()); componentReference.getRequiredIntents().addAll(service.getRequiredIntents()); InterfaceContract interfaceContract = service.getInterfaceContract(); Service componentTypeService = service.getService(); if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) { interfaceContract = componentTypeService.getInterfaceContract(); } interfaceContract = getInterfaceContract(interfaceContract, businessInterface); componentReference.setInterfaceContract(interfaceContract); componentReference.setMultiplicity(Multiplicity.ONE_ONE); // component.getReferences().add(componentReference); return componentReference; } /** * @param interfaceContract * @param businessInterface * @return * @throws CloneNotSupportedException * @throws InvalidInterfaceException */ private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class businessInterface) throws CloneNotSupportedException, InvalidInterfaceException { Interface interfaze = interfaceContract.getInterface(); boolean compatible = false; if (interfaze instanceof JavaInterface) { Class cls = ((JavaInterface)interfaze).getJavaClass(); if (businessInterface.isAssignableFrom(cls)) { compatible = true; } } if (!compatible) { // The interface is not assignable from the interface contract interfaceContract = (InterfaceContract)interfaceContract.clone(); interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); } return interfaceContract; } /** * Bind a component reference to a component service * @param * @param businessInterface * @param reference * @param service * @return * @throws CloneNotSupportedException * @throws InvalidInterfaceException */ public RuntimeComponentReference bindComponentReference(Class businessInterface, RuntimeComponentReference reference, RuntimeComponent component, RuntimeComponentService service) throws CloneNotSupportedException, InvalidInterfaceException { RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone(); InterfaceContract interfaceContract = reference.getInterfaceContract(); Reference componentTypeReference = reference.getReference(); if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) { interfaceContract = componentTypeReference.getInterfaceContract(); } InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface); if (refInterfaceContract != interfaceContract) { ref = (RuntimeComponentReference)reference.clone(); ref.setInterfaceContract(interfaceContract); } ref.setComponent(component); ref.getTargets().add(service); ref.getBindings().clear(); for (Binding binding : service.getBindings()) { if (binding instanceof OptimizableBinding) { OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone(); optimizableBinding.setTargetBinding(binding); optimizableBinding.setTargetComponent(component); optimizableBinding.setTargetComponentService(service); ref.getBindings().add(optimizableBinding); } else { ref.getBindings().add(binding); } } return ref; } public void write(Component component, ComponentReference reference, Writer writer) throws IOException { write(component, reference, null, writer); } public void write(Component component, ComponentReference reference, ComponentService service, Writer writer) throws IOException { try { StAXArtifactProcessor processor = staxProcessors.getProcessor(Composite.class); Composite composite = assemblyFactory.createComposite(); composite.setName(new QName("http://tuscany.apache.org/xmlns/sca/1.0", "default")); Component comp = assemblyFactory.createComponent(); comp.setName("default"); comp.setURI(component.getURI()); composite.getComponents().add(comp); if (reference != null) { comp.getReferences().add(reference); } if (service != null) { comp.getServices().add(service); } XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer); processor.write(composite, streamWriter); } catch (Exception e) { throw new IOException(e.getMessage()); } } public String toXML(Component component, ComponentReference reference) throws IOException { StringWriter writer = new StringWriter(); write(component, reference, writer); return writer.toString(); } public String toXML(Component component, ComponentService service) throws IOException { StringWriter writer = new StringWriter(); write(component, null, service, writer); return writer.toString(); } public RuntimeComponent read(Reader reader) throws IOException { try { XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader streamReader = inputFactory.createXMLStreamReader(reader); return read(streamReader); } catch (Exception e) { throw new IOException(e.getMessage()); } } public RuntimeComponent read(XMLStreamReader streamReader) throws IOException { try { StAXArtifactProcessor processor = staxProcessors.getProcessor(Composite.class); Composite composite = processor.read(streamReader); RuntimeComponent component = (RuntimeComponent)composite.getComponents().get(0); return component; } catch (Exception e) { throw new IOException(e.getMessage()); } } public Component fromXML(String xml) throws IOException { return read(new StringReader(xml)); } public Component fromXML(XMLStreamReader streamReader) throws IOException { return read(streamReader); } public void resolveInterfaceContract(InterfaceContract interfaceContract, ModelResolver resolver) throws Exception { StAXArtifactProcessor processor = staxProcessors.getProcessor(interfaceContract.getClass()); processor.resolve(interfaceContract, resolver); } public void resolveBinding(Binding binding, ModelResolver resolver) throws Exception { StAXArtifactProcessor processor = staxProcessors.getProcessor(binding.getClass()); processor.resolve(binding, resolver); } public Reference createReference(Class businessInterface) throws InvalidInterfaceException { InterfaceContract interfaceContract = createJavaInterfaceContract(businessInterface); Reference reference = assemblyFactory.createReference(); reference.setInterfaceContract(interfaceContract); return reference; } private InterfaceContract createJavaInterfaceContract(Class businessInterface) throws InvalidInterfaceException { InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface); interfaceContract.setInterface(callInterface); if (callInterface.getCallbackClass() != null) { interfaceContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface( callInterface.getCallbackClass())); } return interfaceContract; } public static RuntimeComponent getCurrentComponent() { Message message = ThreadMessageContext.getMessageContext(); if (message != null) { EndpointReference to = message.getTo(); if (to == null) { return null; } RuntimeComponent component = message.getTo().getComponent(); return component; } return null; } public static CompositeActivator getCurrentCompositeActivator() { RuntimeComponent component = getCurrentComponent(); if (component != null) { ComponentContextImpl context = (ComponentContextImpl)component.getComponentContext(); return context.getCompositeActivator(); } return null; } public static ComponentContextHelper getCurrentComponentContextHelper() { CompositeActivator activator = getCurrentCompositeActivator(); if (activator != null) { return activator.getComponentContextHelper(); } return null; } /** * @param component */ public static ComponentService getSingleService(Component component) { ComponentService targetService; List services = component.getServices(); List regularServices = new ArrayList(); for (ComponentService service : services) { if (service.isCallback()) { continue; } String name = service.getName(); if (!name.startsWith("$") || name.startsWith("$dynamic$")) { regularServices.add(service); } } if (regularServices.size() == 0) { throw new ServiceRuntimeException("No service is declared on component " + component.getURI()); } if (regularServices.size() != 1) { throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI() + ". Service name is required to get the service."); } targetService = regularServices.get(0); return targetService; } }