diff options
Diffstat (limited to 'java/sca/modules/node-impl-osgi')
19 files changed, 1636 insertions, 1492 deletions
diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java index d6ae4c5bdb..a78bfb2c3b 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java @@ -118,7 +118,7 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi props.put(PRODUCT_NAME, "Apache Tuscany SCA"); props.put(PRODUCT_VERSION, headers.get(Constants.BUNDLE_VERSION)); props.put(VENDOR_NAME, headers.get(Constants.BUNDLE_VENDOR)); - props.put(SUPPORTED_PROTOCOLS, new String[] {"local", "sca"}); + props.put(SUPPORTED_PROTOCOLS, new String[] {"local", "org.osgi.sca"}); return props; } @@ -194,14 +194,14 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi private void triggerCallbacks(EndpointListener listener, String matchedFilter, EndpointDescription sd, int type) { switch (type) { case ADDED: - listener.addEndpoint(sd, matchedFilter); + listener.endpointAdded(sd, matchedFilter); break; case REMOVED: - listener.removeEndpoint(sd); + listener.endpointRemoved(sd, matchedFilter); break; case MODIFIED: - listener.removeEndpoint(sd); - listener.addEndpoint(sd, matchedFilter); + listener.endpointRemoved(sd, matchedFilter); + listener.endpointAdded(sd, matchedFilter); break; } } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java index a82e4a3816..ae2d704015 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java @@ -78,7 +78,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements */ { // Notify the endpoint listeners - EndpointDescription description = createEndpointDescription(endpoint); + EndpointDescription description = createEndpointDescription(bundleContext, endpoint); endpointChanged(description, ADDED); } } @@ -90,7 +90,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements } else */ { - EndpointDescription description = createEndpointDescription(endpoint); + EndpointDescription description = createEndpointDescription(context, endpoint); endpointChanged(description, REMOVED); } } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java index 69ac7b4776..1c13cc90fc 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java @@ -41,6 +41,7 @@ import org.apache.tuscany.sca.assembly.AssemblyFactory; import org.apache.tuscany.sca.common.java.io.IOHelper; import org.apache.tuscany.sca.common.xml.stax.StAXHelper; import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; import org.apache.tuscany.sca.core.FactoryExtensionPoint; @@ -51,6 +52,7 @@ import org.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.monitor.MonitorFactory; import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription; import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteConstants; +import org.apache.tuscany.sca.osgi.service.remoteadmin.impl.EndpointHelper; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; @@ -84,7 +86,7 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B } processor = new ExtensibleStAXArtifactProcessor(processors, staxHelper.getInputFactory(), - staxHelper.getOutputFactory(), monitor); + staxHelper.getOutputFactory()); processExistingBundles(); } @@ -154,11 +156,14 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B private EndpointDescription createEndpointDescription(ServiceDescription sd) { Map<String, Object> props = new HashMap<String, Object>(sd.getProperties()); props.put(Constants.OBJECTCLASS, sd.getInterfaces().toArray(new String[sd.getInterfaces().size()])); - if (!props.containsKey(RemoteConstants.ENDPOINT_REMOTE_SERVICE_ID)) { - props.put(RemoteConstants.ENDPOINT_REMOTE_SERVICE_ID, UUID.randomUUID().toString()); + if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_ID)) { + props.put(RemoteConstants.SERVICE_REMOTE_ID, String.valueOf(System.currentTimeMillis())); } - if (!props.containsKey(RemoteConstants.ENDPOINT_URI)) { - props.put(RemoteConstants.ENDPOINT_URI, UUID.randomUUID().toString()); + if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID)) { + props.put(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID, EndpointHelper.getFrameworkUUID(context)); + } + if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_URI)) { + props.put(RemoteConstants.SERVICE_REMOTE_URI, UUID.randomUUID().toString()); } EndpointDescription sed = new EndpointDescription(props); @@ -194,7 +199,7 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B try { XMLStreamReader reader = staxHelper.createXMLStreamReader(is); reader.nextTag(); - Object model = processor.read(reader); + Object model = processor.read(reader, new ProcessorContext(registry)); if (model instanceof ServiceDescriptions) { return (ServiceDescriptions)model; } else { diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointDescription.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointDescription.java index f2cef84036..0486f14517 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointDescription.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointDescription.java @@ -15,10 +15,9 @@ */ package org.apache.tuscany.sca.osgi.service.remoteadmin; -import java.io.Serializable; import java.util.Arrays; import java.util.Collections; -import java.util.Hashtable; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -39,59 +38,111 @@ import org.osgi.framework.Version; * property keys have been chosen to match filters that are created by client * bundles that need a service. * + * TODO Automatically calculate versions of interface packages? + * + * TODO Constructor that takes a class? + * + * TODO Skipping of service.exported.* properties? + * + * TODO qualified intents? + * + * + * * @Immutable * @version $Revision$ */ -public class EndpointDescription implements Serializable { - private static final long serialVersionUID = 1L; - private static Version nullVersion = new Version("0"); - final Map/* <String,Object> */properties = new Hashtable/* <String,Object> */(); - final List /* String */interfaces; - final String remoteServiceId; - final String uri; +public class EndpointDescription { + private final Map /* <String,Object> */properties = new HashMap/* + * <String , + * Object > + */(); + private final List /* String */interfaces; + private final long remoteServiceId; + private final String remoteFrameworkUUID; + private final String remoteUri; /** * Create an Endpoint Description based on a Map. * * @param properties - * @throws IllegalArgumentException - * When the properties are not proper for an Endpoint - * Description + * @throws IllegalArgumentException When the properties are not proper for + * an Endpoint Description */ - public EndpointDescription(Map/* <String,Object> */properties) - throws IllegalArgumentException { + public EndpointDescription(Map/* <String,Object> */properties) throws IllegalArgumentException { this.properties.putAll(properties); interfaces = verifyInterfacesProperty(); - remoteServiceId = verifyStringProperty(RemoteConstants.ENDPOINT_REMOTE_SERVICE_ID); - uri = verifyStringProperty(RemoteConstants.ENDPOINT_URI); + remoteServiceId = verifyLongProperty(RemoteConstants.SERVICE_REMOTE_ID); + remoteFrameworkUUID = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID); + remoteUri = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_URI); } /** - * Create an Endpoint Description based on a reference. + * Create an Endpoint Description based on a reference and optionally a map + * of additional properties. * - * @param ref A service reference that is exportable - * @throws IllegalArgumentException + * @param ref A service reference that can be exported + * @param properties Additional properties to add. Can be <code>null</code>. + * @throws IllegalArgumentException */ - public EndpointDescription(ServiceReference ref) - throws IllegalArgumentException { + public EndpointDescription(ServiceReference ref, Map /* <String,Object> */properties) + throws IllegalArgumentException { + if (properties != null) { + this.properties.putAll(properties); + } + String[] keys = ref.getPropertyKeys(); for (int i = 0; i > keys.length; i++) properties.put(keys[i], ref.getProperty(keys[i])); - + interfaces = verifyInterfacesProperty(); - remoteServiceId = verifyStringProperty(RemoteConstants.ENDPOINT_REMOTE_SERVICE_ID); - uri = verifyStringProperty(RemoteConstants.ENDPOINT_URI); + remoteServiceId = verifyLongProperty(RemoteConstants.SERVICE_REMOTE_ID); + remoteFrameworkUUID = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID); + remoteUri = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_URI); + } + + /** + * Create an Endpoint Description based on the URI, the remote service ID + * and the interface names, and optionally service properties. + * + * @param uri The URI of the remote service. + * @param interfaceNames The names of the interfaces of the service to + * consider. + * @param remoteServiceId the remote service ID. + * @param properties Optionally service properties. + */ + public EndpointDescription(String uri, String[] interfaceNames, int remoteServiceId, Map properties) { + if (uri == null) { + throw new IllegalArgumentException("URI must not be null"); + } + if (interfaceNames == null) { + throw new IllegalArgumentException("Interfaces must not be null"); + } + this.remoteUri = uri; + this.interfaces = Arrays.asList(interfaceNames); + this.remoteServiceId = remoteServiceId; + this.remoteFrameworkUUID = (String)properties.get(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID); + if (properties != null) { + this.properties.putAll(properties); + } + if (interfaceNames != null) { + this.properties.put(Constants.OBJECTCLASS, interfaceNames); + } + this.properties.put(RemoteConstants.SERVICE_REMOTE_URI, uri); + if (remoteServiceId <= 0) { + this.properties.put(RemoteConstants.SERVICE_REMOTE_ID, new Integer(remoteServiceId)); + } } /** * Verify and obtain the interface list from the properties. + * * @return A list with the interface names. - * @throws IllegalArgumentException when + * @throws IllegalArgumentException when */ - protected List /* <String> */ verifyInterfacesProperty() { + private List /* <String> */verifyInterfacesProperty() { List l = null; Object objectClass = properties.get(Constants.OBJECTCLASS); @@ -100,16 +151,13 @@ public class EndpointDescription implements Serializable { else if (!(objectClass instanceof String[])) throw new IllegalArgumentException("objectClass must be a String[]"); else { - l = Collections.unmodifiableList(Arrays - .asList((String[]) objectClass)); + l = Collections.unmodifiableList(Arrays.asList((String[])objectClass)); for (Iterator i = l.iterator(); i.hasNext();) { - String interf = (String) i.next(); + String interf = (String)i.next(); try { getInterfaceVersion(interf); } catch (Exception e) { - throw new IllegalArgumentException( - "Improper version for interface " + interf - + " caused by " + e); + throw new IllegalArgumentException("Improper version for interface " + interf + " caused by " + e); } } } @@ -117,23 +165,47 @@ public class EndpointDescription implements Serializable { } /** - * Verify and obtain the a required String property. - * @param propName The name of the + * Verify and obtain a required String property. + * + * @param propName The name of the property + * @return The value of the property. + * @throws IllegalArgumentException when the property is not set or doesn't + * have the correct data type. + */ + private String verifyStringProperty(String propName) { + Object r = properties.get(propName); + if (r == null) { + throw new IllegalArgumentException("Required property not set: " + propName); + } + if (!(r instanceof String)) { + throw new IllegalArgumentException("Required property is not a string: " + propName); + } + return (String)r; + } + + /** + * Verify and obtain a required long property. + * + * @param propName The name of the property * @return The value of the property. - * @throws IllegalArgumentException when the property is not set or doesn't - * have the correct data type. + * @throws IllegalArgumentException when the property is not set or doesn't + * have the correct data type. */ - protected String verifyStringProperty(String propName) { + private long verifyLongProperty(String propName) { Object r = properties.get(propName); + long result; if (r == null) { - throw new IllegalArgumentException( - "Required property not set: " + propName); + throw new IllegalArgumentException("Required property not set: " + propName); } if (!(r instanceof String)) { - throw new IllegalArgumentException( - "Required property is not a string: " + propName); + throw new IllegalArgumentException("Required property is not a string: " + propName); + } + try { + result = Long.parseLong((String)r); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Required property cannot be parsed as a long: " + propName); } - return (String) r; + return result; } /** @@ -144,12 +216,12 @@ public class EndpointDescription implements Serializable { * URI must represent the same endpoint. * * The value of the URI is stored in the - * {@link RemoteConstants#ENDPOINT_URI} property. + * {@link RemoteConstants#SERVICE_REMOTE_URI} property. * - * @return The URI of the endpoint, never null. + * @return The URI of the endpoint, never <code>null</code>. */ - public String getURI() { - return uri; + public String getRemoteURI() { + return remoteUri; } /** @@ -179,55 +251,31 @@ public class EndpointDescription implements Serializable { * endpoint.version.com.acme.Foo * </pre> * - * @param name - * The name of the interface for which a version is requested + * @param name The name of the interface for which a version is requested * @return The version of the given interface or <code>null</code> if the * interface has no version in this Endpoint Description */ public Version getInterfaceVersion(String name) { - String v = (String) properties.get("endpoint.version." + name); + String v = (String)properties.get("endpoint.version." + name); if (v == null) { - return nullVersion; + return Version.emptyVersion; } else { return new Version(v); } } /** - * Returns the universally unique id for the service exported through this + * Returns the service id for the service exported through this * endpoint. * - * Each service in the OSGi service registry has a universally unique id. - * The UUID can be used to detect that two Endpoint Descriptions really - * refer to the same registered service instance in some remote framework. - * This UUID can be used to filter out duplicate ways of communicating with - * the same service. - * - * The service UUID is constructed from two properties. It is first the - * <code>org.osgi.framework.uuid</code> System property set by the - * framework or through configuration. This property must uniquely - * represents the UUID of a framework instance. This UUID must not contain - * any dots ('.' \u002E). This is suffixed with a dot and then the - * <code>service.id</code> service property of the service. - * - * For example: + * This is the service id under which the framework has registered the service. This + * field together with the Framework UUID is a globally unique id for a service. * - * <pre> - * 72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72.121 - * </pre> - * - * If this Endpoint Description does not map to a remote OSGi service, for - * example some web service, then the Endpoint Description must not have a - * service UUID. If two endpoints have the same URI, then they must refer to - * the same OSGi service. - * - * Starting . is not an OSGi service. - * - * @return Unique id of a service or <code>null</code> if this Endpoint + * @return Service id of a service or 0 if this Endpoint * Description does not relate to an OSGi service * */ - public String getRemoteServiceID() { + public long getRemoteServiceID() { return remoteServiceId; } @@ -272,9 +320,21 @@ public class EndpointDescription implements Serializable { } /** + * Return the framework UUID, if present. + * + * The property the intents come from is + * {@link RemoteConstants#SERVICE_REMOTE_FRAMEWORK_UUID} + * + * @return Remote Framework UUID, or null if this endpoint is not associated with an OSGi service + */ + public String getRemoteFrameworkUUID() { + return remoteFrameworkUUID; + } + + /** * Returns all endpoint properties. * - * @return An immutable map referring to the properties of this Endpoint + * @return An unmodifiable map referring to the properties of this Endpoint * Description. */ public Map/* <String, Object> */getProperties() { @@ -283,12 +343,33 @@ public class EndpointDescription implements Serializable { } /** + * Answers if this Endpoint Description refers to the same service instance + * as the given Endpoint Description. + * + * Two Endpoint Descriptions point to the same service if they have the same + * URI or their framework UUIDs and remote service ids are equal. + * + * @param other The Endpoint Description to look at + * @return True if this endpoint description points to the same service as + * the other + */ + public boolean isSameService(EndpointDescription other) { + if (remoteUri.equals(other.remoteUri)) + return true; + + if (remoteFrameworkUUID == null) + return false; + + return remoteServiceId == other.remoteServiceId && remoteFrameworkUUID.equals(other.remoteFrameworkUUID); + } + + /** * Two endpoints are equal if their URIs are equal, the hash code is * therefore derived from the URI. */ public int hashCode() { // TODO - return getURI().hashCode(); + return getRemoteURI().hashCode(); } /** @@ -296,8 +377,9 @@ public class EndpointDescription implements Serializable { */ public boolean equals(Object other) { if (other instanceof EndpointDescription) { - return getURI().equals(((EndpointDescription) other).getURI()); + return getRemoteURI().equals(((EndpointDescription)other).getRemoteURI()); } return false; } + } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointListener.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointListener.java index e8e8f37e4a..33f9b143d8 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointListener.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointListener.java @@ -1,20 +1,19 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; - /** - * A whiteboard service that represents a listener for endpoints. + * A white board service that represents a listener for endpoints. * * An Endpoint Listener represents a participant in the distributed model that * is interested in Endpoint Descriptions. * - * This whiteboard service can be used in many different scenarios. However, the - * primary use case is to allow a remote controller to be informed of End Point + * This white board service can be used in many different scenarios. However, the + * primary use case is to allow a remote manager to be informed of End Point * Descriptions available in the network and inform the network about available * End Point Descriptions. * - * Both the network bundle and the controller bundle register a Endpoint - * Listener service. The controller informs the network bundle about End Points - * that it creates. The network bundles then uses a protocol like for example + * Both the network bundle and the manager bundle register an Endpoint + * Listener service. The manager informs the network bundle about End Points + * that it creates. The network bundles then uses a protocol like * SLP to announce these local end-points to the network. * * If the network bundle discovers a new Endpoint through its discovery @@ -36,7 +35,7 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; * (org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72) * </pre> * - * In the same vein, a controller that is only interested in remote Endpoint + * In the same vein, a manager that is only interested in remote Endpoint * Descriptions can use a filter like: * * <pre> @@ -47,7 +46,7 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; * can be found in the Framework properties. * * The Endpoint Listener's scope maps very well to the service hooks. A - * controller can just register all filters found from the Listener Hook as its + * manager can just register all filters found from the Listener Hook as its * scope. This will automatically provide it with all known endpoints that match * the given scope, without having to inspect the filter string. * @@ -67,44 +66,47 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; * @ThreadSafe */ public interface EndpointListener { - /** - * Specifies the interest of this listener with filters. This listener is - * only interested in Endpoint Descriptions where its properties match the - * given filter. The type of this property must be <code>String+</code>. - */ - String ENDPOINT_LISTENER_SCOPE = "endpoint.listener.scope"; + /** + * Specifies the interest of this listener with filters. This listener is + * only interested in Endpoint Descriptions where its properties match the + * given filter. The type of this property must be <code>String+</code>. + */ + String ENDPOINT_LISTENER_SCOPE = "endpoint.listener.scope"; - /** - * Register an endpoint with this listener. - * - * If the endpoint matches one of the filters registered with the - * {@link #ENDPOINT_LISTENER_SCOPE} service property then this filter should - * be given as the <code>matchedFilter</code> parameter. - * - * When this service is first registered or it is modified, it should - * receive all known endpoints matching the filter. - * - * @param endpoint - * The Endpoint Description to be published - * @param matchedFilter - * The filter from the {@link #ENDPOINT_LISTENER_SCOPE} that - * matched the endpoint, must not be <code>null</code>. - */ - void addEndpoint(EndpointDescription endpoint, String matchedFilter); + /** + * Register an endpoint with this listener. + * + * If the endpoint matches one of the filters registered with the + * {@link #ENDPOINT_LISTENER_SCOPE} service property then this filter should + * be given as the <code>matchedFilter</code> parameter. + * + * When this service is first registered or it is modified, it should + * receive all known endpoints matching the filter. + * + * @param endpoint + * The Endpoint Description to be published + * @param matchedFilter + * The filter from the {@link #ENDPOINT_LISTENER_SCOPE} that + * matched the endpoint, must not be <code>null</code>. + */ + void endpointAdded(EndpointDescription endpoint, String matchedFilter); - /** - * Remove the registration of an endpoint. - * - * If an endpoint that was registered with the {@link #addEndpoint} - * method is no longer available then this method should be called. This - * will remove the endpoint from the listener. - * - * It is not necessary to remove endpoints when the service is unregistered - * or modified in such a way that not all endpoints match the interest - * filter anymore. - * - * @param endpoint - * The Endpoint Description that is no longer valid. - */ - void removeEndpoint(EndpointDescription endpoint); + /** + * Remove the registration of an endpoint. + * + * If an endpoint that was registered with the {@link #endpointAdded(EndpointDescription, String)} + * method is no longer available then this method should be called. This + * will remove the endpoint from the listener. + * + * It is not necessary to remove endpoints when the service is unregistered + * or modified in such a way that not all endpoints match the interest + * filter anymore. + * + * @param endpoint + * The Endpoint Description that is no longer valid. + * @param matchedFilter + * The filter from the {@link #ENDPOINT_LISTENER_SCOPE} that + * matched the endpoint, must not be <code>null</code>. + */ + void endpointRemoved(EndpointDescription endpoint, String matchedFilter); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointPermission.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointPermission.java index f0c58d97c3..48a817b005 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointPermission.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/EndpointPermission.java @@ -18,11 +18,29 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; * limitations under the License. */ -import java.io.*; -import java.security.*; -import java.util.*; - -import org.osgi.framework.*; +import java.io.IOException; +import java.io.NotSerializableException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.security.BasicPermission; +import java.security.Permission; +import java.security.PermissionCollection; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; /** * A bundle's authority to register or get a service. @@ -42,641 +60,632 @@ import org.osgi.framework.*; */ public final class EndpointPermission extends BasicPermission { - static final long serialVersionUID = -7662148639076511574L; - /** - * The action string <code>get</code>. - */ - public final static String EXPORT = "export"; - /** - * The action string <code>register</code>. - */ - public final static String IMPORT = "import"; - - public final static String LISTENING = "listening"; - - private final static int ACTION_EXPORT = 0x00000001; - private final static int ACTION_IMPORT = 0x00000002; - private final static int ACTION_ALL = ACTION_EXPORT | ACTION_IMPORT; - final static int ACTION_NONE = 0; - - /** - * The actions mask. - */ - transient int action_mask; - - /** - * The actions in canonical form. - * - * @serial - */ - private volatile String actions = null; - - /** - * The service used by this EndpointPermission. Must be null if not - * constructed with a service. - */ - transient final EndpointDescription endpoint; - - /** - * The object classes for this EndpointPermission. Must be null if not - * constructed with a service. - */ - transient final String[] objectClass; - - /** - * If this EndpointPermission was constructed with a filter, this holds a - * Filter matching object used to evaluate the filter in implies. - */ - transient Filter filter; - - /** - * This dictionary holds the properties of the permission, used to match a - * filter in implies. This is not initialized until necessary, and then - * cached in this object. - */ - private transient volatile Dictionary properties; - - /** - * True if constructed with a name and the name is "*" or ends with ".*". - */ - private transient boolean wildcard; - - /** - * If constructed with a name and the name ends with ".*", this contains the - * name without the final "*". - */ - private transient String prefix; - - /** - * Create a new EndpointPermission. - * - * <p> - * The name of the service is specified as a fully qualified class name. - * Wildcards may be used. - * - * <pre> - * name ::= <class name> | <class name ending in ".*"> | * - * </pre> - * - * Examples: - * - * <pre> - * org.osgi.service.http.HttpService - * org.osgi.service.http.* - * * - * </pre> - * - * For the <code>get</code> action, the name can also be a filter - * expression. The filter gives access to the service properties as well as - * the following attributes: - * <ul> - * <li>signer - A Distinguished Name chain used to sign the bundle - * publishing the service. Wildcards in a DN are not matched according to - * the filter string rules, but according to the rules defined for a DN - * chain.</li> - * <li>location - The location of the bundle publishing the service.</li> - * <li>id - The bundle ID of the bundle publishing the service.</li> - * <li>name - The symbolic name of the bundle publishing the service.</li> - * </ul> - * Since the above attribute names may conflict with service property names - * used by a service, you can prefix an attribute name with '@' in the - * filter expression to match against the service property and not one of - * the above attributes. Filter attribute names are processed in a case - * sensitive manner unless the attribute references a service property. - * Service properties names are case insensitive. - * - * <p> - * There are two possible actions: <code>get</code> and - * <code>register</code>. The <code>get</code> permission allows the - * owner of this permission to obtain a service with this name. The - * <code>register</code> permission allows the bundle to register a - * service under that name. - * - * @param name - * The service class name - * @param actions - * <code>get</code>,<code>register</code> (canonical order) - * @throws IllegalArgumentException - * If the specified name is a filter expression and either the - * specified action is not <code>get</code> or the filter has - * an invalid syntax. - */ - public EndpointPermission(String name, String actions) { - this(name, parseActions(actions)); - if ((filter != null) && ((action_mask & ACTION_ALL) != ACTION_EXPORT)) { - throw new IllegalArgumentException( - "invalid action string for filter expression"); - } - } - - /** - * Creates a new requested <code>EndpointPermission</code> object to be - * used by code that must perform <code>checkPermission</code> for the - * <code>get</code> action. <code>EndpointPermission</code> objects - * created with this constructor cannot be added to a - * <code>EndpointPermission</code> permission collection. - * - * @param endpoint - * The requested service. - * @param actions - * The action <code>get</code>. - * @throws IllegalArgumentException - * If the specified action is not <code>get</code> or - * reference is <code>null</code>. - * @since 1.5 - */ - public EndpointPermission(EndpointDescription endpoint, String actions) { - super(createName(endpoint)); - setTransients(null, parseActions(actions)); - this.endpoint = endpoint; - this.objectClass = (String[]) endpoint.getProperties().get( - Constants.OBJECTCLASS); - if ((action_mask & ACTION_ALL) != ACTION_EXPORT) { - throw new IllegalArgumentException("invalid action string"); - } - } - - /** - * Create a permission name from a EndpointDescription TODO Needs work - * - * @param endpoint - * EndpointDescription to use to create permission name. - * @return permission name. - */ - private static String createName(EndpointDescription endpoint) { - if (endpoint == null) { - throw new IllegalArgumentException("reference must not be null"); - } - StringBuffer sb = new StringBuffer("(service.id="); - // TODO sb.append(endpoint.getProperty(Constants.SERVICE_ID)); - sb.append(")"); - return sb.toString(); - } - - /** - * Package private constructor used by EndpointPermissionCollection. - * - * @param name - * class name - * @param mask - * action mask - */ - EndpointPermission(String name, int mask) { - super(name); - setTransients(parseFilter(name), mask); - this.endpoint = null; - this.objectClass = null; - } - - /** - * Called by constructors and when deserialized. - * - * @param mask - * action mask - */ - private void setTransients(Filter f, int mask) { - if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) { - throw new IllegalArgumentException("invalid action string"); - } - action_mask = mask; - filter = f; - if (f == null) { - String name = getName(); - int l = name.length(); - /* if "*" or endsWith ".*" */ - wildcard = ((name.charAt(l - 1) == '*') && ((l == 1) || (name - .charAt(l - 2) == '.'))); - if (wildcard && (l > 1)) { - prefix = name.substring(0, l - 1); - } - } - } - - /** - * Parse action string into action mask. - * - * @param actions - * Action string. - * @return action mask. - */ - private static int parseActions(String actions) { - boolean seencomma = false; - - int mask = ACTION_NONE; - - if (actions == null) { - return mask; - } - - char[] a = actions.toCharArray(); - - int i = a.length - 1; - if (i < 0) - return mask; - - while (i != -1) { - char c; - - // skip whitespace - while ((i != -1) - && ((c = a[i]) == ' ' || c == '\r' || c == '\n' - || c == '\f' || c == '\t')) - i--; - - // check for the known strings - int matchlen; - - if (i >= 2 && (a[i - 2] == 'g' || a[i - 2] == 'G') - && (a[i - 1] == 'e' || a[i - 1] == 'E') - && (a[i] == 't' || a[i] == 'T')) { - matchlen = 3; - mask |= ACTION_EXPORT; - - } else if (i >= 7 && (a[i - 7] == 'r' || a[i - 7] == 'R') - && (a[i - 6] == 'e' || a[i - 6] == 'E') - && (a[i - 5] == 'g' || a[i - 5] == 'G') - && (a[i - 4] == 'i' || a[i - 4] == 'I') - && (a[i - 3] == 's' || a[i - 3] == 'S') - && (a[i - 2] == 't' || a[i - 2] == 'T') - && (a[i - 1] == 'e' || a[i - 1] == 'E') - && (a[i] == 'r' || a[i] == 'R')) { - matchlen = 8; - mask |= ACTION_IMPORT; - - } else { - // parse error - throw new IllegalArgumentException("invalid permission: " - + actions); - } - - // make sure we didn't just match the tail of a word - // like "ackbarfregister". Also, skip to the comma. - seencomma = false; - while (i >= matchlen && !seencomma) { - switch (a[i - matchlen]) { - case ',': - seencomma = true; - /* FALLTHROUGH */ - case ' ': - case '\r': - case '\n': - case '\f': - case '\t': - break; - default: - throw new IllegalArgumentException("invalid permission: " - + actions); - } - i--; - } - - // point i at the location of the comma minus one (or -1). - i -= matchlen; - } - - if (seencomma) { - throw new IllegalArgumentException("invalid permission: " + actions); - } - - return mask; - } - - /** - * Parse filter string into a Filter object. - * - * @param filterString - * The filter string to parse. - * @return a Filter for this bundle. If the specified filterString is not a - * filter expression, then <code>null</code> is returned. - * @throws IllegalArgumentException - * If the filter syntax is invalid. - */ - private static Filter parseFilter(String filterString) { - filterString = filterString.trim(); - if (filterString.charAt(0) != '(') { - return null; - } - - try { - return FrameworkUtil.createFilter(filterString); - } catch (InvalidSyntaxException e) { - IllegalArgumentException iae = new IllegalArgumentException( - "invalid filter"); - iae.initCause(e); - throw iae; - } - } - - /** - * Determines if a <code>EndpointPermission</code> object "implies" the - * specified permission. - * - * @param p - * The target permission to check. - * @return <code>true</code> if the specified permission is implied by - * this object; <code>false</code> otherwise. - */ - public boolean implies(Permission p) { - if (!(p instanceof EndpointPermission)) { - return false; - } - EndpointPermission requested = (EndpointPermission) p; - if (endpoint != null) { - return false; - } - // if requested permission has a filter, then it is an invalid argument - if (requested.filter != null) { - return false; - } - return implies0(requested, ACTION_NONE); - } - - /** - * Internal implies method. Used by the implies and the permission - * collection implies methods. - * - * @param requested - * The requested EndpointPermission which has already be - * validated as a proper argument. The requested - * EndpointPermission must not have a filter expression. - * @param effective - * The effective actions with which to start. - * @return <code>true</code> if the specified permission is implied by - * this object; <code>false</code> otherwise. - */ - boolean implies0(EndpointPermission requested, int effective) { - /* check actions first - much faster */ - effective |= action_mask; - final int desired = requested.action_mask; - if ((effective & desired) != desired) { - return false; - } - /* we have name of "*" */ - if (wildcard && (prefix == null)) { - return true; - } - /* if we have a filter */ - Filter f = filter; - if (f != null) { - return f.matchCase(requested.getProperties()); - } - /* if requested permission not created with EndpointDescription */ - String[] requestedNames = requested.objectClass; - if (requestedNames == null) { - return super.implies(requested); - } - /* requested permission created with EndpointDescription */ - if (wildcard) { - int pl = prefix.length(); - for (int i = 0, l = requestedNames.length; i < l; i++) { - String requestedName = requestedNames[i]; - if ((requestedName.length() > pl) - && requestedName.startsWith(prefix)) { - return true; - } - } - } else { - String name = getName(); - for (int i = 0, l = requestedNames.length; i < l; i++) { - if (requestedNames[i].equals(name)) { - return true; - } - } - } - return false; - } - - /** - * Returns the canonical string representation of the actions. Always - * returns present actions in the following order: <code>get</code>, - * <code>register</code>. - * - * @return The canonical string representation of the actions. - */ - public String getActions() { - String result = actions; - if (result == null) { - StringBuffer sb = new StringBuffer(); - boolean comma = false; - - int mask = action_mask; - if ((mask & ACTION_EXPORT) == ACTION_EXPORT) { - sb.append(EXPORT); - comma = true; - } - - if ((mask & ACTION_IMPORT) == ACTION_IMPORT) { - if (comma) - sb.append(','); - sb.append(IMPORT); - } - - actions = result = sb.toString(); - } - - return result; - } - - /** - * Returns a new <code>PermissionCollection</code> object for storing - * <code>EndpointPermission<code> objects. - * - * @return A new <code>PermissionCollection</code> object suitable for storing - * <code>EndpointPermission</code> objects. - */ - public PermissionCollection newPermissionCollection() { - return new EndpointPermissionCollection(); - } - - /** - * Determines the equality of two EndpointPermission objects. - * - * Checks that specified object has the same class name and action as this - * <code>EndpointPermission</code>. - * - * @param obj - * The object to test for equality. - * @return true if obj is a <code>EndpointPermission</code>, and has the - * same class name and actions as this - * <code>EndpointPermission</code> object; <code>false</code> - * otherwise. - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof EndpointPermission)) { - return false; - } - - EndpointPermission sp = (EndpointPermission) obj; - - return (action_mask == sp.action_mask) - && getName().equals(sp.getName()) - && ((endpoint == sp.endpoint) || ((endpoint != null) - && (sp.endpoint != null) && endpoint - .equals(sp.endpoint))); - } - - /** - * Returns the hash code value for this object. - * - * @return Hash code value for this object. - */ - public int hashCode() { - int h = 31 * 17 + getName().hashCode(); - h = 31 * h + getActions().hashCode(); - if (endpoint != null) { - h = 31 * h + endpoint.hashCode(); - } - return h; - } - - /** - * WriteObject is called to save the state of this permission to a stream. - * The actions are serialized, and the superclass takes care of the name. - */ - private synchronized void writeObject(java.io.ObjectOutputStream s) - throws IOException { - if (endpoint != null) { - throw new NotSerializableException("cannot serialize"); - } - // Write out the actions. The superclass takes care of the name - // call getActions to make sure actions field is initialized - if (actions == null) - getActions(); - s.defaultWriteObject(); - } - - /** - * readObject is called to restore the state of this permission from a - * stream. - */ - private synchronized void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - // Read in the action, then initialize the rest - s.defaultReadObject(); - setTransients(parseFilter(getName()), parseActions(actions)); - } - - /** - * Called by <code><@link EndpointPermission#implies(Permission)></code>. - * - * @return a dictionary of properties for this permission. - */ - private Dictionary/*<String,Object>*/ getProperties() { - Dictionary/*<String, Object>*/ result = properties; - if (result != null) { - return result; - } - if (endpoint == null) { - result = new Hashtable/*<String, Object>*/(1); - if (filter == null) { - result.put(Constants.OBJECTCLASS, new String[] { getName() }); - } - return properties = result; - } - final Map props = new HashMap(4); - // TODO needs work - /* - final Bundle bundle = endpoint.getBundle(); - if (bundle != null) { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - props.put("id", new Long(bundle.getBundleId())); - props.put("location", bundle.getLocation()); - String name = bundle.getSymbolicName(); - if (name != null) { - props.put("name", name); - } - SignerProperty signer = new SignerProperty(bundle); - if (signer.isBundleSigned()) { - props.put("signer", signer); - } - return null; - } - }); - } - */ - return properties = new Properties(props, endpoint); - } - - private static class Properties extends Dictionary { - private final Map properties; - private final EndpointDescription service; - - Properties(Map properties, EndpointDescription service) { - this.properties = properties; - this.service = service; - } - - public Object get(Object k) { - if (!(k instanceof String)) { - return null; - } - String key = (String) k; - if (key.charAt(0) == '@') { - return service.getProperties().get(key.substring(1)); - } - Object value = properties.get(key); - if (value != null) { // fall back to service properties - return value; - } - return service.getProperties().get(key); - } - - public int size() { - return properties.size() + service.getProperties().size(); - } - - public boolean isEmpty() { - // we can return false because this must never be empty - return false; - } - - public Enumeration keys() { - Collection pk = properties.keySet(); - String spk[] = (String[]) service.getProperties().keySet().toArray(new String[service.getProperties().size()]); - List all = new ArrayList(pk.size() + spk.length); - all.addAll(pk); - add: for (int i = 0, length = spk.length; i < length; i++) { - String key = spk[i]; - for (Iterator iter = pk.iterator(); iter.hasNext();) { - if (key.equalsIgnoreCase((String) iter.next())) { - continue add; - } - } - all.add(key); - } - return Collections.enumeration(all); - } - - public Enumeration elements() { - Collection pk = properties.keySet(); - String spk[] = (String[])service.getProperties().keySet().toArray(new String[service.getProperties().size()]); - List all = new ArrayList(pk.size() + spk.length); - all.addAll(properties.values()); - add: for (int i = 0, length = spk.length; i < length; i++) { - String key = spk[i]; - for (Iterator iter = pk.iterator(); iter.hasNext();) { - if (key.equalsIgnoreCase((String) iter.next())) { - continue add; - } - } - all.add(service.getProperties().get(key)); - } - return Collections.enumeration(all); - } - - public Object put(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - public Object remove(Object key) { - throw new UnsupportedOperationException(); - } - } + static final long serialVersionUID = -7662148639076511574L; + /** + * The action string <code>get</code>. + */ + public final static String EXPORT = "export"; + /** + * The action string <code>register</code>. + */ + public final static String IMPORT = "import"; + + public final static String LISTENING = "listening"; + + public final static String READ = "listening"; + + private final static int ACTION_EXPORT = 0x00000001; + private final static int ACTION_IMPORT = 0x00000002; + private final static int ACTION_ALL = ACTION_EXPORT | ACTION_IMPORT; + final static int ACTION_NONE = 0; + + /** + * The actions mask. + */ + transient int action_mask; + + /** + * The actions in canonical form. + * + * @serial + */ + private volatile String actions = null; + + /** + * The service used by this EndpointPermission. Must be null if not + * constructed with a service. + */ + transient final EndpointDescription endpoint; + + /** + * The object classes for this EndpointPermission. Must be null if not + * constructed with a service. + */ + transient final String[] objectClass; + + /** + * If this EndpointPermission was constructed with a filter, this holds a + * Filter matching object used to evaluate the filter in implies. + */ + transient Filter filter; + + /** + * This dictionary holds the properties of the permission, used to match a + * filter in implies. This is not initialized until necessary, and then + * cached in this object. + */ + private transient volatile Dictionary properties; + + /** + * True if constructed with a name and the name is "*" or ends with ".*". + */ + private transient boolean wildcard; + + /** + * If constructed with a name and the name ends with ".*", this contains the + * name without the final "*". + */ + private transient String prefix; + + /** + * Create a new EndpointPermission. + * + * <p> + * The name of the service is specified as a fully qualified class name. + * Wildcards may be used. + * + * <pre> + * name ::= <class name> | <class name ending in ".*"> | * + * </pre> + * + * Examples: + * + * <pre> + * org.osgi.service.http.HttpService + * org.osgi.service.http.* + * * + * </pre> + * + * For the <code>get</code> action, the name can also be a filter + * expression. The filter gives access to the service properties as well as + * the following attributes: + * <ul> + * <li>signer - A Distinguished Name chain used to sign the bundle + * publishing the service. Wildcards in a DN are not matched according to + * the filter string rules, but according to the rules defined for a DN + * chain.</li> + * <li>location - The location of the bundle publishing the service.</li> + * <li>id - The bundle ID of the bundle publishing the service.</li> + * <li>name - The symbolic name of the bundle publishing the service.</li> + * </ul> + * Since the above attribute names may conflict with service property names + * used by a service, you can prefix an attribute name with '@' in the + * filter expression to match against the service property and not one of + * the above attributes. Filter attribute names are processed in a case + * sensitive manner unless the attribute references a service property. + * Service properties names are case insensitive. + * + * <p> + * There are two possible actions: <code>get</code> and + * <code>register</code>. The <code>get</code> permission allows the + * owner of this permission to obtain a service with this name. The + * <code>register</code> permission allows the bundle to register a + * service under that name. + * + * @param name + * The service class name + * @param actions + * <code>get</code>,<code>register</code> (canonical order) + * @throws IllegalArgumentException + * If the specified name is a filter expression and either the + * specified action is not <code>get</code> or the filter has + * an invalid syntax. + */ + public EndpointPermission(String name, String actions) { + this(name, parseActions(actions)); + if ((filter != null) && ((action_mask & ACTION_ALL) != ACTION_EXPORT)) { + throw new IllegalArgumentException("invalid action string for filter expression"); + } + } + + /** + * Creates a new requested <code>EndpointPermission</code> object to be + * used by code that must perform <code>checkPermission</code> for the + * <code>get</code> action. <code>EndpointPermission</code> objects + * created with this constructor cannot be added to a + * <code>EndpointPermission</code> permission collection. + * + * @param endpoint + * The requested service. + * @param actions + * The action <code>get</code>. + * @throws IllegalArgumentException + * If the specified action is not <code>get</code> or + * reference is <code>null</code>. + * @since 1.5 + */ + public EndpointPermission(EndpointDescription endpoint, String actions) { + super(createName(endpoint)); + setTransients(null, parseActions(actions)); + this.endpoint = endpoint; + this.objectClass = (String[])endpoint.getProperties().get(Constants.OBJECTCLASS); + if ((action_mask & ACTION_ALL) != ACTION_EXPORT) { + throw new IllegalArgumentException("invalid action string"); + } + } + + /** + * Create a permission name from a EndpointDescription TODO Needs work + * + * @param endpoint + * EndpointDescription to use to create permission name. + * @return permission name. + */ + private static String createName(EndpointDescription endpoint) { + if (endpoint == null) { + throw new IllegalArgumentException("reference must not be null"); + } + StringBuffer sb = new StringBuffer("(service.id="); + // TODO sb.append(endpoint.getProperty(Constants.SERVICE_ID)); + sb.append(")"); + return sb.toString(); + } + + /** + * Package private constructor used by EndpointPermissionCollection. + * + * @param name + * class name + * @param mask + * action mask + */ + EndpointPermission(String name, int mask) { + super(name); + setTransients(parseFilter(name), mask); + this.endpoint = null; + this.objectClass = null; + } + + /** + * Called by constructors and when deserialized. + * + * @param mask + * action mask + */ + private void setTransients(Filter f, int mask) { + if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) { + throw new IllegalArgumentException("invalid action string"); + } + action_mask = mask; + filter = f; + if (f == null) { + String name = getName(); + int l = name.length(); + /* if "*" or endsWith ".*" */ + wildcard = ((name.charAt(l - 1) == '*') && ((l == 1) || (name.charAt(l - 2) == '.'))); + if (wildcard && (l > 1)) { + prefix = name.substring(0, l - 1); + } + } + } + + /** + * Parse action string into action mask. + * + * @param actions + * Action string. + * @return action mask. + */ + private static int parseActions(String actions) { + boolean seencomma = false; + + int mask = ACTION_NONE; + + if (actions == null) { + return mask; + } + + char[] a = actions.toCharArray(); + + int i = a.length - 1; + if (i < 0) + return mask; + + while (i != -1) { + char c; + + // skip whitespace + while ((i != -1) && ((c = a[i]) == ' ' || c == '\r' || c == '\n' || c == '\f' || c == '\t')) + i--; + + // check for the known strings + int matchlen; + + if (i >= 2 && (a[i - 2] == 'g' || a[i - 2] == 'G') + && (a[i - 1] == 'e' || a[i - 1] == 'E') + && (a[i] == 't' || a[i] == 'T')) { + matchlen = 3; + mask |= ACTION_EXPORT; + + } else if (i >= 7 && (a[i - 7] == 'r' || a[i - 7] == 'R') + && (a[i - 6] == 'e' || a[i - 6] == 'E') + && (a[i - 5] == 'g' || a[i - 5] == 'G') + && (a[i - 4] == 'i' || a[i - 4] == 'I') + && (a[i - 3] == 's' || a[i - 3] == 'S') + && (a[i - 2] == 't' || a[i - 2] == 'T') + && (a[i - 1] == 'e' || a[i - 1] == 'E') + && (a[i] == 'r' || a[i] == 'R')) { + matchlen = 8; + mask |= ACTION_IMPORT; + + } else { + // parse error + throw new IllegalArgumentException("invalid permission: " + actions); + } + + // make sure we didn't just match the tail of a word + // like "ackbarfregister". Also, skip to the comma. + seencomma = false; + while (i >= matchlen && !seencomma) { + switch (a[i - matchlen]) { + case ',': + seencomma = true; + /* FALLTHROUGH */ + case ' ': + case '\r': + case '\n': + case '\f': + case '\t': + break; + default: + throw new IllegalArgumentException("invalid permission: " + actions); + } + i--; + } + + // point i at the location of the comma minus one (or -1). + i -= matchlen; + } + + if (seencomma) { + throw new IllegalArgumentException("invalid permission: " + actions); + } + + return mask; + } + + /** + * Parse filter string into a Filter object. + * + * @param filterString + * The filter string to parse. + * @return a Filter for this bundle. If the specified filterString is not a + * filter expression, then <code>null</code> is returned. + * @throws IllegalArgumentException + * If the filter syntax is invalid. + */ + private static Filter parseFilter(String filterString) { + filterString = filterString.trim(); + if (filterString.charAt(0) != '(') { + return null; + } + + try { + return FrameworkUtil.createFilter(filterString); + } catch (InvalidSyntaxException e) { + IllegalArgumentException iae = new IllegalArgumentException("invalid filter"); + iae.initCause(e); + throw iae; + } + } + + /** + * Determines if a <code>EndpointPermission</code> object "implies" the + * specified permission. + * + * @param p + * The target permission to check. + * @return <code>true</code> if the specified permission is implied by + * this object; <code>false</code> otherwise. + */ + public boolean implies(Permission p) { + if (!(p instanceof EndpointPermission)) { + return false; + } + EndpointPermission requested = (EndpointPermission)p; + if (endpoint != null) { + return false; + } + // if requested permission has a filter, then it is an invalid argument + if (requested.filter != null) { + return false; + } + return implies0(requested, ACTION_NONE); + } + + /** + * Internal implies method. Used by the implies and the permission + * collection implies methods. + * + * @param requested + * The requested EndpointPermission which has already be + * validated as a proper argument. The requested + * EndpointPermission must not have a filter expression. + * @param effective + * The effective actions with which to start. + * @return <code>true</code> if the specified permission is implied by + * this object; <code>false</code> otherwise. + */ + boolean implies0(EndpointPermission requested, int effective) { + /* check actions first - much faster */ + effective |= action_mask; + final int desired = requested.action_mask; + if ((effective & desired) != desired) { + return false; + } + /* we have name of "*" */ + if (wildcard && (prefix == null)) { + return true; + } + /* if we have a filter */ + Filter f = filter; + if (f != null) { + return f.matchCase(requested.getProperties()); + } + /* if requested permission not created with EndpointDescription */ + String[] requestedNames = requested.objectClass; + if (requestedNames == null) { + return super.implies(requested); + } + /* requested permission created with EndpointDescription */ + if (wildcard) { + int pl = prefix.length(); + for (int i = 0, l = requestedNames.length; i < l; i++) { + String requestedName = requestedNames[i]; + if ((requestedName.length() > pl) && requestedName.startsWith(prefix)) { + return true; + } + } + } else { + String name = getName(); + for (int i = 0, l = requestedNames.length; i < l; i++) { + if (requestedNames[i].equals(name)) { + return true; + } + } + } + return false; + } + + /** + * Returns the canonical string representation of the actions. Always + * returns present actions in the following order: <code>get</code>, + * <code>register</code>. + * + * @return The canonical string representation of the actions. + */ + public String getActions() { + String result = actions; + if (result == null) { + StringBuffer sb = new StringBuffer(); + boolean comma = false; + + int mask = action_mask; + if ((mask & ACTION_EXPORT) == ACTION_EXPORT) { + sb.append(EXPORT); + comma = true; + } + + if ((mask & ACTION_IMPORT) == ACTION_IMPORT) { + if (comma) + sb.append(','); + sb.append(IMPORT); + } + + actions = result = sb.toString(); + } + + return result; + } + + /** + * Returns a new <code>PermissionCollection</code> object for storing + * <code>EndpointPermission<code> objects. + * + * @return A new <code>PermissionCollection</code> object suitable for storing + * <code>EndpointPermission</code> objects. + */ + public PermissionCollection newPermissionCollection() { + return new EndpointPermissionCollection(); + } + + /** + * Determines the equality of two EndpointPermission objects. + * + * Checks that specified object has the same class name and action as this + * <code>EndpointPermission</code>. + * + * @param obj + * The object to test for equality. + * @return true if obj is a <code>EndpointPermission</code>, and has the + * same class name and actions as this + * <code>EndpointPermission</code> object; <code>false</code> + * otherwise. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof EndpointPermission)) { + return false; + } + + EndpointPermission sp = (EndpointPermission)obj; + + return (action_mask == sp.action_mask) && getName().equals(sp.getName()) + && ((endpoint == sp.endpoint) || ((endpoint != null) && (sp.endpoint != null) && endpoint + .equals(sp.endpoint))); + } + + /** + * Returns the hash code value for this object. + * + * @return Hash code value for this object. + */ + public int hashCode() { + int h = 31 * 17 + getName().hashCode(); + h = 31 * h + getActions().hashCode(); + if (endpoint != null) { + h = 31 * h + endpoint.hashCode(); + } + return h; + } + + /** + * WriteObject is called to save the state of this permission to a stream. + * The actions are serialized, and the superclass takes care of the name. + */ + private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { + if (endpoint != null) { + throw new NotSerializableException("cannot serialize"); + } + // Write out the actions. The superclass takes care of the name + // call getActions to make sure actions field is initialized + if (actions == null) + getActions(); + s.defaultWriteObject(); + } + + /** + * readObject is called to restore the state of this permission from a + * stream. + */ + private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { + // Read in the action, then initialize the rest + s.defaultReadObject(); + setTransients(parseFilter(getName()), parseActions(actions)); + } + + /** + * Called by <code><@link EndpointPermission#implies(Permission)></code>. + * + * @return a dictionary of properties for this permission. + */ + private Dictionary/*<String,Object>*/getProperties() { + Dictionary/*<String, Object>*/result = properties; + if (result != null) { + return result; + } + if (endpoint == null) { + result = new Hashtable/*<String, Object>*/(1); + if (filter == null) { + result.put(Constants.OBJECTCLASS, new String[] {getName()}); + } + return properties = result; + } + final Map props = new HashMap(4); + // TODO needs work + /* + final Bundle bundle = endpoint.getBundle(); + if (bundle != null) { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + props.put("id", new Long(bundle.getBundleId())); + props.put("location", bundle.getLocation()); + String name = bundle.getSymbolicName(); + if (name != null) { + props.put("name", name); + } + SignerProperty signer = new SignerProperty(bundle); + if (signer.isBundleSigned()) { + props.put("signer", signer); + } + return null; + } + }); + } + */ + return properties = new Properties(props, endpoint); + } + + private static class Properties extends Dictionary { + private final Map properties; + private final EndpointDescription service; + + Properties(Map properties, EndpointDescription service) { + this.properties = properties; + this.service = service; + } + + public Object get(Object k) { + if (!(k instanceof String)) { + return null; + } + String key = (String)k; + if (key.charAt(0) == '@') { + return service.getProperties().get(key.substring(1)); + } + Object value = properties.get(key); + if (value != null) { // fall back to service properties + return value; + } + return service.getProperties().get(key); + } + + public int size() { + return properties.size() + service.getProperties().size(); + } + + public boolean isEmpty() { + // we can return false because this must never be empty + return false; + } + + public Enumeration keys() { + Collection pk = properties.keySet(); + String spk[] = + (String[])service.getProperties().keySet().toArray(new String[service.getProperties().size()]); + List all = new ArrayList(pk.size() + spk.length); + all.addAll(pk); + add: for (int i = 0, length = spk.length; i < length; i++) { + String key = spk[i]; + for (Iterator iter = pk.iterator(); iter.hasNext();) { + if (key.equalsIgnoreCase((String)iter.next())) { + continue add; + } + } + all.add(key); + } + return Collections.enumeration(all); + } + + public Enumeration elements() { + Collection pk = properties.keySet(); + String spk[] = + (String[])service.getProperties().keySet().toArray(new String[service.getProperties().size()]); + List all = new ArrayList(pk.size() + spk.length); + all.addAll(properties.values()); + add: for (int i = 0, length = spk.length; i < length; i++) { + String key = spk[i]; + for (Iterator iter = pk.iterator(); iter.hasNext();) { + if (key.equalsIgnoreCase((String)iter.next())) { + continue add; + } + } + all.add(service.getProperties().get(key)); + } + return Collections.enumeration(all); + } + + public Object put(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + public Object remove(Object key) { + throw new UnsupportedOperationException(); + } + } } /** @@ -687,253 +696,243 @@ public final class EndpointPermission extends BasicPermission { * @see java.security.PermissionCollection */ final class EndpointPermissionCollection extends PermissionCollection { - static final long serialVersionUID = 662615640374640621L; - /** - * Table of permissions. - * - * @GuardedBy this - */ - private transient Map permissions; - - /** - * Boolean saying if "*" is in the collection. - * - * @serial - * @GuardedBy this - */ - private boolean all_allowed; - - /** - * Table of permissions with filter expressions. - * - * @serial - * @GuardedBy this - */ - private Map filterPermissions; - - /** - * Creates an empty EndpointPermissions object. - */ - public EndpointPermissionCollection() { - permissions = new HashMap(); - all_allowed = false; - } - - /** - * Adds a permission to this permission collection. - * - * @param permission - * The Permission object to add. - * @throws IllegalArgumentException - * If the specified permission is not a EndpointPermission - * object. - * @throws SecurityException - * If this <code>EndpointPermissionCollection</code> object - * has been marked read-only. - */ - public void add(final Permission permission) { - if (!(permission instanceof EndpointPermission)) { - throw new IllegalArgumentException("invalid permission: " - + permission); - } - if (isReadOnly()) { - throw new SecurityException("attempt to add a Permission to a " - + "readonly PermissionCollection"); - } - - final EndpointPermission sp = (EndpointPermission) permission; - if (sp.endpoint != null) { - throw new IllegalArgumentException("cannot add to collection: " - + sp); - } - - final String name = sp.getName(); - final Filter f = sp.filter; - synchronized (this) { - /* select the bucket for the permission */ - Map pc; - if (f != null) { - pc = filterPermissions; - if (pc == null) { - filterPermissions = pc = new HashMap(); - } - } else { - pc = permissions; - } - final EndpointPermission existing = (EndpointPermission) pc - .get(name); - - if (existing != null) { - final int oldMask = existing.action_mask; - final int newMask = sp.action_mask; - if (oldMask != newMask) { - pc.put(name, - new EndpointPermission(name, oldMask | newMask)); - } - } else { - pc.put(name, sp); - } - - if (!all_allowed) { - if (name.equals("*")) { - all_allowed = true; - } - } - } - } - - /** - * Determines if a set of permissions implies the permissions expressed in - * <code>permission</code>. - * - * @param permission - * The Permission object to compare. - * @return <code>true</code> if <code>permission</code> is a proper - * subset of a permission in the set; <code>false</code> - * otherwise. - */ - public boolean implies(final Permission permission) { - if (!(permission instanceof EndpointPermission)) { - return false; - } - final EndpointPermission requested = (EndpointPermission) permission; - /* if requested permission has a filter, then it is an invalid argument */ - if (requested.filter != null) { - return false; - } - - int effective = EndpointPermission.ACTION_NONE; - Collection perms; - synchronized (this) { - final int desired = requested.action_mask; - /* short circuit if the "*" Permission was added */ - if (all_allowed) { - EndpointPermission sp = (EndpointPermission) permissions - .get("*"); - if (sp != null) { - effective |= sp.action_mask; - if ((effective & desired) == desired) { - return true; - } - } - } - - String[] requestedNames = requested.objectClass; - /* if requested permission not created with EndpointDescription */ - if (requestedNames == null) { - effective |= effective(requested.getName(), desired, effective); - if ((effective & desired) == desired) { - return true; - } - } - /* requested permission created with EndpointDescription */ - else { - for (int i = 0, l = requestedNames.length; i < l; i++) { - if ((effective(requestedNames[i], desired, effective) & desired) == desired) { - return true; - } - } - } - Map pc = filterPermissions; - if (pc == null) { - return false; - } - perms = pc.values(); - } - - /* iterate one by one over filteredPermissions */ - for (Iterator iter = perms.iterator(); iter.hasNext();) { - if (((EndpointPermission) iter.next()).implies0(requested, - effective)) { - return true; - } - } - return false; - } - - /** - * Consult permissions map to compute the effective permission for the - * requested permission name. - * - * @param requestedName - * The requested service name. - * @param desired - * The desired actions. - * @param effective - * The effective actions. - * @return The new effective actions. - */ - private int effective(String requestedName, final int desired, int effective) { - final Map pc = permissions; - EndpointPermission sp = (EndpointPermission) pc.get(requestedName); - // strategy: - // Check for full match first. Then work our way up the - // name looking for matches on a.b.* - if (sp != null) { - // we have a direct hit! - effective |= sp.action_mask; - if ((effective & desired) == desired) { - return effective; - } - } - // work our way up the tree... - int last; - int offset = requestedName.length() - 1; - while ((last = requestedName.lastIndexOf(".", offset)) != -1) { - requestedName = requestedName.substring(0, last + 1) + "*"; - sp = (EndpointPermission) pc.get(requestedName); - if (sp != null) { - effective |= sp.action_mask; - if ((effective & desired) == desired) { - return effective; - } - } - offset = last - 1; - } - /* - * we don't have to check for "*" as it was already checked before we - * were called. - */ - return effective; - } - - /** - * Returns an enumeration of all the <code>EndpointPermission</code> - * objects in the container. - * - * @return Enumeration of all the EndpointPermission objects. - */ - public synchronized Enumeration elements() { - List all = new ArrayList(permissions.values()); - Map pc = filterPermissions; - if (pc != null) { - all.addAll(pc.values()); - } - return Collections.enumeration(all); - } - - /* serialization logic */ - private static final ObjectStreamField[] serialPersistentFields = { - new ObjectStreamField("permissions", Hashtable.class), - new ObjectStreamField("all_allowed", Boolean.TYPE), - new ObjectStreamField("filterPermissions", HashMap.class) }; - - private synchronized void writeObject(ObjectOutputStream out) - throws IOException { - Hashtable hashtable = new Hashtable(permissions); - ObjectOutputStream.PutField pfields = out.putFields(); - pfields.put("permissions", hashtable); - pfields.put("all_allowed", all_allowed); - pfields.put("filterPermissions", filterPermissions); - out.writeFields(); - } - - private synchronized void readObject(java.io.ObjectInputStream in) - throws IOException, ClassNotFoundException { - ObjectInputStream.GetField gfields = in.readFields(); - Hashtable hashtable = (Hashtable) gfields.get("permissions", null); - permissions = new HashMap(hashtable); - all_allowed = gfields.get("all_allowed", false); - filterPermissions = (HashMap) gfields.get("filterPermissions", null); - } + static final long serialVersionUID = 662615640374640621L; + /** + * Table of permissions. + * + * @GuardedBy this + */ + private transient Map permissions; + + /** + * Boolean saying if "*" is in the collection. + * + * @serial + * @GuardedBy this + */ + private boolean all_allowed; + + /** + * Table of permissions with filter expressions. + * + * @serial + * @GuardedBy this + */ + private Map filterPermissions; + + /** + * Creates an empty EndpointPermissions object. + */ + public EndpointPermissionCollection() { + permissions = new HashMap(); + all_allowed = false; + } + + /** + * Adds a permission to this permission collection. + * + * @param permission + * The Permission object to add. + * @throws IllegalArgumentException + * If the specified permission is not a EndpointPermission + * object. + * @throws SecurityException + * If this <code>EndpointPermissionCollection</code> object + * has been marked read-only. + */ + public void add(final Permission permission) { + if (!(permission instanceof EndpointPermission)) { + throw new IllegalArgumentException("invalid permission: " + permission); + } + if (isReadOnly()) { + throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection"); + } + + final EndpointPermission sp = (EndpointPermission)permission; + if (sp.endpoint != null) { + throw new IllegalArgumentException("cannot add to collection: " + sp); + } + + final String name = sp.getName(); + final Filter f = sp.filter; + synchronized (this) { + /* select the bucket for the permission */ + Map pc; + if (f != null) { + pc = filterPermissions; + if (pc == null) { + filterPermissions = pc = new HashMap(); + } + } else { + pc = permissions; + } + final EndpointPermission existing = (EndpointPermission)pc.get(name); + + if (existing != null) { + final int oldMask = existing.action_mask; + final int newMask = sp.action_mask; + if (oldMask != newMask) { + pc.put(name, new EndpointPermission(name, oldMask | newMask)); + } + } else { + pc.put(name, sp); + } + + if (!all_allowed) { + if (name.equals("*")) { + all_allowed = true; + } + } + } + } + + /** + * Determines if a set of permissions implies the permissions expressed in + * <code>permission</code>. + * + * @param permission + * The Permission object to compare. + * @return <code>true</code> if <code>permission</code> is a proper + * subset of a permission in the set; <code>false</code> + * otherwise. + */ + public boolean implies(final Permission permission) { + if (!(permission instanceof EndpointPermission)) { + return false; + } + final EndpointPermission requested = (EndpointPermission)permission; + /* if requested permission has a filter, then it is an invalid argument */ + if (requested.filter != null) { + return false; + } + + int effective = EndpointPermission.ACTION_NONE; + Collection perms; + synchronized (this) { + final int desired = requested.action_mask; + /* short circuit if the "*" Permission was added */ + if (all_allowed) { + EndpointPermission sp = (EndpointPermission)permissions.get("*"); + if (sp != null) { + effective |= sp.action_mask; + if ((effective & desired) == desired) { + return true; + } + } + } + + String[] requestedNames = requested.objectClass; + /* if requested permission not created with EndpointDescription */ + if (requestedNames == null) { + effective |= effective(requested.getName(), desired, effective); + if ((effective & desired) == desired) { + return true; + } + } + /* requested permission created with EndpointDescription */ + else { + for (int i = 0, l = requestedNames.length; i < l; i++) { + if ((effective(requestedNames[i], desired, effective) & desired) == desired) { + return true; + } + } + } + Map pc = filterPermissions; + if (pc == null) { + return false; + } + perms = pc.values(); + } + + /* iterate one by one over filteredPermissions */ + for (Iterator iter = perms.iterator(); iter.hasNext();) { + if (((EndpointPermission)iter.next()).implies0(requested, effective)) { + return true; + } + } + return false; + } + + /** + * Consult permissions map to compute the effective permission for the + * requested permission name. + * + * @param requestedName + * The requested service name. + * @param desired + * The desired actions. + * @param effective + * The effective actions. + * @return The new effective actions. + */ + private int effective(String requestedName, final int desired, int effective) { + final Map pc = permissions; + EndpointPermission sp = (EndpointPermission)pc.get(requestedName); + // strategy: + // Check for full match first. Then work our way up the + // name looking for matches on a.b.* + if (sp != null) { + // we have a direct hit! + effective |= sp.action_mask; + if ((effective & desired) == desired) { + return effective; + } + } + // work our way up the tree... + int last; + int offset = requestedName.length() - 1; + while ((last = requestedName.lastIndexOf(".", offset)) != -1) { + requestedName = requestedName.substring(0, last + 1) + "*"; + sp = (EndpointPermission)pc.get(requestedName); + if (sp != null) { + effective |= sp.action_mask; + if ((effective & desired) == desired) { + return effective; + } + } + offset = last - 1; + } + /* + * we don't have to check for "*" as it was already checked before we + * were called. + */ + return effective; + } + + /** + * Returns an enumeration of all the <code>EndpointPermission</code> + * objects in the container. + * + * @return Enumeration of all the EndpointPermission objects. + */ + public synchronized Enumeration elements() { + List all = new ArrayList(permissions.values()); + Map pc = filterPermissions; + if (pc != null) { + all.addAll(pc.values()); + } + return Collections.enumeration(all); + } + + /* serialization logic */ + private static final ObjectStreamField[] serialPersistentFields = + {new ObjectStreamField("permissions", Hashtable.class), new ObjectStreamField("all_allowed", Boolean.TYPE), + new ObjectStreamField("filterPermissions", HashMap.class)}; + + private synchronized void writeObject(ObjectOutputStream out) throws IOException { + Hashtable hashtable = new Hashtable(permissions); + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("permissions", hashtable); + pfields.put("all_allowed", all_allowed); + pfields.put("filterPermissions", filterPermissions); + out.writeFields(); + } + + private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gfields = in.readFields(); + Hashtable hashtable = (Hashtable)gfields.get("permissions", null); + permissions = new HashMap(hashtable); + all_allowed = gfields.get("all_allowed", false); + filterPermissions = (HashMap)gfields.get("filterPermissions", null); + } } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ExportRegistration.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ExportRegistration.java index 4e98d633d8..0f1805131c 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ExportRegistration.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ExportRegistration.java @@ -1,13 +1,13 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; -import org.osgi.framework.*; +import org.osgi.framework.ServiceReference; /** * An Export Registration associates a service to a local endpoint. * * The Export Registration can be used to delete the endpoint associated with an - * this registration. It is created with the{@link RemoteAdmin#exportService(ServiceReference)} - * method. + * this registration. It is created with the + * {@link RemoteServiceAdmin#exportService(ServiceReference,java.util.Map)} method. * * When this Export Registration has been unregistered, the methods must all * return <code>null</code>. @@ -15,49 +15,47 @@ import org.osgi.framework.*; * @ThreadSafe */ public interface ExportRegistration { - /** - * Return the service being exported. - * - * @return The service being exported, must be <code>null</code> when this - * registration is unregistered. - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - ServiceReference getExportedService() throws IllegalStateException; + /** + * Return the service being exported. + * + * @return The service being exported, must be <code>null</code> when this + * registration is unregistered. + * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} + */ + ServiceReference getExportedService() throws IllegalStateException; - /** - * Return the Endpoint Description that is created for this registration. - * - * @return the local Endpoint Description - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - EndpointDescription getEndpointDescription(); + /** + * Return the Endpoint Description that is created for this registration. + * + * @return the local Endpoint Description + * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} + */ + EndpointDescription getEndpointDescription(); - /** - * Delete the local endpoint and disconnect any remote distribution - * providers. After this method returns, all the methods must return - * <code>null</code>. - * - * This method has no effect when the endpoint is already destroyed or being - * destroyed. - */ - void close(); + /** + * Delete the local endpoint and disconnect any remote distribution + * providers. After this method returns, all the methods must return + * <code>null</code>. + * + * This method has no effect when the endpoint is already destroyed or being + * destroyed. + */ + void close(); - /** - * Exception for any error during the import process. - * - * If the Remote Admin for some reasons is unable to create a registration, - * then it must return a <code>Throwable</code> from this method. In this - * case, all other methods must return on this interface must thrown an - * Illegal State Exception. If no error occurred, this method must return - * <code>null</code>. - * - * The error must be set before this Import Registration is returned. - * Asynchronously occurring errors must be reported to the log. - * - * future .... - * - * @return The exception that occurred during the creation of the - * registration or <code>null</code> if no exception occurred. - */ - Throwable getException(); + /** + * Exception for any error during the import process. + * + * If the Remote Admin for some reasons is unable to create a registration, + * then it must return a <code>Throwable</code> from this method. In this + * case, all other methods must return on this interface must throw an + * Illegal State Exception. If no error occurred, this method must return + * <code>null</code>. + * + * The error must be set before this Import Registration is returned. + * Asynchronously occurring errors must be reported to the log. + * + * @return The exception that occurred during the creation of the + * registration or <code>null</code> if no exception occurred. + */ + Throwable getException(); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ImportRegistration.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ImportRegistration.java index 1d55dbfc75..c943380068 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ImportRegistration.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/ImportRegistration.java @@ -1,59 +1,60 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; -import org.osgi.framework.*; +import org.osgi.framework.ServiceReference; /** * An Import Registration associates an active proxy service to a remote * endpoint. * * The Import Registration can be used to delete the proxy associated with an - * endpoint. It is created with the{@link RemoteAdmin#importService} + * endpoint. It is created with the{@link RemoteServiceAdmin#importService} * method. * * @ThreadSafe */ public interface ImportRegistration { - /** - * Answer the associated Service Reference for the proxy to the endpoint. - * - * @return A Service Reference to the proxy for the endpoint. - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - ServiceReference getImportedService(); + /** + * Answer the associated Service Reference for the proxy to the endpoint. + * + * @return A Service Reference to the proxy for the endpoint. + * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} + */ + ServiceReference getImportedService(); - /** - * Answer the associated remote Endpoint Description. - * - * @return A Endpoint Description for the remote endpoint. - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - EndpointDescription getImportedEndpointDescription(); + /** + * Answer the associated remote Endpoint Description. + * + * @return A Endpoint Description for the remote endpoint. + * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} + */ + EndpointDescription getImportedEndpointDescription(); - /** - * Unregister this Import Registration. This must close the connection - * to the end endpoint unregister the proxy. After this method returns, - * all other methods must return null. - * - * This method has no effect when the service is already unregistered or in the process off. - */ - void close(); - - - /** - * Exception for any error during the import process. - * - * If the Remote Admin for some reasons is unable to create a registration, - * then it must return a <code>Throwable</code> from this method. In this - * case, all other methods must return on this interface must thrown an - * Illegal State Exception. If no error occurred, this method must return - * <code>null</code>. - * - * The error must be set before this Import Registration is returned. - * Asynchronously occurring errors must be reported to the log. - * - * @return The exception that occurred during the creation of the - * registration or <code>null</code> if no exception occurred. - */ - Throwable getException(); + /** + * Unregister this Import Registration. This must close the connection + * to the end endpoint unregister the proxy. After this method returns, + * all other methods must return null. + * + * This method has no effect when the service is already unregistered or in the process off. + */ + void close(); + + /** + * Exception for any error during the import process. + * + * If the Remote Admin for some reasons is unable to create a registration, + * then it must return a <code>Throwable</code> from this method. In this + * case, all other methods must return on this interface must thrown an + * Illegal State Exception. If no error occurred, this method must return + * <code>null</code>. + * + * The error must be set before this Import Registration is returned. + * Asynchronously occurring errors must be reported to the log. + * + * TODO can we assume the proxy service is registered when getException==null? + * + * @return The exception that occurred during the creation of the + * registration or <code>null</code> if no exception occurred. + */ + Throwable getException(); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteAdminEvent.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteAdminEvent.java deleted file mode 100644 index 8bc0502b17..0000000000 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteAdminEvent.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.apache.tuscany.sca.osgi.service.remoteadmin; - -import org.osgi.framework.Bundle; - -/** - * - * Provides the event information for a Remote Admin event. - * - * @Immutable - */ -public class RemoteAdminEvent { - /** - * Add an import registration. The Remote Services Admin will call this - * method when it imports a service. When this service is registered, the - * Remote Service Admin must notify the listener of all existing Import - * Registrations. - * - */ - public static final int IMPORT_REGISTRATION = 1; - - /** - * Add an export registration. The Remote Services Admin will call this - * method when it exports a service. When this service is registered, the - * Remote Service Admin must notify the listener of all existing Export - * Registrations. - */ - public static final int EXPORT_REGISTRATION = 2; - - /** - * Remove an export registration. The Remote Services Admin will call this - * method when it removes the export of a service. - * - */ - public static final int EXPORT_UNREGISTRATION = 3; - - /** - * Remove an import registration. The Remote Services Admin will call this - * method when it removes the import of a service. - * - */ - public static final int IMPORT_UNREGISTRATION = 4; - - /** - * A fatal importing error occurred. The Import Registration has been - * closed. - */ - public static final int IMPORT_ERROR = 5; - - /** - * A fatal exporting error occurred. The Export Registration has been - * closed. - */ - public static final int EXPORT_ERROR = 6; - - /** - * A problematic situation occurred, the export is still active. - */ - public static final int EXPORT_WARNING = 7; - /** - * A problematic situation occurred, the import is still active. - */ - public static final int IMPORT_WARNING = 8; - - private ImportRegistration importRegistration; - private ExportRegistration exportRegistration; - private Throwable exception; - private int type; - private Bundle source; - - RemoteAdminEvent(int type, Bundle source, - ImportRegistration importRegistration, - ExportRegistration exportRegistration, Throwable exception) { - this.type = type; - this.source = source; - this.importRegistration = importRegistration; - this.exportRegistration = exportRegistration; - this.exception = exception; - } - - /** - * @return the importRegistration - */ - public ImportRegistration getImportRegistration() { - return importRegistration; - } - - /** - * @return the exportRegistration - */ - public ExportRegistration getExportRegistration() { - return exportRegistration; - } - - /** - * @return the exception - */ - public Throwable getException() { - return exception; - } - - /** - * @return the type - */ - public int getType() { - return type; - } - - /** - * @return the source - */ - public Bundle getSource() { - return source; - } -} diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteConstants.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteConstants.java index 6207554c98..e45a600347 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteConstants.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteConstants.java @@ -3,155 +3,153 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; /** * Provide the definition of the constants used in the Remote Services API. * + * TODO Should some of the properties in chapter 13 go the framework constants? */ public class RemoteConstants { - private RemoteConstants() { - } + private RemoteConstants() { + } - /** - * 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 - * {@link #SERVICE_EXPORTED_CONFIGS} or {@link #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 <code>String+</code> - * - * @see #SERVICE_EXPORTED_CONFIGS - * @see #SERVICE_IMPORTED_CONFIGS - */ - public final static String REMOTE_CONFIGS_SUPPORTED = "remote.configs.supported"; + /** + * 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 + * {@link #SERVICE_EXPORTED_CONFIGS} or {@link #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 <code>String+</code> + * + * @see #SERVICE_EXPORTED_CONFIGS + * @see #SERVICE_IMPORTED_CONFIGS + */ + public final static 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 <code>String+</code>. - * - * @see #SERVICE_INTENTS - * @see #SERVICE_EXPORTED_INTENTS - * @see #SERVICE_EXPORTED_INTENTS_EXTRA - */ - public final static String REMOTE_INTENTS_SUPPORTED = "remote.intents.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 <code>String+</code>. + * + * @see #SERVICE_INTENTS + * @see #SERVICE_EXPORTED_INTENTS + * @see #SERVICE_EXPORTED_INTENTS_EXTRA + */ + public final static String REMOTE_INTENTS_SUPPORTED = "remote.intents.supported"; - /** - * 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 ('*' \u002A) 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+. - */ - public final static String SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces"; + /** + * 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 ('*' \u002A) 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+. + */ + public final static String SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces"; - /** - * 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 <code>String+</code>. - */ - public final static String SERVICE_EXPORTED_INTENTS = "service.exported.intents"; + /** + * 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 <code>String+</code>. + */ + public final static String SERVICE_EXPORTED_INTENTS = "service.exported.intents"; - /** - * Extra intents configured in addition to the the intents specified in - * {@link #SERVICE_EXPORTED_INTENTS}. - * - * These intents are merged with the service.exported.intents and therefore - * have the same semantics. They are extra, so that the - * {@link #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 <code>String+</code>. - */ - public final static String SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra"; + /** + * Extra intents configured in addition to the the intents specified in + * {@link #SERVICE_EXPORTED_INTENTS}. + * + * These intents are merged with the service.exported.intents and therefore + * have the same semantics. They are extra, so that the + * {@link #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 <code>String+</code>. + */ + public final static String SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra"; - /** - * A list of configuration types that should be used to export the service. - * - * Configuration types can be <em>synonymous</em> or <em>alternatives</em>. - * 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 <code>String+</code>. - */ - public final static String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; + /** + * A list of configuration types that should be used to export the service. + * + * Configuration types can be <em>synonymous</em> or <em>alternatives</em>. + * 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 <code>String+</code>. + */ + public final static String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; - /** - * Must be set by a distribution provider to <code>true</code> 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. - */ - public final static String SERVICE_IMPORTED = "service.imported"; + /** + * Must be set by a distribution provider to <code>true</code> 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. + */ + public final static String SERVICE_IMPORTED = "service.imported"; - /** - * The configuration type used to import this services, as described in - * {@link #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 <code>String+</code>. - */ - public final String SERVICE_IMPORTED_CONFIGS = "service.imported.configs"; + /** + * The configuration type used to import this services, as described in + * {@link #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 <code>String+</code>. + */ + public final String SERVICE_IMPORTED_CONFIGS = "service.imported.configs"; - /** - * 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 <code>String+</code>. - */ - public final static String SERVICE_INTENTS = "service.intents"; + /** + * 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 <code>String+</code>. + */ + public final static String SERVICE_INTENTS = "service.intents"; + /** + * The property key for the endpoint URI. This is a unique id for an + * endpoint following the URI syntax. As far as this specification is + * concerned, this unique id is opaque. + */ + final public static String SERVICE_REMOTE_URI = "service.remote.uri"; - /** - * The property key for the endpoint URI. This is a unique id for an - * endpoint following the URI syntax. As far as this specification is - * concerned, this unique id is opaque. - */ - final public static String ENDPOINT_URI = "endpoint.uri"; + /** + * The property key for the endpoint service id. This is a unique id for a + * service based on the framework id '.' service id or another model. As far as this specification is + * concerned, this unique id is opaque. + */ + final public static String SERVICE_REMOTE_ID = "service.remote.id"; - /** - * The property key for the endpoint service id. This is a unique id for a - * service based on the framework id '.' service id or another model. As far as this specification is - * concerned, this unique id is opaque. - */ - final public static String ENDPOINT_REMOTE_SERVICE_ID = "endpoint.remote.service.id"; - - /** - * The key for a framework property that defines the UUID of the framework. - * - * The property must be set by the framework or through configuration before - * the VM is started or some bundle. The value must be a Universally Unique - * Id, it must not contain any dots ('.' \u002E). - */ - public final static String FRAMEWORK_UUID = "org.osgi.framework.uuid"; + /** + * The property key for the endpoint service id. This is a unique id for a + * service based on the framework id '.' service id or another model. As far as this specification is + * concerned, this unique id is opaque. + */ + final public static String SERVICE_REMOTE_FRAMEWORK_UUID = "service.remote.framework.id"; } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdmin.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdmin.java index 450f205d04..627780b46f 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdmin.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdmin.java @@ -10,85 +10,101 @@ import org.osgi.framework.ServiceReference; * A Remote Service Admin manages the import and export of services. * * A Distribution Provider can expose a control interface. This interface allows - * the a remote controller to control the export and import of services. + * the a remote manager to control the export and import of services. + * + * The API allows a remote manager to export a service, to import a service, and + * find out about the current imports and exports. + * * - * The API allows a remote controller to export a service, to import a service, - * and find out about the current imports and exports. * * @ThreadSafe */ public interface RemoteServiceAdmin { - /** - * Export a service to an endpoint. The Remote Service Admin must create an - * endpoint that can be used by other Distrbution Providers to connect to - * this Remote Service Admin and use the exported service. This method can - * return null if the service could not be exported. ### do we need - * exceptions? - * - * @param ref - * The Service Reference to export - * @return An Export Registration that combines the Endpoint Description and - * the Service Reference or - * <code>null</code> if the service could not be exported - * @throws IllegalArgumentException - * @throws UnsupportedOperationException - */ - List/*<ExportRegistration>*/ exportService(ServiceReference ref) throws IllegalArgumentException, UnsupportedOperationException; - - /** - * Export a service to a given endpoint. The Remote Service Admin must - * create an endpoint from the given description that can be used by other - * Distrbution Providers to connect to this Remote Service Admin and use the - * exported service. This method can return null if the service could not be - * exported because the endpoint could not be implemented by this Remote - * Service Admin. ### do we need exceptions? - * - * @param ref - * The Service Reference to export - * @param properties - * The properties to create a local endpoint that can be implemented by - * this Remote Service Admin. If this is null, the endpoint will - * be determined by the properties on the service, see - * {@link #exportService(ServiceReference)}. The properties are - * the same as given for an exported service. They are overlaid - * over any properties the service defines. - * @return An Export Registration that combines the Endpoint Description and - * the Service Reference or - * <code>null</code> if the service could not be exported - * @throws IllegalArgumentException - * @throws UnsupportedOperationException - */ - List/*<ExportRegistration>*/ exportService(ServiceReference ref, - Map/*<String,Object>*/ properties) throws IllegalArgumentException, UnsupportedOperationException; - + /** + * Export a service to a given endpoint. The Remote Service Admin must + * create an endpoint from the given description that can be used by other + * Distrbution Providers to connect to this Remote Service Admin and use the + * exported service. This method can return null if the service could not be + * exported because the endpoint could not be implemented by this Remote + * Service Admin. + * + * The properties on a Service Reference are case insensitive while the + * properties on a <code>properties</code> are case sensitive. A value in + * the <code>properties</code> must therefore override any case variant in + * the properties of the Service Reference. + * + * If an endpoint can not be created because no + * {@link EndpointPermission#EXPORT} can be obtained to export this service, + * then this endpoint must be ignored and no Export Registration must be + * included in the returned list. + * + * @param ref The Service Reference to export + * @param properties The properties to create a local endpoint that can be + * implemented by this Remote Service Admin. If this is null, the + * endpoint will be determined by the properties on the service. The + * properties are the same as given for an exported service. They are + * overlaid over any properties the service defines (case + * insensitive). This parameter can be <code>null</code>, this + * should be treated as an empty map. + * @return An Export Registration that combines the Endpoint Description and + * the Service Reference or <code>null</code> if the service could + * not be exported + * @throws IllegalArgumentException + * @throws UnsupportedOperationException + * + * TODO discuss case difference in properties + * + * TODO More exceptions? + * TODO Can you export ANY service by providing the proper properties? + */ + List/* <ExportRegistration> */exportService(ServiceReference ref, Map/* <String,Object> */properties) + throws IllegalArgumentException, UnsupportedOperationException; - /** - * Import a service from an endpoint. The Remote Service Admin must use the - * given endpoint to create a proxy. This method can return null if the - * service could not be imported. ### do we need exceptions? - * - * @param endpoint - * The Endpoint Description to be used for import - * @return An Import Registration that combines the Endpoint Description and - * the Service Reference or - * <code>null</code> if the endpoint could not be imported - */ - ImportRegistration importService(EndpointDescription endpoint); + /** + * Import a service from an endpoint. The Remote Service Admin must use the + * given endpoint to create a proxy. This method can return null if the + * service could not be imported. + * + * TODO if the import reg. is valid (getException==null), can we then assume the + * service is registered? + * + * If an endpoint can not be imported because no + * {@link EndpointPermission#IMPORT} can be obtained, then this endpoint + * must be ignored and no Import Registration must included in the returned + * list. + * + * @param endpoint The Endpoint Description to be used for import + * @return An Import Registration that combines the Endpoint Description and + * the Service Reference or <code>null</code> if the endpoint + * could not be imported + */ + ImportRegistration importService(EndpointDescription endpoint); - - /** - * Answer the currently active Export Registrations. - * - * @return A collection of Export Registrations that are currently active. - */ - Collection/*<? extends ExportRegistration>*/ getExportedServices(); + /** + * Answer the currently active Export Registrations. + * + * @return A collection of Export Registrations that are currently active. + * @throws SecurityException When the caller no + * {@link EndpointPermission#READ} could be obtained + * + * TODO I guess we must ensure these registrations cannot be closed? Only the owners should be able to close them, + * TODO should we make sure that the list contains the registration objects that the caller created? + */ + Collection/* <ExportRegistration> */getExportedServices(); - /** - * Answer the currently active Import Registrations. - * - * @return A collection of Import Registrations that are currently active. - */ - Collection/*<? extends ImportRegistration>*/ getImportedEndpoints(); + /** + * Answer the currently active Import Registrations. + * + * @throws SecurityException When the caller no EndpointPermission LIST + * could be obtained + * @return A collection of Import Registrations that are currently active. + * @throws SecurityException When the caller no + * {@link EndpointPermission#READ} could be obtained + * + * TODO I guess we must ensure these registrations cannot be closed? Only the owners should be able to close them, + * TODO should we make sure that the list contains the registration objects that the caller created? + */ + Collection/* <ImportRegistration> */getImportedEndpoints(); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdminEvent.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdminEvent.java new file mode 100644 index 0000000000..ad2e0c4057 --- /dev/null +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdminEvent.java @@ -0,0 +1,149 @@ +package org.apache.tuscany.sca.osgi.service.remoteadmin; + +import org.osgi.framework.Bundle; + +/** + * + * Provides the event information for a Remote Admin event. + * + * @Immutable + */ +public class RemoteServiceAdminEvent { + /** + * Add an import registration. The Remote Services Admin will call this + * method when it imports a service. When this service is registered, the + * Remote Service Admin must notify the listener of all existing Import + * Registrations. + * + */ + public static final int IMPORT_REGISTRATION = 1; + + /** + * Add an export registration. The Remote Services Admin will call this + * method when it exports a service. When this service is registered, the + * Remote Service Admin must notify the listener of all existing Export + * Registrations. + */ + public static final int EXPORT_REGISTRATION = 2; + + /** + * Remove an export registration. The Remote Services Admin will call this + * method when it removes the export of a service. + * + */ + public static final int EXPORT_UNREGISTRATION = 3; + + /** + * Remove an import registration. The Remote Services Admin will call this + * method when it removes the import of a service. + * + */ + public static final int IMPORT_UNREGISTRATION = 4; + + /** + * A fatal importing error occurred. The Import Registration has been + * closed. + */ + public static final int IMPORT_ERROR = 5; + + /** + * A fatal exporting error occurred. The Export Registration has been + * closed. + */ + public static final int EXPORT_ERROR = 6; + + /** + * A problematic situation occurred, the export is still active. + */ + public static final int EXPORT_WARNING = 7; + /** + * A problematic situation occurred, the import is still active. + */ + public static final int IMPORT_WARNING = 8; + + private final ImportRegistration importRegistration; + private final ExportRegistration exportRegistration; + private final Throwable exception; + private final int type; + private final Bundle source; + + /** + * Private constructor. + * + * @param type The event type + * @param source The source bundle, must not be <code>null</code>. + * @param importRegistration The importRegistration, can be <code>null</code>. + * @param exportRegistration The exportRegistration, can be <code>null</code>. + * @param exception Any exceptions encountered, can be <code>null</code> + */ + RemoteServiceAdminEvent(int type, + Bundle source, + ImportRegistration importRegistration, + ExportRegistration exportRegistration, + Throwable exception) { + this.type = type; + this.source = source; + this.importRegistration = importRegistration; + this.exportRegistration = exportRegistration; + this.exception = exception; + } + + /** + * Create a Remote Service Admin Event for an export issue. + * + * @param type The event type + * @param source The source bundle, must not be <code>null</code>. + * @param exportRegistration The exportRegistration, can not be <code>null</code>. + * @param exception Any exceptions encountered, can be <code>null</code> + */ + public RemoteServiceAdminEvent(int type, Bundle source, ExportRegistration exportRegistration, Throwable exception) { + this(type, source, null, exportRegistration, exception); + } + + /** + * Create a Remote Service Admin Event for an import issue. + * + * @param type The event type + * @param source The source bundle, must not be <code>null</code>. + * @param importRegistration The importRegistration, can not be <code>null</code>. + * @param exception Any exceptions encountered, can be <code>null</code> + */ + public RemoteServiceAdminEvent(int type, Bundle source, ImportRegistration importRegistration, Throwable exception) { + this(type, source, importRegistration, null, exception); + } + + /** + * @return the importRegistration or <code>null</code> + */ + public ImportRegistration getImportRegistration() { + return importRegistration; + } + + /** + * @return the exportRegistration or <code>null</code> + */ + public ExportRegistration getExportRegistration() { + return exportRegistration; + } + + /** + * @return the exception or <code>null</code> + */ + public Throwable getException() { + return exception; + } + + /** + * @return the type + */ + public int getType() { + return type; + } + + /** + * @return the source + */ + public Bundle getSource() { + return source; + } +} diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteAdminListener.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdminListener.java index 7aa5ae0abe..f653c323c0 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteAdminListener.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/RemoteServiceAdminListener.java @@ -7,9 +7,10 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin; * @ThreadSafe */ -public interface RemoteAdminListener { - /** - * @param event - */ - void remoteAdminEvent( RemoteAdminEvent event); +public interface RemoteServiceAdminListener { + /** + * Receive a Remote Service Admin event. + * @param event + */ + void remoteAdminEvent(RemoteServiceAdminEvent event); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointHelper.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointHelper.java index e847680fda..a372b62a6c 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointHelper.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointHelper.java @@ -19,6 +19,7 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin.impl; +import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -30,17 +31,20 @@ import org.apache.tuscany.sca.interfacedef.Interface; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription; import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteConstants; +import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; /** * Implementation of {@link EndpointDescription} */ public class EndpointHelper { + private static final String FRAMEWORK_UUID = UUID.randomUUID().toString(); + private EndpointHelper() { } - public static EndpointDescription createEndpointDescription(Endpoint endpoint) { - return new EndpointDescription(getProperties(endpoint)); + public static EndpointDescription createEndpointDescription(BundleContext bundleContext, Endpoint endpoint) { + return new EndpointDescription(getProperties(bundleContext, endpoint)); } private static List<String> getInterfaces(Endpoint endpoint) { @@ -49,17 +53,32 @@ public class EndpointHelper { return Collections.singletonList(javaInterface.getName()); } - private static Map<String, Object> getProperties(Endpoint endpoint) { + private static Map<String, Object> getProperties(BundleContext bundleContext, Endpoint endpoint) { Map<String, Object> props = new HashMap<String, Object>(); - props.put(RemoteConstants.ENDPOINT_URI, endpoint.getURI()); - props.put(RemoteConstants.ENDPOINT_REMOTE_SERVICE_ID, UUID.randomUUID().toString()); - props.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, new String[] {"sca"}); + + String uuid = getFrameworkUUID(bundleContext); + + props.put(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID, uuid); + props.put(RemoteConstants.SERVICE_REMOTE_URI, endpoint.getURI()); + props.put(RemoteConstants.SERVICE_REMOTE_ID, String.valueOf(System.currentTimeMillis())); + props.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, new String[] {"org.osgi.sca"}); props.put(Endpoint.class.getName(), endpoint); List<String> interfaces = getInterfaces(endpoint); props.put(Constants.OBJECTCLASS, interfaces.toArray(new String[interfaces.size()])); return props; } + public static String getFrameworkUUID(BundleContext bundleContext) { + String uuid = null; + if (bundleContext != null) { + URL url = bundleContext.getBundle(0).getEntry("/"); // bundleentry://0.fwk24942249/ + uuid = url.getHost(); + } else { + uuid = FRAMEWORK_UUID; + } + return uuid; + } + public static Endpoint getEndpoint(EndpointDescription endpointDescription) { return (Endpoint)endpointDescription.getProperties().get(Endpoint.class.getName()); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointIntrospector.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointIntrospector.java index 289c0e22f2..6ce012ba2a 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointIntrospector.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/EndpointIntrospector.java @@ -60,6 +60,7 @@ import org.apache.tuscany.sca.contribution.Contribution; import org.apache.tuscany.sca.contribution.ContributionFactory; import org.apache.tuscany.sca.contribution.processor.ContributionReadException; import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver; @@ -76,7 +77,6 @@ import org.apache.tuscany.sca.implementation.osgi.ServiceDescriptionsFactory; 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.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.monitor.MonitorFactory; import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription; import org.apache.tuscany.sca.policy.Intent; @@ -102,7 +102,6 @@ public class EndpointIntrospector { private XMLOutputFactory xmlOutputFactory; private JavaInterfaceFactory javaInterfaceFactory; private StAXArtifactProcessor processor; - private Monitor monitor; /** * @param intentName @@ -145,10 +144,7 @@ public class EndpointIntrospector { registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); UtilityExtensionPoint utilities = this.registry.getExtensionPoint(UtilityExtensionPoint.class); MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class); - if (monitorFactory != null) { - monitor = monitorFactory.createMonitor(); - } - processor = new ExtensibleStAXArtifactProcessor(processors, xmlInputFactory, xmlOutputFactory, monitor); + processor = new ExtensibleStAXArtifactProcessor(processors, xmlInputFactory, xmlOutputFactory); } private Intent getIntent(String intent) { @@ -285,7 +281,7 @@ public class EndpointIntrospector { contribution.setURI("urn:" + id); contribution.setLocation(bundle.getEntry("/").toString()); contribution.getDeployables().add(composite); - ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories, monitor); + ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories); contribution.setModelResolver(modelResolver); contribution.setUnresolved(true); return contribution; @@ -361,7 +357,7 @@ public class EndpointIntrospector { contribution.setURI("urn:" + id); contribution.setLocation(bundle.getEntry("/").toString()); contribution.getDeployables().add(composite); - ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories, monitor); + ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories); contribution.setModelResolver(modelResolver); contribution.setUnresolved(true); return contribution; @@ -409,7 +405,7 @@ public class EndpointIntrospector { contribution.setURI("urn:" + id); contribution.setLocation(bundle.getEntry("/").toString()); contribution.getDeployables().add(composite); - ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories, monitor); + ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories); contribution.setModelResolver(modelResolver); contribution.setUnresolved(true); return contribution; @@ -436,7 +432,7 @@ public class EndpointIntrospector { try { XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(is); reader.nextTag(); - Object model = processor.read(reader); + Object model = processor.read(reader, new ProcessorContext(registry)); if (model instanceof BindingDescriptions) { return ((BindingDescriptions)model); } else { diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/OSGiServiceExporter.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/OSGiServiceExporter.java index b2260de34d..bfe024e746 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/OSGiServiceExporter.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/OSGiServiceExporter.java @@ -95,7 +95,7 @@ public class OSGiServiceExporter implements ServiceTrackerCustomizer, LifeCycleL Component component = contribution.getDeployables().get(0).getComponents().get(0); ComponentService service = component.getServices().get(0); for (Endpoint endpoint : service.getEndpoints()) { - EndpointDescription endpointDescription = createEndpointDescription(endpoint); + EndpointDescription endpointDescription = createEndpointDescription(context, endpoint); ExportRegistration exportRegistration = new ExportRegistrationImpl(node, reference, endpointDescription); exportedServices.add(exportRegistration); diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteControllerImpl.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteControllerImpl.java index 3c4e0747f9..bc1cf86055 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteControllerImpl.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteControllerImpl.java @@ -20,14 +20,6 @@ package org.apache.tuscany.sca.osgi.service.remoteadmin.impl; import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTERFACES; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.EXPORT_ERROR; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.EXPORT_REGISTRATION; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.EXPORT_UNREGISTRATION; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.EXPORT_WARNING; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.IMPORT_ERROR; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.IMPORT_REGISTRATION; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.IMPORT_UNREGISTRATION; -import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent.IMPORT_WARNING; import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS; import static org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteConstants.SERVICE_IMPORTED; @@ -49,9 +41,9 @@ import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription; import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointListener; import org.apache.tuscany.sca.osgi.service.remoteadmin.ExportRegistration; import org.apache.tuscany.sca.osgi.service.remoteadmin.ImportRegistration; -import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent; -import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminListener; import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteServiceAdmin; +import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteServiceAdminEvent; +import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteServiceAdminListener; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -66,7 +58,7 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer; /** * Implementation of Remote Controller */ -public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, EndpointListener, +public class RemoteControllerImpl implements ListenerHook, RemoteServiceAdminListener, EndpointListener, ServiceTrackerCustomizer, LifeCycleListener /*, EventHook */{ private final static Logger logger = Logger.getLogger(RemoteControllerImpl.class.getName()); public final static String ENDPOINT_LOCAL = "service.local"; @@ -100,7 +92,7 @@ public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, + SERVICE_EXPORTED_INTERFACES + "=*) (" + SERVICE_EXPORTED_CONFIGS - + "=sca) )"; + + "=org.osgi.sca) )"; try { remotableServiceFilter = context.createFilter(filter); } catch (InvalidSyntaxException e) { @@ -112,7 +104,7 @@ public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, remoteAdmins.open(); // DO NOT register EventHook.class.getName() as it cannot report existing services - String interfaceNames[] = new String[] {ListenerHook.class.getName(), RemoteAdminListener.class.getName()}; + String interfaceNames[] = new String[] {ListenerHook.class.getName(), RemoteServiceAdminListener.class.getName()}; // The registration will trigger the added() method before registration is assigned registration = context.registerService(interfaceNames, this, null); @@ -185,7 +177,7 @@ public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, } else { for (Object ra : admins) { RemoteServiceAdmin remoteAdmin = (RemoteServiceAdmin)ra; - List<ExportRegistration> exportRegistrations = remoteAdmin.exportService(reference); + List<ExportRegistration> exportRegistrations = remoteAdmin.exportService(reference, null); if (exportRegistrations != null && !exportRegistrations.isEmpty()) { exportedServices.putValues(reference, exportRegistrations); } @@ -304,17 +296,17 @@ public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, /** * @see org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminListener#remoteAdminEvent(org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminEvent) */ - public void remoteAdminEvent(RemoteAdminEvent event) { + public void remoteAdminEvent(RemoteServiceAdminEvent event) { switch (event.getType()) { - case EXPORT_ERROR: - case EXPORT_REGISTRATION: - case EXPORT_UNREGISTRATION: - case EXPORT_WARNING: + case RemoteServiceAdminEvent.EXPORT_ERROR: + case RemoteServiceAdminEvent.EXPORT_REGISTRATION: + case RemoteServiceAdminEvent.EXPORT_UNREGISTRATION: + case RemoteServiceAdminEvent.EXPORT_WARNING: break; - case IMPORT_ERROR: - case IMPORT_REGISTRATION: - case IMPORT_UNREGISTRATION: - case IMPORT_WARNING: + case RemoteServiceAdminEvent.IMPORT_ERROR: + case RemoteServiceAdminEvent.IMPORT_REGISTRATION: + case RemoteServiceAdminEvent.IMPORT_UNREGISTRATION: + case RemoteServiceAdminEvent.IMPORT_WARNING: break; } } @@ -323,14 +315,14 @@ public class RemoteControllerImpl implements ListenerHook, RemoteAdminListener, * @see org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointListener#addEndpoint(org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription, * java.lang.String) */ - public void addEndpoint(EndpointDescription endpoint, String matchedFilter) { + public void endpointAdded(EndpointDescription endpoint, String matchedFilter) { importService(endpoint, matchedFilter); } /** * @see org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointListener#removeEndpoint(org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription) */ - public void removeEndpoint(EndpointDescription endpoint) { + public void endpointRemoved(EndpointDescription endpoint, String matchedFilter) { unimportService(endpoint); } diff --git a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteServiceAdminImpl.java b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteServiceAdminImpl.java index 1f2c03a5c6..4c92bab569 100644 --- a/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteServiceAdminImpl.java +++ b/java/sca/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/remoteadmin/impl/RemoteServiceAdminImpl.java @@ -27,8 +27,8 @@ import java.util.Map; import org.apache.tuscany.sca.osgi.service.remoteadmin.EndpointDescription; import org.apache.tuscany.sca.osgi.service.remoteadmin.ExportRegistration; import org.apache.tuscany.sca.osgi.service.remoteadmin.ImportRegistration; -import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteAdminListener; import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteServiceAdmin; +import org.apache.tuscany.sca.osgi.service.remoteadmin.RemoteServiceAdminListener; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -59,7 +59,7 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin { exporter.start(); importer.start(); registration = context.registerService(RemoteServiceAdmin.class.getName(), this, null); - listeners = new ServiceTracker(this.context, RemoteAdminListener.class.getName(), null); + listeners = new ServiceTracker(this.context, RemoteServiceAdminListener.class.getName(), null); listeners.open(); } diff --git a/java/sca/modules/node-impl-osgi/src/test/resources/calculator/dosgi/OSGI-INF/remote-service/calculator-service-descriptions.xml b/java/sca/modules/node-impl-osgi/src/test/resources/calculator/dosgi/OSGI-INF/remote-service/calculator-service-descriptions.xml index da76d00024..0dc812c503 100644 --- a/java/sca/modules/node-impl-osgi/src/test/resources/calculator/dosgi/OSGI-INF/remote-service/calculator-service-descriptions.xml +++ b/java/sca/modules/node-impl-osgi/src/test/resources/calculator/dosgi/OSGI-INF/remote-service/calculator-service-descriptions.xml @@ -23,7 +23,7 @@ <service-description> <provide interface="calculator.dosgi.operations.AddService" /> <property name="service.intents">sca:SOAP sca:HTTP</property> - <property name="osgi.remote.configuration.type">sca</property> + <property name="osgi.remote.configuration.type">org.osgi.sca</property> <property name="osgi.remote.configuration.sca.componentType"> OSGI-INF/sca/bundle.componentType </property> @@ -34,7 +34,7 @@ <service-description> <provide interface="calculator.dosgi.operations.SubtractService" /> <property name="service.intents">sca:SOAP sca:HTTP</property> - <property name="osgi.remote.configuration.type">sca</property> + <property name="osgi.remote.configuration.type">org.osgi.sca</property> <property name="osgi.remote.configuration.sca.componentType"> OSGI-INF/sca/bundle.componentType </property> @@ -45,7 +45,7 @@ <service-description> <provide interface="calculator.dosgi.operations.MultiplyService" /> <property name="service.intents">sca:SOAP sca:HTTP</property> - <property name="osgi.remote.configuration.type">sca</property> + <property name="osgi.remote.configuration.type">org.osgi.sca</property> <property name="osgi.remote.configuration.sca.componentType"> OSGI-INF/sca/bundle.componentType </property> @@ -56,7 +56,7 @@ <service-description> <provide interface="calculator.dosgi.operations.DivideService" /> <property name="service.intents">sca:SOAP sca:HTTP</property> - <property name="osgi.remote.configuration.type">sca</property> + <property name="osgi.remote.configuration.type">org.osgi.sca</property> <property name="osgi.remote.configuration.sca.componentType"> OSGI-INF/sca/bundle.componentType </property> |