| /* |
| * 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.implementation.java.invocation; |
| |
| import java.lang.annotation.ElementType; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.lang.reflect.Type; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| 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.EndpointReference; |
| import org.apache.tuscany.sca.assembly.Multiplicity; |
| import org.apache.tuscany.sca.assembly.Reference; |
| import org.apache.tuscany.sca.context.ComponentContextFactory; |
| import org.apache.tuscany.sca.context.PropertyValueFactory; |
| import org.apache.tuscany.sca.context.RequestContextFactory; |
| import org.apache.tuscany.sca.core.factory.InstanceWrapper; |
| import org.apache.tuscany.sca.core.factory.ObjectCreationException; |
| import org.apache.tuscany.sca.core.factory.ObjectFactory; |
| import org.apache.tuscany.sca.core.invocation.CallableReferenceObjectFactory; |
| import org.apache.tuscany.sca.core.invocation.CallbackReferenceObjectFactory; |
| import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; |
| import org.apache.tuscany.sca.core.invocation.ProxyFactory; |
| import org.apache.tuscany.sca.core.invocation.WireObjectFactory; |
| import org.apache.tuscany.sca.core.scope.ScopeContainer; |
| import org.apache.tuscany.sca.core.scope.TargetResolutionException; |
| import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; |
| import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl; |
| import org.apache.tuscany.sca.implementation.java.JavaElementImpl; |
| import org.apache.tuscany.sca.implementation.java.JavaResourceImpl; |
| import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; |
| import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; |
| import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; |
| import org.apache.tuscany.sca.interfacedef.Operation; |
| import org.apache.tuscany.sca.interfacedef.java.JavaOperation; |
| import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; |
| import org.apache.tuscany.sca.invocation.Invoker; |
| import org.apache.tuscany.sca.runtime.RuntimeComponent; |
| import org.apache.tuscany.sca.runtime.RuntimeComponentReference; |
| import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; |
| import org.oasisopen.sca.ServiceReference; |
| |
| /** |
| * The runtime instantiation of Java component implementations |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class JavaComponentContextProvider { |
| private JavaPropertyValueObjectFactory propertyValueFactory; |
| private RuntimeComponent component; |
| private JavaInstanceFactoryProvider<?> instanceFactoryProvider; |
| private ProxyFactory proxyFactory; |
| private InstanceFactory instanceFactory; |
| |
| public JavaComponentContextProvider(RuntimeComponent component, |
| JavaInstanceFactoryProvider configuration, |
| DataBindingExtensionPoint dataBindingExtensionPoint, |
| PropertyValueFactory propertyValueObjectFactory, |
| ComponentContextFactory componentContextFactory, |
| RequestContextFactory requestContextFactory) { |
| super(); |
| this.instanceFactoryProvider = configuration; |
| this.proxyFactory = configuration.getProxyFactory(); |
| // if (componentContextFactory != null) { |
| // this.componentContext = componentContextFactory.createComponentContext(component, requestContextFactory); |
| // } else { |
| // this.componentContext = new ComponentContextImpl(this, requestContextFactory, this.proxyService); |
| // } |
| this.component = component; |
| this.propertyValueFactory = (JavaPropertyValueObjectFactory) propertyValueObjectFactory; |
| } |
| |
| InstanceWrapper<?> createInstanceWrapper() throws ObjectCreationException { |
| if (instanceFactory == null) { |
| start(); |
| } |
| return instanceFactory.newInstance(); |
| } |
| |
| void configureProperties(List<ComponentProperty> definedProperties) { |
| for (ComponentProperty p : definedProperties) { |
| configureProperty(p); |
| } |
| } |
| |
| private void configureProperty(ComponentProperty configuredProperty) { |
| JavaElementImpl element = |
| instanceFactoryProvider.getImplementation().getPropertyMembers().get(configuredProperty.getName()); |
| |
| if (element != null && configuredProperty.getValue() != null) { |
| if (!(element.getAnchor() instanceof Constructor)) { |
| if(element.getElementType() == ElementType.FIELD) { |
| // Field field = (Field)element.getAnchor(); |
| instanceFactoryProvider.getInjectionSites().add(element); |
| /* |
| if(Modifier.isPublic(field.getModifiers())) { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } else if(field.getAnnotation(org.oasisopen.sca.annotation.Property.class) != null) { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } |
| */ |
| } else { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } |
| } |
| |
| //Class propertyJavaType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); |
| ObjectFactory<?> propertyObjectFactory = |
| createPropertyValueFactory(configuredProperty, configuredProperty.getValue(), element); |
| instanceFactoryProvider.setObjectFactory(element, propertyObjectFactory); |
| |
| JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); |
| for(JavaElementImpl p: constructor.getParameters()){ |
| if(element.getName().equals(p.getName())) { |
| instanceFactoryProvider.setObjectFactory(p, propertyObjectFactory); |
| } |
| } |
| } |
| } |
| |
| void start() { |
| if (!instanceFactoryProvider.getImplementation().getCallbackMembers().isEmpty()) { |
| Map<String, List<EndpointReference>> callbackWires = new HashMap<String, List<EndpointReference>>(); |
| for (ComponentService service : component.getServices()) { |
| |
| RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); |
| if (callbackReference != null) { |
| List<EndpointReference> wires = callbackReference.getEndpointReferences(); |
| if (!wires.isEmpty()) { |
| RuntimeEndpointReference epr = (RuntimeEndpointReference) wires.get(0); |
| callbackWires.put(epr.getComponentTypeReferenceInterfaceContract().getInterface().toString(), |
| wires); |
| } |
| } |
| } |
| |
| for (Map.Entry<String, Collection<JavaElementImpl>> entry : instanceFactoryProvider.getImplementation() |
| .getCallbackMembers().entrySet()) { |
| List<EndpointReference> wires = callbackWires.get(entry.getKey()); |
| if (wires == null) { |
| // this can happen when there are no client wires to a |
| // component that has a callback |
| continue; |
| } |
| for(JavaElementImpl element : entry.getValue()) { |
| Class<?> businessInterface = element.getType(); |
| ObjectFactory<?> factory = null; |
| if (ServiceReference.class.isAssignableFrom(element.getType())) { |
| businessInterface = |
| JavaIntrospectionHelper.getBusinessInterface(element.getType(), element.getGenericType()); |
| factory = |
| new CallbackReferenceObjectFactory(businessInterface, proxyFactory, wires); |
| } else { |
| factory = new CallbackWireObjectFactory(businessInterface, proxyFactory, wires); |
| } |
| if (!(element.getAnchor() instanceof Constructor)) { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } |
| instanceFactoryProvider.setObjectFactory(element, factory); |
| } |
| } |
| } |
| for (Reference ref : instanceFactoryProvider.getImplementation().getReferences()) { |
| JavaElementImpl element = |
| instanceFactoryProvider.getImplementation().getReferenceMembers().get(ref.getName()); |
| if (element != null) { |
| if (!(element.getAnchor() instanceof Constructor)) { |
| if(element.getElementType() == ElementType.FIELD) { |
| Field field = (Field)element.getAnchor(); |
| if(Modifier.isPublic(field.getModifiers())) { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } else if(field.getAnnotation(org.oasisopen.sca.annotation.Reference.class) != null) { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } |
| } else { |
| instanceFactoryProvider.getInjectionSites().add(element); |
| } |
| } |
| ComponentReference componentReference = null; |
| List<EndpointReference> wireList = null; |
| for (ComponentReference reference : component.getReferences()) { |
| if (reference.getName().equals(ref.getName())) { |
| wireList = ((RuntimeComponentReference)reference).getEndpointReferences(); |
| componentReference = reference; |
| break; |
| } |
| } |
| if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { |
| List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>(); |
| Class<?> baseType = |
| JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); |
| for (int i = 0; i < wireList.size(); i++) { |
| ObjectFactory<?> factory = null; |
| if (ServiceReference.class.isAssignableFrom(baseType)) { |
| Type callableRefType = JavaIntrospectionHelper.getParameterType(element.getGenericType()); |
| // Type businessType = JavaIntrospectionHelper.getParameterType(callableRefType); |
| Class<?> businessInterface = |
| JavaIntrospectionHelper.getBusinessInterface(baseType, callableRefType); |
| factory = new CallableReferenceObjectFactory(businessInterface, (RuntimeEndpointReference) wireList.get(i)); |
| } else { |
| factory = createObjectFactory(baseType, wireList.get(i)); |
| } |
| factories.add(factory); |
| } |
| instanceFactoryProvider.setObjectFactories(element, factories); |
| JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); |
| for(JavaElementImpl p: constructor.getParameters()){ |
| if(element.getName().equals(p.getName())) { |
| instanceFactoryProvider.setObjectFactories(p, factories); |
| } |
| } |
| } else { |
| if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { |
| throw new IllegalStateException("Required reference is missing: " + ref.getName()); |
| } |
| if (wireList != null && !wireList.isEmpty()) { |
| ObjectFactory<?> factory = null; |
| if (ServiceReference.class.isAssignableFrom(element.getType())) { |
| Class<?> businessInterface = |
| JavaIntrospectionHelper.getBusinessInterface(element.getType(), element |
| .getGenericType()); |
| factory = |
| new CallableReferenceObjectFactory(businessInterface, (RuntimeEndpointReference) wireList.get(0)); |
| } else { |
| factory = createObjectFactory(element.getType(), wireList.get(0)); |
| } |
| instanceFactoryProvider.setObjectFactory(element, factory); |
| JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); |
| for(JavaElementImpl p: constructor.getParameters()){ |
| if(element.getName().equals(p.getName())) { |
| instanceFactoryProvider.setObjectFactory(p, factory); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| //setUpPolicyHandlers(); |
| this.instanceFactory = instanceFactoryProvider.createFactory(); |
| |
| } |
| |
| void addResourceFactory(String name, ObjectFactory<?> factory) { |
| JavaResourceImpl resource = instanceFactoryProvider.getImplementation().getResources().get(name); |
| |
| if (resource != null && !(resource.getElement().getAnchor() instanceof Constructor)) { |
| instanceFactoryProvider.getInjectionSites().add(resource.getElement()); |
| } |
| |
| instanceFactoryProvider.setObjectFactory(resource.getElement(), factory); |
| } |
| |
| Object createInstance() throws ObjectCreationException { |
| return createInstanceWrapper().getInstance(); |
| } |
| |
| JavaInstanceFactoryProvider<?> getInstanceFactoryProvider() { |
| return instanceFactoryProvider; |
| } |
| |
| void stop() { |
| //cleanUpPolicyHandlers(); |
| } |
| |
| Invoker createInvoker(Operation operation) throws NoSuchMethodException { |
| Class<?> implClass = instanceFactoryProvider.getImplementationClass(); |
| |
| Method method = JavaInterfaceUtil.findMethod(implClass, operation); |
| if( ((JavaOperation) operation).isAsyncServer() ) { |
| return new JavaAsyncImplementationInvoker(operation, method, component); |
| } else { |
| return new JavaImplementationInvoker(operation, method, component); |
| } // end if |
| } // end |
| |
| private static class OptimizedObjectFactory<T> implements ObjectFactory<T> { |
| private ScopeContainer scopeContainer; |
| |
| public OptimizedObjectFactory(ScopeContainer scopeContainer) { |
| super(); |
| this.scopeContainer = scopeContainer; |
| } |
| |
| public T getInstance() throws ObjectCreationException { |
| try { |
| return (T)scopeContainer.getWrapper(null).getInstance(); |
| } catch (TargetResolutionException e) { |
| throw new ObjectCreationException(e); |
| } |
| } |
| |
| } |
| |
| private <B> ObjectFactory<B> createObjectFactory(Class<B> interfaze, EndpointReference wire) { |
| // FIXME: [rfeng] Disable the optimization for new as it needs more discussions |
| /* |
| boolean conversational = wire.getSource().getInterfaceContract().getInterface().isConversational(); |
| Binding binding = wire.getSource().getBinding(); |
| // Check if it's wireable binding for optimization |
| if (!conversational && binding instanceof OptimizableBinding) { |
| OptimizableBinding optimizableBinding = (OptimizableBinding)binding; |
| Component component = optimizableBinding.getTargetComponent(); |
| if (component != null) { |
| Implementation implementation = component.getImplementation(); |
| // Check if the target component is java component |
| if (implementation instanceof JavaImplementation) { |
| JavaImplementation javaImplementation = (JavaImplementation)implementation; |
| if (interfaze.isAssignableFrom(javaImplementation.getJavaClass())) { |
| ScopedRuntimeComponent scopedComponent = (ScopedRuntimeComponent)component; |
| ScopeContainer scopeContainer = scopedComponent.getScopeContainer(); |
| Scope scope = scopeContainer.getScope(); |
| if (scope == Scope.COMPOSITE || scope == Scope.STATELESS || scope == Scope.SYSTEM) { |
| boolean optimizable = true; |
| for (InvocationChain chain : wire.getInvocationChains()) { |
| if (chain.getHeadInvoker() != chain.getTailInvoker()) { |
| optimizable = false; |
| break; |
| } |
| } |
| if (optimizable) { |
| return new OptimizedObjectFactory<B>(scopeContainer); |
| } |
| } |
| } |
| } |
| } |
| } |
| */ |
| return new WireObjectFactory<B>(interfaze, (RuntimeEndpointReference) wire, proxyFactory); |
| } |
| |
| private ObjectFactory<?> createPropertyValueFactory(ComponentProperty property, |
| Object propertyValue, |
| JavaElementImpl javaElement) { |
| return propertyValueFactory.createValueFactory(property, propertyValue, javaElement); |
| } |
| |
| /** |
| * @return the component |
| */ |
| RuntimeComponent getComponent() { |
| return component; |
| } |
| |
| /*private void setUpPolicyHandlers() { |
| for (PolicyHandler policyHandler : policyHandlers.values()) { |
| policyHandler.setUp(component.getImplementation()); |
| } |
| } |
| |
| private void cleanUpPolicyHandlers() { |
| for (PolicyHandler policyHandler : policyHandlers.values() ) { |
| policyHandler.cleanUp(this); |
| } |
| }*/ |
| |
| } |