From 54dd9a865f3f22be632da59fd25d3f674dcbfb6c Mon Sep 17 00:00:00 2001 From: rfeng Date: Wed, 6 Aug 2008 21:08:43 +0000 Subject: Refactor the package names to be consistent with other implementation types. We will split it into model and runtime later on. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@683413 13f79535-47bb-0310-9956-ffa450edef68 --- .../implementation/osgi/OSGiImplementation.java | 45 + .../osgi/OSGiImplementationInterface.java | 45 - .../osgi/impl/OSGiImplementationImpl.java | 168 +++ .../invocation/OSGiImplementationProvider.java | 1254 -------------------- .../OSGiImplementationProviderFactory.java | 111 -- .../osgi/invocation/OSGiInstanceWrapper.java | 299 ----- .../osgi/invocation/OSGiRemotableInvoker.java | 139 --- .../osgi/invocation/OSGiTargetInvoker.java | 199 ---- .../osgi/runtime/OSGiImplementationProvider.java | 1254 ++++++++++++++++++++ .../runtime/OSGiImplementationProviderFactory.java | 111 ++ .../osgi/runtime/OSGiInstanceWrapper.java | 299 +++++ .../osgi/runtime/OSGiRemotableInvoker.java | 139 +++ .../osgi/runtime/OSGiTargetInvoker.java | 199 ++++ .../osgi/xml/OSGiImplementation.java | 168 --- .../osgi/xml/OSGiImplementationProcessor.java | 15 +- ...ca.contribution.processor.StAXArtifactProcessor | 2 +- ...cany.sca.provider.ImplementationProviderFactory | 2 +- .../osgi/invocation/OSGiPropertyTestCase.java | 49 - .../osgi/invocation/OSGiTestCase.java | 74 -- .../osgi/runtime/OSGiPropertyTestCase.java | 49 + .../implementation/osgi/runtime/OSGiTestCase.java | 74 ++ .../osgi/xml/OSGiReadImplTestCase.java | 3 +- .../implementation/osgi/xml/TestModelResolver.java | 5 +- 23 files changed, 2353 insertions(+), 2350 deletions(-) create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementation.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/impl/OSGiImplementationImpl.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java create mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java delete mode 100644 java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java delete mode 100644 java/sca/modules/implementation-osgi/src/test/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiPropertyTestCase.java delete mode 100644 java/sca/modules/implementation-osgi/src/test/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTestCase.java create mode 100644 java/sca/modules/implementation-osgi/src/test/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiPropertyTestCase.java create mode 100644 java/sca/modules/implementation-osgi/src/test/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTestCase.java (limited to 'java/sca/modules') diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementation.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementation.java new file mode 100644 index 0000000000..7bcb0a1da5 --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementation.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.implementation.osgi; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.assembly.Implementation; + +/** + * + * The model representing an OSGi implementation in an SCA assembly model. + * + * @version $Rev$ $Date$ + */ +public interface OSGiImplementation extends Implementation, Extensible { + + String getBundleSymbolicName(); + + String getBundleVersion(); + + String[] getImports(); + + List getReferenceProperties(String referenceName); + + List getServiceProperties(String serviceName); + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java deleted file mode 100644 index 73cae46324..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.osgi; - -import java.util.List; - -import org.apache.tuscany.sca.assembly.ComponentProperty; -import org.apache.tuscany.sca.assembly.Extensible; -import org.apache.tuscany.sca.assembly.Implementation; - -/** - * - * The model representing an OSGi implementation in an SCA assembly model. - * - * @version $Rev$ $Date$ - */ -public interface OSGiImplementationInterface extends Implementation, Extensible { - - String getBundleSymbolicName(); - - String getBundleVersion(); - - String[] getImports(); - - List getReferenceProperties(String referenceName); - - List getServiceProperties(String serviceName); - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/impl/OSGiImplementationImpl.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/impl/OSGiImplementationImpl.java new file mode 100644 index 0000000000..fe3efd22cd --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/impl/OSGiImplementationImpl.java @@ -0,0 +1,168 @@ +/* + * 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.osgi.impl; + + +import java.util.Hashtable; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.implementation.osgi.OSGiImplementation; + + +/** + * OSGi implementation + * All attributes from have getters in this class + * This class implements OSGiImplementationInterface which is associated with OSGiImplementationProvider. + * + * @version $Rev$ $Date$ + */ +public class OSGiImplementationImpl extends ImplementationImpl implements OSGiImplementation { + + private String bundleSymbolicName; + private String bundleVersion; + + private String[] imports; + private Hashtable> referenceProperties; + private Hashtable> serviceProperties; + + private Hashtable> referenceCallbackProperties; + private Hashtable> serviceCallbackProperties; + + private String[] classList; + + private ModelFactoryExtensionPoint modelFactories; + + private Object osgiBundle; + + public OSGiImplementationImpl( + ModelFactoryExtensionPoint modelFactories, + String bundleSymbolicName, + String bundleVersion, + String[] imports, + String[] classList, + Hashtable> refProperties, + Hashtable> serviceProperties) { + + super(); + this.bundleSymbolicName = bundleSymbolicName; + this.bundleVersion = bundleVersion; + this.imports = imports; + this.referenceProperties = refProperties; + this.serviceProperties = serviceProperties; + this.classList = classList; + this.modelFactories = modelFactories; + } + + public void setCallbackProperties(Hashtable> refCallbackProperties, + Hashtable> serviceCallbackProperties) { + + this.referenceCallbackProperties = refCallbackProperties; + this.serviceCallbackProperties = serviceCallbackProperties; + + } + + + public String getBundleSymbolicName() { + return bundleSymbolicName; + } + + public String getBundleVersion() { + return bundleVersion; + } + + public String[] getImports() { + return imports; + } + + public String[] getClassList() { + return classList; + } + + public ModelFactoryExtensionPoint getModelFactories() { + return modelFactories; + } + + public List getReferenceProperties(String referenceName) { + return referenceProperties.get(referenceName); + } + + public List getServiceProperties(String serviceName) { + return serviceProperties.get(serviceName); + } + + public List getReferenceCallbackProperties(String referenceName) { + return referenceCallbackProperties.get(referenceName); + } + + public List getServiceCallbackProperties(String serviceName) { + return serviceCallbackProperties.get(serviceName); + } + + /** + * Since OSGi implementation annotations may not be processed until much later, leave it to + * the OSGi invoker to decide whether pass-by-reference is allowed. + * @return + */ + public boolean isAllowsPassByReference() { + return true; + } + + public Object getOSGiBundle() { + return osgiBundle; + } + + public void setOSGiBundle(Object osgiBundle) { + this.osgiBundle = osgiBundle; + } + + private boolean areEqual(Object obj1, Object obj2) { + if (obj1 == obj2) + return true; + if (obj1 == null || obj2 == null) + return false; + return obj1.equals(obj2); + } + + @Override + public boolean equals(Object obj) { + + if (!(obj instanceof OSGiImplementationImpl)) + return super.equals(obj); + OSGiImplementationImpl impl = (OSGiImplementationImpl)obj; + if (!areEqual(bundleSymbolicName, impl.bundleSymbolicName)) + return false; + if (!areEqual(bundleVersion, impl.bundleVersion)) + return false; + if (!areEqual(serviceProperties, impl.serviceProperties)) + return false; + if (!areEqual(serviceCallbackProperties, impl.serviceCallbackProperties)) + return false; + if (!areEqual(referenceProperties, impl.referenceProperties)) + return false; + if (!areEqual(referenceCallbackProperties, impl.referenceCallbackProperties)) + return false; + return super.equals(obj); + } + + + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java deleted file mode 100644 index 3b08bbc7dc..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * 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.osgi.invocation; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Dictionary; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; -import java.util.StringTokenizer; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; -import java.util.zip.ZipEntry; - -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.Multiplicity; -import org.apache.tuscany.sca.assembly.Property; -import org.apache.tuscany.sca.assembly.Reference; -import org.apache.tuscany.sca.assembly.Service; -import org.apache.tuscany.sca.context.RequestContextFactory; -import org.apache.tuscany.sca.core.context.InstanceWrapper; -import org.apache.tuscany.sca.core.factory.ObjectCreationException; -import org.apache.tuscany.sca.core.factory.ObjectFactory; -import org.apache.tuscany.sca.core.invocation.JDKProxyFactory; -import org.apache.tuscany.sca.core.invocation.ProxyFactory; -import org.apache.tuscany.sca.core.scope.Scope; -import org.apache.tuscany.sca.core.scope.ScopeContainer; -import org.apache.tuscany.sca.core.scope.ScopeRegistry; -import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; -import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; -import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; -import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; -import org.apache.tuscany.sca.implementation.java.IntrospectionException; -import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; -import org.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface; -import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; -import org.apache.tuscany.sca.implementation.osgi.xml.OSGiImplementation; -import org.apache.tuscany.sca.interfacedef.Interface; -import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; -import org.apache.tuscany.sca.interfacedef.Operation; -import org.apache.tuscany.sca.interfacedef.java.JavaInterface; -import org.apache.tuscany.sca.invocation.Invoker; -import org.apache.tuscany.sca.invocation.MessageFactory; -import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime; -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.apache.tuscany.sca.runtime.RuntimeWire; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleEvent; -import org.osgi.framework.BundleException; -import org.osgi.framework.BundleListener; -import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkEvent; -import org.osgi.framework.FrameworkListener; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceEvent; -import org.osgi.framework.ServiceListener; -import org.osgi.service.packageadmin.ExportedPackage; -import org.osgi.service.packageadmin.PackageAdmin; - -/** - * The runtime instantiation of OSGi component implementations - * - * @version $Rev$ $Date$ - */ -public class OSGiImplementationProvider implements ScopedImplementationProvider, - FrameworkListener, - BundleListener { - - private static final String COMPONENT_SERVICE_NAME = "component.service.name"; - - // Maximum milliseconds to wait for a method to complete - private static final long METHOD_TIMEOUT_MILLIS = 60000; - // Maximum milliseconds to wait for services to be registered into OSGi service registry - private static final long SERVICE_TIMEOUT_MILLIS = 300000; - - private OSGiImplementation implementation; - private OSGiAnnotations osgiAnnotations; - private BundleContext bundleContext; - - private Hashtable referenceWires = new Hashtable(); - private Hashtable componentReferenceWires - = new Hashtable(); - private HashSet resolvedWires = new HashSet(); - private boolean wiresResolved; - - private AtomicInteger startBundleEntryCount = new AtomicInteger(); - private AtomicInteger processAnnotationsEntryCount = new AtomicInteger(); - - private JavaPropertyValueObjectFactory propertyValueFactory; - - - private Hashtable componentProperties = new Hashtable(); - private RuntimeComponent runtimeComponent; - - private Bundle osgiBundle; - private ArrayList dependentBundles = new ArrayList(); - private OSGiServiceListener osgiServiceListener; - private PackageAdmin packageAdmin; - - private OSGiRuntime osgiRuntime; - - private ScopeRegistry scopeRegistry; - private DataBindingExtensionPoint dataBindingRegistry; - - private boolean packagesRefreshed; - - private MessageFactory messageFactory; - private InterfaceContractMapper mapper; - - - public OSGiImplementationProvider(RuntimeComponent definition, - OSGiImplementationInterface impl, - DataBindingExtensionPoint dataBindingRegistry, - JavaPropertyValueObjectFactory propertyValueFactory, - ProxyFactory proxyFactory, - ScopeRegistry scopeRegistry, - RequestContextFactory requestContextFactory, - MessageFactory messageFactory, - InterfaceContractMapper mapper) throws BundleException { - - - this.implementation = (OSGiImplementation)impl; - this.runtimeComponent = definition; - this.dataBindingRegistry = dataBindingRegistry; - this.propertyValueFactory = propertyValueFactory; - this.scopeRegistry = scopeRegistry; - this.messageFactory = messageFactory; - this.mapper = mapper; - - bundleContext = getBundleContext(); - osgiBundle = (Bundle)implementation.getOSGiBundle(); - bundleContext.addBundleListener(this); - osgiServiceListener = new OSGiServiceListener(osgiBundle); - bundleContext.addServiceListener(osgiServiceListener); - - // Install and start all dependent bundles - String[] imports = implementation.getImports(); - for (int i = 0; i < imports.length; i++) { - String location = imports[i].trim(); - if (location.length() > 0) { - Bundle bundle = bundleContext.installBundle(location); - dependentBundles.add(bundle); - } - } - - - this.osgiAnnotations = new OSGiAnnotations( - implementation.getModelFactories(), - implementation.getClassList(), - runtimeComponent, - propertyValueFactory, - proxyFactory, - requestContextFactory, - osgiBundle, - dependentBundles); - - - // PackageAdmin is used to resolve bundles - org.osgi.framework.ServiceReference packageAdminReference = - bundleContext.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); - if (packageAdminReference != null) { - packageAdmin = (PackageAdmin) bundleContext.getService(packageAdminReference); - bundleContext.addFrameworkListener(this); - } - - - } - - protected RuntimeComponent getRuntimeComponent() { - return runtimeComponent; - } - - protected OSGiImplementation getImplementation() { - return implementation; - } - - // Create a property table from the list of properties - // The source properties are properties read from elements - // Create property values in the table of the appropriate class based - // on the property type specified. - private void processProperties(List props, Hashtable propsTable) { - - if (props != null) { - for (Object p : props) { - - Property prop = (Property)p; - Class javaType = SimpleTypeMapperImpl.getJavaType(prop.getXSDType()); - ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue(), javaType); - Object value = objFactory.getInstance(); - - propsTable.put(prop.getName(), value); - } - } - } - - - private BundleContext getBundleContext() throws BundleException { - - try { - if (bundleContext == null) { - osgiRuntime = OSGiRuntime.getRuntime(); - bundleContext = osgiRuntime .getBundleContext(); - } - } catch (BundleException e) { - throw e; - } catch (Exception e) { - throw new BundleException("Could not start OSGi runtime", e); - } - - - return bundleContext; - } - - - private String getOSGiFilter(Hashtable props) { - - String filter = ""; - - if (props != null && props.size() > 0) { - int propCount = 0; - for (String propName : props.keySet()) { - if (propName.equals("service.pid")) - continue; - filter = filter + "(" + propName + "=" + props.get(propName) + ")"; - propCount++; - } - - if (propCount > 1) filter = "(&" + filter + ")"; - } - else - filter = null; - return filter; - } - - /* - * Return a matching service registered by the specified bundle. - * If has the attribute filter defined, return a service - * reference that matches the filter. Otherwise, return a service which has a component - * name equal to this component's name. If not found, return a service which no - * component name set. - * - * Even though services registered by this bundle can be filtered using the - * service listener, we use this method to filter all service references so that - * the service matching functionality of OSGi can be directly used. - */ - private org.osgi.framework.ServiceReference getOSGiServiceReference( - String scaServiceName, - String osgiServiceName, String filter) - throws InvalidSyntaxException { - - String compServiceName = runtimeComponent.getName() + "/" + scaServiceName; - if (filter != null && filter.length() > 0) { - org.osgi.framework.ServiceReference[] references = - bundleContext.getServiceReferences(osgiServiceName, filter); - - - org.osgi.framework.ServiceReference reference = null; - if (references != null) { - for (org.osgi.framework.ServiceReference ref : references) { - if (ref.getBundle() != osgiBundle) - continue; - Object compName = ref.getProperty(COMPONENT_SERVICE_NAME); - if (compName == null && reference == null) - reference = ref; - if (scaServiceName == null || compServiceName.equals(compName)) { - reference = ref; - break; - } - } - } - - return reference; - - } - - filter = scaServiceName == null? null : - "(" + COMPONENT_SERVICE_NAME + "="+ compServiceName + ")"; - - org.osgi.framework.ServiceReference[] references = - bundleContext.getServiceReferences(osgiServiceName, filter); - - if (references != null) { - for (org.osgi.framework.ServiceReference ref : references) { - if (ref.getBundle() == osgiBundle) { - return ref; - } - } - } - - references = bundleContext.getServiceReferences(osgiServiceName, null); - - org.osgi.framework.ServiceReference reference = null; - - if (references != null) { - for (org.osgi.framework.ServiceReference ref : references) { - - if (ref.getBundle() != osgiBundle) - continue; - Object compName = ref.getProperty(COMPONENT_SERVICE_NAME); - if (compName == null && reference == null) - reference = ref; - if (compServiceName.equals(compName)) { - reference = ref; - break; - } - } - } - - return reference; - } - - /** - * This method is used to avoid full synchronization of methods which should - * be executed only once. - * - * entryCount=0: The count is incremented, and this thread executes the method. Returns true. - * - * entryCount=1: Another thread is already executing this method. - * Wait for the thread to complete if doWait is true. Returns false. - * - * entryCount=2: The method has already been executed. Returns false. - * - * @param doWait If true, and another method is executing this method - * wait for method execution to complete - * @param entryCount Atomic integer used to ensure that the method is - * executed only once - * @return true if this thread has exclusive access to execute this method - */ - private boolean enterMethod(boolean doWait, AtomicInteger entryCount) { - - if (entryCount.compareAndSet(0, 1)) { - return true; - } - else { - if (doWait) { - synchronized (entryCount) { - if (entryCount.get() != 2) { - try { - entryCount.wait(METHOD_TIMEOUT_MILLIS); - } catch (InterruptedException e) { - } - } - } - } - return false; - } - } - - /** - * Called on method exit of methods which were entered after - * enterMethod returned true. Increments entryCount, and wakes - * up threads waiting for the method to complete. - * - * @param entryCount Atomic integer used for synchronization - */ - private void exitMethod(AtomicInteger entryCount) { - entryCount.compareAndSet(1, 2); - synchronized (entryCount) { - entryCount.notifyAll(); - } - } - - protected Bundle startBundle(boolean doWait) throws ObjectCreationException { - - try { - - if (enterMethod(doWait, startBundleEntryCount)) { - - configurePropertiesUsingConfigAdmin(); - - resolveBundle(); - - processAnnotations(true); - - - for (Bundle bundle : dependentBundles) { - try { - if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) { - bundle.start(); - } - } catch (BundleException e) { - if (bundle.getHeaders().get("Fragment-Host") == null) - throw e; - } - } - - } - - if (osgiBundle.getState() != Bundle.ACTIVE && osgiBundle.getState() != Bundle.STARTING) { - - - int retry = 0; - - while (retry++ < 10) { - try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws BundleException { - osgiBundle.start(); - return null; - } - }); - break; - // } catch ( BundleException e) { - } catch ( PrivilegedActionException e) { - // It is possible that the thread "Refresh Packages" is in the process of - // changing the state of this bundle. - Thread.yield(); - - if (retry == 10) - throw e; - } - } - } - - } catch (Exception e) { - throw new ObjectCreationException(e); - } finally { - exitMethod(startBundleEntryCount); - } - return osgiBundle; - } - - - // This method is called by OSGiInstanceWrapper.getInstance to obtain the OSGi service reference - // corresponding to the specified service. The properties used to filter the service should - // be chosen based on whether this is a normal service or a callback. - protected org.osgi.framework.ServiceReference getOSGiServiceReference(ComponentService service) - throws ObjectCreationException { - - Hashtable props = new Hashtable(); - if (!service.isCallback()) - processProperties(implementation.getServiceProperties(service.getName()), props); - else - processProperties(implementation.getServiceCallbackProperties(service.getName()), props); - - String filter = getOSGiFilter(props); - Interface serviceInterface = service.getInterfaceContract().getInterface(); - String scaServiceName = service.getName(); - - return getOSGiServiceReference(serviceInterface, filter, scaServiceName); - - } - - protected org.osgi.framework.ServiceReference getOSGiServiceReference( - EndpointReference from, Interface callbackInterface) - throws ObjectCreationException { - - RuntimeWire refWire = null; - String filter = null; - for (RuntimeWire wire : referenceWires.keySet()) { - if (wire.getSource() == from) { - refWire = wire; - break; - } - } - if (refWire != null) { - Hashtable props = new Hashtable(); - ComponentReference scaRef = componentReferenceWires.get(refWire); - processProperties(implementation.getReferenceCallbackProperties(scaRef.getName()), props); - filter = getOSGiFilter(props); - } - - return getOSGiServiceReference(callbackInterface, filter, null); - } - - private org.osgi.framework.ServiceReference getOSGiServiceReference(Interface serviceInterface, - String filter, String scaServiceName) - throws ObjectCreationException { - - try { - - String serviceInterfaceName = null; - - org.osgi.framework.ServiceReference osgiServiceReference = null; - - if (serviceInterface instanceof JavaInterface) { - serviceInterfaceName = ((JavaInterface)serviceInterface).getJavaClass().getName(); - - if ((osgiServiceReference = getOSGiServiceReference( - scaServiceName, - serviceInterfaceName, filter)) == null) { - - // The service listener for our bundle will notify us when the service is registered. - synchronized (implementation) { - - // When declarative services are used, the component is started asynchronously - // So this thread has to wait for the service to be registered by the component - // activate method - // For regular bundle activators, bundle.start activates the bundle synchronously - // and hence the service would probably have been started by the bundle activator - long startTime = System.currentTimeMillis(); - while ((osgiServiceReference = getOSGiServiceReference( - scaServiceName, - serviceInterfaceName, filter)) == null) { - - // Wait for the bundle to register the service - implementation.wait(100); - if (System.currentTimeMillis() - startTime > SERVICE_TIMEOUT_MILLIS) - break; - } - } - - } - } - - return osgiServiceReference; - - } catch (Exception e) { - throw new ObjectCreationException(e); - } - } - - - // Felix does not support bundle fragments. This is a temporary workaround. - protected Bundle installDummyBundleWithoutFragments(Class interfaceClass) - throws Exception { - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - String EOL = System.getProperty("line.separator"); - - String interfaceName = interfaceClass.getName(); - String packageName = getPackageName(interfaceClass); - String bundleName = "dummy.sca." + packageName; - - String manifestStr = "Manifest-Version: 1.0" + EOL - + "Bundle-ManifestVersion: 2" + EOL + "Bundle-Name: " - + bundleName + EOL + "Bundle-SymbolicName: " + bundleName + EOL - + "Bundle-Version: " + "1.0.0" + EOL - + "Bundle-Localization: plugin" + EOL; - - ArrayList dummyClasses = new ArrayList(); - - StringBuilder manifestBuf = new StringBuilder(); - manifestBuf.append(manifestStr); - manifestBuf.append("Export-Package: " + packageName + EOL); - String exportedInterfaces = interfaceName; - Bundle existingBundle = getDummyHostBundle(packageName); - String existingClasses; - dummyClasses.add(interfaceClass.getName()); - for (Class clazz : interfaceClass.getClasses()) { - dummyClasses.add(clazz.getName()); - } - if (existingBundle != null && - (existingClasses = (String)existingBundle.getHeaders().get("SCA-Dummy-Classes")) != null) { - exportedInterfaces = exportedInterfaces + " " + existingClasses; - - StringTokenizer tokenizer = new StringTokenizer(existingClasses); - while (tokenizer.hasMoreTokens()) { - String className = tokenizer.nextToken(); - if (!dummyClasses.contains(className)) - dummyClasses.add(className); - } - } - - manifestBuf.append("SCA-Dummy-Classes: " + exportedInterfaces + EOL); - - ByteArrayInputStream manifestStream = new ByteArrayInputStream( - manifestBuf.toString().getBytes()); - Manifest manifest = new Manifest(); - manifest.read(manifestStream); - - JarOutputStream jarOut = new JarOutputStream(out, manifest); - - for (int i = 0; i < dummyClasses.size(); i++) { - - String className = dummyClasses.get(i); - - Class clazz = interfaceClass.getClassLoader().loadClass(className); - className = clazz.getName().replaceAll("\\.", "/") + ".class"; - ZipEntry ze = new ZipEntry(className); - jarOut.putNextEntry(ze); - InputStream stream = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); - - byte[] bytes = new byte[stream.available()]; - stream.read(bytes); - jarOut.write(bytes); - stream.close(); - } - - - jarOut.close(); - out.close(); - - if (existingBundle != null) { - existingBundle.stop(); - existingBundle.uninstall(); - } - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - - Bundle bundle = bundleContext.installBundle("file://" + bundleName - + ".jar", in); - - bundle.start(); - - if (existingBundle != null && packageAdmin != null) { - refreshPackages(); - - } - - return bundle; - - } - - private Bundle getDummyHostBundle(String packageName) { - - if (packageAdmin == null) - return null; - - ExportedPackage exp = packageAdmin.getExportedPackage(packageName); - if (exp == null) - return null; - else - return exp.getExportingBundle(); - } - - private static String getPackageName(Class cls) { - String name = cls.getName(); - int index = name.lastIndexOf('.'); - return index == -1 ? "" : name.substring(0, index); - } - - private Bundle installDummyBundle(Class interfaceClass) - throws Exception { - - - if (!osgiRuntime.supportsBundleFragments()) { - return installDummyBundleWithoutFragments(interfaceClass); - } - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - String EOL = System.getProperty("line.separator"); - ArrayList> dummyClasses = new ArrayList>(); - - String interfaceName = interfaceClass.getName(); - String packageName = getPackageName(interfaceClass); - String bundleName = "dummy.sca." + interfaceName; - - - String manifestStr = "Manifest-Version: 1.0" + EOL + - "Bundle-ManifestVersion: 2" + EOL + - "Bundle-Name: " + bundleName + EOL + - "Bundle-SymbolicName: " + bundleName + EOL + - "Bundle-Version: " + "1.0.0" + EOL + - "Bundle-Localization: plugin" + EOL; - - - StringBuilder manifestBuf = new StringBuilder(); - manifestBuf.append(manifestStr); - manifestBuf.append("Export-Package: " + packageName + EOL); - Bundle dummyHost = getDummyHostBundle(packageName); - if (dummyHost != null) - manifestBuf.append("Fragment-Host: " + dummyHost.getSymbolicName() + EOL); - - ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestBuf.toString().getBytes()); - Manifest manifest = new Manifest(); - manifest.read(manifestStream); - - dummyClasses.add(interfaceClass); - for (Class clazz : interfaceClass.getClasses()) { - dummyClasses.add(clazz); - } - - JarOutputStream jarOut = new JarOutputStream(out, manifest); - - for (int i = 0; i < dummyClasses.size(); i++) { - - Class clazz = dummyClasses.get(i); - String className = clazz.getName(); - className = clazz.getName().replaceAll("\\.", "/") + ".class"; - ZipEntry ze = new ZipEntry(className); - jarOut.putNextEntry(ze); - InputStream stream = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); - - byte[] bytes = new byte[stream.available()]; - stream.read(bytes); - jarOut.write(bytes); - stream.close(); - } - - jarOut.close(); - out.close(); - - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - - - Bundle bundle = bundleContext.installBundle( - "file://" + bundleName + ".jar", - in); - - if (dummyHost == null) - bundle.start(); - - return bundle; - - } - - - - public InstanceWrapper createInstanceWrapper() throws ObjectCreationException { - - return new OSGiInstanceWrapper(this, osgiAnnotations, bundleContext); - } - - - - private void resolveWireCreateDummyBundles(final Class interfaceClass) throws Exception { - - - try { - - osgiBundle.loadClass(interfaceClass.getName()); - - } catch (ClassNotFoundException e) { - - // The interface used by the proxy is not in the source bundle - // A dummy bundle needs to be installed to create the proxy - // Allow privileged access to file system. Requires FileSystem permission in security - // policy. - Bundle dummyBundle = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Bundle run() throws Exception { - return installDummyBundle(interfaceClass); - } - }); - - if (packageAdmin != null) { - - packageAdmin.resolveBundles(new Bundle[]{dummyBundle, osgiBundle}); - - } - - } - } - - /** - * For OSGi->Java wires, create a proxy corresponding to the Java interfaces - * and register the proxy with the OSGi registry, so that the source OSGi bundle can - * locate the target Java instance from the registry like a regular OSGi service. - * - * For OSGi->OSGi wires, start the target OSGi bundle, so that references of the - * target are resolved before the source OSGi bundle is started. If the reference - * has properties specified, create a Proxy and register a service with highest - * possible ranking. The Proxy should wire to the correct OSGi instance specified - * in the SCA composite. - * - * The first phase determines whether a proxy should be installed. It also registers - * a dummy bundle if necessary to resolve the bundle. When phase1 is completed on all - * wires of the component, the bundle should be resolved. Phase2 registers the proxy service. - */ - private boolean resolveWireResolveReferences(Bundle bundle, Class interfaceClass, RuntimeWire wire, - boolean isOSGiToOSGiWire) throws Exception { - - - // FIXME: At the moment injection of values into instances require an instance to be obtained - // through the instance wrapper, and hence requires a proxy. When we do this processing here, - // we don't yet know whether the target requires any property or callback injection. So it is - // safer to create a proxy all the time. - boolean createProxy = true; - - ComponentReference scaRef = componentReferenceWires.get(wire); - Hashtable targetProperties = new Hashtable(); - processProperties(implementation.getReferenceProperties(scaRef.getName()), targetProperties); - - - if (isOSGiToOSGiWire) { - - OSGiImplementationProvider implProvider = (OSGiImplementationProvider)wire.getTarget().getComponent().getImplementationProvider(); - - // This is an OSGi->OSGi wire - isOSGiToOSGiWire = true; - - // If the target component is stateless, use a proxy to create a new service each time - if (!implProvider.getScope().equals(Scope.COMPOSITE)) createProxy = true; - - Interface interfaze = wire.getTarget().getInterfaceContract().getInterface(); - - // If the target interface is remotable, create a proxy to support pass-by-value semantics - // AllowsPassByReference is not detected until the target instance is obtained. - if (interfaze.isRemotable()) - createProxy = true; - - // If any of the operations in the target interface is non-blocking, create a proxy - List ops = interfaze.getOperations(); - for (Operation op : ops) { - if (op.isNonBlocking()) - createProxy = true; - } - - // If properties are specified for the reference, create a proxy since rewiring may be required - if (targetProperties.size() > 0) { - createProxy = true; - } - - // If properties are specified for the component, create a proxy for configuring - // the component services. - if (componentProperties.size() > 0) { - createProxy = true; - } - - // Since this is an OSGi->OSGi wire, start the target bundle before starting the - // source bundle if there is no proxy. For direct wiring without a proxy, this ordering - // is irrelevant in terms of class resolution, but the target needs to be started at some - // point. But there is no opportunity later on to start the target OSGi bundle without a proxy. - // When a Proxy is used, the target bundle needs to be resolved for the source bundle - // to be resolved so that the interface is visible to the source. In this case the bundle - // will be started when an instance is needed. - if (!createProxy) { - implProvider.startBundle(false); - } - else { - implProvider.resolveBundle(); - } - } - else { - createProxy = true; - } - - return createProxy; - } - - - // Register proxy service - private void resolveWireRegisterProxyService(final Bundle bundle, final Class interfaceClass, RuntimeWire wire) throws Exception { - - ComponentReference scaRef = componentReferenceWires.get(wire); - Hashtable targetProperties = new Hashtable(); - processProperties(implementation.getReferenceProperties(scaRef.getName()), targetProperties); - targetProperties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); - - if (targetProperties.get(COMPONENT_SERVICE_NAME) == null && wire.getTarget().getComponent() != null) { - String compServiceName = wire.getTarget().getComponent().getName() + "/" + - wire.getTarget().getContract().getName(); - targetProperties.put(COMPONENT_SERVICE_NAME, compServiceName); - } - - - JDKProxyFactory proxyService = new JDKProxyFactory(messageFactory, mapper); - - // Allow privileged access to load classes. Requires getClassLoader permission in security - // policy. - final Class proxyInterface = AccessController.doPrivileged(new PrivilegedExceptionAction>() { - public Class run() throws Exception { - return bundle.loadClass(interfaceClass.getName()); - } - }); - - final Object proxy = proxyService.createProxy(proxyInterface, wire); - final Hashtable finalTargetProperties = targetProperties; - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - bundleContext.registerService(proxyInterface.getName(), proxy, finalTargetProperties); - return null; - } - }); - - - } - - - private void refreshPackages() { - - if (packageAdmin != null) { - synchronized (this) { - packagesRefreshed = false; - packageAdmin.refreshPackages(null); - - if (!packagesRefreshed) { - try { - this.wait(2000); - } catch (InterruptedException e) { - // ignore - } - } - packagesRefreshed = false; - } - } - } - - - private void resolveBundle() throws ObjectCreationException { - - - try { - - if (!wiresResolved) { - wiresResolved = true; - - if (!setReferencesAndProperties()) { - wiresResolved = false; - return; - } - - int refPlusServices = referenceWires.size() + runtimeComponent.getServices().size(); - boolean[] createProxyService = new boolean[refPlusServices]; - Class[] interfaceClasses = new Class[refPlusServices] ; - boolean[] isOSGiToOSGiWire = new boolean[refPlusServices]; - boolean[] wireResolved = new boolean[refPlusServices]; - int index = 0; - for (RuntimeWire wire : referenceWires.keySet()) { - - Reference reference = referenceWires.get(wire); - - isOSGiToOSGiWire[index] = wire.getTarget().getComponent() != null && - wire.getTarget().getComponent().getImplementationProvider() - instanceof OSGiImplementationProvider; - - Interface refInterface = reference.getInterfaceContract().getInterface(); - if (refInterface instanceof JavaInterface) { - interfaceClasses[index] = ((JavaInterface)refInterface).getJavaClass(); - - if (!isOSGiToOSGiWire[index]) - resolveWireCreateDummyBundles(interfaceClasses[index]); - - } - - if (!resolvedWires.contains(wire)) { - resolvedWires.add(wire); - } - else - wireResolved[index] = true; - - index++; - } - for (ComponentService service : runtimeComponent.getServices()) { - Interface callbackInterface = service.getInterfaceContract().getCallbackInterface(); - if (callbackInterface instanceof JavaInterface) { - interfaceClasses[index] = ((JavaInterface)callbackInterface).getJavaClass(); - - resolveWireCreateDummyBundles(interfaceClasses[index]); - } - - index++; - } - - index = 0; - for (RuntimeWire wire : referenceWires.keySet()) { - - if (!wireResolved[index]) { - createProxyService[index] = resolveWireResolveReferences(osgiBundle, - interfaceClasses[index], - wire, - isOSGiToOSGiWire[index]); - } - index++; - } - - refreshPackages(); - - - index = 0; - for (RuntimeWire wire : referenceWires.keySet()) { - - if (createProxyService[index] && !wireResolved[index]) - resolveWireRegisterProxyService(osgiBundle, interfaceClasses[index], wire); - index++; - } - } - else if (osgiBundle.getState() == Bundle.INSTALLED && packageAdmin != null) { - packageAdmin.resolveBundles(new Bundle[] {osgiBundle}); - } - - } catch (Exception e) { - e.printStackTrace(); - throw new ObjectCreationException(e); - } - } - - - @SuppressWarnings("unchecked") - private void configurePropertiesUsingConfigAdmin() { - - try { - - if (componentProperties.size() == 0) - return; - - org.osgi.framework.ServiceReference configAdminReference = - bundleContext.getServiceReference("org.osgi.service.cm.ConfigurationAdmin"); - if (configAdminReference != null) { - - Object cm = bundleContext.getService(configAdminReference); - Class cmClass = cm.getClass().getClassLoader().loadClass("org.osgi.service.cm.ConfigurationAdmin"); - Method getConfigMethod = cmClass.getMethod("getConfiguration", String.class, String.class); - - - Class configClass = cm.getClass().getClassLoader().loadClass("org.osgi.service.cm.Configuration"); - - Method getMethod = configClass.getMethod("getProperties"); - Method updateMethod = configClass.getMethod("update", Dictionary.class); - - List services = implementation.getServices(); - HashSet pidsProcessed = new HashSet(); - - for (Service service : services) { - - List serviceProps = implementation.getServiceProperties(service.getName()); - String pid = null; - - if (serviceProps != null) { - for (ComponentProperty prop : serviceProps) { - if (prop.getName().equals("service.pid")) { - ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, - prop.getValue(), String.class); - pid = (String)objFactory.getInstance(); - } - } - } - if (pid == null || pidsProcessed.contains(pid)) - continue; - - - - - Object config = getConfigMethod.invoke(cm, pid, null); - Dictionary props = (Dictionary) getMethod.invoke(config); - if (props == null) - props = new Hashtable(); - for (String propertyName : componentProperties.keySet()) { - - props.put(propertyName, componentProperties.get(propertyName)); - } - - updateMethod.invoke(config, props); - - - } - - } - - } catch (Exception e) { - e.printStackTrace(); - } - - } - - - - public boolean isOptimizable() { - return false; - } - - public Scope getScope() { - return osgiAnnotations.getScope(); - } - - public boolean isEagerInit() { - return osgiAnnotations.isEagerInit(); - } - - public long getMaxAge() { - return osgiAnnotations.getMaxAge(); - } - - public long getMaxIdleTime() { - return osgiAnnotations.getMaxIdleTime(); - } - - protected ScopeContainer getScopeContainer() { - startBundle(true); - return ((ScopedRuntimeComponent)runtimeComponent).getScopeContainer(); - } - - public Invoker createTargetInvoker(RuntimeComponentService service, Operation operation) { - - - Interface serviceInterface = operation.getInterface(); - boolean isRemotable = serviceInterface.isRemotable(); - - - Invoker invoker = new OSGiTargetInvoker(operation, this, service); - if (isRemotable) { - return new OSGiRemotableInvoker(osgiAnnotations, dataBindingRegistry, operation, this, service); - } else { - return invoker; - } - - } - - - public Invoker createInvoker(RuntimeComponentService service, Operation operation) { - return createTargetInvoker(service, operation); - } - - public boolean supportsOneWayInvocation() { - return false; - } - - private boolean setReferencesAndProperties() { - - for (Reference ref: implementation.getReferences()) { - List wireList = null; - ComponentReference compRef = null; - for (ComponentReference cRef : runtimeComponent.getReferences()) { - if (cRef.getName().equals(ref.getName())) { - - wireList = ((RuntimeComponentReference)cRef).getRuntimeWires(); - - compRef = cRef; - break; - } - } - - if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { - for (RuntimeWire wire : wireList) { - referenceWires.put(wire, ref); - componentReferenceWires.put(wire, compRef); - } - - } else { - if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { - throw new IllegalStateException("Required reference is missing: " + ref.getName()); - } - if (wireList != null && !wireList.isEmpty()) { - RuntimeWire wire = wireList.get(0); - referenceWires.put(wire, ref); - componentReferenceWires.put(wire, compRef); - } - - } - - } - - processProperties(runtimeComponent.getProperties(), componentProperties); - - return true; - - } - - public void start() { - setReferencesAndProperties(); - } - - public void processAnnotations(boolean doWait) throws IntrospectionException { - - if (!enterMethod(doWait, processAnnotationsEntryCount)) - return; - - try { - osgiAnnotations.processAnnotations(); - - Scope scope = osgiAnnotations.getScope(); - if (scope.equals(Scope.SYSTEM) || scope.equals(Scope.COMPOSITE)) { - // Nothing - } else { - - if (runtimeComponent instanceof ScopedRuntimeComponent) { - - ScopedRuntimeComponent component = (ScopedRuntimeComponent) runtimeComponent; - - ScopeContainer oldScopeContainer = component.getScopeContainer(); - component.setScopeContainer(null); - ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); - - if (oldScopeContainer != null && oldScopeContainer.getLifecycleState() == ScopeContainer.RUNNING) { - scopeContainer.start(); - } - - component.setScopeContainer(scopeContainer); - } - - } - } finally { - exitMethod(processAnnotationsEntryCount); - } - } - - public void stop() { - - if (osgiServiceListener != null) - bundleContext.removeServiceListener(osgiServiceListener); - } - - - - public void frameworkEvent(FrameworkEvent event) { - if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) { - synchronized (this) { - packagesRefreshed = true; - this.notifyAll(); - } - } - - } - - public void bundleChanged(BundleEvent event) { - if (event.getType() == BundleEvent.RESOLVED && event.getBundle() == osgiBundle) { - try { - processAnnotations(false); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - private class OSGiServiceListener implements ServiceListener { - - private Bundle bundle; - - OSGiServiceListener(Bundle bundle) { - this.bundle = bundle; - } - - public void serviceChanged(org.osgi.framework.ServiceEvent event) { - - - org.osgi.framework.ServiceReference reference = event.getServiceReference(); - - if (event.getType() == ServiceEvent.REGISTERED && reference.getBundle() == bundle) { - - synchronized (implementation) { - - implementation.notifyAll(); - } - } - - if (event.getType() == ServiceEvent.UNREGISTERING && reference.getBundle() == bundle) { - // TODO: Process deregistering of OSGi services. - } - } - } -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java deleted file mode 100644 index 5c9bfc94f0..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.osgi.invocation; - - -import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; -import org.apache.tuscany.sca.context.RequestContextFactory; -import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; -import org.apache.tuscany.sca.core.ExtensionPointRegistry; -import org.apache.tuscany.sca.core.UtilityExtensionPoint; -import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; -import org.apache.tuscany.sca.core.invocation.ProxyFactory; -import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; -import org.apache.tuscany.sca.core.scope.ScopeRegistry; -import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; -import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; -import org.apache.tuscany.sca.databinding.impl.MediatorImpl; -import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; -import org.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface; -import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; -import org.apache.tuscany.sca.invocation.MessageFactory; -import org.apache.tuscany.sca.provider.ImplementationProvider; -import org.apache.tuscany.sca.provider.ImplementationProviderFactory; -import org.apache.tuscany.sca.runtime.RuntimeComponent; -import org.osgi.framework.BundleException; - - -/** - * Builds a OSGi-based implementation provider from a component definition - * - * @version $Rev$ $Date$ - */ -public class OSGiImplementationProviderFactory implements ImplementationProviderFactory { - - private DataBindingExtensionPoint dataBindings; - private JavaPropertyValueObjectFactory propertyFactory; - private ProxyFactory proxyFactory; - private ScopeRegistry scopeRegistry; - private MessageFactory messageFactory; - private InterfaceContractMapper mapper; - - private RequestContextFactory requestContextFactory; - - public OSGiImplementationProviderFactory(ExtensionPointRegistry extensionPoints ) { - - dataBindings = extensionPoints.getExtensionPoint(DataBindingExtensionPoint.class); - ProxyFactoryExtensionPoint proxyFactories = extensionPoints.getExtensionPoint(ProxyFactoryExtensionPoint.class); - proxyFactory = new ExtensibleProxyFactory(proxyFactories); - ContextFactoryExtensionPoint contextFactories = extensionPoints.getExtensionPoint(ContextFactoryExtensionPoint.class); - requestContextFactory = contextFactories.getFactory(RequestContextFactory.class); - - - // FIXME: Scope registry is not an extension point, and this usage is specific - // to implementation.osgi since it needs to change scope after the component is - // created. Do we need to find a better way? - scopeRegistry = extensionPoints.getExtensionPoint(ScopeRegistry.class); - - TransformerExtensionPoint transformers = extensionPoints.getExtensionPoint(TransformerExtensionPoint.class); - MediatorImpl mediator = new MediatorImpl(dataBindings, transformers); - propertyFactory = new JavaPropertyValueObjectFactory(mediator); - - ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); - messageFactory = modelFactories.getFactory(MessageFactory.class); - - UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); - mapper = utilities.getUtility(InterfaceContractMapper.class); - } - - public ImplementationProvider createImplementationProvider(RuntimeComponent component, - OSGiImplementationInterface implementation) { - - try { - - return new OSGiImplementationProvider(component, - implementation, - dataBindings, - propertyFactory, - proxyFactory, - scopeRegistry, - requestContextFactory, - messageFactory, - mapper - ); - - } catch (BundleException e) { - throw new RuntimeException(e); - } - - } - - public Class getModelType() { - return OSGiImplementationInterface.class; - } - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java deleted file mode 100644 index ab1c9fedba..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * 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.osgi.invocation; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; - -import org.apache.tuscany.sca.assembly.ComponentService; -import org.apache.tuscany.sca.core.context.InstanceWrapper; -import org.apache.tuscany.sca.core.scope.Scope; -import org.apache.tuscany.sca.core.scope.TargetDestructionException; -import org.apache.tuscany.sca.core.scope.TargetInitializationException; -import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; -import org.apache.tuscany.sca.interfacedef.Interface; -import org.apache.tuscany.sca.interfacedef.java.JavaInterface; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.ServiceReference; -import org.osoa.sca.annotations.Destroy; -import org.osoa.sca.annotations.Init; - - -/** - * InstanceWrapper for creating instances for OSGi components. - * This class needs to implement InstanceWrapper since the wrapper is stored in - * the scope container. But getInstance() is called on this wrapper only through the - * OSGi target invoker. OSGiTargetInvoker always invokes getInstance for a specific - * service since one OSGi SCA component can associate different objects with - * different services (this is different from Java SCA components which always associate - * a single component instance with multiple services). - * - * @version $Rev$ $Date$ - */ -public class OSGiInstanceWrapper implements InstanceWrapper { - private static final Random RANDOM_NUMBER_GENERATOR = new Random(); - - private OSGiAnnotations annotationProcessor; - private OSGiImplementationProvider provider; - private BundleContext bundleContext; - private Hashtable> instanceInfoList = - new Hashtable>(); - - // Dummy bundles are used to create a new service object for scopes other than COMPOSITE - private Bundle dummyReferenceBundle; - - - public OSGiInstanceWrapper(OSGiImplementationProvider provider, - OSGiAnnotations annotationProcessor, - BundleContext bundleContext) { - - this.provider = provider; - this.annotationProcessor = annotationProcessor; - this.bundleContext = bundleContext; - } - - public synchronized T getInstance(ComponentService service) throws TargetInitializationException { - - // If an instance corresponding to this service has already been created, return the instance. - if (instanceInfoList.get(service) != null) - return instanceInfoList.get(service).osgiInstance; - - // There is no strict relation between service and callback instances. The instance semantics - // actually applies to the component instance in SCA. But for OSGi services, the callback - // is just another OSGi service, and could correspond to any of the service instances in - // the component. To implement the SCA scope semantics for callbacks, OSGi callbacks - // should also be made on the service object which implements the callback. The following code - // finds the first possible callback instance based on the interfaces implemented by the service - // objects in this component. Note that the interfaces are checked by name rather than using - // instanceof since the class seen by Tuscany could be from a different classloader from that - // used by the bundle. - if (service.isCallback()) { - Iterator> instances = instanceInfoList.values().iterator(); - while (instances.hasNext()) { - InstanceInfo instanceInfo = instances.next(); - Interface interfaze = service.getInterfaceContract().getInterface(); - if (interfaze instanceof JavaInterface && ((JavaInterface)interfaze).getJavaClass() != null) { - String interfaceName = ((JavaInterface)interfaze).getJavaClass().getName(); - Class[] interfaces = instanceInfo.osgiInstance.getClass().getInterfaces(); - for (Class clazz : interfaces) { - if (clazz.getName().equals(interfaceName)) { - return instanceInfo.osgiInstance; - } - } - - } - - } - } - - Bundle refBundle = provider.startBundle(true); - - // For scopes other than composite, the service object is obtained using a dummy reference - // bundle to guarantee that a new instance is created each time. This combined with the Tuscany - // scope container code guarantee SCA scope semantics for OSGi components as long as service - // factories are used. - if (!annotationProcessor.getScope().equals(Scope.COMPOSITE)) { - refBundle = getDummyReferenceBundle(); - } - - InstanceInfo instanceInfo = new InstanceInfo(); - - instanceInfo.refBundleContext = refBundle.getBundleContext(); - - instanceInfo.osgiInstance = getInstanceObject(instanceInfo, service); - - try { - - if (!isInitialized(instanceInfo.osgiInstance)) { - - annotationProcessor.injectProperties(instanceInfo.osgiInstance); - callLifecycleMethod(instanceInfo.osgiInstance, Init.class); - - instanceInfo.isFirstInstance = true; - } - - instanceInfoList.put(service, instanceInfo); - - } catch (Exception e) { - throw new TargetInitializationException(e); - } - - return instanceInfo.osgiInstance; - } - - - - // This method is provided purely to implement InstanceWrapper interface, and is never called. - public T getInstance() { - - return null; - } - - public void start() throws TargetInitializationException { - - if (provider.isEagerInit()) { - List services = provider.getRuntimeComponent().getServices(); - for (ComponentService service : services) { - getInstance(service); - } - } - } - - public synchronized void stop() throws TargetDestructionException { - - for (InstanceInfo instanceInfo : instanceInfoList.values()) { - if (instanceInfo.osgiInstance != null && instanceInfo.osgiServiceReference != null) { - - try { - - if (instanceInfo.isFirstInstance) - callLifecycleMethod(instanceInfo.osgiInstance, Destroy.class); - - instanceInfo.refBundleContext.ungetService(instanceInfo.osgiServiceReference); - - instanceInfo.osgiInstance = null; - instanceInfo.osgiServiceReference = null; - - } catch (Exception e) { - throw new TargetDestructionException(e); - } - } - } - instanceInfoList.clear(); - if (dummyReferenceBundle != null) { - try { - dummyReferenceBundle.uninstall(); - } catch (BundleException e) { - throw new TargetDestructionException(e); - } - dummyReferenceBundle = null; - } - } - - @SuppressWarnings("unchecked") - private T getInstanceObject(InstanceInfo instanceInfo, ComponentService service) { - - /** - * Since implementation.osgi is not well integrated with the OSGi lifecycle - * it is possible that the service is deactivated before the service instance - * is obtained when using declarative services. Retry in this case. - */ - int maxRetries = 10; - for (int i = 0; i < maxRetries; i++) { - instanceInfo.osgiServiceReference = provider.getOSGiServiceReference(service); - if (instanceInfo.osgiServiceReference == null) - return null; - T obj = (T)instanceInfo.refBundleContext.getService(instanceInfo.osgiServiceReference); - if (obj != null) - return obj; - } - return null; - } - - private Bundle getDummyReferenceBundle() throws TargetInitializationException { - - if (dummyReferenceBundle != null) - return dummyReferenceBundle; - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - String EOL = System.getProperty("line.separator"); - String bundleName = "dummy.sca." + RANDOM_NUMBER_GENERATOR.nextInt(); - - - String manifestStr = "Manifest-Version: 1.0" + EOL + - "Bundle-ManifestVersion: 2" + EOL + - "Bundle-Name: " + bundleName + EOL + - "Bundle-SymbolicName: " + bundleName + EOL + - "Bundle-Version: " + "1.0.0" + EOL + - "Bundle-Localization: plugin" + EOL; - - - StringBuilder manifestBuf = new StringBuilder(); - manifestBuf.append(manifestStr); - - try { - ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestBuf.toString().getBytes()); - Manifest manifest = new Manifest(); - manifest.read(manifestStream); - - - JarOutputStream jarOut = new JarOutputStream(out, manifest); - - jarOut.close(); - out.close(); - - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - - dummyReferenceBundle = bundleContext.installBundle("file://" + bundleName + ".jar", in); - - dummyReferenceBundle.start(); - - } catch (Exception e) { - throw new TargetInitializationException(e); - } - - return dummyReferenceBundle; - - } - - private void callLifecycleMethod(Object instance, - Class annotationClass) throws Exception { - - Method method = null; - if (annotationClass == Init.class) { - method = annotationProcessor.getInitMethod(instance); - } else if (annotationClass == Destroy.class) { - method = annotationProcessor.getDestroyMethod(instance); - } - - if (method != null) { - method.setAccessible(true); - method.invoke(instance); - } - } - - private boolean isInitialized(Object instance) { - for (InstanceInfo info : instanceInfoList.values()) { - if (info.osgiInstance == instance) - return true; - } - return false; - } - - private static class InstanceInfo { - private T osgiInstance; - private ServiceReference osgiServiceReference; - private BundleContext refBundleContext; - private boolean isFirstInstance; - - } - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java deleted file mode 100644 index d8f19580eb..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.osgi.invocation; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.IdentityHashMap; -import java.util.Map; - -import org.apache.tuscany.sca.databinding.DataBinding; -import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; -import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; -import org.apache.tuscany.sca.interfacedef.DataType; -import org.apache.tuscany.sca.interfacedef.Operation; -import org.apache.tuscany.sca.invocation.DataExchangeSemantics; -import org.apache.tuscany.sca.invocation.Message; -import org.apache.tuscany.sca.runtime.RuntimeComponentService; - -/** - * An interceptor to enforce pass-by-value semantics for remotable interfaces - * - * @version $Rev$ $Date$ - */ -public class OSGiRemotableInvoker extends OSGiTargetInvoker implements DataExchangeSemantics { - - private DataBindingExtensionPoint registry; - private Operation operation; - private OSGiAnnotations osgiAnnotations; - - /** - * @param registry - * @param operation - * @param method - * @param component - */ - public OSGiRemotableInvoker(OSGiAnnotations osgiAnnotations, - DataBindingExtensionPoint registry, - Operation operation, - OSGiImplementationProvider provider, - RuntimeComponentService service) { - super(operation, provider, service); - this.osgiAnnotations = osgiAnnotations; - this.registry = registry; - this.operation = operation; - } - - @Override - public Object invokeMethod(Object targetObject, Method m, Message msg) throws InvocationTargetException { - - Object result; - if (osgiAnnotations.isAllowsPassByReference(targetObject, m)) { - result = super.invokeMethod(targetObject, m, msg); - } else { - Object obj = msg.getBody(); - msg.setBody(copy((Object[])obj)); - - result = super.invokeMethod(targetObject, m, msg); - - if (operation.getOutputType() != null) { - String dataBindingId = operation.getOutputType().getDataBinding(); - DataBinding dataBinding = registry.getDataBinding(dataBindingId); - result = copy(result, operation.getOutputType(), dataBinding); - } - } - return result; - } - - public Object[] copy(Object[] args) { - if (args == null) { - return null; - } - Object[] copiedArgs = new Object[args.length]; - Map map = new IdentityHashMap(); - for (int i = 0; i < args.length; i++) { - if (args[i] == null) { - copiedArgs[i] = null; - } else { - Object copiedArg = map.get(args[i]); - if (copiedArg != null) { - copiedArgs[i] = copiedArg; - } else { - DataType dt = operation.getInputType().getLogical().get(i); - String dataBindingId = dt.getDataBinding(); - DataBinding dataBinding = registry.getDataBinding(dataBindingId); - copiedArg = copy(args[i], dt, dataBinding); - map.put(args[i], copiedArg); - copiedArgs[i] = copiedArg; - } - } - } - return copiedArgs; - } - - public Object copy(Object arg, DataType dataType, DataBinding argDataBinding) { - if (arg == null) { - return null; - } - Object copiedArg; - if (argDataBinding != null) { - copiedArg = argDataBinding.copy(arg, dataType, operation); - } else { - copiedArg = arg; - dataType = registry.introspectType(arg, operation); - if (dataType != null) { - DataBinding binding = registry.getDataBinding(dataType.getDataBinding()); - if (binding != null) { - copiedArg = binding.copy(arg, dataType, operation); - } - } - // FIXME: What to do if it's not recognized? - } - return copiedArg; - } - - /** - * @see org.apache.tuscany.sca.invocation.PassByValueAware#allowsPassByReference() - */ - public boolean allowsPassByReference() { - return true; - } - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java deleted file mode 100644 index e464b3b15d..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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.osgi.invocation; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.apache.tuscany.sca.core.context.InstanceWrapper; -import org.apache.tuscany.sca.core.invocation.TargetInvocationException; -import org.apache.tuscany.sca.core.scope.Scope; -import org.apache.tuscany.sca.core.scope.ScopeContainer; -import org.apache.tuscany.sca.core.scope.TargetResolutionException; -import org.apache.tuscany.sca.interfacedef.ConversationSequence; -import org.apache.tuscany.sca.interfacedef.Operation; -import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; -import org.apache.tuscany.sca.invocation.Invoker; -import org.apache.tuscany.sca.invocation.Message; -import org.apache.tuscany.sca.runtime.EndpointReference; -import org.apache.tuscany.sca.runtime.ReferenceParameters; -import org.apache.tuscany.sca.runtime.RuntimeComponentService; - -/** - * Java->OSGi references use OSGiTargetInvoker to call methods from OSGi bundles - * OSGi->Java references use JDKProxyService and invocation handler and do not use this class - * OSGi->OSGi references go through OSGi reference mechanisms when a proxy is not used - * When a proxy is used, this invoker is used to call methods from OSGi bundles - * A proxy is used for OSGi->OSGi if - * 1) target reference properties are specified OR - * 2) there are one or more non-blocking methods in the target interface OR - * 3) scope is not COMPOSITE - * - * @version $Rev$ $Date$ - */ -public class OSGiTargetInvoker implements Invoker { - - private Operation operation; - protected InstanceWrapper target; - - private final OSGiImplementationProvider provider; - private final RuntimeComponentService service; - - // Scope container is reset by the OSGi implementation provider if @Scope - // annotation is used to modify the scope (default is composite) - // Hence this field is initialized on the first invoke. - private ScopeContainer scopeContainer; - - public OSGiTargetInvoker( - Operation operation, - OSGiImplementationProvider provider, - RuntimeComponentService service) { - - - this.operation = operation; - this.service = service; - this.provider = provider; - - } - - /** - * Resolves the target service instance or returns a cached one - */ - @SuppressWarnings("unchecked") - protected InstanceWrapper getInstance(Object contextId) - throws TargetResolutionException, TargetInvocationException { - - if (scopeContainer == null) - scopeContainer = provider.getScopeContainer(); - - - return scopeContainer.getWrapper(contextId); - - } - - @SuppressWarnings("unchecked") - private Object invokeTarget(Message msg) throws InvocationTargetException { - - if (scopeContainer == null) - scopeContainer = provider.getScopeContainer(); - - - Operation op = msg.getOperation(); - if (op == null) { - op = this.operation; - } - ConversationSequence sequence = op.getConversationSequence(); - - Object contextId = null; - - EndpointReference from = msg.getFrom(); - ReferenceParameters parameters = null; - - if (from != null) { - parameters = from.getReferenceParameters(); - } - // check what sort of context is required - if (scopeContainer != null) { - Scope scope = scopeContainer.getScope(); - if (scope == Scope.REQUEST) { - contextId = Thread.currentThread(); - } else if (scope == Scope.CONVERSATION && parameters != null) { - contextId = parameters.getConversationID(); - } - } - - try { - - OSGiInstanceWrapper wrapper = (OSGiInstanceWrapper)getInstance(contextId); - Object instance; - - - // detects whether the scope container has created a conversation Id. This will - // happen in the case that the component has conversational scope but only the - // callback interface is conversational. Or in the callback case if the service interface - // is conversational and the callback interface isn't. If we are in this situation we need - // to get the contextId of this component and remove it after we have invoked the method on - // it. It is possible that the component instance will not go away when it is removed below - // because a callback conversation will still be holding a reference to it - boolean removeTemporaryConversationalComponentAfterCall = false; - if (parameters != null && (contextId == null) && (parameters.getConversationID() != null)) { - contextId = parameters.getConversationID(); - removeTemporaryConversationalComponentAfterCall = true; - } - - instance = wrapper.getInstance(service); - - Method m = JavaInterfaceUtil.findMethod(instance.getClass(), operation); - - Object ret = invokeMethod(instance, m, msg); - - scopeContainer.returnWrapper(wrapper, contextId); - - if ((sequence == ConversationSequence.CONVERSATION_END) || (removeTemporaryConversationalComponentAfterCall)) { - // if end conversation, or we have the special case where a conversational - // object was created to service the stateless half of a stateful component - scopeContainer.remove(contextId); - parameters.setConversationID(null); - } - - return ret; - } catch (InvocationTargetException e) { - throw e; - } catch (Exception e) { - throw new InvocationTargetException(e); - } - } - - protected Object invokeMethod(Object instance, Method m, Message msg) throws InvocationTargetException { - - try { - - Object payload = msg.getBody(); - - if (payload != null && !payload.getClass().isArray()) { - return m.invoke(instance, payload); - } else { - return m.invoke(instance, (Object[])payload); - } - - } catch (InvocationTargetException e) { - throw e; - } catch (Exception e) { - throw new InvocationTargetException(e); - } - } - - public Message invoke(Message msg) { - try { - // Object messageId = msg.getMessageID(); - // Message workContext = ThreadMessageContext.getMessageContext(); - // if (messageId != null) { - // workContext.setCorrelationID(messageId); - // } - Object resp = invokeTarget(msg); - msg.setBody(resp); - } catch (InvocationTargetException e) { - msg.setFaultBody(e.getCause()); - } - return msg; - } - - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java new file mode 100644 index 0000000000..5664c77618 --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java @@ -0,0 +1,1254 @@ +/* + * 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.osgi.runtime; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.StringTokenizer; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +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.Multiplicity; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.JDKProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.osgi.OSGiImplementation; +import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; +import org.apache.tuscany.sca.implementation.osgi.impl.OSGiImplementationImpl; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime; +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.apache.tuscany.sca.runtime.RuntimeWire; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkEvent; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.service.packageadmin.ExportedPackage; +import org.osgi.service.packageadmin.PackageAdmin; + +/** + * The runtime instantiation of OSGi component implementations + * + * @version $Rev$ $Date$ + */ +public class OSGiImplementationProvider implements ScopedImplementationProvider, + FrameworkListener, + BundleListener { + + private static final String COMPONENT_SERVICE_NAME = "component.service.name"; + + // Maximum milliseconds to wait for a method to complete + private static final long METHOD_TIMEOUT_MILLIS = 60000; + // Maximum milliseconds to wait for services to be registered into OSGi service registry + private static final long SERVICE_TIMEOUT_MILLIS = 300000; + + private OSGiImplementationImpl implementation; + private OSGiAnnotations osgiAnnotations; + private BundleContext bundleContext; + + private Hashtable referenceWires = new Hashtable(); + private Hashtable componentReferenceWires + = new Hashtable(); + private HashSet resolvedWires = new HashSet(); + private boolean wiresResolved; + + private AtomicInteger startBundleEntryCount = new AtomicInteger(); + private AtomicInteger processAnnotationsEntryCount = new AtomicInteger(); + + private JavaPropertyValueObjectFactory propertyValueFactory; + + + private Hashtable componentProperties = new Hashtable(); + private RuntimeComponent runtimeComponent; + + private Bundle osgiBundle; + private ArrayList dependentBundles = new ArrayList(); + private OSGiServiceListener osgiServiceListener; + private PackageAdmin packageAdmin; + + private OSGiRuntime osgiRuntime; + + private ScopeRegistry scopeRegistry; + private DataBindingExtensionPoint dataBindingRegistry; + + private boolean packagesRefreshed; + + private MessageFactory messageFactory; + private InterfaceContractMapper mapper; + + + public OSGiImplementationProvider(RuntimeComponent definition, + OSGiImplementation impl, + DataBindingExtensionPoint dataBindingRegistry, + JavaPropertyValueObjectFactory propertyValueFactory, + ProxyFactory proxyFactory, + ScopeRegistry scopeRegistry, + RequestContextFactory requestContextFactory, + MessageFactory messageFactory, + InterfaceContractMapper mapper) throws BundleException { + + + this.implementation = (OSGiImplementationImpl)impl; + this.runtimeComponent = definition; + this.dataBindingRegistry = dataBindingRegistry; + this.propertyValueFactory = propertyValueFactory; + this.scopeRegistry = scopeRegistry; + this.messageFactory = messageFactory; + this.mapper = mapper; + + bundleContext = getBundleContext(); + osgiBundle = (Bundle)implementation.getOSGiBundle(); + bundleContext.addBundleListener(this); + osgiServiceListener = new OSGiServiceListener(osgiBundle); + bundleContext.addServiceListener(osgiServiceListener); + + // Install and start all dependent bundles + String[] imports = implementation.getImports(); + for (int i = 0; i < imports.length; i++) { + String location = imports[i].trim(); + if (location.length() > 0) { + Bundle bundle = bundleContext.installBundle(location); + dependentBundles.add(bundle); + } + } + + + this.osgiAnnotations = new OSGiAnnotations( + implementation.getModelFactories(), + implementation.getClassList(), + runtimeComponent, + propertyValueFactory, + proxyFactory, + requestContextFactory, + osgiBundle, + dependentBundles); + + + // PackageAdmin is used to resolve bundles + org.osgi.framework.ServiceReference packageAdminReference = + bundleContext.getServiceReference("org.osgi.service.packageadmin.PackageAdmin"); + if (packageAdminReference != null) { + packageAdmin = (PackageAdmin) bundleContext.getService(packageAdminReference); + bundleContext.addFrameworkListener(this); + } + + + } + + protected RuntimeComponent getRuntimeComponent() { + return runtimeComponent; + } + + protected OSGiImplementationImpl getImplementation() { + return implementation; + } + + // Create a property table from the list of properties + // The source properties are properties read from elements + // Create property values in the table of the appropriate class based + // on the property type specified. + private void processProperties(List props, Hashtable propsTable) { + + if (props != null) { + for (Object p : props) { + + Property prop = (Property)p; + Class javaType = SimpleTypeMapperImpl.getJavaType(prop.getXSDType()); + ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue(), javaType); + Object value = objFactory.getInstance(); + + propsTable.put(prop.getName(), value); + } + } + } + + + private BundleContext getBundleContext() throws BundleException { + + try { + if (bundleContext == null) { + osgiRuntime = OSGiRuntime.getRuntime(); + bundleContext = osgiRuntime .getBundleContext(); + } + } catch (BundleException e) { + throw e; + } catch (Exception e) { + throw new BundleException("Could not start OSGi runtime", e); + } + + + return bundleContext; + } + + + private String getOSGiFilter(Hashtable props) { + + String filter = ""; + + if (props != null && props.size() > 0) { + int propCount = 0; + for (String propName : props.keySet()) { + if (propName.equals("service.pid")) + continue; + filter = filter + "(" + propName + "=" + props.get(propName) + ")"; + propCount++; + } + + if (propCount > 1) filter = "(&" + filter + ")"; + } + else + filter = null; + return filter; + } + + /* + * Return a matching service registered by the specified bundle. + * If has the attribute filter defined, return a service + * reference that matches the filter. Otherwise, return a service which has a component + * name equal to this component's name. If not found, return a service which no + * component name set. + * + * Even though services registered by this bundle can be filtered using the + * service listener, we use this method to filter all service references so that + * the service matching functionality of OSGi can be directly used. + */ + private org.osgi.framework.ServiceReference getOSGiServiceReference( + String scaServiceName, + String osgiServiceName, String filter) + throws InvalidSyntaxException { + + String compServiceName = runtimeComponent.getName() + "/" + scaServiceName; + if (filter != null && filter.length() > 0) { + org.osgi.framework.ServiceReference[] references = + bundleContext.getServiceReferences(osgiServiceName, filter); + + + org.osgi.framework.ServiceReference reference = null; + if (references != null) { + for (org.osgi.framework.ServiceReference ref : references) { + if (ref.getBundle() != osgiBundle) + continue; + Object compName = ref.getProperty(COMPONENT_SERVICE_NAME); + if (compName == null && reference == null) + reference = ref; + if (scaServiceName == null || compServiceName.equals(compName)) { + reference = ref; + break; + } + } + } + + return reference; + + } + + filter = scaServiceName == null? null : + "(" + COMPONENT_SERVICE_NAME + "="+ compServiceName + ")"; + + org.osgi.framework.ServiceReference[] references = + bundleContext.getServiceReferences(osgiServiceName, filter); + + if (references != null) { + for (org.osgi.framework.ServiceReference ref : references) { + if (ref.getBundle() == osgiBundle) { + return ref; + } + } + } + + references = bundleContext.getServiceReferences(osgiServiceName, null); + + org.osgi.framework.ServiceReference reference = null; + + if (references != null) { + for (org.osgi.framework.ServiceReference ref : references) { + + if (ref.getBundle() != osgiBundle) + continue; + Object compName = ref.getProperty(COMPONENT_SERVICE_NAME); + if (compName == null && reference == null) + reference = ref; + if (compServiceName.equals(compName)) { + reference = ref; + break; + } + } + } + + return reference; + } + + /** + * This method is used to avoid full synchronization of methods which should + * be executed only once. + * + * entryCount=0: The count is incremented, and this thread executes the method. Returns true. + * + * entryCount=1: Another thread is already executing this method. + * Wait for the thread to complete if doWait is true. Returns false. + * + * entryCount=2: The method has already been executed. Returns false. + * + * @param doWait If true, and another method is executing this method + * wait for method execution to complete + * @param entryCount Atomic integer used to ensure that the method is + * executed only once + * @return true if this thread has exclusive access to execute this method + */ + private boolean enterMethod(boolean doWait, AtomicInteger entryCount) { + + if (entryCount.compareAndSet(0, 1)) { + return true; + } + else { + if (doWait) { + synchronized (entryCount) { + if (entryCount.get() != 2) { + try { + entryCount.wait(METHOD_TIMEOUT_MILLIS); + } catch (InterruptedException e) { + } + } + } + } + return false; + } + } + + /** + * Called on method exit of methods which were entered after + * enterMethod returned true. Increments entryCount, and wakes + * up threads waiting for the method to complete. + * + * @param entryCount Atomic integer used for synchronization + */ + private void exitMethod(AtomicInteger entryCount) { + entryCount.compareAndSet(1, 2); + synchronized (entryCount) { + entryCount.notifyAll(); + } + } + + protected Bundle startBundle(boolean doWait) throws ObjectCreationException { + + try { + + if (enterMethod(doWait, startBundleEntryCount)) { + + configurePropertiesUsingConfigAdmin(); + + resolveBundle(); + + processAnnotations(true); + + + for (Bundle bundle : dependentBundles) { + try { + if (bundle.getState() != Bundle.ACTIVE && bundle.getState() != Bundle.STARTING) { + bundle.start(); + } + } catch (BundleException e) { + if (bundle.getHeaders().get("Fragment-Host") == null) + throw e; + } + } + + } + + if (osgiBundle.getState() != Bundle.ACTIVE && osgiBundle.getState() != Bundle.STARTING) { + + + int retry = 0; + + while (retry++ < 10) { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws BundleException { + osgiBundle.start(); + return null; + } + }); + break; + // } catch ( BundleException e) { + } catch ( PrivilegedActionException e) { + // It is possible that the thread "Refresh Packages" is in the process of + // changing the state of this bundle. + Thread.yield(); + + if (retry == 10) + throw e; + } + } + } + + } catch (Exception e) { + throw new ObjectCreationException(e); + } finally { + exitMethod(startBundleEntryCount); + } + return osgiBundle; + } + + + // This method is called by OSGiInstanceWrapper.getInstance to obtain the OSGi service reference + // corresponding to the specified service. The properties used to filter the service should + // be chosen based on whether this is a normal service or a callback. + protected org.osgi.framework.ServiceReference getOSGiServiceReference(ComponentService service) + throws ObjectCreationException { + + Hashtable props = new Hashtable(); + if (!service.isCallback()) + processProperties(implementation.getServiceProperties(service.getName()), props); + else + processProperties(implementation.getServiceCallbackProperties(service.getName()), props); + + String filter = getOSGiFilter(props); + Interface serviceInterface = service.getInterfaceContract().getInterface(); + String scaServiceName = service.getName(); + + return getOSGiServiceReference(serviceInterface, filter, scaServiceName); + + } + + protected org.osgi.framework.ServiceReference getOSGiServiceReference( + EndpointReference from, Interface callbackInterface) + throws ObjectCreationException { + + RuntimeWire refWire = null; + String filter = null; + for (RuntimeWire wire : referenceWires.keySet()) { + if (wire.getSource() == from) { + refWire = wire; + break; + } + } + if (refWire != null) { + Hashtable props = new Hashtable(); + ComponentReference scaRef = componentReferenceWires.get(refWire); + processProperties(implementation.getReferenceCallbackProperties(scaRef.getName()), props); + filter = getOSGiFilter(props); + } + + return getOSGiServiceReference(callbackInterface, filter, null); + } + + private org.osgi.framework.ServiceReference getOSGiServiceReference(Interface serviceInterface, + String filter, String scaServiceName) + throws ObjectCreationException { + + try { + + String serviceInterfaceName = null; + + org.osgi.framework.ServiceReference osgiServiceReference = null; + + if (serviceInterface instanceof JavaInterface) { + serviceInterfaceName = ((JavaInterface)serviceInterface).getJavaClass().getName(); + + if ((osgiServiceReference = getOSGiServiceReference( + scaServiceName, + serviceInterfaceName, filter)) == null) { + + // The service listener for our bundle will notify us when the service is registered. + synchronized (implementation) { + + // When declarative services are used, the component is started asynchronously + // So this thread has to wait for the service to be registered by the component + // activate method + // For regular bundle activators, bundle.start activates the bundle synchronously + // and hence the service would probably have been started by the bundle activator + long startTime = System.currentTimeMillis(); + while ((osgiServiceReference = getOSGiServiceReference( + scaServiceName, + serviceInterfaceName, filter)) == null) { + + // Wait for the bundle to register the service + implementation.wait(100); + if (System.currentTimeMillis() - startTime > SERVICE_TIMEOUT_MILLIS) + break; + } + } + + } + } + + return osgiServiceReference; + + } catch (Exception e) { + throw new ObjectCreationException(e); + } + } + + + // Felix does not support bundle fragments. This is a temporary workaround. + protected Bundle installDummyBundleWithoutFragments(Class interfaceClass) + throws Exception { + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + String EOL = System.getProperty("line.separator"); + + String interfaceName = interfaceClass.getName(); + String packageName = getPackageName(interfaceClass); + String bundleName = "dummy.sca." + packageName; + + String manifestStr = "Manifest-Version: 1.0" + EOL + + "Bundle-ManifestVersion: 2" + EOL + "Bundle-Name: " + + bundleName + EOL + "Bundle-SymbolicName: " + bundleName + EOL + + "Bundle-Version: " + "1.0.0" + EOL + + "Bundle-Localization: plugin" + EOL; + + ArrayList dummyClasses = new ArrayList(); + + StringBuilder manifestBuf = new StringBuilder(); + manifestBuf.append(manifestStr); + manifestBuf.append("Export-Package: " + packageName + EOL); + String exportedInterfaces = interfaceName; + Bundle existingBundle = getDummyHostBundle(packageName); + String existingClasses; + dummyClasses.add(interfaceClass.getName()); + for (Class clazz : interfaceClass.getClasses()) { + dummyClasses.add(clazz.getName()); + } + if (existingBundle != null && + (existingClasses = (String)existingBundle.getHeaders().get("SCA-Dummy-Classes")) != null) { + exportedInterfaces = exportedInterfaces + " " + existingClasses; + + StringTokenizer tokenizer = new StringTokenizer(existingClasses); + while (tokenizer.hasMoreTokens()) { + String className = tokenizer.nextToken(); + if (!dummyClasses.contains(className)) + dummyClasses.add(className); + } + } + + manifestBuf.append("SCA-Dummy-Classes: " + exportedInterfaces + EOL); + + ByteArrayInputStream manifestStream = new ByteArrayInputStream( + manifestBuf.toString().getBytes()); + Manifest manifest = new Manifest(); + manifest.read(manifestStream); + + JarOutputStream jarOut = new JarOutputStream(out, manifest); + + for (int i = 0; i < dummyClasses.size(); i++) { + + String className = dummyClasses.get(i); + + Class clazz = interfaceClass.getClassLoader().loadClass(className); + className = clazz.getName().replaceAll("\\.", "/") + ".class"; + ZipEntry ze = new ZipEntry(className); + jarOut.putNextEntry(ze); + InputStream stream = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); + + byte[] bytes = new byte[stream.available()]; + stream.read(bytes); + jarOut.write(bytes); + stream.close(); + } + + + jarOut.close(); + out.close(); + + if (existingBundle != null) { + existingBundle.stop(); + existingBundle.uninstall(); + } + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + + Bundle bundle = bundleContext.installBundle("file://" + bundleName + + ".jar", in); + + bundle.start(); + + if (existingBundle != null && packageAdmin != null) { + refreshPackages(); + + } + + return bundle; + + } + + private Bundle getDummyHostBundle(String packageName) { + + if (packageAdmin == null) + return null; + + ExportedPackage exp = packageAdmin.getExportedPackage(packageName); + if (exp == null) + return null; + else + return exp.getExportingBundle(); + } + + private static String getPackageName(Class cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + private Bundle installDummyBundle(Class interfaceClass) + throws Exception { + + + if (!osgiRuntime.supportsBundleFragments()) { + return installDummyBundleWithoutFragments(interfaceClass); + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + String EOL = System.getProperty("line.separator"); + ArrayList> dummyClasses = new ArrayList>(); + + String interfaceName = interfaceClass.getName(); + String packageName = getPackageName(interfaceClass); + String bundleName = "dummy.sca." + interfaceName; + + + String manifestStr = "Manifest-Version: 1.0" + EOL + + "Bundle-ManifestVersion: 2" + EOL + + "Bundle-Name: " + bundleName + EOL + + "Bundle-SymbolicName: " + bundleName + EOL + + "Bundle-Version: " + "1.0.0" + EOL + + "Bundle-Localization: plugin" + EOL; + + + StringBuilder manifestBuf = new StringBuilder(); + manifestBuf.append(manifestStr); + manifestBuf.append("Export-Package: " + packageName + EOL); + Bundle dummyHost = getDummyHostBundle(packageName); + if (dummyHost != null) + manifestBuf.append("Fragment-Host: " + dummyHost.getSymbolicName() + EOL); + + ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestBuf.toString().getBytes()); + Manifest manifest = new Manifest(); + manifest.read(manifestStream); + + dummyClasses.add(interfaceClass); + for (Class clazz : interfaceClass.getClasses()) { + dummyClasses.add(clazz); + } + + JarOutputStream jarOut = new JarOutputStream(out, manifest); + + for (int i = 0; i < dummyClasses.size(); i++) { + + Class clazz = dummyClasses.get(i); + String className = clazz.getName(); + className = clazz.getName().replaceAll("\\.", "/") + ".class"; + ZipEntry ze = new ZipEntry(className); + jarOut.putNextEntry(ze); + InputStream stream = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); + + byte[] bytes = new byte[stream.available()]; + stream.read(bytes); + jarOut.write(bytes); + stream.close(); + } + + jarOut.close(); + out.close(); + + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + + + Bundle bundle = bundleContext.installBundle( + "file://" + bundleName + ".jar", + in); + + if (dummyHost == null) + bundle.start(); + + return bundle; + + } + + + + public InstanceWrapper createInstanceWrapper() throws ObjectCreationException { + + return new OSGiInstanceWrapper(this, osgiAnnotations, bundleContext); + } + + + + private void resolveWireCreateDummyBundles(final Class interfaceClass) throws Exception { + + + try { + + osgiBundle.loadClass(interfaceClass.getName()); + + } catch (ClassNotFoundException e) { + + // The interface used by the proxy is not in the source bundle + // A dummy bundle needs to be installed to create the proxy + // Allow privileged access to file system. Requires FileSystem permission in security + // policy. + Bundle dummyBundle = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Bundle run() throws Exception { + return installDummyBundle(interfaceClass); + } + }); + + if (packageAdmin != null) { + + packageAdmin.resolveBundles(new Bundle[]{dummyBundle, osgiBundle}); + + } + + } + } + + /** + * For OSGi->Java wires, create a proxy corresponding to the Java interfaces + * and register the proxy with the OSGi registry, so that the source OSGi bundle can + * locate the target Java instance from the registry like a regular OSGi service. + * + * For OSGi->OSGi wires, start the target OSGi bundle, so that references of the + * target are resolved before the source OSGi bundle is started. If the reference + * has properties specified, create a Proxy and register a service with highest + * possible ranking. The Proxy should wire to the correct OSGi instance specified + * in the SCA composite. + * + * The first phase determines whether a proxy should be installed. It also registers + * a dummy bundle if necessary to resolve the bundle. When phase1 is completed on all + * wires of the component, the bundle should be resolved. Phase2 registers the proxy service. + */ + private boolean resolveWireResolveReferences(Bundle bundle, Class interfaceClass, RuntimeWire wire, + boolean isOSGiToOSGiWire) throws Exception { + + + // FIXME: At the moment injection of values into instances require an instance to be obtained + // through the instance wrapper, and hence requires a proxy. When we do this processing here, + // we don't yet know whether the target requires any property or callback injection. So it is + // safer to create a proxy all the time. + boolean createProxy = true; + + ComponentReference scaRef = componentReferenceWires.get(wire); + Hashtable targetProperties = new Hashtable(); + processProperties(implementation.getReferenceProperties(scaRef.getName()), targetProperties); + + + if (isOSGiToOSGiWire) { + + OSGiImplementationProvider implProvider = (OSGiImplementationProvider)wire.getTarget().getComponent().getImplementationProvider(); + + // This is an OSGi->OSGi wire + isOSGiToOSGiWire = true; + + // If the target component is stateless, use a proxy to create a new service each time + if (!implProvider.getScope().equals(Scope.COMPOSITE)) createProxy = true; + + Interface interfaze = wire.getTarget().getInterfaceContract().getInterface(); + + // If the target interface is remotable, create a proxy to support pass-by-value semantics + // AllowsPassByReference is not detected until the target instance is obtained. + if (interfaze.isRemotable()) + createProxy = true; + + // If any of the operations in the target interface is non-blocking, create a proxy + List ops = interfaze.getOperations(); + for (Operation op : ops) { + if (op.isNonBlocking()) + createProxy = true; + } + + // If properties are specified for the reference, create a proxy since rewiring may be required + if (targetProperties.size() > 0) { + createProxy = true; + } + + // If properties are specified for the component, create a proxy for configuring + // the component services. + if (componentProperties.size() > 0) { + createProxy = true; + } + + // Since this is an OSGi->OSGi wire, start the target bundle before starting the + // source bundle if there is no proxy. For direct wiring without a proxy, this ordering + // is irrelevant in terms of class resolution, but the target needs to be started at some + // point. But there is no opportunity later on to start the target OSGi bundle without a proxy. + // When a Proxy is used, the target bundle needs to be resolved for the source bundle + // to be resolved so that the interface is visible to the source. In this case the bundle + // will be started when an instance is needed. + if (!createProxy) { + implProvider.startBundle(false); + } + else { + implProvider.resolveBundle(); + } + } + else { + createProxy = true; + } + + return createProxy; + } + + + // Register proxy service + private void resolveWireRegisterProxyService(final Bundle bundle, final Class interfaceClass, RuntimeWire wire) throws Exception { + + ComponentReference scaRef = componentReferenceWires.get(wire); + Hashtable targetProperties = new Hashtable(); + processProperties(implementation.getReferenceProperties(scaRef.getName()), targetProperties); + targetProperties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + + if (targetProperties.get(COMPONENT_SERVICE_NAME) == null && wire.getTarget().getComponent() != null) { + String compServiceName = wire.getTarget().getComponent().getName() + "/" + + wire.getTarget().getContract().getName(); + targetProperties.put(COMPONENT_SERVICE_NAME, compServiceName); + } + + + JDKProxyFactory proxyService = new JDKProxyFactory(messageFactory, mapper); + + // Allow privileged access to load classes. Requires getClassLoader permission in security + // policy. + final Class proxyInterface = AccessController.doPrivileged(new PrivilegedExceptionAction>() { + public Class run() throws Exception { + return bundle.loadClass(interfaceClass.getName()); + } + }); + + final Object proxy = proxyService.createProxy(proxyInterface, wire); + final Hashtable finalTargetProperties = targetProperties; + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + bundleContext.registerService(proxyInterface.getName(), proxy, finalTargetProperties); + return null; + } + }); + + + } + + + private void refreshPackages() { + + if (packageAdmin != null) { + synchronized (this) { + packagesRefreshed = false; + packageAdmin.refreshPackages(null); + + if (!packagesRefreshed) { + try { + this.wait(2000); + } catch (InterruptedException e) { + // ignore + } + } + packagesRefreshed = false; + } + } + } + + + private void resolveBundle() throws ObjectCreationException { + + + try { + + if (!wiresResolved) { + wiresResolved = true; + + if (!setReferencesAndProperties()) { + wiresResolved = false; + return; + } + + int refPlusServices = referenceWires.size() + runtimeComponent.getServices().size(); + boolean[] createProxyService = new boolean[refPlusServices]; + Class[] interfaceClasses = new Class[refPlusServices] ; + boolean[] isOSGiToOSGiWire = new boolean[refPlusServices]; + boolean[] wireResolved = new boolean[refPlusServices]; + int index = 0; + for (RuntimeWire wire : referenceWires.keySet()) { + + Reference reference = referenceWires.get(wire); + + isOSGiToOSGiWire[index] = wire.getTarget().getComponent() != null && + wire.getTarget().getComponent().getImplementationProvider() + instanceof OSGiImplementationProvider; + + Interface refInterface = reference.getInterfaceContract().getInterface(); + if (refInterface instanceof JavaInterface) { + interfaceClasses[index] = ((JavaInterface)refInterface).getJavaClass(); + + if (!isOSGiToOSGiWire[index]) + resolveWireCreateDummyBundles(interfaceClasses[index]); + + } + + if (!resolvedWires.contains(wire)) { + resolvedWires.add(wire); + } + else + wireResolved[index] = true; + + index++; + } + for (ComponentService service : runtimeComponent.getServices()) { + Interface callbackInterface = service.getInterfaceContract().getCallbackInterface(); + if (callbackInterface instanceof JavaInterface) { + interfaceClasses[index] = ((JavaInterface)callbackInterface).getJavaClass(); + + resolveWireCreateDummyBundles(interfaceClasses[index]); + } + + index++; + } + + index = 0; + for (RuntimeWire wire : referenceWires.keySet()) { + + if (!wireResolved[index]) { + createProxyService[index] = resolveWireResolveReferences(osgiBundle, + interfaceClasses[index], + wire, + isOSGiToOSGiWire[index]); + } + index++; + } + + refreshPackages(); + + + index = 0; + for (RuntimeWire wire : referenceWires.keySet()) { + + if (createProxyService[index] && !wireResolved[index]) + resolveWireRegisterProxyService(osgiBundle, interfaceClasses[index], wire); + index++; + } + } + else if (osgiBundle.getState() == Bundle.INSTALLED && packageAdmin != null) { + packageAdmin.resolveBundles(new Bundle[] {osgiBundle}); + } + + } catch (Exception e) { + e.printStackTrace(); + throw new ObjectCreationException(e); + } + } + + + @SuppressWarnings("unchecked") + private void configurePropertiesUsingConfigAdmin() { + + try { + + if (componentProperties.size() == 0) + return; + + org.osgi.framework.ServiceReference configAdminReference = + bundleContext.getServiceReference("org.osgi.service.cm.ConfigurationAdmin"); + if (configAdminReference != null) { + + Object cm = bundleContext.getService(configAdminReference); + Class cmClass = cm.getClass().getClassLoader().loadClass("org.osgi.service.cm.ConfigurationAdmin"); + Method getConfigMethod = cmClass.getMethod("getConfiguration", String.class, String.class); + + + Class configClass = cm.getClass().getClassLoader().loadClass("org.osgi.service.cm.Configuration"); + + Method getMethod = configClass.getMethod("getProperties"); + Method updateMethod = configClass.getMethod("update", Dictionary.class); + + List services = implementation.getServices(); + HashSet pidsProcessed = new HashSet(); + + for (Service service : services) { + + List serviceProps = implementation.getServiceProperties(service.getName()); + String pid = null; + + if (serviceProps != null) { + for (ComponentProperty prop : serviceProps) { + if (prop.getName().equals("service.pid")) { + ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, + prop.getValue(), String.class); + pid = (String)objFactory.getInstance(); + } + } + } + if (pid == null || pidsProcessed.contains(pid)) + continue; + + + + + Object config = getConfigMethod.invoke(cm, pid, null); + Dictionary props = (Dictionary) getMethod.invoke(config); + if (props == null) + props = new Hashtable(); + for (String propertyName : componentProperties.keySet()) { + + props.put(propertyName, componentProperties.get(propertyName)); + } + + updateMethod.invoke(config, props); + + + } + + } + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + + public boolean isOptimizable() { + return false; + } + + public Scope getScope() { + return osgiAnnotations.getScope(); + } + + public boolean isEagerInit() { + return osgiAnnotations.isEagerInit(); + } + + public long getMaxAge() { + return osgiAnnotations.getMaxAge(); + } + + public long getMaxIdleTime() { + return osgiAnnotations.getMaxIdleTime(); + } + + protected ScopeContainer getScopeContainer() { + startBundle(true); + return ((ScopedRuntimeComponent)runtimeComponent).getScopeContainer(); + } + + public Invoker createTargetInvoker(RuntimeComponentService service, Operation operation) { + + + Interface serviceInterface = operation.getInterface(); + boolean isRemotable = serviceInterface.isRemotable(); + + + Invoker invoker = new OSGiTargetInvoker(operation, this, service); + if (isRemotable) { + return new OSGiRemotableInvoker(osgiAnnotations, dataBindingRegistry, operation, this, service); + } else { + return invoker; + } + + } + + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + return createTargetInvoker(service, operation); + } + + public boolean supportsOneWayInvocation() { + return false; + } + + private boolean setReferencesAndProperties() { + + for (Reference ref: implementation.getReferences()) { + List wireList = null; + ComponentReference compRef = null; + for (ComponentReference cRef : runtimeComponent.getReferences()) { + if (cRef.getName().equals(ref.getName())) { + + wireList = ((RuntimeComponentReference)cRef).getRuntimeWires(); + + compRef = cRef; + break; + } + } + + if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { + for (RuntimeWire wire : wireList) { + referenceWires.put(wire, ref); + componentReferenceWires.put(wire, compRef); + } + + } else { + if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { + throw new IllegalStateException("Required reference is missing: " + ref.getName()); + } + if (wireList != null && !wireList.isEmpty()) { + RuntimeWire wire = wireList.get(0); + referenceWires.put(wire, ref); + componentReferenceWires.put(wire, compRef); + } + + } + + } + + processProperties(runtimeComponent.getProperties(), componentProperties); + + return true; + + } + + public void start() { + setReferencesAndProperties(); + } + + public void processAnnotations(boolean doWait) throws IntrospectionException { + + if (!enterMethod(doWait, processAnnotationsEntryCount)) + return; + + try { + osgiAnnotations.processAnnotations(); + + Scope scope = osgiAnnotations.getScope(); + if (scope.equals(Scope.SYSTEM) || scope.equals(Scope.COMPOSITE)) { + // Nothing + } else { + + if (runtimeComponent instanceof ScopedRuntimeComponent) { + + ScopedRuntimeComponent component = (ScopedRuntimeComponent) runtimeComponent; + + ScopeContainer oldScopeContainer = component.getScopeContainer(); + component.setScopeContainer(null); + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); + + if (oldScopeContainer != null && oldScopeContainer.getLifecycleState() == ScopeContainer.RUNNING) { + scopeContainer.start(); + } + + component.setScopeContainer(scopeContainer); + } + + } + } finally { + exitMethod(processAnnotationsEntryCount); + } + } + + public void stop() { + + if (osgiServiceListener != null) + bundleContext.removeServiceListener(osgiServiceListener); + } + + + + public void frameworkEvent(FrameworkEvent event) { + if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) { + synchronized (this) { + packagesRefreshed = true; + this.notifyAll(); + } + } + + } + + public void bundleChanged(BundleEvent event) { + if (event.getType() == BundleEvent.RESOLVED && event.getBundle() == osgiBundle) { + try { + processAnnotations(false); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + private class OSGiServiceListener implements ServiceListener { + + private Bundle bundle; + + OSGiServiceListener(Bundle bundle) { + this.bundle = bundle; + } + + public void serviceChanged(org.osgi.framework.ServiceEvent event) { + + + org.osgi.framework.ServiceReference reference = event.getServiceReference(); + + if (event.getType() == ServiceEvent.REGISTERED && reference.getBundle() == bundle) { + + synchronized (implementation) { + + implementation.notifyAll(); + } + } + + if (event.getType() == ServiceEvent.UNREGISTERING && reference.getBundle() == bundle) { + // TODO: Process deregistering of OSGi services. + } + } + } +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java new file mode 100644 index 0000000000..814d37f203 --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java @@ -0,0 +1,111 @@ +/* + * 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.osgi.runtime; + + +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.MediatorImpl; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.osgi.OSGiImplementation; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.osgi.framework.BundleException; + + +/** + * Builds a OSGi-based implementation provider from a component definition + * + * @version $Rev$ $Date$ + */ +public class OSGiImplementationProviderFactory implements ImplementationProviderFactory { + + private DataBindingExtensionPoint dataBindings; + private JavaPropertyValueObjectFactory propertyFactory; + private ProxyFactory proxyFactory; + private ScopeRegistry scopeRegistry; + private MessageFactory messageFactory; + private InterfaceContractMapper mapper; + + private RequestContextFactory requestContextFactory; + + public OSGiImplementationProviderFactory(ExtensionPointRegistry extensionPoints ) { + + dataBindings = extensionPoints.getExtensionPoint(DataBindingExtensionPoint.class); + ProxyFactoryExtensionPoint proxyFactories = extensionPoints.getExtensionPoint(ProxyFactoryExtensionPoint.class); + proxyFactory = new ExtensibleProxyFactory(proxyFactories); + ContextFactoryExtensionPoint contextFactories = extensionPoints.getExtensionPoint(ContextFactoryExtensionPoint.class); + requestContextFactory = contextFactories.getFactory(RequestContextFactory.class); + + + // FIXME: Scope registry is not an extension point, and this usage is specific + // to implementation.osgi since it needs to change scope after the component is + // created. Do we need to find a better way? + scopeRegistry = extensionPoints.getExtensionPoint(ScopeRegistry.class); + + TransformerExtensionPoint transformers = extensionPoints.getExtensionPoint(TransformerExtensionPoint.class); + MediatorImpl mediator = new MediatorImpl(dataBindings, transformers); + propertyFactory = new JavaPropertyValueObjectFactory(mediator); + + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + messageFactory = modelFactories.getFactory(MessageFactory.class); + + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + mapper = utilities.getUtility(InterfaceContractMapper.class); + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + OSGiImplementation implementation) { + + try { + + return new OSGiImplementationProvider(component, + implementation, + dataBindings, + propertyFactory, + proxyFactory, + scopeRegistry, + requestContextFactory, + messageFactory, + mapper + ); + + } catch (BundleException e) { + throw new RuntimeException(e); + } + + } + + public Class getModelType() { + return OSGiImplementation.class; + } + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java new file mode 100644 index 0000000000..e775041592 --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java @@ -0,0 +1,299 @@ +/* + * 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.osgi.runtime; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.ServiceReference; +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; + + +/** + * InstanceWrapper for creating instances for OSGi components. + * This class needs to implement InstanceWrapper since the wrapper is stored in + * the scope container. But getInstance() is called on this wrapper only through the + * OSGi target invoker. OSGiTargetInvoker always invokes getInstance for a specific + * service since one OSGi SCA component can associate different objects with + * different services (this is different from Java SCA components which always associate + * a single component instance with multiple services). + * + * @version $Rev$ $Date$ + */ +public class OSGiInstanceWrapper implements InstanceWrapper { + private static final Random RANDOM_NUMBER_GENERATOR = new Random(); + + private OSGiAnnotations annotationProcessor; + private OSGiImplementationProvider provider; + private BundleContext bundleContext; + private Hashtable> instanceInfoList = + new Hashtable>(); + + // Dummy bundles are used to create a new service object for scopes other than COMPOSITE + private Bundle dummyReferenceBundle; + + + public OSGiInstanceWrapper(OSGiImplementationProvider provider, + OSGiAnnotations annotationProcessor, + BundleContext bundleContext) { + + this.provider = provider; + this.annotationProcessor = annotationProcessor; + this.bundleContext = bundleContext; + } + + public synchronized T getInstance(ComponentService service) throws TargetInitializationException { + + // If an instance corresponding to this service has already been created, return the instance. + if (instanceInfoList.get(service) != null) + return instanceInfoList.get(service).osgiInstance; + + // There is no strict relation between service and callback instances. The instance semantics + // actually applies to the component instance in SCA. But for OSGi services, the callback + // is just another OSGi service, and could correspond to any of the service instances in + // the component. To implement the SCA scope semantics for callbacks, OSGi callbacks + // should also be made on the service object which implements the callback. The following code + // finds the first possible callback instance based on the interfaces implemented by the service + // objects in this component. Note that the interfaces are checked by name rather than using + // instanceof since the class seen by Tuscany could be from a different classloader from that + // used by the bundle. + if (service.isCallback()) { + Iterator> instances = instanceInfoList.values().iterator(); + while (instances.hasNext()) { + InstanceInfo instanceInfo = instances.next(); + Interface interfaze = service.getInterfaceContract().getInterface(); + if (interfaze instanceof JavaInterface && ((JavaInterface)interfaze).getJavaClass() != null) { + String interfaceName = ((JavaInterface)interfaze).getJavaClass().getName(); + Class[] interfaces = instanceInfo.osgiInstance.getClass().getInterfaces(); + for (Class clazz : interfaces) { + if (clazz.getName().equals(interfaceName)) { + return instanceInfo.osgiInstance; + } + } + + } + + } + } + + Bundle refBundle = provider.startBundle(true); + + // For scopes other than composite, the service object is obtained using a dummy reference + // bundle to guarantee that a new instance is created each time. This combined with the Tuscany + // scope container code guarantee SCA scope semantics for OSGi components as long as service + // factories are used. + if (!annotationProcessor.getScope().equals(Scope.COMPOSITE)) { + refBundle = getDummyReferenceBundle(); + } + + InstanceInfo instanceInfo = new InstanceInfo(); + + instanceInfo.refBundleContext = refBundle.getBundleContext(); + + instanceInfo.osgiInstance = getInstanceObject(instanceInfo, service); + + try { + + if (!isInitialized(instanceInfo.osgiInstance)) { + + annotationProcessor.injectProperties(instanceInfo.osgiInstance); + callLifecycleMethod(instanceInfo.osgiInstance, Init.class); + + instanceInfo.isFirstInstance = true; + } + + instanceInfoList.put(service, instanceInfo); + + } catch (Exception e) { + throw new TargetInitializationException(e); + } + + return instanceInfo.osgiInstance; + } + + + + // This method is provided purely to implement InstanceWrapper interface, and is never called. + public T getInstance() { + + return null; + } + + public void start() throws TargetInitializationException { + + if (provider.isEagerInit()) { + List services = provider.getRuntimeComponent().getServices(); + for (ComponentService service : services) { + getInstance(service); + } + } + } + + public synchronized void stop() throws TargetDestructionException { + + for (InstanceInfo instanceInfo : instanceInfoList.values()) { + if (instanceInfo.osgiInstance != null && instanceInfo.osgiServiceReference != null) { + + try { + + if (instanceInfo.isFirstInstance) + callLifecycleMethod(instanceInfo.osgiInstance, Destroy.class); + + instanceInfo.refBundleContext.ungetService(instanceInfo.osgiServiceReference); + + instanceInfo.osgiInstance = null; + instanceInfo.osgiServiceReference = null; + + } catch (Exception e) { + throw new TargetDestructionException(e); + } + } + } + instanceInfoList.clear(); + if (dummyReferenceBundle != null) { + try { + dummyReferenceBundle.uninstall(); + } catch (BundleException e) { + throw new TargetDestructionException(e); + } + dummyReferenceBundle = null; + } + } + + @SuppressWarnings("unchecked") + private T getInstanceObject(InstanceInfo instanceInfo, ComponentService service) { + + /** + * Since implementation.osgi is not well integrated with the OSGi lifecycle + * it is possible that the service is deactivated before the service instance + * is obtained when using declarative services. Retry in this case. + */ + int maxRetries = 10; + for (int i = 0; i < maxRetries; i++) { + instanceInfo.osgiServiceReference = provider.getOSGiServiceReference(service); + if (instanceInfo.osgiServiceReference == null) + return null; + T obj = (T)instanceInfo.refBundleContext.getService(instanceInfo.osgiServiceReference); + if (obj != null) + return obj; + } + return null; + } + + private Bundle getDummyReferenceBundle() throws TargetInitializationException { + + if (dummyReferenceBundle != null) + return dummyReferenceBundle; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + String EOL = System.getProperty("line.separator"); + String bundleName = "dummy.sca." + RANDOM_NUMBER_GENERATOR.nextInt(); + + + String manifestStr = "Manifest-Version: 1.0" + EOL + + "Bundle-ManifestVersion: 2" + EOL + + "Bundle-Name: " + bundleName + EOL + + "Bundle-SymbolicName: " + bundleName + EOL + + "Bundle-Version: " + "1.0.0" + EOL + + "Bundle-Localization: plugin" + EOL; + + + StringBuilder manifestBuf = new StringBuilder(); + manifestBuf.append(manifestStr); + + try { + ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestBuf.toString().getBytes()); + Manifest manifest = new Manifest(); + manifest.read(manifestStream); + + + JarOutputStream jarOut = new JarOutputStream(out, manifest); + + jarOut.close(); + out.close(); + + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + + dummyReferenceBundle = bundleContext.installBundle("file://" + bundleName + ".jar", in); + + dummyReferenceBundle.start(); + + } catch (Exception e) { + throw new TargetInitializationException(e); + } + + return dummyReferenceBundle; + + } + + private void callLifecycleMethod(Object instance, + Class annotationClass) throws Exception { + + Method method = null; + if (annotationClass == Init.class) { + method = annotationProcessor.getInitMethod(instance); + } else if (annotationClass == Destroy.class) { + method = annotationProcessor.getDestroyMethod(instance); + } + + if (method != null) { + method.setAccessible(true); + method.invoke(instance); + } + } + + private boolean isInitialized(Object instance) { + for (InstanceInfo info : instanceInfoList.values()) { + if (info.osgiInstance == instance) + return true; + } + return false; + } + + private static class InstanceInfo { + private T osgiInstance; + private ServiceReference osgiServiceReference; + private BundleContext refBundleContext; + private boolean isFirstInstance; + + } + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java new file mode 100644 index 0000000000..deb44d26fb --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java @@ -0,0 +1,139 @@ +/* + * 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.osgi.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.IdentityHashMap; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.osgi.context.OSGiAnnotations; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * An interceptor to enforce pass-by-value semantics for remotable interfaces + * + * @version $Rev$ $Date$ + */ +public class OSGiRemotableInvoker extends OSGiTargetInvoker implements DataExchangeSemantics { + + private DataBindingExtensionPoint registry; + private Operation operation; + private OSGiAnnotations osgiAnnotations; + + /** + * @param registry + * @param operation + * @param method + * @param component + */ + public OSGiRemotableInvoker(OSGiAnnotations osgiAnnotations, + DataBindingExtensionPoint registry, + Operation operation, + OSGiImplementationProvider provider, + RuntimeComponentService service) { + super(operation, provider, service); + this.osgiAnnotations = osgiAnnotations; + this.registry = registry; + this.operation = operation; + } + + @Override + public Object invokeMethod(Object targetObject, Method m, Message msg) throws InvocationTargetException { + + Object result; + if (osgiAnnotations.isAllowsPassByReference(targetObject, m)) { + result = super.invokeMethod(targetObject, m, msg); + } else { + Object obj = msg.getBody(); + msg.setBody(copy((Object[])obj)); + + result = super.invokeMethod(targetObject, m, msg); + + if (operation.getOutputType() != null) { + String dataBindingId = operation.getOutputType().getDataBinding(); + DataBinding dataBinding = registry.getDataBinding(dataBindingId); + result = copy(result, operation.getOutputType(), dataBinding); + } + } + return result; + } + + public Object[] copy(Object[] args) { + if (args == null) { + return null; + } + Object[] copiedArgs = new Object[args.length]; + Map map = new IdentityHashMap(); + for (int i = 0; i < args.length; i++) { + if (args[i] == null) { + copiedArgs[i] = null; + } else { + Object copiedArg = map.get(args[i]); + if (copiedArg != null) { + copiedArgs[i] = copiedArg; + } else { + DataType dt = operation.getInputType().getLogical().get(i); + String dataBindingId = dt.getDataBinding(); + DataBinding dataBinding = registry.getDataBinding(dataBindingId); + copiedArg = copy(args[i], dt, dataBinding); + map.put(args[i], copiedArg); + copiedArgs[i] = copiedArg; + } + } + } + return copiedArgs; + } + + public Object copy(Object arg, DataType dataType, DataBinding argDataBinding) { + if (arg == null) { + return null; + } + Object copiedArg; + if (argDataBinding != null) { + copiedArg = argDataBinding.copy(arg, dataType, operation); + } else { + copiedArg = arg; + dataType = registry.introspectType(arg, operation); + if (dataType != null) { + DataBinding binding = registry.getDataBinding(dataType.getDataBinding()); + if (binding != null) { + copiedArg = binding.copy(arg, dataType, operation); + } + } + // FIXME: What to do if it's not recognized? + } + return copiedArg; + } + + /** + * @see org.apache.tuscany.sca.invocation.PassByValueAware#allowsPassByReference() + */ + public boolean allowsPassByReference() { + return true; + } + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java new file mode 100644 index 0000000000..deb39a47cd --- /dev/null +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java @@ -0,0 +1,199 @@ +/* + * 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.osgi.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.invocation.TargetInvocationException; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Java->OSGi references use OSGiTargetInvoker to call methods from OSGi bundles + * OSGi->Java references use JDKProxyService and invocation handler and do not use this class + * OSGi->OSGi references go through OSGi reference mechanisms when a proxy is not used + * When a proxy is used, this invoker is used to call methods from OSGi bundles + * A proxy is used for OSGi->OSGi if + * 1) target reference properties are specified OR + * 2) there are one or more non-blocking methods in the target interface OR + * 3) scope is not COMPOSITE + * + * @version $Rev$ $Date$ + */ +public class OSGiTargetInvoker implements Invoker { + + private Operation operation; + protected InstanceWrapper target; + + private final OSGiImplementationProvider provider; + private final RuntimeComponentService service; + + // Scope container is reset by the OSGi implementation provider if @Scope + // annotation is used to modify the scope (default is composite) + // Hence this field is initialized on the first invoke. + private ScopeContainer scopeContainer; + + public OSGiTargetInvoker( + Operation operation, + OSGiImplementationProvider provider, + RuntimeComponentService service) { + + + this.operation = operation; + this.service = service; + this.provider = provider; + + } + + /** + * Resolves the target service instance or returns a cached one + */ + @SuppressWarnings("unchecked") + protected InstanceWrapper getInstance(Object contextId) + throws TargetResolutionException, TargetInvocationException { + + if (scopeContainer == null) + scopeContainer = provider.getScopeContainer(); + + + return scopeContainer.getWrapper(contextId); + + } + + @SuppressWarnings("unchecked") + private Object invokeTarget(Message msg) throws InvocationTargetException { + + if (scopeContainer == null) + scopeContainer = provider.getScopeContainer(); + + + Operation op = msg.getOperation(); + if (op == null) { + op = this.operation; + } + ConversationSequence sequence = op.getConversationSequence(); + + Object contextId = null; + + EndpointReference from = msg.getFrom(); + ReferenceParameters parameters = null; + + if (from != null) { + parameters = from.getReferenceParameters(); + } + // check what sort of context is required + if (scopeContainer != null) { + Scope scope = scopeContainer.getScope(); + if (scope == Scope.REQUEST) { + contextId = Thread.currentThread(); + } else if (scope == Scope.CONVERSATION && parameters != null) { + contextId = parameters.getConversationID(); + } + } + + try { + + OSGiInstanceWrapper wrapper = (OSGiInstanceWrapper)getInstance(contextId); + Object instance; + + + // detects whether the scope container has created a conversation Id. This will + // happen in the case that the component has conversational scope but only the + // callback interface is conversational. Or in the callback case if the service interface + // is conversational and the callback interface isn't. If we are in this situation we need + // to get the contextId of this component and remove it after we have invoked the method on + // it. It is possible that the component instance will not go away when it is removed below + // because a callback conversation will still be holding a reference to it + boolean removeTemporaryConversationalComponentAfterCall = false; + if (parameters != null && (contextId == null) && (parameters.getConversationID() != null)) { + contextId = parameters.getConversationID(); + removeTemporaryConversationalComponentAfterCall = true; + } + + instance = wrapper.getInstance(service); + + Method m = JavaInterfaceUtil.findMethod(instance.getClass(), operation); + + Object ret = invokeMethod(instance, m, msg); + + scopeContainer.returnWrapper(wrapper, contextId); + + if ((sequence == ConversationSequence.CONVERSATION_END) || (removeTemporaryConversationalComponentAfterCall)) { + // if end conversation, or we have the special case where a conversational + // object was created to service the stateless half of a stateful component + scopeContainer.remove(contextId); + parameters.setConversationID(null); + } + + return ret; + } catch (InvocationTargetException e) { + throw e; + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + + protected Object invokeMethod(Object instance, Method m, Message msg) throws InvocationTargetException { + + try { + + Object payload = msg.getBody(); + + if (payload != null && !payload.getClass().isArray()) { + return m.invoke(instance, payload); + } else { + return m.invoke(instance, (Object[])payload); + } + + } catch (InvocationTargetException e) { + throw e; + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + + public Message invoke(Message msg) { + try { + // Object messageId = msg.getMessageID(); + // Message workContext = ThreadMessageContext.getMessageContext(); + // if (messageId != null) { + // workContext.setCorrelationID(messageId); + // } + Object resp = invokeTarget(msg); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } + return msg; + } + + +} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java deleted file mode 100644 index 684816b756..0000000000 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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.osgi.xml; - - -import java.util.Hashtable; -import java.util.List; - -import org.apache.tuscany.sca.assembly.ComponentProperty; -import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; -import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; -import org.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface; - - -/** - * OSGi implementation - * All attributes from have getters in this class - * This class implements OSGiImplementationInterface which is associated with OSGiImplementationProvider. - * - * @version $Rev$ $Date$ - */ -public class OSGiImplementation extends ImplementationImpl implements OSGiImplementationInterface { - - private String bundleSymbolicName; - private String bundleVersion; - - private String[] imports; - private Hashtable> referenceProperties; - private Hashtable> serviceProperties; - - private Hashtable> referenceCallbackProperties; - private Hashtable> serviceCallbackProperties; - - private String[] classList; - - private ModelFactoryExtensionPoint modelFactories; - - private Object osgiBundle; - - public OSGiImplementation( - ModelFactoryExtensionPoint modelFactories, - String bundleSymbolicName, - String bundleVersion, - String[] imports, - String[] classList, - Hashtable> refProperties, - Hashtable> serviceProperties) { - - super(); - this.bundleSymbolicName = bundleSymbolicName; - this.bundleVersion = bundleVersion; - this.imports = imports; - this.referenceProperties = refProperties; - this.serviceProperties = serviceProperties; - this.classList = classList; - this.modelFactories = modelFactories; - } - - protected void setCallbackProperties(Hashtable> refCallbackProperties, - Hashtable> serviceCallbackProperties) { - - this.referenceCallbackProperties = refCallbackProperties; - this.serviceCallbackProperties = serviceCallbackProperties; - - } - - - public String getBundleSymbolicName() { - return bundleSymbolicName; - } - - public String getBundleVersion() { - return bundleVersion; - } - - public String[] getImports() { - return imports; - } - - public String[] getClassList() { - return classList; - } - - public ModelFactoryExtensionPoint getModelFactories() { - return modelFactories; - } - - public List getReferenceProperties(String referenceName) { - return referenceProperties.get(referenceName); - } - - public List getServiceProperties(String serviceName) { - return serviceProperties.get(serviceName); - } - - public List getReferenceCallbackProperties(String referenceName) { - return referenceCallbackProperties.get(referenceName); - } - - public List getServiceCallbackProperties(String serviceName) { - return serviceCallbackProperties.get(serviceName); - } - - /** - * Since OSGi implementation annotations may not be processed until much later, leave it to - * the OSGi invoker to decide whether pass-by-reference is allowed. - * @return - */ - public boolean isAllowsPassByReference() { - return true; - } - - public Object getOSGiBundle() { - return osgiBundle; - } - - public void setOSGiBundle(Object osgiBundle) { - this.osgiBundle = osgiBundle; - } - - private boolean areEqual(Object obj1, Object obj2) { - if (obj1 == obj2) - return true; - if (obj1 == null || obj2 == null) - return false; - return obj1.equals(obj2); - } - - @Override - public boolean equals(Object obj) { - - if (!(obj instanceof OSGiImplementation)) - return super.equals(obj); - OSGiImplementation impl = (OSGiImplementation)obj; - if (!areEqual(bundleSymbolicName, impl.bundleSymbolicName)) - return false; - if (!areEqual(bundleVersion, impl.bundleVersion)) - return false; - if (!areEqual(serviceProperties, impl.serviceProperties)) - return false; - if (!areEqual(serviceCallbackProperties, impl.serviceCallbackProperties)) - return false; - if (!areEqual(referenceProperties, impl.referenceProperties)) - return false; - if (!areEqual(referenceCallbackProperties, impl.referenceCallbackProperties)) - return false; - return super.equals(obj); - } - - - -} diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java index 62578bee33..7f246cb76c 100644 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java @@ -53,6 +53,7 @@ import org.apache.tuscany.sca.contribution.service.ContributionReadException; import org.apache.tuscany.sca.contribution.service.ContributionResolveException; import org.apache.tuscany.sca.contribution.service.ContributionWriteException; import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.implementation.osgi.impl.OSGiImplementationImpl; import org.apache.tuscany.sca.interfacedef.Interface; import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; @@ -75,7 +76,7 @@ import org.w3c.dom.Node; * * @version $Rev$ $Date$ */ -public class OSGiImplementationProcessor implements StAXArtifactProcessor { +public class OSGiImplementationProcessor implements StAXArtifactProcessor { public static final QName IMPLEMENTATION_OSGI = new QName(Constants.SCA10_TUSCANY_NS, "implementation.osgi"); @@ -136,8 +137,8 @@ public class OSGiImplementationProcessor implements StAXArtifactProcessor getModelType() { - return OSGiImplementation.class; + public Class getModelType() { + return OSGiImplementationImpl.class; } private String[] tokenize(String str) { @@ -150,7 +151,7 @@ public class OSGiImplementationProcessor implements StAXArtifactProcessor properties = componentType.getProperties(); -- cgit v1.2.3