summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi')
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java47
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java225
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java1217
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java67
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java205
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java132
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java194
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/EquinoxRuntime.java106
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/FelixRuntime.java193
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/KnopflerfishRuntime.java156
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRuntime.java91
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java199
-rw-r--r--sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java494
13 files changed, 3326 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java
new file mode 100644
index 0000000000..cfc98c711a
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiImplementationInterface.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+import org.apache.tuscany.sca.core.scope.Scope;
+
+/**
+ *
+ * The model representing an OSGi implementation in an SCA assembly model.
+ *
+ */
+public interface OSGiImplementationInterface extends Implementation, Extensible {
+
+ public String getBundleName();
+
+ public String getBundleLocation();
+
+ public String[] getImports();
+
+ public Scope getScope();
+
+ public List<ComponentProperty> getReferenceProperties(String referenceName);
+
+ public List<ComponentProperty> getServiceProperties(String serviceName);
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java
new file mode 100644
index 0000000000..af09013b6e
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java
@@ -0,0 +1,225 @@
+/*
+ * 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.context;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.core.factory.ObjectCreationException;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.databinding.Mediator;
+import org.apache.tuscany.sca.databinding.SimpleTypeMapper;
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.databinding.xml.DOMDataBinding;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * Process properties and create property values.
+ *
+ * This code has been copied from the Java implementation to avoid dependencies on the Java implementation.
+ *
+ */
+public class OSGiPropertyValueObjectFactory {
+ protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl();
+ boolean isSimpleType;
+
+
+ public OSGiPropertyValueObjectFactory() {
+ }
+
+ public OSGiPropertyValueObjectFactory(Mediator mediator) {
+ }
+
+ public ObjectFactory createValueFactory(Property property, Object propertyValue) {
+
+ Class javaType = SimpleTypeMapperImpl.getJavaType(property.getXSDType());
+ isSimpleType = isSimpleType(property);
+ Document doc = (Document)propertyValue;
+ Element rootElement = doc.getDocumentElement();
+ if (property.isMany()) {
+ if (isSimpleType) {
+ String value = "";
+ if (rootElement.getChildNodes().getLength() > 0) {
+ value = rootElement.getChildNodes().item(0).getTextContent();
+ }
+ List<String> values =
+ getSimplePropertyValues(value, javaType);
+ return new ListObjectFactoryImpl(property,
+ values,
+ isSimpleType,
+ javaType);
+ } else {
+ return new ListObjectFactoryImpl(property,
+ getComplexPropertyValues(doc),
+ isSimpleType,
+ javaType);
+ }
+ } else {
+ if (isSimpleType) {
+ String value = "";
+ if (rootElement.getChildNodes().getLength() > 0) {
+ value = rootElement.getChildNodes().item(0).getTextContent();
+ }
+ return new ObjectFactoryImpl(property,
+ value,
+ isSimpleType,
+ javaType);
+ } else {
+ Object value = getComplexPropertyValues(doc).get(0);
+ return new ObjectFactoryImpl(property,
+ value,
+ isSimpleType,
+ javaType);
+ }
+
+ }
+ }
+
+ private boolean isSimpleType(Property property) {
+ if (property.getXSDType() != null) {
+ return SimpleTypeMapperImpl.isSimpleXSDType(property.getXSDType());
+ } else {
+ if (property instanceof Document) {
+ Document doc = (Document)property;
+ Element element = doc.getDocumentElement();
+ if (element.getChildNodes().getLength() == 1 &&
+ element.getChildNodes().item(0).getNodeType() == Node.TEXT_NODE) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private List<String> getSimplePropertyValues(String concatenatedValue, Class javaType) {
+ List<String> propValues = new ArrayList<String>();
+ StringTokenizer st = null;
+ if ( javaType.getName().equals("java.lang.String")) {
+ st = new StringTokenizer(concatenatedValue, "\"");
+ } else {
+ st = new StringTokenizer(concatenatedValue);
+ }
+ String aToken = null;
+ while (st.hasMoreTokens()) {
+ aToken = st.nextToken();
+ if (aToken.trim().length() > 0) {
+ propValues.add(aToken);
+ }
+ }
+ return propValues;
+ }
+
+ private List<Node> getComplexPropertyValues(Document document) {
+ Element rootElement = document.getDocumentElement();
+ List<Node> propValues = new ArrayList<Node>();
+ for (int count = 0 ; count < rootElement.getChildNodes().getLength() ; ++count) {
+ if (rootElement.getChildNodes().item(count).getNodeType() == Node.ELEMENT_NODE) {
+ propValues.add(rootElement.getChildNodes().item(count));
+ }
+ }
+ return propValues;
+ }
+
+ public abstract class ObjectFactoryImplBase implements ObjectFactory {
+ protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl();
+ protected Property property;
+ protected Object propertyValue;
+ protected Class javaType;
+ protected DataType<XMLType> sourceDataType;
+ protected DataType<?> targetDataType;
+ boolean isSimpleType;
+
+ public ObjectFactoryImplBase(Property property, Object propertyValue, boolean isSimpleType, Class javaType) {
+ this.isSimpleType = isSimpleType;
+ this.property = property;
+ this.propertyValue = propertyValue;
+ this.javaType = javaType;
+ sourceDataType =
+ new DataTypeImpl<XMLType>(DOMDataBinding.NAME, Node.class,
+ new XMLType(null, this.property.getXSDType()));
+ TypeInfo typeInfo = null;
+ if (this.property.getXSDType() != null) {
+ if (SimpleTypeMapperImpl.isSimpleXSDType(this.property.getXSDType())) {
+ typeInfo = new TypeInfo(property.getXSDType(), true, null);
+ } else {
+ typeInfo = new TypeInfo(property.getXSDType(), false, null);
+ }
+ } else {
+ typeInfo = new TypeInfo(property.getXSDType(), false, null);
+ }
+
+ XMLType xmlType = new XMLType(typeInfo);
+ String dataBinding = null; //(String)property.getExtensions().get(DataBinding.class.getName());
+ if (dataBinding != null) {
+ targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType);
+ } else {
+ targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType);
+ }
+ }
+ }
+
+ public class ObjectFactoryImpl extends ObjectFactoryImplBase {
+ public ObjectFactoryImpl(Property property, Object propertyValue, boolean isSimpleType, Class javaType) {
+ super(property, propertyValue, isSimpleType, javaType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getInstance() throws ObjectCreationException {
+ if (isSimpleType) {
+ return simpleTypeMapper.toJavaObject(property.getXSDType(), (String)propertyValue, null);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public class ListObjectFactoryImpl extends ObjectFactoryImplBase {
+ public ListObjectFactoryImpl(Property property, List<?>propertyValues, boolean isSimpleType, Class javaType) {
+ super(property, propertyValues, isSimpleType, javaType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<?> getInstance() throws ObjectCreationException {
+ if (isSimpleType) {
+ List<Object> values = new ArrayList<Object>();
+ for (String aValue : (List<String>)propertyValue) {
+ values.add(simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null));
+ }
+ return values;
+ } else {
+ List instances = new ArrayList();
+ for (Node aValue : (List<Node>)propertyValue) {
+ instances.add(aValue);
+ }
+ return instances;
+ }
+ }
+ }
+}
+
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java
new file mode 100644
index 0000000000..c621794006
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProvider.java
@@ -0,0 +1,1217 @@
+/*
+ * 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.beans.Introspector;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+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.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.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.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider;
+import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint;
+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.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface;
+import org.apache.tuscany.sca.implementation.osgi.context.OSGiPropertyValueObjectFactory;
+import org.apache.tuscany.sca.implementation.osgi.runtime.OSGiRuntime;
+import org.apache.tuscany.sca.implementation.osgi.xml.OSGiImplementation;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+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
+ *
+ */
+public class OSGiImplementationProvider implements ScopedImplementationProvider, FrameworkListener {
+
+ private static final String COMPONENT_SERVICE_NAME = "component.service.name";
+
+ private OSGiImplementation implementation;
+ 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 OSGiPropertyValueObjectFactory propertyValueFactory = new OSGiPropertyValueObjectFactory();
+
+
+ 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 DataBindingExtensionPoint dataBindingRegistry;
+
+ private boolean packagesRefreshed;
+
+
+ public OSGiImplementationProvider(RuntimeComponent definition,
+ OSGiImplementationInterface impl,
+ DataBindingExtensionPoint dataBindingRegistry) throws BundleException {
+
+
+ this.implementation = (OSGiImplementation)impl;
+ this.runtimeComponent = definition;
+ this.dataBindingRegistry = dataBindingRegistry;
+
+ bundleContext = getBundleContext();
+ osgiBundle = installBundle();
+
+ // 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);
+ }
+ }
+
+
+ // 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);
+ }
+
+
+ }
+
+ 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 <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;
+ ObjectFactory<?> objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue());
+ Object value = objFactory.getInstance();
+
+ propsTable.put(prop.getName(), value);
+ }
+ }
+ }
+
+
+ private BundleContext getBundleContext() throws BundleException {
+
+ if (bundleContext == null) {
+ osgiRuntime = OSGiRuntime.getRuntime();
+ bundleContext = osgiRuntime .getBundleContext();
+ }
+
+ return bundleContext;
+ }
+
+ private Bundle getBundle() throws Exception {
+
+ Bundle[] bundles = bundleContext.getBundles();
+ for (Bundle b : bundles) {
+ if (b.getLocation().equals(implementation.getBundleName())) {
+ return b;
+ }
+ }
+ return null;
+ }
+
+
+ // Install the bundle corresponding to this component.
+ private Bundle installBundle() throws ObjectCreationException {
+ try {
+
+ Bundle bundle = null;
+
+ if ((bundle = getBundle()) == null) {
+
+ String bundleName = implementation.getBundleLocation();
+
+ bundle = bundleContext.installBundle(bundleName);
+
+ }
+
+ osgiServiceListener = new OSGiServiceListener(bundle);
+
+ bundleContext.addServiceListener(osgiServiceListener);
+
+ return bundle;
+
+ } catch (Exception e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+
+ 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;
+ }
+
+ protected Bundle startBundle() throws ObjectCreationException {
+
+ try {
+
+ if (osgiBundle.getState() != Bundle.ACTIVE && osgiBundle.getState() != Bundle.STARTING) {
+
+ configurePropertiesUsingConfigAdmin();
+
+ resolveBundle();
+
+ 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 {
+ osgiBundle.start();
+ break;
+ } catch (BundleException 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);
+ }
+ return osgiBundle;
+ }
+
+
+ protected org.osgi.framework.ServiceReference getOSGiServiceReference(ComponentService service)
+ throws ObjectCreationException {
+
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ processProperties(implementation.getServiceProperties(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
+ while ((osgiServiceReference = getOSGiServiceReference(
+ scaServiceName,
+ serviceInterfaceName, filter)) == null) {
+
+ // Wait for the bundle to register the service
+ implementation.wait(100);
+ }
+ }
+
+ }
+ }
+
+ 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 = interfaceClass.getPackage().getName();
+ 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) {
+
+
+ bundleContext.addFrameworkListener(this);
+
+ packagesRefreshed = false;
+ packageAdmin.refreshPackages(null);
+
+ synchronized (this) {
+ if (!packagesRefreshed) {
+ this.wait(2000);
+ }
+ }
+ packagesRefreshed = false;
+ bundleContext.removeFrameworkListener(this);
+
+ }
+
+ 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 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 = interfaceClass.getPackage().getName();
+ 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, bundleContext);
+ }
+
+
+
+ private void resolveWireCreateDummyBundles(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
+
+ Bundle dummyBundle = 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 {
+
+ boolean createProxy = false;
+
+ 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();
+ }
+ else {
+ implProvider.resolveBundle();
+ }
+ }
+ else {
+ createProxy = true;
+ }
+
+ return createProxy;
+ }
+
+
+ // Register proxy service
+ private void resolveWireRegisterProxyService(Bundle bundle, 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();
+
+ Class<?> proxyInterface = bundle.loadClass(interfaceClass.getName());
+
+
+ Object proxy = proxyService.createProxy(proxyInterface, wire);
+
+
+ bundleContext.registerService(proxyInterface.getName(), proxy, targetProperties);
+
+
+ }
+
+ private void registerCallbackProxyService(Bundle bundle, Class interfaceClass,
+ RuntimeComponentService service) throws Exception {
+
+ List<RuntimeWire> wires = service.getCallbackWires();
+ Hashtable<String, Object> targetProperties = new Hashtable<String, Object>();
+ processProperties(implementation.getServiceCallbackProperties(service.getName()), targetProperties);
+ targetProperties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
+
+ JDKProxyFactory proxyService = new JDKProxyFactory();
+
+ Class<?> proxyInterface = bundle.loadClass(interfaceClass.getName());
+
+
+ Object proxy = proxyService.createCallbackProxy(proxyInterface, wires);
+
+
+ bundleContext.registerService(proxyInterface.getName(), proxy, targetProperties);
+
+
+ }
+
+
+ private void resolveBundle() throws ObjectCreationException {
+
+
+ try {
+
+ if (!wiresResolved) {
+ wiresResolved = true;
+
+ 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++;
+ }
+
+
+ index = 0;
+ for (RuntimeWire wire : referenceWires.keySet()) {
+
+ if (createProxyService[index] && !wireResolved[index])
+ resolveWireRegisterProxyService(osgiBundle, interfaceClasses[index], wire);
+ index++;
+ }
+ for (ComponentService service : runtimeComponent.getServices()) {
+ if (interfaceClasses[index] != null) {
+ registerCallbackProxyService(osgiBundle, interfaceClasses[index],
+ ((RuntimeComponentService)service));
+ }
+ index++;
+ }
+ }
+ else if (osgiBundle.getState() == Bundle.INSTALLED && packageAdmin != null) {
+ packageAdmin.resolveBundles(new Bundle[] {osgiBundle});
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new ObjectCreationException(e);
+ }
+ }
+
+
+
+ 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());
+ 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();
+ }
+
+ }
+
+ protected void injectProperties(Object instance) {
+
+ if (!implementation.needsPropertyInjection())
+ return;
+
+ Class implClass = instance.getClass();
+ List<ComponentProperty> compProps = runtimeComponent.getProperties();
+
+ for (ComponentProperty prop : compProps) {
+
+ boolean hasSetProp = false;
+ String propName = prop.getName();
+ ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue());
+
+ try {
+ Field field = implClass.getDeclaredField(propName);
+ org.osoa.sca.annotations.Property propAnn;
+
+ if ((propAnn = field.getAnnotation(org.osoa.sca.annotations.Property.class)) != null
+ || Modifier.isPublic(field.getModifiers())) {
+
+ try {
+ if (!field.isAccessible())
+ field.setAccessible(true);
+
+ field.set(instance, objFactory.getInstance());
+ hasSetProp = true;
+ } catch (IllegalAccessException e) {
+ if (propAnn.required())
+ throw new RuntimeException(e);
+ }
+
+ }
+ } catch (NoSuchFieldException e) {
+ // Ignore exception
+ }
+
+ if (!hasSetProp) {
+ Method[] methods = implClass.getDeclaredMethods();
+ org.osoa.sca.annotations.Property propAnn = null;
+
+ for (Method method : methods) {
+
+ if (!method.getName().startsWith("set"))
+ continue;
+ if ((propAnn = method.getAnnotation(org.osoa.sca.annotations.Property.class)) != null
+ || Modifier.isPublic(method.getModifiers())) {
+
+ String methodPropName = Introspector.decapitalize(method.getName().substring(3));
+ if (!propName.equals(methodPropName))
+ continue;
+ }
+ try {
+ if (!method.isAccessible())
+ method.setAccessible(true);
+
+ method.invoke(instance, objFactory.getInstance());
+ hasSetProp = true;
+ } catch (Exception e) {
+ if (propAnn != null && propAnn.required())
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ }
+
+ }
+
+ protected void injectPropertiesWithoutAnnotations(Object instance) {
+
+ if (!implementation.needsPropertyInjection())
+ return;
+
+ Class implClass = instance.getClass();
+ List<ComponentProperty> compProps = runtimeComponent.getProperties();
+
+ for (ComponentProperty prop : compProps) {
+
+ boolean hasSetProp = false;
+ String propName = prop.getName();
+ ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue());
+
+ try {
+ Field field = implClass.getDeclaredField(propName);
+
+ if (Modifier.isPublic(field.getModifiers())) {
+
+ try {
+ field.set(instance, objFactory.getInstance());
+ hasSetProp = true;
+
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ } catch (NoSuchFieldException e) {
+ // Ignore exception
+ }
+
+ if (!hasSetProp) {
+ Method[] methods = implClass.getDeclaredMethods();
+ for (Method method : methods) {
+
+ if (!method.getName().startsWith("set"))
+ continue;
+ if (Modifier.isPublic(method.getModifiers())) {
+
+ String methodPropName = Introspector.decapitalize(method.getName().substring(3));
+ if (!propName.equals(methodPropName))
+ continue;
+ }
+ try {
+ method.invoke(instance, objFactory.getInstance());
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+
+ }
+
+ }
+
+
+
+ public boolean isOptimizable() {
+ return false;
+ }
+
+ public Scope getScope() {
+ return implementation.getScope();
+ }
+
+ public boolean isEagerInit() {
+ return implementation.isEagerInit();
+ }
+
+ public long getMaxAge() {
+ return implementation.getMaxAge();
+ }
+
+ public long getMaxIdleTime() {
+ return implementation.getMaxIdleTime();
+ }
+
+
+ public Invoker createTargetInvoker(RuntimeComponentService service, Operation operation) {
+
+
+ Interface serviceInterface = operation.getInterface();
+ boolean isRemotable = serviceInterface.isRemotable();
+
+
+ Invoker invoker = new OSGiTargetInvoker(operation, runtimeComponent, service);
+ if (isRemotable) {
+ return new OSGiRemotableInvoker(implementation, dataBindingRegistry, operation, runtimeComponent, service);
+ } else {
+ return invoker;
+ }
+
+ }
+
+
+ public Invoker createCallbackInvoker(Operation operation) {
+
+ return createTargetInvoker(null, operation);
+ }
+
+ public Invoker createInvoker(RuntimeComponentService service, Operation operation) {
+ return createTargetInvoker(service, operation);
+ }
+
+ public void start() {
+
+ 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);
+
+ }
+
+
+ public void stop() {
+
+ bundleContext.removeServiceListener(osgiServiceListener);
+ }
+
+
+
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+ synchronized (this) {
+ packagesRefreshed = true;
+ this.notifyAll();
+ }
+ }
+
+ }
+
+
+
+ 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/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java
new file mode 100644
index 0000000000..f6bf8a8b1e
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiImplementationProviderFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint;
+import org.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface;
+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
+ *
+ */
+public class OSGiImplementationProviderFactory implements ImplementationProviderFactory<OSGiImplementationInterface> {
+
+ DataBindingExtensionPoint dataBindings;
+
+ public OSGiImplementationProviderFactory(ExtensionPointRegistry extensionPoints) {
+
+ dataBindings = extensionPoints.getExtensionPoint(DataBindingExtensionPoint.class);
+ //FIXME transformers is never used
+ //TransformerExtensionPoint transformers = extensionPoints.getExtensionPoint(TransformerExtensionPoint.class);
+ //FIXME mediator is never used
+ //MediatorImpl mediator =new MediatorImpl(dataBindings, transformers);
+ //FIXME factory is never used
+ //OSGiPropertyValueObjectFactory factory = new OSGiPropertyValueObjectFactory(mediator);
+ }
+
+ public ImplementationProvider createImplementationProvider(RuntimeComponent component,
+ OSGiImplementationInterface implementation) {
+
+ try {
+
+ return new OSGiImplementationProvider(component, implementation, dataBindings);
+
+ } catch (BundleException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public Class<OSGiImplementationInterface> getModelType() {
+ return OSGiImplementationInterface.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java
new file mode 100644
index 0000000000..4d221d6669
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiInstanceWrapper.java
@@ -0,0 +1,205 @@
+/*
+ * 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.util.Hashtable;
+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.interfacedef.Interface;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+
+/**
+ * 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).
+ *
+ */
+public class OSGiInstanceWrapper<T> implements InstanceWrapper<T> {
+
+ private OSGiImplementationProvider provider;
+ private BundleContext bundleContext;
+ private Hashtable<Object,InstanceInfo<T>> instanceInfoList =
+ new Hashtable<Object,InstanceInfo<T>>();
+
+
+ public OSGiInstanceWrapper(OSGiImplementationProvider provider,
+ BundleContext bundleContext) {
+
+ this.provider = provider;
+ this.bundleContext = bundleContext;
+ }
+
+ public synchronized T getInstance(ComponentService service) throws TargetInitializationException {
+
+ if (instanceInfoList.get(service) != null)
+ return instanceInfoList.get(service).osgiInstance;
+
+ Bundle refBundle = provider.startBundle();
+
+ if (!provider.getImplementation().getScope().equals(Scope.COMPOSITE)) {
+ refBundle = getDummyReferenceBundle();
+ }
+
+ InstanceInfo<T> instanceInfo = new InstanceInfo<T>();
+ instanceInfoList.put(service, instanceInfo);
+
+ instanceInfo.osgiServiceReference = provider.getOSGiServiceReference(service);
+
+ instanceInfo.refBundleContext = refBundle.getBundleContext();
+ instanceInfo.osgiInstance = (T)instanceInfo.refBundleContext.getService(instanceInfo.osgiServiceReference);
+
+ provider.injectProperties(instanceInfo.osgiInstance);
+
+ return instanceInfo.osgiInstance;
+ }
+
+ public synchronized T getCallbackInstance(EndpointReference from, Interface callbackInterface)
+ throws TargetInitializationException {
+
+ if (instanceInfoList.get(callbackInterface) != null)
+ return instanceInfoList.get(callbackInterface).osgiInstance;
+
+ Bundle refBundle = provider.startBundle();
+
+ if (!provider.getImplementation().getScope().equals(Scope.COMPOSITE)) {
+ refBundle = getDummyReferenceBundle();
+ }
+
+ InstanceInfo<T> instanceInfo = new InstanceInfo<T>();
+ instanceInfoList.put(callbackInterface, instanceInfo);
+
+
+ instanceInfo.osgiServiceReference = provider.getOSGiServiceReference(from, callbackInterface);
+
+ instanceInfo.refBundleContext = refBundle.getBundleContext();
+ instanceInfo.osgiInstance = (T)instanceInfo.refBundleContext.getService(instanceInfo.osgiServiceReference);
+
+ 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) {
+
+ instanceInfo.refBundleContext.ungetService(instanceInfo.osgiServiceReference);
+
+ instanceInfo.osgiInstance = null;
+ instanceInfo.osgiServiceReference = null;
+
+ try {
+ if (instanceInfo.dummyBundle != null) {
+ instanceInfo.dummyBundle.uninstall();
+ }
+ } catch (Exception e) {
+ throw new TargetDestructionException(e);
+ }
+ }
+ }
+ instanceInfoList.clear();
+ }
+
+ private Bundle getDummyReferenceBundle() throws TargetInitializationException {
+
+ Bundle dummyBundle = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ String EOL = System.getProperty("line.separator");
+ String bundleName = "dummy.sca." + new Random().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());
+
+ dummyBundle = bundleContext.installBundle("file://" + bundleName + ".jar", in);
+
+ dummyBundle.start();
+
+ } catch (Exception e) {
+ throw new TargetInitializationException(e);
+ }
+
+ return dummyBundle;
+
+ }
+
+ private static class InstanceInfo<T> {
+ private T osgiInstance;
+ private ServiceReference osgiServiceReference;
+ private Bundle dummyBundle;
+ private BundleContext refBundleContext;
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java
new file mode 100644
index 0000000000..59efe57bae
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiRemotableInvoker.java
@@ -0,0 +1,132 @@
+/*
+ * 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.xml.OSGiImplementation;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * An interceptor to enforce pass-by-value semantics for remotable interfaces
+ *
+ */
+public class OSGiRemotableInvoker extends OSGiTargetInvoker {
+
+ private DataBindingExtensionPoint registry;
+ private Operation operation;
+ private OSGiImplementation osgiImplementation;
+
+ /**
+ * @param registry
+ * @param operation
+ * @param method
+ * @param component
+ */
+ public OSGiRemotableInvoker(OSGiImplementation osgiImplementation,
+ DataBindingExtensionPoint registry,
+ Operation operation,
+ RuntimeComponent component,
+ RuntimeComponentService service) {
+ super(operation, component, service);
+ this.osgiImplementation = osgiImplementation;
+ this.registry = registry;
+ this.operation = operation;
+ }
+
+ @Override
+ public Object invokeMethod(Object targetObject, Method m, Message msg)
+ throws InvocationTargetException {
+
+ Object result;
+ if (osgiImplementation.isAllowsPassByReference(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, 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 {
+ String dataBindingId = operation.getInputType().getLogical().get(i).getDataBinding();
+ DataBinding dataBinding = registry.getDataBinding(dataBindingId);
+ copiedArg = copy(args[i], dataBinding);
+ map.put(args[i], copiedArg);
+ copiedArgs[i] = copiedArg;
+ }
+ }
+ }
+ return copiedArgs;
+ }
+
+ public Object copy(Object arg, DataBinding argDataBinding) {
+ if (arg == null) {
+ return null;
+ }
+ Object copiedArg;
+ if (argDataBinding != null) {
+ copiedArg = argDataBinding.copy(arg);
+ } else {
+ copiedArg = arg;
+ DataType<?> dataType = registry.introspectType(arg);
+ if (dataType != null) {
+ DataBinding binding = registry.getDataBinding(dataType.getDataBinding());
+ if (binding != null) {
+ copiedArg = binding.copy(arg);
+ }
+ }
+ // FIXME: What to do if it's not recognized?
+ }
+ return copiedArg;
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java
new file mode 100644
index 0000000000..b128905703
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/invocation/OSGiTargetInvoker.java
@@ -0,0 +1,194 @@
+/*
+ * 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.List;
+
+import org.apache.tuscany.sca.core.context.InstanceWrapper;
+import org.apache.tuscany.sca.core.invocation.TargetInvocationException;
+import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.core.scope.ScopeContainer;
+import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent;
+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.InvocationChain;
+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.RuntimeComponent;
+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
+ */
+public class OSGiTargetInvoker<T> implements Invoker {
+
+ private Operation operation;
+ protected InstanceWrapper<T> target;
+ protected boolean stateless;
+ protected boolean cacheable;
+
+ private final RuntimeComponentService service;
+ private final ScopeContainer scopeContainer;
+
+ public OSGiTargetInvoker(
+ Operation operation,
+ RuntimeComponent component,
+ RuntimeComponentService service) {
+
+ this.operation = operation;
+ this.service = service;
+ this.scopeContainer = ((ScopedRuntimeComponent) component).getScopeContainer();
+ this.cacheable = true;
+ stateless = Scope.STATELESS == scopeContainer.getScope();
+
+ }
+
+ /**
+ * Resolves the target service instance or returns a cached one
+ */
+ protected InstanceWrapper getInstance(ConversationSequence sequence, Object contextId)
+ throws TargetResolutionException, TargetInvocationException {
+
+ if (sequence == null) {
+ if (cacheable) {
+ if (target == null) {
+ target = scopeContainer.getWrapper(contextId);
+ }
+ return target;
+ } else {
+ return scopeContainer.getWrapper(contextId);
+ }
+ } else {
+ switch (sequence) {
+ case CONVERSATION_START:
+ assert !cacheable;
+ return scopeContainer.getWrapper(contextId);
+ case CONVERSATION_CONTINUE:
+ case CONVERSATION_END:
+ assert !cacheable;
+ return scopeContainer.getAssociatedWrapper(contextId);
+ default:
+ throw new TargetInvocationException("Unknown sequence type: " + String.valueOf(sequence));
+ }
+ }
+ }
+
+
+ private Object invokeTarget(Message msg) throws InvocationTargetException {
+
+
+ ConversationSequence sequence = msg.getConversationSequence();
+ Object contextId = ThreadMessageContext.getMessageContext().getConversationID();
+ EndpointReference from = ThreadMessageContext.getMessageContext().getFrom();
+ try {
+ OSGiInstanceWrapper wrapper = (OSGiInstanceWrapper)getInstance(sequence, contextId);
+ Object instance;
+
+ if (service != null)
+ instance = wrapper.getInstance(service);
+ else
+ instance = wrapper.getCallbackInstance(from, operation.getInterface());
+
+ Method m = JavaInterfaceUtil.findMethod(instance.getClass(), operation);
+
+ Object ret = invokeMethod(instance, m, msg);
+
+ scopeContainer.returnWrapper(wrapper, contextId);
+ if (sequence == ConversationSequence.CONVERSATION_END) {
+ // if end conversation, remove resource
+ scopeContainer.remove(contextId);
+ }
+ 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;
+ }
+
+ public boolean isCacheable() {
+ return cacheable;
+ }
+
+ public void setCacheable(boolean cacheable) {
+ this.cacheable = cacheable;
+ }
+
+ protected InvocationChain getInvocationChain(List<InvocationChain> chains, Operation targetOperation) {
+ for (InvocationChain chain : chains) {
+ if (chain.getTargetOperation().equals(targetOperation)) {
+ return chain;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/EquinoxRuntime.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/EquinoxRuntime.java
new file mode 100644
index 0000000000..37fc76fca1
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/EquinoxRuntime.java
@@ -0,0 +1,106 @@
+/*
+ * 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.Field;
+import java.lang.reflect.Method;
+
+import org.osgi.framework.BundleContext;
+
+public class EquinoxRuntime extends OSGiRuntime {
+
+
+ private static BundleContext bundleContext;
+
+ private static EquinoxRuntime instance;
+
+ private static Class eclipseStarterClass;
+
+ public static OSGiRuntime getInstance() throws Exception {
+ if (instance == null) {
+ EquinoxRuntime runtime = new EquinoxRuntime();
+ runtime.startRuntime();
+ instance = runtime;
+ }
+ return instance;
+ }
+
+
+ protected BundleContext startRuntime() throws Exception {
+
+ if (bundleContext != null)
+ return bundleContext;
+
+ eclipseStarterClass = EquinoxRuntime.class.getClassLoader().loadClass("org.eclipse.core.runtime.adaptor.EclipseStarter");
+ Method startupMethod = eclipseStarterClass.getMethod("startup", String [].class, Runnable.class);
+
+ // Equinox version 3.2 upwards have a startup method which returns BundleContext
+ if (startupMethod.getReturnType() == BundleContext.class) {
+ bundleContext = (BundleContext) startupMethod.invoke(null, new String[] {"-clean", "-console"}, null );
+ }
+ else {
+
+ // Older versions of Equinox dont have a public method to obtain system bundlecontext
+ // Extract bundleContext from the private field 'context'. We are assuming that
+ // there is no access restriction
+ Method mainMethod = eclipseStarterClass.getMethod("main", String [].class);
+ mainMethod.invoke(null, (Object)new String[] {"-clean", "-console"});
+
+ Field contextField = eclipseStarterClass.getDeclaredField("context");
+ contextField.setAccessible(true);
+ bundleContext = (BundleContext) contextField.get(null);
+
+ }
+
+
+ return bundleContext;
+
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ @Override
+ public void shutdown() throws Exception {
+
+ if (bundleContext == null)
+ return;
+ bundleContext = null;
+ instance = null;
+ if (eclipseStarterClass != null) {
+ Method shutdownMethod = eclipseStarterClass.getMethod("shutdown");
+ try {
+ shutdownMethod.invoke(eclipseStarterClass);
+ } catch (Exception e) {
+ // Ignore errors.
+ }
+ }
+ }
+
+
+ @Override
+ public boolean supportsBundleFragments() {
+ return false;
+ }
+
+
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/FelixRuntime.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/FelixRuntime.java
new file mode 100644
index 0000000000..1ba8ce3c6b
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/FelixRuntime.java
@@ -0,0 +1,193 @@
+/*
+ * 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.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class FelixRuntime extends OSGiRuntime implements BundleActivator {
+
+ private static BundleContext bundleContext;
+
+ private static FelixRuntime instance;
+
+ private static Class felixClass;
+ private static Object felix;
+
+ public static OSGiRuntime getInstance() throws Exception {
+ if (instance == null) {
+ FelixRuntime runtime = new FelixRuntime();
+ runtime.startRuntime();
+ instance = runtime;
+ }
+ return instance;
+ }
+
+
+ private static void deleteDirectory(File dir) {
+
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory())
+ deleteDirectory(files[i]);
+ else
+ files[i].delete();
+ }
+ dir.delete();
+
+ }
+
+ private BundleContext startRuntime() throws Exception {
+
+ if (bundleContext != null)
+ return bundleContext;
+
+
+ ClassLoader cl = FelixRuntime.class.getClassLoader();
+
+ Class felixMainClass = cl.loadClass("org.apache.felix.main.Main");
+ felixClass = cl.loadClass("org.apache.felix.framework.Felix");
+ Method propsMethod = felixMainClass.getMethod("loadConfigProperties");
+ Properties props = (Properties)propsMethod.invoke(null);
+
+ File profileDir = new File(".felix");
+ if (profileDir.isDirectory())
+ deleteDirectory(profileDir);
+ else
+ profileDir.delete();
+ profileDir.mkdir();
+ profileDir.deleteOnExit();
+
+ props.put("felix.cache.profiledir", profileDir.getAbsolutePath());
+ props.put("felix.embedded.execution", "true");
+ props.put("org.osgi.framework.system.packages",
+ "org.osgi.framework; version=1.3.0," +
+ "org.osgi.service.packageadmin; version=1.2.0, " +
+ "org.osgi.service.startlevel; version=1.0.0, " +
+ "org.osgi.service.url; version=1.0.0, " +
+ "org.osoa.sca.annotations; version=1.0.0, " +
+ "org.osoa.sca; version=1.0.0");
+
+
+ try {
+ Constructor felixConstructor = felixClass.getConstructor(Map.class, List.class);
+ List<BundleActivator> activators = new ArrayList<BundleActivator>();
+ felix = felixConstructor.newInstance(props, activators);
+ ((Bundle)felix).start();
+ bundleContext = ((Bundle)felix).getBundleContext();
+
+
+ } catch (Exception e) {
+
+ // This is the older Felix API which has been retained temporarily to avoid build break
+ // TODO: Remove these once Felix 1.0.0 is released.
+
+ Class propertyResolverClass = cl.loadClass("org.apache.felix.framework.util.MutablePropertyResolver");
+ Class propertyResolverImplClass = cl.loadClass("org.apache.felix.framework.util.MutablePropertyResolverImpl");
+
+ Constructor implConstructor = propertyResolverImplClass.getConstructor(Map.class);
+ Object mutableProps = implConstructor.newInstance(props);
+
+
+ try {
+ Constructor felixConstructor = felixClass.getConstructor(propertyResolverClass, List.class);
+ List<BundleActivator> activators = new ArrayList<BundleActivator>();
+ felix = felixConstructor.newInstance(mutableProps, activators);
+ ((Bundle)felix).start();
+ bundleContext = ((Bundle)felix).getBundleContext();
+ } catch (Exception e1) {
+
+
+ felix = felixClass.newInstance();
+ Method startMethod = felixClass.getMethod("start", propertyResolverClass, List.class);
+ List<BundleActivator> activators = new ArrayList<BundleActivator>();
+ BundleActivator activator = new FelixRuntime();
+ activators.add(activator);
+ startMethod.invoke(felix, mutableProps, activators);
+
+ synchronized (activator) {
+ int retries = 0;
+ while (bundleContext == null && retries++ < 10) {
+ activator.wait(1000);
+ }
+ }
+ }
+ }
+
+ return bundleContext;
+
+ }
+
+ public void start(BundleContext context) throws Exception {
+
+ bundleContext = context;
+ synchronized (this) {
+ this.notify();
+ }
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ bundleContext = null;
+ }
+
+
+
+ @Override
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+
+ @Override
+ public void shutdown() throws Exception {
+
+ if (bundleContext == null)
+ return;
+ bundleContext = null;
+ instance = null;
+
+ if (felix instanceof Bundle) {
+ ((Bundle)felix).stop();
+ }
+ else if (felix != null) {
+ Method shutdownMethod = felixClass.getMethod("shutdown");
+ try {
+ shutdownMethod.invoke(felix);
+ } catch (Exception e) {
+ // Ignore errors
+ }
+ felix = null;
+ }
+ }
+
+ @Override
+ public boolean supportsBundleFragments() {
+ return false;
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/KnopflerfishRuntime.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/KnopflerfishRuntime.java
new file mode 100644
index 0000000000..6a273015f3
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/KnopflerfishRuntime.java
@@ -0,0 +1,156 @@
+/*
+ * 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.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+public class KnopflerfishRuntime extends OSGiRuntime {
+
+ private static BundleContext bundleContext;
+
+ private static KnopflerfishRuntime instance;
+
+
+ private static Class frameworkClass;
+
+ private static Object framework;
+
+ public static OSGiRuntime getInstance() throws Exception {
+ if (instance == null) {
+ KnopflerfishRuntime runtime = new KnopflerfishRuntime();
+ runtime.startRuntime();
+ instance = runtime;
+ }
+ return instance;
+ }
+
+
+
+ // FIXME: Knopflerfish does not expose the methods used for configuration as public methods
+ // It may be worth using the private methods in org.knopflerfish.framework.Main for
+ // configuring using reflection if security policies allow it.
+ // For now, a simple configuration routine reads sca.xargs from the directory in
+ // the classpath which contains framework.jar. The entries in init.xargs starting with
+ // -install are assumed to be single-line entries with full bundle location.
+ //
+ private BundleContext startRuntime() throws Exception {
+
+ if (bundleContext != null)
+ return bundleContext;
+
+
+
+ System.setProperty("org.knopflerfish.framework.bundlestorage", "memory");
+
+ frameworkClass = KnopflerfishRuntime.class.getClassLoader().loadClass("org.knopflerfish.framework.Framework");
+ Constructor frameworkConstructor = frameworkClass.getConstructor(Object.class);
+ framework = frameworkConstructor.newInstance(new KnopflerfishRuntime());
+ Method launchMethod = frameworkClass.getMethod("launch", long.class);
+ launchMethod.invoke(framework, 0);
+ Method getContextMethod = frameworkClass.getMethod("getSystemBundleContext");
+ bundleContext = (BundleContext)getContextMethod.invoke(framework);
+
+ System.setProperty("com.gatespace.bundle.cm.store", "knopflerfish.store");
+ File xargsFile = null;
+ String classpath = System.getProperty("java.class.path");
+ String[] classpathEntries = classpath.split(System.getProperty("path.separator"));
+ for (int i = 0; i < classpathEntries.length; i++) {
+ if (classpathEntries[i].endsWith("framework.jar")) {
+ String path = classpathEntries[i].substring(0, classpathEntries[i].length() - "framework.jar".length());
+ path = path + "sca.xargs";
+ xargsFile = new File(path);
+ if (!xargsFile.exists())
+ xargsFile = null;
+ break;
+ }
+ }
+ if (xargsFile != null) {
+ BufferedReader reader = new BufferedReader(new FileReader(xargsFile));
+ String line;
+ Hashtable<String, Bundle> bundles = new Hashtable<String, Bundle>();
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("-install")) {
+ try {
+
+ String bundleLocation = line.substring("-install".length()).trim();
+ Bundle bundle = bundleContext.installBundle(bundleLocation);
+ bundles.put(bundleLocation, bundle);
+
+ } catch (BundleException e) {
+ e.printStackTrace();
+ }
+
+ }
+ if (line.startsWith("-start")) {
+
+ try {
+ String bundleLocation = line.substring("-start".length()).trim();
+ Bundle bundle = bundles.get(bundleLocation);
+ bundle.start();
+ } catch (BundleException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+
+ return bundleContext;
+
+ }
+
+ @Override
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ @Override
+ public void shutdown() throws Exception {
+
+ if (bundleContext == null)
+ return;
+ bundleContext = null;
+ instance = null;
+ if (framework != null) {
+ Method shutdownMethod = frameworkClass.getMethod("shutdown");
+ try {
+ shutdownMethod.invoke(framework);
+ } catch (Exception e) {
+ // Ignore errors
+ }
+ framework = null;
+ }
+
+ }
+
+ @Override
+ public boolean supportsBundleFragments() {
+ return true;
+ }
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRuntime.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRuntime.java
new file mode 100644
index 0000000000..cd416be39a
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiRuntime.java
@@ -0,0 +1,91 @@
+/*
+ * 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.Method;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+public abstract class OSGiRuntime {
+
+ public abstract BundleContext getBundleContext();
+
+ public abstract void shutdown() throws Exception;
+
+ public abstract boolean supportsBundleFragments();
+
+
+ /**
+ * System property org.apache.tuscany.implementation.osgi.runtime.OSGiRuntime can be set to the
+ * name of the OSGiRuntime class (eg. EquinoxRuntime). If set, start this runtime and return the
+ * system bundlecontext. If not set, start Equinox/Felix/Knopflerfish (in that order) from the
+ * classpath.
+ *
+ * @throws BundleException
+ */
+ public static OSGiRuntime getRuntime() throws BundleException {
+
+ String runtimeClassName = System.getProperty(OSGiRuntime.class.getName());
+
+ if (runtimeClassName != null) {
+ try {
+ Class<?> runtimeClass = OSGiRuntime.class.getClassLoader().loadClass(runtimeClassName);
+ Method method = runtimeClass.getMethod("getInstance");
+ return (OSGiRuntime) method.invoke(null);
+
+ } catch (Exception e) {
+ throw new BundleException("Could not start OSGi runtime " + runtimeClassName, e);
+ }
+ }
+
+ try {
+
+ return EquinoxRuntime.getInstance();
+
+ } catch (ClassNotFoundException e) {
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ try {
+
+ return FelixRuntime.getInstance();
+
+ } catch (ClassNotFoundException e) {
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ try {
+
+ return KnopflerfishRuntime.getInstance();
+
+ } catch (ClassNotFoundException e) {
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ throw new BundleException("Could not start OSGi runtime from the classpath");
+ }
+
+
+
+}
diff --git a/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.java
new file mode 100644
index 0000000000..a5d86bb92b
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementation.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.xml;
+
+
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.assembly.impl.ComponentTypeImpl;
+import org.apache.tuscany.sca.core.scope.Scope;
+import org.apache.tuscany.sca.implementation.osgi.OSGiImplementationInterface;
+import org.osoa.sca.annotations.AllowsPassByReference;
+
+
+/**
+ * OSGi implementation
+ * All attributes from <implementation.osgi> have getters in this class
+ * This class implements OSGiImplementationInterface which is associated with OSGiImplementationProvider.
+ */
+public class OSGiImplementation extends ComponentTypeImpl implements OSGiImplementationInterface {
+
+ private String bundleName;
+ private String bundleLocation;
+ private String[] imports;
+ private Scope scope;
+ private boolean isEagerInit;
+ private String[] allowsPassByRef;
+ private boolean needsPropertyInjection;
+ private Hashtable<String, List<ComponentProperty>> referenceProperties;
+ private Hashtable<String, List<ComponentProperty>> serviceProperties;
+
+ private Hashtable<String, List<ComponentProperty>> referenceCallbackProperties;
+ private Hashtable<String, List<ComponentProperty>> serviceCallbackProperties;
+
+
+ public OSGiImplementation(String bundleName,
+ String bundleLocation,
+ String[] imports,
+ String scopeName,
+ boolean isEagerInit,
+ String[] allowsPassByRef,
+ Hashtable<String, List<ComponentProperty>> refProperties,
+ Hashtable<String, List<ComponentProperty>> serviceProperties,
+ boolean needsPropertyInjection) {
+
+ super();
+ this.bundleName = bundleName;
+ this.bundleLocation = bundleLocation;
+ setURI(bundleName);
+ this.imports = imports;
+ this.scope = new Scope(scopeName == null?"COMPOSITE":scopeName);
+ this.isEagerInit = isEagerInit;
+ this.allowsPassByRef = allowsPassByRef;
+ this.referenceProperties = refProperties;
+ this.serviceProperties = serviceProperties;
+ this.needsPropertyInjection = needsPropertyInjection;
+
+ }
+
+
+ public String getBundleName() {
+ return bundleName;
+ }
+
+ public String getBundleLocation() {
+ return bundleLocation;
+ }
+
+
+ public String[] getImports() {
+ return imports;
+ }
+
+
+ public Scope getScope() {
+ return scope;
+ }
+
+ public List<ComponentProperty> getReferenceProperties(String referenceName) {
+ return referenceProperties.get(referenceName);
+ }
+
+ public List<ComponentProperty> getServiceProperties(String serviceName) {
+ return serviceProperties.get(serviceName);
+ }
+
+ public List<ComponentProperty> getReferenceCallbackProperties(String referenceName) {
+ return referenceCallbackProperties.get(referenceName);
+ }
+
+ public List<ComponentProperty> getServiceCallbackProperties(String serviceName) {
+ return serviceCallbackProperties.get(serviceName);
+ }
+
+
+ public boolean isAllowsPassByReference(Method method) {
+
+ if (allowsPassByRef == null || allowsPassByRef.length == 0)
+ return false;
+
+ String className = method.getDeclaringClass().getName();
+ String methodName = className + "." + method.getName();
+
+ for (String opName : allowsPassByRef) {
+ if (className.equals(opName) || methodName.equals(opName))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isAllowsPassByReferenceAnnotation(Method method) {
+
+ if (method.getAnnotation(AllowsPassByReference.class) != null) {
+ return true;
+ }
+ else if (method.getClass().getAnnotation(AllowsPassByReference.class) != null) {
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+ public boolean needsPropertyInjection() {
+ return needsPropertyInjection;
+ }
+
+
+ public boolean isEagerInit() {
+ return isEagerInit;
+ }
+
+ public long getMaxAge() {
+ return Long.MAX_VALUE;
+ }
+
+ public long getMaxIdleTime() {
+ return Long.MAX_VALUE;
+ }
+
+
+ protected void setCallbackProperties(Hashtable<String, List<ComponentProperty>> refCallbackProperties,
+ Hashtable<String, List<ComponentProperty>> serviceCallbackProperties) {
+
+ this.referenceCallbackProperties = refCallbackProperties;
+ this.serviceCallbackProperties = serviceCallbackProperties;
+
+ }
+
+ 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(bundleName, impl.bundleName))
+ return false;
+ if (!areEqual(bundleLocation, impl.bundleLocation))
+ 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/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java
new file mode 100644
index 0000000000..e2f2f81dce
--- /dev/null
+++ b/sca-java-1.x/tags/0.99-incubating/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/xml/OSGiImplementationProcessor.java
@@ -0,0 +1,494 @@
+/*
+ * 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 static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
+import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static org.osoa.sca.Constants.SCA_NS;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.assembly.ComponentType;
+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.assembly.xml.Constants;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+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.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * Process an <implementation.osgi/> element in a component definition. An instance of
+ * OSGiImplementation is created.
+ * Also associates the component type file with the implementation.
+ *
+ *
+ */
+public class OSGiImplementationProcessor implements StAXArtifactProcessor<OSGiImplementation> {
+
+ public static final QName IMPLEMENTATION_OSGI = new QName(Constants.SCA10_TUSCANY_NS, "implementation.osgi");
+
+ private static final String BUNDLE = "bundle";
+ private static final String BUNDLE_LOCATION = "bundleLocation";
+ private static final String SCOPE = "scope";
+ private static final String EAGER_INIT = "eagerInit";
+ private static final String IMPORTS = "imports";
+ private static final String ALLOWS_PASS_BY_REF = "allowsPassByReference";
+ private static final String INJECT_PROPERTIES = "injectProperties";
+
+
+ private static final QName PROPERTIES_QNAME = new QName(Constants.SCA10_TUSCANY_NS, "properties");
+ private static final QName PROPERTY_QNAME = new QName(Constants.SCA10_TUSCANY_NS, "property");
+
+ private JavaInterfaceFactory javaInterfaceFactory;
+ private AssemblyFactory assemblyFactory;
+
+ private static final DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ static {
+ domFactory.setNamespaceAware(true);
+ }
+
+ public OSGiImplementationProcessor(ModelFactoryExtensionPoint modelFactories) {
+
+ this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ this.javaInterfaceFactory = modelFactories.getFactory(JavaInterfaceFactory.class);
+ }
+
+ public QName getArtifactType() {
+ return IMPLEMENTATION_OSGI;
+ }
+
+ public Class<OSGiImplementation> getModelType() {
+ return OSGiImplementation.class;
+ }
+
+ private String[] tokenize(String str) {
+ StringTokenizer tokenizer = new StringTokenizer(str);
+ String[] tokens = new String[tokenizer.countTokens()];
+ for (int i= 0; i < tokens.length; i++) {
+ tokens[i] = tokenizer.nextToken();
+ }
+
+ return tokens;
+ }
+
+ public OSGiImplementation read(XMLStreamReader reader) throws ContributionReadException {
+
+ assert IMPLEMENTATION_OSGI.equals(reader.getName());
+
+ try {
+ String bundleName = reader.getAttributeValue(null, BUNDLE);
+ String bundleLocation = reader.getAttributeValue(null, BUNDLE_LOCATION);
+ String imports = reader.getAttributeValue(null, IMPORTS);
+ String[] importList;
+ if (imports != null)
+ importList = tokenize(imports);
+ else
+ importList = new String[0];
+ String scope = reader.getAttributeValue(null, SCOPE);
+ String allowsPassByRef = reader.getAttributeValue(null, ALLOWS_PASS_BY_REF);
+ String[] allowsPassByRefList;
+ if (allowsPassByRef != null)
+ allowsPassByRefList = tokenize(allowsPassByRef);
+ else
+ allowsPassByRefList = new String[0];
+
+ boolean injectProperties = !"false".equalsIgnoreCase(reader.getAttributeValue(null, INJECT_PROPERTIES));
+ boolean eagerInit = "true".equalsIgnoreCase(reader.getAttributeValue(null, EAGER_INIT));
+
+
+ Hashtable<String, List<ComponentProperty>> refProperties =
+ new Hashtable<String, List<ComponentProperty>>();
+ Hashtable<String, List<ComponentProperty>> serviceProperties =
+ new Hashtable<String, List<ComponentProperty>>();
+ Hashtable<String, List<ComponentProperty>> refCallbackProperties =
+ new Hashtable<String, List<ComponentProperty>>();
+ Hashtable<String, List<ComponentProperty>> serviceCallbackProperties =
+ new Hashtable<String, List<ComponentProperty>>();
+
+ while (reader.hasNext()) {
+
+ int next = reader.next();
+ if (next == END_ELEMENT && IMPLEMENTATION_OSGI.equals(reader.getName())) {
+ break;
+ }
+ else if (next == START_ELEMENT && PROPERTIES_QNAME.equals(reader.getName())) {
+
+ // FIXME: This is temporary code which allows reference and service properties used
+ // for filtering OSGi services to be specified in <implementation.osgi/>
+ // This should really be provided in the component type file since these
+ // properties are associated with an implementation rather than a configured
+ // instance of an implementation.
+ String refName = reader.getAttributeValue(null, "reference");
+ String serviceName = reader.getAttributeValue(null, "service");
+ String refCallbackName = reader.getAttributeValue(null, "referenceCallback");
+ String serviceCallbackName = reader.getAttributeValue(null, "serviceCallback");
+ List<ComponentProperty> props = readProperties(reader);
+ if (refName != null)
+ refProperties.put(refName, props);
+ else if (serviceName != null)
+ serviceProperties.put(serviceName, props);
+ else if (refCallbackName != null)
+ refCallbackProperties.put(refCallbackName, props);
+ else if (serviceCallbackName != null)
+ serviceCallbackProperties.put(serviceCallbackName, props);
+ else
+ throw new ContributionReadException("Properties in implementation.osgi should specify service or reference"); }
+ }
+
+ OSGiImplementation implementation = new OSGiImplementation(
+ bundleName,
+ bundleLocation,
+ importList,
+ scope,
+ eagerInit,
+ allowsPassByRefList,
+ refProperties,
+ serviceProperties,
+ injectProperties);
+ implementation.setCallbackProperties(refCallbackProperties, serviceCallbackProperties);
+
+
+ implementation.setUnresolved(true);
+
+ return implementation;
+
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ public void resolve(OSGiImplementation impl, ModelResolver resolver) throws ContributionResolveException {
+
+ try {
+
+ impl.setUnresolved(false);
+
+
+ String bundleName = impl.getBundleName();
+ String ctURI = bundleName.replaceAll("\\.", "/") + ".componentType";
+
+ ComponentType componentType = assemblyFactory.createComponentType();
+ componentType.setURI(ctURI);
+ componentType.setUnresolved(true);
+ componentType = resolver.resolveModel(ComponentType.class, componentType);
+ if (componentType.isUnresolved()) {
+ throw new ContributionResolveException("missing .componentType side file");
+ }
+
+ List<Service> services = componentType.getServices();
+ for (Service service : services) {
+ Interface interfaze = service.getInterfaceContract().getInterface();
+ if (interfaze instanceof JavaInterface) {
+ JavaInterface javaInterface = (JavaInterface)interfaze;
+ if (javaInterface.getJavaClass() == null) {
+ Class<?> javaClass = Class.forName(javaInterface.getName());
+ javaInterface.setJavaClass(javaClass);
+ }
+ Class<?> callback = null;
+ if (service.getInterfaceContract().getCallbackInterface() instanceof JavaInterface) {
+ JavaInterface callbackInterface = (JavaInterface)service.getInterfaceContract().getCallbackInterface();
+ if (callbackInterface.getJavaClass() == null) {
+ Class<?> javaClass = Class.forName(javaInterface.getName());
+ callbackInterface.setJavaClass(javaClass);
+ }
+ callback = callbackInterface.getJavaClass();
+ }
+
+ Service serv = createService(service, javaInterface.getJavaClass(), callback);
+ impl.getServices().add(serv);
+ }
+ }
+
+ List<Reference> references = componentType.getReferences();
+ for (Reference reference : references) {
+ Interface interfaze = reference.getInterfaceContract().getInterface();
+ if (interfaze instanceof JavaInterface) {
+ JavaInterface javaInterface = (JavaInterface)interfaze;
+ if (javaInterface.getJavaClass() == null) {
+ Class<?> javaClass = Class.forName(javaInterface.getName());
+ javaInterface.setJavaClass(javaClass);
+ }
+ Reference ref = createReference(reference, javaInterface.getJavaClass());
+ impl.getReferences().add(ref);
+ }
+ else
+ impl.getReferences().add(reference);
+ }
+
+ List<Property> properties = componentType.getProperties();
+ for (Property property : properties) {
+ impl.getProperties().add(property);
+ }
+ impl.setConstrainingType(componentType.getConstrainingType());
+
+
+ } catch (Exception e) {
+ throw new ContributionResolveException(e);
+ }
+
+ }
+
+ private Service createService(Service serv, Class<?> interfaze, Class<?> callbackInterfaze) throws InvalidInterfaceException {
+ Service service = assemblyFactory.createService();
+ JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+
+ // create a relative URI
+ service.setName(serv.getName());
+
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+
+ if (callbackInterfaze != null) {
+ JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callbackInterfaze);
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ else if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ return service;
+ }
+
+ private Reference createReference(Reference ref, Class<?> clazz) throws InvalidInterfaceException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+
+ reference.setName(ref.getName());
+ reference.setMultiplicity(ref.getMultiplicity());
+
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(clazz);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaInterfaceFactory.createJavaInterface(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ return reference;
+ }
+
+ public void write(OSGiImplementation model, XMLStreamWriter outputSource) throws ContributionWriteException {
+ }
+
+
+ private QName getQNameValue(XMLStreamReader reader, String value) {
+ if (value != null) {
+ int index = value.indexOf(':');
+ String prefix = index == -1 ? "" : value.substring(0, index);
+ String localName = index == -1 ? value : value.substring(index + 1);
+ String ns = reader.getNamespaceContext().getNamespaceURI(prefix);
+ if (ns == null) {
+ ns = "";
+ }
+ return new QName(ns, localName, prefix);
+ } else {
+ return null;
+ }
+ }
+
+ private void declareNamespace(Element element, String prefix, String ns) {
+ String qname = null;
+ if ("".equals(prefix)) {
+ qname = "xmlns";
+ } else {
+ qname = "xmlns:" + prefix;
+ }
+ Node node = element;
+ boolean declared = false;
+ while (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
+ NamedNodeMap attrs = node.getAttributes();
+ if (attrs == null) {
+ break;
+ }
+ Node attr = attrs.getNamedItem(qname);
+ if (attr != null) {
+ declared = ns.equals(attr.getNodeValue());
+ break;
+ }
+ node = node.getParentNode();
+ }
+ if (!declared) {
+ org.w3c.dom.Attr attr = element.getOwnerDocument().createAttributeNS(XMLNS_ATTRIBUTE_NS_URI, qname);
+ attr.setValue(ns);
+ element.setAttributeNodeNS(attr);
+ }
+ }
+
+ private Element createElement(Document document, QName name) {
+ String prefix = name.getPrefix();
+ String qname = (prefix != null && prefix.length() > 0) ? prefix + ":" + name.getLocalPart() : name
+ .getLocalPart();
+ return document.createElementNS(name.getNamespaceURI(), qname);
+ }
+
+ private void loadElement(XMLStreamReader reader, Element root) throws XMLStreamException {
+ Document document = root.getOwnerDocument();
+ Node current = root;
+ while (true) {
+ switch (reader.next()) {
+ case XMLStreamConstants.START_ELEMENT:
+ QName name = reader.getName();
+ Element child = createElement(document, name);
+
+ // push the new element and make it the current one
+ current.appendChild(child);
+ current = child;
+
+ declareNamespace(child, name.getPrefix(), name.getNamespaceURI());
+
+ int count = reader.getNamespaceCount();
+ for (int i = 0; i < count; i++) {
+ String prefix = reader.getNamespacePrefix(i);
+ String ns = reader.getNamespaceURI(i);
+ declareNamespace(child, prefix, ns);
+ }
+
+ // add the attributes for this element
+ count = reader.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ String ns = reader.getAttributeNamespace(i);
+ String prefix = reader.getAttributePrefix(i);
+ String localPart = reader.getAttributeLocalName(i);
+ String value = reader.getAttributeValue(i);
+ child.setAttributeNS(ns, localPart, value);
+ declareNamespace(child, prefix, ns);
+ }
+
+ break;
+ case XMLStreamConstants.CDATA:
+ current.appendChild(document.createCDATASection(reader.getText()));
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ current.appendChild(document.createTextNode(reader.getText()));
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ // if we are back at the root then we are done
+ if (current == root) {
+ return;
+ }
+
+ // pop the element off the stack
+ current = current.getParentNode();
+ }
+ }
+ }
+
+ private Document readPropertyValue(XMLStreamReader reader, QName type)
+ throws XMLStreamException, ParserConfigurationException {
+
+ Document doc = domFactory.newDocumentBuilder().newDocument();
+
+ // root element has no namespace and local name "value"
+ Element root = doc.createElementNS(null, "value");
+ if (type != null) {
+ org.w3c.dom.Attr xsi = doc.createAttributeNS(XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi");
+ xsi.setValue(W3C_XML_SCHEMA_INSTANCE_NS_URI);
+ root.setAttributeNodeNS(xsi);
+
+ String prefix = type.getPrefix();
+ if (prefix == null || prefix.length() == 0) {
+ prefix = "ns";
+ }
+
+ declareNamespace(root, prefix, type.getNamespaceURI());
+
+ org.w3c.dom.Attr xsiType = doc.createAttributeNS(W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type");
+ xsiType.setValue(prefix + ":" + type.getLocalPart());
+ root.setAttributeNodeNS(xsiType);
+ }
+ doc.appendChild(root);
+
+ loadElement(reader, root);
+ return doc;
+ }
+
+ private void readProperty(ComponentProperty prop, XMLStreamReader reader)
+ throws XMLStreamException, ContributionReadException {
+
+
+ prop.setName(reader.getAttributeValue(null, "name"));
+ String xsdType = reader.getAttributeValue(null, "type");
+ if (xsdType != null)
+ prop.setXSDType(getQNameValue(reader, xsdType));
+ else
+ prop.setXSDType(SimpleTypeMapperImpl.XSD_STRING);
+
+ try {
+ Document value = readPropertyValue(reader, prop.getXSDType());
+ prop.setValue(value);
+ } catch (ParserConfigurationException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ private List<ComponentProperty> readProperties(XMLStreamReader reader)
+ throws XMLStreamException, ContributionReadException {
+
+ List<ComponentProperty> properties = new ArrayList<ComponentProperty>();
+
+ while (reader.hasNext()) {
+
+ int next = reader.next();
+ if (next == END_ELEMENT && PROPERTIES_QNAME.equals(reader.getName())) {
+ break;
+ }
+ else if (next == START_ELEMENT && PROPERTY_QNAME.equals(reader.getName())) {
+
+ ComponentProperty componentProperty = assemblyFactory.createComponentProperty();
+ readProperty(componentProperty, reader);
+ properties.add(componentProperty);
+ }
+ }
+
+ return properties;
+
+ }
+}