summaryrefslogtreecommitdiffstats
path: root/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime')
-rw-r--r--tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java1254
-rw-r--r--tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java109
-rw-r--r--tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java299
-rw-r--r--tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java139
-rw-r--r--tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java199
5 files changed, 2000 insertions, 0 deletions
diff --git a/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java b/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java
new file mode 100644
index 0000000000..b49f94c1e0
--- /dev/null
+++ b/tags/java/sca/1.5.1/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<RuntimeWire, Reference> referenceWires = new Hashtable<RuntimeWire,Reference>();
+ private Hashtable<RuntimeWire, ComponentReference> componentReferenceWires
+ = new Hashtable<RuntimeWire,ComponentReference>();
+ private HashSet<RuntimeWire> resolvedWires = new HashSet<RuntimeWire>();
+ private boolean wiresResolved;
+
+ private AtomicInteger startBundleEntryCount = new AtomicInteger();
+ private AtomicInteger processAnnotationsEntryCount = new AtomicInteger();
+
+ private JavaPropertyValueObjectFactory propertyValueFactory;
+
+
+ private Hashtable<String, Object> componentProperties = new Hashtable<String, Object>();
+ private RuntimeComponent runtimeComponent;
+
+ private Bundle osgiBundle;
+ private ArrayList<Bundle> dependentBundles = new ArrayList<Bundle>();
+ 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 <property/> elements
+ // Create property values in the table of the appropriate class based
+ // on the property type specified.
+ private void processProperties(List<?> props, Hashtable<String, Object> 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<String, Object> 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 <implementation.osgi /> 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<Object>() {
+ 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<String, Object> props = new Hashtable<String, Object>();
+ 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<String, Object> props = new Hashtable<String, Object>();
+ 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<String> dummyClasses = new ArrayList<String>();
+
+ 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<Class<?>> dummyClasses = new ArrayList<Class<?>>();
+
+ 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<Object>(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<Bundle>() {
+ 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<String, Object> targetProperties = new Hashtable<String, Object>();
+ 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<Operation> 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<String, Object> targetProperties = new Hashtable<String, Object>();
+ 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<Class<?>>() {
+ public Class<?> run() throws Exception {
+ return bundle.loadClass(interfaceClass.getName());
+ }
+ });
+
+ final Object proxy = proxyService.createProxy(proxyInterface, wire);
+ final Hashtable<String, Object> finalTargetProperties = targetProperties;
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ 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<Service> services = implementation.getServices();
+ HashSet<String> pidsProcessed = new HashSet<String>();
+
+ for (Service service : services) {
+
+ List<ComponentProperty> 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<String, Object>();
+ 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<RuntimeWire> 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/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java b/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java
new file mode 100644
index 0000000000..1a13ef99f7
--- /dev/null
+++ b/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProviderFactory.java
@@ -0,0 +1,109 @@
+/*
+ * 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.Mediator;
+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<OSGiImplementation> {
+
+ 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);
+
+ Mediator mediator = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class);
+ 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<OSGiImplementation> getModelType() {
+ return OSGiImplementation.class;
+ }
+
+}
diff --git a/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiInstanceWrapper.java b/tags/java/sca/1.5.1/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/tags/java/sca/1.5.1/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<T> implements InstanceWrapper<T> {
+ private static final Random RANDOM_NUMBER_GENERATOR = new Random();
+
+ private OSGiAnnotations annotationProcessor;
+ private OSGiImplementationProvider provider;
+ private BundleContext bundleContext;
+ private Hashtable<Object,InstanceInfo<T>> instanceInfoList =
+ new Hashtable<Object,InstanceInfo<T>>();
+
+ // 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<InstanceInfo<T>> instances = instanceInfoList.values().iterator();
+ while (instances.hasNext()) {
+ InstanceInfo<T> 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<T> instanceInfo = new InstanceInfo<T>();
+
+ 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<ComponentService> services = provider.getRuntimeComponent().getServices();
+ for (ComponentService service : services) {
+ getInstance(service);
+ }
+ }
+ }
+
+ public synchronized void stop() throws TargetDestructionException {
+
+ for (InstanceInfo<T> 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<T> 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<? extends Annotation> 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<T> {
+ private T osgiInstance;
+ private ServiceReference osgiServiceReference;
+ private BundleContext refBundleContext;
+ private boolean isFirstInstance;
+
+ }
+
+}
diff --git a/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRemotableInvoker.java b/tags/java/sca/1.5.1/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/tags/java/sca/1.5.1/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<Object, Object> map = new IdentityHashMap<Object, Object>();
+ 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/tags/java/sca/1.5.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java b/tags/java/sca/1.5.1/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/tags/java/sca/1.5.1/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<T> implements Invoker {
+
+ private Operation operation;
+ protected InstanceWrapper<T> 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;
+ }
+
+
+}