| /* |
| * 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.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| 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.ComponentProperty; |
| import org.apache.tuscany.sca.assembly.ComponentReference; |
| 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.EndpointReference; |
| import org.apache.tuscany.sca.assembly.Multiplicity; |
| import org.apache.tuscany.sca.assembly.SCABinding; |
| import org.apache.tuscany.sca.assembly.Service; |
| import org.apache.tuscany.sca.context.CompositeContext; |
| import org.apache.tuscany.sca.context.PropertyValueFactory; |
| import org.apache.tuscany.sca.context.RequestContextFactory; |
| import org.apache.tuscany.sca.core.ExtensionPointRegistry; |
| import org.apache.tuscany.sca.core.invocation.ProxyFactory; |
| import org.apache.tuscany.sca.interfacedef.Interface; |
| import org.apache.tuscany.sca.interfacedef.InterfaceContract; |
| import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; |
| import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; |
| import org.apache.tuscany.sca.interfacedef.java.JavaInterface; |
| import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; |
| import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; |
| import org.apache.tuscany.sca.runtime.CompositeActivator; |
| import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; |
| import org.apache.tuscany.sca.runtime.RuntimeComponent; |
| import org.apache.tuscany.sca.runtime.RuntimeComponentContext; |
| import org.apache.tuscany.sca.runtime.RuntimeComponentReference; |
| import org.apache.tuscany.sca.runtime.RuntimeEndpoint; |
| import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; |
| import org.apache.tuscany.sca.runtime.TuscanyServiceReference; |
| import org.oasisopen.sca.RequestContext; |
| import org.oasisopen.sca.ServiceReference; |
| import org.oasisopen.sca.ServiceRuntimeException; |
| |
| /** |
| * Implementation of ComponentContext that delegates to a ComponentContextProvider. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class ComponentContextImpl implements RuntimeComponentContext { |
| private final RuntimeComponent component; |
| |
| private final CompositeContext compositeContext; |
| private final CompositeActivator compositeActivator; |
| private final RequestContextFactory requestContextFactory; |
| private final ProxyFactory proxyFactory; |
| private final AssemblyFactory assemblyFactory; |
| private final JavaInterfaceFactory javaInterfaceFactory; |
| private final PropertyValueFactory propertyFactory; |
| private final EndpointReferenceBinder eprBinder; |
| private final ExtensionPointRegistry registry; |
| |
| public ComponentContextImpl(ExtensionPointRegistry registry, |
| AssemblyFactory assemblyFactory, |
| JavaInterfaceFactory javaInterfaceFactory, |
| CompositeActivator compositeActivator, |
| RequestContextFactory requestContextFactory, |
| PropertyValueFactory propertyFactory, |
| EndpointReferenceBinder eprBinder, |
| ProxyFactory proxyFactory, |
| CompositeContext compositeContext, |
| RuntimeComponent component) { |
| this.registry = registry; |
| this.assemblyFactory = assemblyFactory; |
| this.javaInterfaceFactory = javaInterfaceFactory; |
| this.compositeActivator = compositeActivator; |
| this.requestContextFactory = requestContextFactory; |
| this.propertyFactory = propertyFactory; |
| this.eprBinder = eprBinder; |
| this.proxyFactory = proxyFactory; |
| this.compositeContext = compositeContext; |
| this.component = component; |
| } |
| |
| public String getURI() { |
| return component.getURI(); |
| } |
| |
| public <B> ServiceReference<B> cast(B target) throws IllegalArgumentException { |
| return proxyFactory.cast(target); |
| } |
| |
| public <B> B getService(Class<B> businessInterface, String referenceName) throws IllegalArgumentException { |
| B service = null; |
| |
| ServiceReference<B> serviceRef = getServiceReference(businessInterface, referenceName); |
| if (serviceRef != null) { |
| service = serviceRef.getService(); |
| } |
| |
| return service; |
| } |
| |
| public <B> TuscanyServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) |
| throws IllegalArgumentException { |
| |
| for (ComponentReference ref : component.getReferences()) { |
| if (referenceName.equals(ref.getName())) { |
| Multiplicity multiplicity = ref.getMultiplicity(); |
| if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) { |
| throw new IllegalArgumentException("Reference " + referenceName |
| + " has multiplicity " |
| + multiplicity); |
| } |
| if (ref.getEndpointReferences().size() < 1) { |
| return null; |
| } |
| TuscanyServiceReference<B> sr = |
| getServiceReference(businessInterface, (RuntimeEndpointReference)getEndpointReference(ref)); |
| if (sr == null) { |
| throw new IllegalArgumentException("Reference " + referenceName + " is null"); |
| } |
| return sr; |
| } |
| } |
| throw new IllegalArgumentException("[JCA80011] Reference not found: " + referenceName); |
| |
| } |
| |
| /** |
| * Select an endpoint reference from the component reference |
| * @param ref |
| * @return |
| */ |
| private EndpointReference getEndpointReference(ComponentReference ref) { |
| List<EndpointReference> eprs = ref.getEndpointReferences(); |
| if (eprs.size() == 1) { |
| // Return 1st one |
| return eprs.get(0); |
| } else { |
| for (EndpointReference epr : eprs) { |
| // Try to see if there is an EPR using binding.sca |
| if (epr.getBinding().getType().equals(SCABinding.TYPE)) { |
| return epr; |
| } |
| } |
| return eprs.get(0); |
| } |
| } |
| |
| /** |
| * Select an endpoint reference from the component reference |
| * @param ref |
| * @return |
| */ |
| private Endpoint getEndpoint(ComponentService service, String bindingName) { |
| if (bindingName == null) { |
| // The default binding name is the name of the promoted service |
| bindingName = getPromotedService(service).getName(); |
| } |
| Endpoint returnEp = null; |
| List<Endpoint> eps = service.getEndpoints(); |
| for (Endpoint ep : eps) { |
| Binding binding = ep.getBinding(); |
| if (bindingName.equals(binding.getName()) || binding.getName() == null) { |
| returnEp = ep; |
| break; |
| } |
| } |
| //TUSCANY-3543 |
| if (returnEp == null) { |
| returnEp = eps.get(0); |
| } |
| |
| return returnEp; |
| } |
| |
| private ComponentService getPromotedService(ComponentService componentService) { |
| Service service = componentService.getService(); |
| if (service instanceof CompositeService) { |
| return getPromotedService(((CompositeService)service).getPromotedService()); |
| } else { |
| return componentService; |
| } |
| |
| } |
| |
| /** |
| * Gets the value for the specified property with the specified type. |
| * |
| * @param type The type of the property value we are getting |
| * @param propertyName The name of the property we are getting |
| * @param B The class of the property value we are getting |
| * |
| * @throws ServiceRuntimeException If a Property for the specified propertyName |
| * is not found |
| * |
| * @see #setPropertyValueFactory(PropertyValueFactory) |
| */ |
| public <B> B getProperty(Class<B> type, String propertyName) { |
| for (ComponentProperty p : component.getProperties()) { |
| if (propertyName.equals(p.getName())) { |
| return propertyFactory.createPropertyValue(p, type); |
| } |
| } |
| throw new IllegalArgumentException("Property not found: " + propertyName); |
| } |
| |
| /** |
| * @param component |
| */ |
| public static ComponentService getSingleService(Component component) { |
| ComponentService targetService; |
| List<ComponentService> services = component.getServices(); |
| List<ComponentService> regularServices = new ArrayList<ComponentService>(); |
| for (ComponentService service : services) { |
| if (service.isForCallback()) { |
| 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; |
| } |
| |
| public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) { |
| ComponentService service = getSingleService(component); |
| try { |
| return createSelfReference(businessInterface, service); |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e.getMessage(), e); |
| } |
| } |
| |
| public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) { |
| if (serviceName == null) { |
| return createSelfReference(businessInterface); |
| } |
| try { |
| String bindingName = null; |
| int index = serviceName.indexOf('/'); |
| if (index != -1) { |
| bindingName = serviceName.substring(index + 1); |
| serviceName = serviceName.substring(0, index); |
| } |
| for (ComponentService service : component.getServices()) { |
| if (serviceName.equals(service.getName())) { |
| Endpoint endpoint = getEndpoint(service, bindingName); |
| if (endpoint == null) { |
| break; |
| } |
| return getServiceReference(businessInterface, (RuntimeEndpoint)endpoint); |
| } |
| } |
| throw new IllegalArgumentException("Service not found: " + serviceName); |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (ServiceRuntimeException e) { |
| throw e; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e.getMessage(), e); |
| } |
| } |
| |
| /** |
| * @param <B> |
| * @param businessInterface |
| * @param service |
| * @return |
| */ |
| public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, ComponentService service) { |
| try { |
| RuntimeEndpointReference ref = |
| (RuntimeEndpointReference)createEndpointReference(component, service, null, businessInterface); |
| ref.setComponent(component); |
| return getServiceReference(businessInterface, ref); |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e); |
| } |
| } |
| |
| public RequestContext getRequestContext() { |
| if (requestContextFactory != null) { |
| return requestContextFactory.createRequestContext(component); |
| } else { |
| return new RequestContextImpl(component); |
| } |
| } |
| |
| /** |
| * @param businessInterface |
| * @param reference |
| * @return |
| * @throws CloneNotSupportedException |
| * @throws InvalidInterfaceException |
| */ |
| public <B> TuscanyServiceReference<B> getServiceReference(Class<B> businessInterface, |
| RuntimeEndpointReference endpointReference) { |
| TuscanyServiceReference<B> result = null; |
| |
| try { |
| InterfaceContract interfaceContract = endpointReference.getComponentTypeReferenceInterfaceContract(); |
| if (businessInterface == null) { |
| businessInterface = (Class<B>)((JavaInterface)interfaceContract.getInterface()).getJavaClass(); |
| } |
| RuntimeComponentReference ref = (RuntimeComponentReference)endpointReference.getReference(); |
| InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface); |
| if (refInterfaceContract != null) { |
| if (refInterfaceContract != interfaceContract) { |
| ref = (RuntimeComponentReference)ref.clone(); |
| if (interfaceContract != null) { |
| ref.setInterfaceContract(interfaceContract); |
| } else { |
| ref.setInterfaceContract(refInterfaceContract); |
| } |
| } |
| |
| ref.setComponent(component); |
| result = |
| new ServiceReferenceImpl<B>(businessInterface, endpointReference, component.getComponentContext() |
| .getCompositeContext()); |
| } |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e); |
| } |
| |
| return result; |
| } |
| |
| public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, RuntimeEndpoint endpoint) { |
| try { |
| if (businessInterface == null) { |
| InterfaceContract contract = endpoint.getBindingInterfaceContract(); |
| if (contract.getInterface() instanceof JavaInterface) { |
| businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass(); |
| } else { |
| contract = endpoint.getComponentTypeServiceInterfaceContract(); |
| if (contract.getInterface() instanceof JavaInterface) { |
| businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass(); |
| } |
| } |
| } |
| RuntimeEndpointReference ref = |
| (RuntimeEndpointReference)createEndpointReference(endpoint, businessInterface); |
| ref.setComponent(component); |
| return new ServiceReferenceImpl<B>(businessInterface, ref, compositeContext); |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e); |
| } |
| } |
| |
| /** |
| * Create a self-reference for a component service |
| * @param component |
| * @param service |
| * @throws CloneNotSupportedException |
| * @throws InvalidInterfaceException |
| */ |
| private EndpointReference createEndpointReference(Component component, |
| ComponentService service, |
| String bindingName, |
| Class<?> businessInterface) throws CloneNotSupportedException, |
| InvalidInterfaceException { |
| |
| Endpoint endpoint = getEndpoint(service, bindingName); |
| return createEndpointReference(endpoint, businessInterface); |
| } |
| |
| private EndpointReference createEndpointReference(Endpoint endpoint, Class<?> businessInterface) |
| throws CloneNotSupportedException, InvalidInterfaceException { |
| Component component = endpoint.getComponent(); |
| ComponentService service = endpoint.getService(); |
| ComponentReference componentReference = assemblyFactory.createComponentReference(); |
| componentReference.setName("$self$." + service.getName()); |
| |
| componentReference.setCallback(service.getCallback()); |
| componentReference.getTargets().add(service); |
| componentReference.getPolicySets().addAll(service.getPolicySets()); |
| componentReference.getRequiredIntents().addAll(service.getRequiredIntents()); |
| componentReference.getBindings().add(endpoint.getBinding()); |
| |
| // For the self-reference, allows pass by reference |
| componentReference.setAllowsPassByReference(true); |
| |
| 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); |
| |
| // create endpoint reference |
| EndpointReference endpointReference = assemblyFactory.createEndpointReference(); |
| endpointReference.setComponent(component); |
| endpointReference.setReference(componentReference); |
| endpointReference.setBinding(endpoint.getBinding()); |
| endpointReference.setUnresolved(false); |
| endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING); |
| |
| endpointReference.setTargetEndpoint(endpoint); |
| |
| componentReference.getEndpointReferences().add(endpointReference); |
| ((RuntimeComponentReference)componentReference).setComponent((RuntimeComponent)component); |
| ((RuntimeEndpointReference)endpointReference).bind(compositeContext); |
| |
| return endpointReference; |
| } |
| |
| /** |
| * @param interfaceContract |
| * @param businessInterface |
| * @return |
| * @throws CloneNotSupportedException |
| * @throws InvalidInterfaceException |
| */ |
| private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface) |
| throws CloneNotSupportedException, InvalidInterfaceException { |
| if (businessInterface == null) { |
| return interfaceContract; |
| } |
| if (interfaceContract == null) { |
| JavaInterfaceContract ic = javaInterfaceFactory.createJavaInterfaceContract(); |
| ic.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); |
| return ic; |
| } |
| boolean compatible = false; |
| if (interfaceContract != null && interfaceContract.getInterface() != null) { |
| Interface interfaze = interfaceContract.getInterface(); |
| if (interfaze instanceof JavaInterface) { |
| Class<?> cls = ((JavaInterface)interfaze).getJavaClass(); |
| if (businessInterface.isAssignableFrom(cls)) { |
| compatible = true; |
| } |
| if (!compatible) { |
| InterfaceContract biContract = javaInterfaceFactory.createJavaInterfaceContract(); |
| JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface); |
| biContract.setInterface(callInterface); |
| if (callInterface.getCallbackClass() != null) { |
| biContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface |
| .getCallbackClass())); |
| } |
| InterfaceContractMapper ifcm = registry.getExtensionPoint(InterfaceContractMapper.class); |
| compatible = ifcm.isCompatibleSubset(biContract, interfaceContract); |
| // If the business interface class is not assignable from the service interface class but |
| // they are compatible, we need to return an InterfaceContract with the business interface |
| // class to store on the reference side. |
| if ( compatible ) { |
| return biContract; |
| } |
| } |
| |
| } |
| } |
| |
| if (!compatible) { |
| // JCA-9011 |
| throw new IllegalArgumentException("Business interface " + businessInterface.getName() |
| + " is not compatible with " |
| + interfaceContract.getInterface()); |
| } |
| |
| return interfaceContract; |
| } |
| |
| /* ******************** Contribution for issue TUSCANY-2281 ******************** */ |
| |
| /** |
| * @see ComponentContext#getServices(Class<B>, String) |
| */ |
| public <B> Collection<B> getServices(Class<B> businessInterface, String referenceName) { |
| ArrayList<B> services = new ArrayList<B>(); |
| Collection<ServiceReference<B>> serviceRefs = getServiceReferences(businessInterface, referenceName); |
| for (ServiceReference<B> serviceRef : serviceRefs) { |
| services.add(serviceRef.getService()); |
| } |
| return services; |
| } |
| |
| /** |
| * @see ComponentContext#getServiceReferences(Class<B>, String) |
| */ |
| public <B> Collection<ServiceReference<B>> getServiceReferences(Class<B> businessInterface, String referenceName) { |
| try { |
| for (ComponentReference ref : component.getReferences()) { |
| if (referenceName.equals(ref.getName())) { |
| if (ref.getMultiplicity() == Multiplicity.ONE_ONE) |
| throw new IllegalArgumentException("Reference " + referenceName |
| + " is not a valid argument for getServiceReferences because it has a multiplicity of 1..1"); |
| if (ref.getMultiplicity() == Multiplicity.ZERO_ONE) |
| throw new IllegalArgumentException("Reference " + referenceName |
| + " is not a valid argument for getServiceReferences because it has a multiplicity of 0..1"); |
| |
| ArrayList<ServiceReference<B>> serviceRefs = new ArrayList<ServiceReference<B>>(); |
| for (EndpointReference endpointReference : ref.getEndpointReferences()) { |
| RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference; |
| serviceRefs.add(getServiceReference(businessInterface, epr)); |
| } |
| return serviceRefs; |
| } |
| } |
| throw new IllegalArgumentException("Reference not found: " + referenceName); |
| } catch (IllegalArgumentException iae) { |
| throw iae; |
| } catch (ServiceRuntimeException e) { |
| throw e; |
| } catch (Exception e) { |
| throw new ServiceRuntimeException(e.getMessage(), e); |
| } |
| } |
| |
| /* ******************** Contribution for issue TUSCANY-2281 ******************** */ |
| |
| public CompositeContext getCompositeContext() { |
| return compositeContext; |
| } |
| |
| public ExtensionPointRegistry getExtensionPointRegistry() { |
| return getCompositeContext().getExtensionPointRegistry(); |
| } |
| |
| public Object getNode() { |
| return getCompositeContext().getNode(); |
| } |
| |
| } |