/* * 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.JavaImplementation; import org.apache.tuscany.sca.implementation.java.JavaResourceImpl; import org.apache.tuscany.sca.implementation.java.JavaScopeImpl; 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.InterfaceContract; 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; private JavaScopeImpl scope; 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; this.scope = ((JavaImplementation)component.getImplementation()).getJavaScope(); } 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() { List<JavaElementImpl> callbackInjectionList = null; // If the component implementation is stateless, we need to inject the callbacks on service invocation // rather than doing it once at the component level. if ( scope.equals(JavaScopeImpl.STATELESS)) { callbackInjectionList = instanceFactoryProvider.getCallbackInjectionSites(); } else { callbackInjectionList = instanceFactoryProvider.getInjectionSites(); } 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)) { callbackInjectionList.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, InterfaceContract interfaceContract) throws NoSuchMethodException { Class<?> implClass = instanceFactoryProvider.getImplementationClass(); Method method = JavaInterfaceUtil.findMethod(implClass, operation); if (operation instanceof JavaOperation && ((JavaOperation) operation).isAsyncServer() ) { return new JavaAsyncImplementationInvoker(operation, method, component, interfaceContract); } else { return new JavaImplementationInvoker(operation, method, component, interfaceContract); } // 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); } }*/ }