diff options
6 files changed, 190 insertions, 64 deletions
diff --git a/java/sca/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java b/java/sca/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java index 8f032efc47..be38b46f52 100644 --- a/java/sca/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java +++ b/java/sca/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiImplementationProvider.java @@ -19,6 +19,10 @@ package org.apache.tuscany.sca.implementation.osgi.runtime; +import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.REMOTE_CONFIG_SCA; +import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SCA_REFERENCE; +import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_IMPORTED; +import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_IMPORTED_CONFIGS; import static org.osgi.framework.Constants.SERVICE_RANKING; import java.security.AccessController; @@ -91,18 +95,17 @@ public class OSGiImplementationProvider implements ImplementationProvider { JavaInterface javaInterface = (JavaInterface)interfaceContract.getInterface(); final Class<?> interfaceClass = javaInterface.getJavaClass(); -// final Hashtable<String, Object> props = new Hashtable<String, Object>(); -// props.put(FILTER_MATCH_CRITERIA, ""); -// Collection<String> interfaceNames = new ArrayList<String>(); -// props.put(INTERFACE_MATCH_CRITERIA, interfaceNames); -// interfaceNames.add(interfaceClass.getName()); + // final Hashtable<String, Object> props = new Hashtable<String, Object>(); + // props.put(FILTER_MATCH_CRITERIA, ""); + // Collection<String> interfaceNames = new ArrayList<String>(); + // props.put(INTERFACE_MATCH_CRITERIA, interfaceNames); + // interfaceNames.add(interfaceClass.getName()); final Hashtable<String, Object> osgiProps = getOSGiProperties(reference); osgiProps.put(SERVICE_RANKING, Integer.MAX_VALUE); - osgiProps.put("sca.reference", component.getURI() + "#reference(" + ref.getName() + ")"); - osgiProps.put(OSGiProperty.OSGI_REMOTE, "true"); - osgiProps.put(OSGiProperty.OSGI_REMOTE_CONFIGURATION_TYPE, "sca"); - osgiProps.put(OSGiProperty.OSGI_REMOTE_INTERFACES, new String[] {interfaceClass.getName()}); + osgiProps.put(SCA_REFERENCE, component.getURI() + "#reference(" + ref.getName() + ")"); + osgiProps.put(SERVICE_IMPORTED, "true"); + osgiProps.put(SERVICE_IMPORTED_CONFIGS, new String[] {REMOTE_CONFIG_SCA}); ProxyFactory proxyService = proxyFactoryExtensionPoint.getInterfaceProxyFactory(); if (!interfaceClass.isInterface()) { @@ -119,8 +122,8 @@ public class OSGiImplementationProvider implements ImplementationProvider { ServiceRegistration registration = context.registerService(interfaceClass.getName(), proxy, osgiProps); // Create a DiscoveredServiceTracker to track the status of the remote service -// RemoteServiceTracker tracker = new RemoteServiceTracker(registration); -// context.registerService(DiscoveredServiceTracker.class.getName(), tracker, props); + // RemoteServiceTracker tracker = new RemoteServiceTracker(registration); + // context.registerService(DiscoveredServiceTracker.class.getName(), tracker, props); return registration; } }); @@ -163,12 +166,12 @@ public class OSGiImplementationProvider implements ImplementationProvider { } return props; } - + protected Object getOSGiService(ComponentService service) { JavaInterface javaInterface = (JavaInterface)service.getInterfaceContract().getInterface(); // String filter = getOSGiFilter(provider.getOSGiProperties(service)); // FIXME: What is the filter? - String filter = "(!(sca.reference=*))"; + String filter = "(!(" + SERVICE_IMPORTED + "=*))"; // "(sca.service=" + component.getURI() + "#service-name\\(" + service.getName() + "\\))"; BundleContext bundleContext = osgiBundle.getBundleContext(); ServiceReference ref; @@ -193,23 +196,23 @@ public class OSGiImplementationProvider implements ImplementationProvider { return implementation; } -// private class RemoteServiceTracker implements DiscoveredServiceTracker { -// private ServiceRegistration referenceRegistration; -// -// private RemoteServiceTracker(ServiceRegistration referenceRegistration) { -// super(); -// this.referenceRegistration = referenceRegistration; -// } -// -// public void serviceChanged(DiscoveredServiceNotification notification) { -// ServiceEndpointDescription description = notification.getServiceEndpointDescription(); -// switch(notification.getType()) { -// case UNAVAILABLE: -// case AVAILABLE: -// case MODIFIED: -// case MODIFIED_ENDMATCH: -// } -// } -// } + // private class RemoteServiceTracker implements DiscoveredServiceTracker { + // private ServiceRegistration referenceRegistration; + // + // private RemoteServiceTracker(ServiceRegistration referenceRegistration) { + // super(); + // this.referenceRegistration = referenceRegistration; + // } + // + // public void serviceChanged(DiscoveredServiceNotification notification) { + // ServiceEndpointDescription description = notification.getServiceEndpointDescription(); + // switch(notification.getType()) { + // case UNAVAILABLE: + // case AVAILABLE: + // case MODIFIED: + // case MODIFIED_ENDMATCH: + // } + // } + // } } diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiProperty.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiProperty.java index 26b588a099..455071dbb8 100644 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiProperty.java +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/OSGiProperty.java @@ -28,20 +28,106 @@ public interface OSGiProperty { String NAME = "name"; QName PROPERTY_QNAME = new QName(OSGiImplementation.SCA11_TUSCANY_NS, "osgi.property"); + String SCA_BINDINGS = "sca.bindings"; + String SCA_REFERENCE = "sca.reference"; + String SCA_SERVICE = "sca.service"; + String SCA_REFERENCE_BINDING = "sca.reference.binding"; + String SCA_SERVICE_BINDING = "sca.service.binding"; + String REMOTE_CONFIG_SCA = "sca"; + /** - * Standard OSGi property names + * The configuration types supported by this Distribution Provider. Services + * that are suitable for distribution list the configuration types that + * describe the configuration information for that service in the + * SERVICE_EXPORTED_CONFIGS or SERVICE_IMPORTED_CONFIGS property. A + * distribution provider must register a service that has this property and + * enumerate all configuration types that it supports. The type of this + * property String+ + * + * @see SERVICE_EXPORTED_CONFIGS + * @see SERVICE_IMPORTED_CONFIGS + */ + String REMOTE_CONFIGS_SUPPORTED = "remote.configs.supported"; + /** + * Service property that lists the intents supported by the distribution + * provider. Each distribution provider must register a service that has + * this property and enumerate all the supported intents, having any + * qualified intents expanded. The value of this property is of type + * String+. + * + * @see SERVICE_INTENTS + * @see SERVICE_EXPORTED_INTENTS + * @see SERVICE_EXPORTED_INTENTS_EXTRA + */ + String REMOTE_INTENTS_SUPPORTED = "remote.intents.supported"; + /** + * A list of configuration types that should be used to export the service. + * Configuration types can be synonymous or alternatives. In principle, a + * distribution provider should create an endpoint for each recognized + * configuration type, the deployer is responsible that synonyms do not + * clash. Each configuration type has an associated specification that + * describes how the configuration data for the exported service is + * represented in an OSGi framework. The value of this property is of type + * String+. + */ + String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; + /** + * A list of intents that the distribution provider must implement to + * distribute the service. Intents listed in this property are reserved for + * intents that are critical for the code to function correctly, for + * example, ordering of messages. These intents should not be configurable. + * The value of this property is of type String+. + */ + String SERVICE_EXPORTED_INTENTS = "service.exported.intents"; + /** + * Extra intents configured in addition to the the intents specified in + * SERVICE_EXPORTED_INTENTS. These intents are merged with the service. + * exported.intents and therefore have the same semantics. They are extra, + * so that the SERVICE_EXPORTED_INTENTS can be set by the bundle developer + * and this property is then set by the administrator/deployer. Bundles + * should make this property configurable, for example through the + * Configuration Admin service. The value of this property is of type + * String+. + */ + String SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra"; + /** + * Defines the interfaces under which this service can be exported. This + * list must be a subset of the types listed in the objectClass service + * property. The single value of an asterisk ('*' *) indicates all + * interfaces in the registration's objectClass property (not classes). It + * is highly recommended to only export interfaces and not concrete classes + * due to the complexity of creating proxies for some type of classes. The + * value of this property is of type String+. + */ + String SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces"; + /** + * Must be set by a distribution provider to true when it registers the + * end-point proxy as an imported service. Can be used by a bundle to + * prevent it from getting an imported service. The value of this property + * is not defined, setting it is sufficient. + */ + String SERVICE_IMPORTED = "service.imported"; + /** + * A list of intents that this service implements. This property has dual + * purpose. A bundle can use this service property to notify the + * distribution provider that these intents are already implemented by the + * exported service object. For an imported service, a distribution provider + * must use this property to convey the combined intents of the exporting + * service and the intents that the distribution providers add. To export a + * service, a distribution provider must recognize all these intents and + * expand any qualified intents. The value of this property is of type + * String+. */ - String OSGI_REMOTE = "osgi.remote"; String SERVICE_INTENTS = "service.intents"; - String OSGI_REMOTE_INTERFACES = "osgi.remote.interfaces"; - String OSGI_REMOTE_INTENTS = "osgi.remote.requires.intents"; - String OSGI_REMOTE_CONFIGURATION_TYPE = "osgi.remote.configuration.type"; - String SCA_BINDINGS = "osgi.remote.configuration.sca.bindings"; - String SCA_REFERENCE = "osgi.remote.configuration.sca.reference"; - String SCA_SERVICE = "osgi.remote.configuration.sca.service"; - String SCA_REFERENCE_BINDING = "osgi.remote.configuration.sca.reference.binding"; - String SCA_SERVICE_BINDING = "osgi.remote.configuration.sca.service.binding"; - String OSGI_REMOTE_CONFIGURATION_TYPE_SCA = "sca"; + /** + * The configuration type used to import this services, as described in + * SERVICE_EXPORTED_CONFIGS. Any associated properties for this + * configuration types must be properly mapped to the importing system. For + * example, a URL in these properties must point to a valid resource when + * used in the importing framework. Configuration types in this property + * must be synonymous. The value of this property is of type String+. + */ + String SERVICE_IMPORTED_CONFIGS = "service.imported.configs"; String getValue(); diff --git a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/introspection/ExportedServiceIntrospector.java b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/introspection/ExportedServiceIntrospector.java index f6abf3b2b4..a997724ce0 100644 --- a/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/introspection/ExportedServiceIntrospector.java +++ b/java/sca/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/introspection/ExportedServiceIntrospector.java @@ -20,11 +20,12 @@ package org.apache.tuscany.sca.implementation.osgi.introspection;
import static org.apache.tuscany.sca.assembly.Base.SCA11_TUSCANY_NS;
-import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.OSGI_REMOTE_CONFIGURATION_TYPE;
-import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.OSGI_REMOTE_CONFIGURATION_TYPE_SCA;
-import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.OSGI_REMOTE_INTENTS;
-import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.OSGI_REMOTE_INTERFACES;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.REMOTE_CONFIG_SCA;
import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SCA_BINDINGS;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTENTS;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTENTS_EXTRA;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTERFACES;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_IMPORTED_CONFIGS;
import static org.osgi.framework.Constants.OBJECTCLASS;
import static org.osgi.framework.Constants.SERVICE_ID;
@@ -34,6 +35,7 @@ import java.net.MalformedURLException; import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
@@ -236,9 +238,9 @@ public class ExportedServiceIntrospector { component.setImplementation(implementation);
implementation.setUnresolved(false);
- String[] remoteInterfaces = (String[])reference.getProperty(OSGI_REMOTE_INTERFACES);
+ String[] remoteInterfaces = getStrings(reference.getProperty(SERVICE_EXPORTED_INTERFACES));
if (remoteInterfaces == null || remoteInterfaces.length > 0 && "*".equals(remoteInterfaces[0])) {
- remoteInterfaces = (String[])reference.getProperty(OBJECTCLASS);
+ remoteInterfaces = getStrings(reference.getProperty(OBJECTCLASS));
} else {
remoteInterfaces = parse(remoteInterfaces);
}
@@ -261,18 +263,22 @@ public class ExportedServiceIntrospector { implementation.getServices().add(service);
ComponentService componentService = assemblyFactory.createComponentService();
+ componentService.setName(service.getName());
component.getServices().add(componentService);
componentService.setService(service);
}
- String[] requiredIntents = (String[])properties.get(OSGI_REMOTE_INTENTS);
+ String[] requiredIntents = getStrings(properties.get(SERVICE_EXPORTED_INTENTS));
List<Intent> intents = getIntents(requiredIntents);
+ String[] requiredIntentsExtra = getStrings(properties.get(SERVICE_EXPORTED_INTENTS_EXTRA));
+ List<Intent> extraIntents = getIntents(requiredIntentsExtra);
- String[] bindingDocuments = (String[])properties.get(SCA_BINDINGS);
+ String[] bindingDocuments = getStrings(properties.get(SCA_BINDINGS));
List<Binding> bindings = loadBindings(reference.getBundle(), bindingDocuments);
for (ComponentService componentService : component.getServices()) {
componentService.getRequiredIntents().addAll(intents);
+ componentService.getRequiredIntents().addAll(extraIntents);
componentService.getBindings().addAll(bindings);
}
@@ -286,7 +292,7 @@ public class ExportedServiceIntrospector { contribution.setUnresolved(true);
return contribution;
}
-
+
/**
* Introspect an OSGi filter to create an SCA reference
*
@@ -304,9 +310,10 @@ public class ExportedServiceIntrospector { e.printStackTrace();
return null;
}
+
Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(OSGI_REMOTE_CONFIGURATION_TYPE, OSGI_REMOTE_CONFIGURATION_TYPE_SCA);
- if(!filter.match(props)) {
+ props.put(SERVICE_IMPORTED_CONFIGS, new String[] {REMOTE_CONFIG_SCA});
+ if (!filter.match(props)) {
return null;
}
String id = "osgi.reference." + UUID.randomUUID();
@@ -325,9 +332,9 @@ public class ExportedServiceIntrospector { component.setImplementation(implementation);
implementation.setUnresolved(false);
- String[] remoteInterfaces = (String[])properties.get(OSGiProperty.OSGI_REMOTE_INTERFACES);
+ String[] remoteInterfaces = getStrings(properties.get(SERVICE_EXPORTED_INTERFACES));
if (remoteInterfaces == null || remoteInterfaces.length > 0 && "*".equals(remoteInterfaces[0])) {
- remoteInterfaces = (String[])properties.get(OBJECTCLASS);
+ remoteInterfaces = getStrings(properties.get(OBJECTCLASS));
} else {
remoteInterfaces = parse(remoteInterfaces);
}
@@ -355,10 +362,10 @@ public class ExportedServiceIntrospector { componentReference.setWiredByImpl(true);
}
- String[] requiredIntents = (String[])properties.get(OSGI_REMOTE_INTENTS);
+ String[] requiredIntents = getStrings(properties.get(SERVICE_EXPORTED_INTENTS));
List<Intent> intents = getIntents(requiredIntents);
- String[] bindingDocuments = (String[])properties.get(SCA_BINDINGS);
+ String[] bindingDocuments = getStrings(properties.get(SCA_BINDINGS));
List<Binding> bindings = loadBindings(bundle, bindingDocuments);
for (ComponentReference componentReference : component.getReferences()) {
@@ -419,4 +426,23 @@ public class ExportedServiceIntrospector { return bundle.getEntry(location);
}
+ /**
+ * In OSGi, the value of String+ can be a single String, String[] or Collection<String>
+ * @param value
+ * @return
+ */
+ private String[] getStrings(Object value) {
+ if (value == null) {
+ return null;
+ }
+ if (value instanceof String) {
+ return new String[] {(String)value};
+ } else if (value instanceof Collection) {
+ Collection<String> collection = (Collection)value;
+ return collection.toArray(new String[collection.size()]);
+ }
+ return (String[])value;
+
+ }
+
}
diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/node/osgi/impl/OSGiServiceExporter.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/node/osgi/impl/OSGiServiceExporter.java index 329ce09a5b..67fa384b4a 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/node/osgi/impl/OSGiServiceExporter.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/node/osgi/impl/OSGiServiceExporter.java @@ -19,6 +19,10 @@ package org.apache.tuscany.sca.node.osgi.impl;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_CONFIGS;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTERFACES;
+import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_IMPORTED;
+
import java.util.Collections;
import org.apache.tuscany.sca.contribution.Contribution;
@@ -30,6 +34,7 @@ import org.apache.tuscany.sca.node.configuration.NodeConfiguration; import org.apache.tuscany.sca.node.impl.NodeFactoryImpl;
import org.apache.tuscany.sca.node.impl.NodeImpl;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
@@ -64,7 +69,13 @@ public class OSGiServiceExporter implements ServiceTrackerCustomizer { }
public void start() {
- String filterStr = "(& (osgi.remote.configuration.type=sca) (osgi.remote.interfaces=*) (!(osgi.remote=true)) )";
+ String filterStr =
+ "(& (" + SERVICE_EXPORTED_CONFIGS
+ + "=sca) ("
+ + SERVICE_EXPORTED_INTERFACES
+ + "=*) (!("
+ + SERVICE_IMPORTED
+ + "=*)) )";
try {
Filter filter = context.createFilter(filterStr);
serviceTracker = new ServiceTracker(context, filter, this);
@@ -88,7 +99,7 @@ public class OSGiServiceExporter implements ServiceTrackerCustomizer { if (contribution != null) {
NodeConfiguration configuration = nodeFactory.createNodeConfiguration();
- configuration.setURI(String.valueOf(reference.getProperty("service.id")));
+ configuration.setURI("osgi.service." + String.valueOf(reference.getProperty(Constants.SERVICE_ID)));
configuration.getExtensions().add(reference.getBundle());
// FIXME: Configure the domain and node URI
NodeImpl node = new NodeImpl(nodeFactory, configuration, Collections.singletonList(contribution));
diff --git a/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorActivator.java b/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorActivator.java index 8bfa6772da..e484dc3e0b 100644 --- a/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorActivator.java +++ b/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorActivator.java @@ -59,9 +59,9 @@ public class CalculatorActivator implements BundleActivator { Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put("sca.service", "CalculatorComponent#service-name(Calculator)");
props.put("calculator", "Calculator");
- props.put("osgi.remote.configuration.type", "sca");
- props.put("osgi.remote.configuration.sca.bindings", new String[] {"OSGI-INF/sca/calculator-service.bindings"});
- props.put("osgi.remote.interfaces", new String[] {"*"});
+ props.put("service.exported.configs", new String[] {"sca"});
+ props.put("sca.bindings", new String[] {"OSGI-INF/sca/calculator-service.bindings"});
+ props.put("service.exported.interfaces", new String[] {"*"});
logger.info("Registering " + CalculatorService.class.getName());
CalculatorService calculator = new CalculatorServiceImpl(context);
context.registerService(CalculatorService.class.getName(), calculator, props);
diff --git a/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorServiceImpl.java b/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorServiceImpl.java index 046e8cf565..276bcdc76f 100644 --- a/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorServiceImpl.java +++ b/java/sca/samples/dosgi-calculator/src/main/java/calculator/dosgi/impl/CalculatorServiceImpl.java @@ -47,9 +47,9 @@ public class CalculatorServiceImpl implements CalculatorService { Filter remoteFilter = null, localFilter = null;
try {
remoteFilter =
- context.createFilter("(&(" + OBJECTCLASS + "=calculator.dosgi.operations.*) (sca.reference=*))");
+ context.createFilter("(&(" + OBJECTCLASS + "=calculator.dosgi.operations.*) (service.imported=*))");
localFilter =
- context.createFilter("(&(" + OBJECTCLASS + "=calculator.dosgi.operations.*) (!(sca.reference=*)))");
+ context.createFilter("(&(" + OBJECTCLASS + "=calculator.dosgi.operations.*) (!(service.imported=*)))");
} catch (InvalidSyntaxException e) {
e.printStackTrace();
}
|