diff options
author | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-09 18:00:24 +0000 |
---|---|---|
committer | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-09 18:00:24 +0000 |
commit | de3ec14e972052db72a3fd9589c898cf3ae0ae26 (patch) | |
tree | 12bc5ebe1034ca71a59e0faf1596f8b76cb5948b /sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service | |
parent | 9c79f7307e589f0e4921f7ec1505fd0bff3eb9f1 (diff) |
Update to the latest version of OSGi enterprise draft specs
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@897502 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service')
3 files changed, 300 insertions, 518 deletions
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java index 4bc3b34c7c..65f1000265 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved. + * Copyright (c) OSGi Alliance (2008, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,18 +42,21 @@ import org.osgi.framework.Version; * A description of an endpoint that provides sufficient information for a * compatible distribution provider to create a connection to this endpoint * - * An Endpoint Description is easy to transfer between different systems. This - * allows it to be used as a communications device to convey available endpoint - * information to nodes in a network. + * An Endpoint Description is easy to transfer between different systems because + * it is property based where the property keys are strings and the values are + * simple types. This allows it to be used as a communications device to convey + * available endpoint information to nodes in a network. * - * An Endpoint Description reflects the perspective of an importer. That is, the - * property keys have been chosen to match filters that are created by client - * bundles that need a service. Therefore the map must not contain any - * service.exported.* property and must contain the service.imported.* ones. + * An Endpoint Description reflects the perspective of an <i>importer</i>. That + * is, the property keys have been chosen to match filters that are created by + * client bundles that need a service. Therefore the map must not contain any + * <code>service.exported.*</code> property and must contain the corresponding + * <code>service.imported.*</code> ones. * - * The service.intents property contains the intents provided by the service - * itself combined with the intents added by the exporting distribution - * provider. Qualified intents appear expanded on this property. + * The <code>service.intents</code> property must contain the intents provided + * by the service itself combined with the intents added by the exporting + * distribution provider. Qualified intents appear fully expanded on this + * property. * * @Immutable * @version $Revision$ @@ -62,15 +65,17 @@ import org.osgi.framework.Version; public class EndpointDescription { private final Map<String, Object> properties; private final List<String> interfaces; - private final long remoteServiceId; + private final long remoteServiceID; private final String remoteFrameworkUUID; - private final String remoteUri; + private final String remoteID; /** - * Create an Endpoint Description based on a Map. + * Create an Endpoint Description from a Map. * * <p> - * The {@link RemoteConstants#ENDPOINT_URI} property must be set. + * The {@link RemoteConstants#ENDPOINT_ID endpoint.id}, + * {@link RemoteConstants#SERVICE_IMPORTED_CONFIGS service.imported.configs} + * and <code>objectClass</code> properties must be set. * * @param properties The map from which to create the Endpoint Description. * The keys in the map must be type <code>String</code> and, since @@ -94,28 +99,46 @@ public class EndpointDescription { } if (props.size() < properties.size()) { throw new IllegalArgumentException( - "duplicate keys with different cases in properties"); + "duplicate keys with different cases in properties: " + + new ArrayList<String>(props.keySet()) + .removeAll(properties.keySet())); } + if (!props.containsKey(SERVICE_IMPORTED)) { + props.put(SERVICE_IMPORTED, Boolean.toString(true)); + } this.properties = Collections.unmodifiableMap(props); /* properties must be initialized before calling the following methods */ interfaces = verifyObjectClassProperty(); - remoteServiceId = verifyLongProperty(ENDPOINT_ID); + remoteServiceID = verifyLongProperty(ENDPOINT_SERVICE_ID); remoteFrameworkUUID = verifyStringProperty(ENDPOINT_FRAMEWORK_UUID); - remoteUri = verifyStringProperty(ENDPOINT_URI); - if (remoteUri == null) { - throw new IllegalArgumentException(ENDPOINT_URI + remoteID = verifyStringProperty(ENDPOINT_ID); + if (remoteID == null) { + throw new IllegalArgumentException(ENDPOINT_ID + " property must be set"); } + if (getConfigurationTypes().isEmpty()) { + throw new IllegalArgumentException(SERVICE_IMPORTED_CONFIGS + + " property must be set and non-empty"); + } } /** - * Create an Endpoint Description based on a service reference and a map of + * Create an Endpoint Description based on a Service Reference and a Map of * properties. The properties in the map take precedence over the properties - * in the service reference. + * in the Service Reference. * * <p> - * The {@link RemoteConstants#ENDPOINT_URI} property must be set. + * This method will automatically set the + * {@link RemoteConstants#ENDPOINT_FRAMEWORK_UUID endpoint.framework.uuid} + * and {@link RemoteConstants#ENDPOINT_SERVICE_ID endpoint.service.id} + * properties based on the specified Service Reference as well as the + * {@link RemoteConstants#SERVICE_IMPORTED service.imported} property if + * they are not specified as properties. + * <p> + * The {@link RemoteConstants#ENDPOINT_ID endpoint.id}, + * {@link RemoteConstants#SERVICE_IMPORTED_CONFIGS service.imported.configs} + * and <code>objectClass</code> properties must be set. * * @param reference A service reference that can be exported. * @param properties Map of properties. This argument can be @@ -142,7 +165,9 @@ public class EndpointDescription { } if (props.size() < properties.size()) { throw new IllegalArgumentException( - "duplicate keys with different cases in properties"); + "duplicate keys with different cases in properties: " + + new ArrayList<String>(props.keySet()) + .removeAll(properties.keySet())); } } @@ -152,8 +177,8 @@ public class EndpointDescription { } } - if (!props.containsKey(ENDPOINT_ID)) { - props.put(ENDPOINT_ID, reference.getProperty(Constants.SERVICE_ID)); + if (!props.containsKey(ENDPOINT_SERVICE_ID)) { + props.put(ENDPOINT_SERVICE_ID, reference.getProperty(Constants.SERVICE_ID)); } if (!props.containsKey(ENDPOINT_FRAMEWORK_UUID)) { String uuid = null; @@ -173,36 +198,43 @@ public class EndpointDescription { props.put(ENDPOINT_FRAMEWORK_UUID, uuid); } } + if (!props.containsKey(SERVICE_IMPORTED)) { + props.put(SERVICE_IMPORTED, Boolean.toString(true)); + } this.properties = Collections.unmodifiableMap(props); /* properties must be initialized before calling the following methods */ interfaces = verifyObjectClassProperty(); - remoteServiceId = verifyLongProperty(ENDPOINT_ID); + remoteServiceID = verifyLongProperty(ENDPOINT_SERVICE_ID); remoteFrameworkUUID = verifyStringProperty(ENDPOINT_FRAMEWORK_UUID); - remoteUri = verifyStringProperty(ENDPOINT_URI); - if (remoteUri == null) { - throw new IllegalArgumentException(ENDPOINT_URI + remoteID = verifyStringProperty(ENDPOINT_ID); + if (remoteID == null) { + throw new IllegalArgumentException(ENDPOINT_ID + " property must be set"); } + if (getConfigurationTypes().isEmpty()) { + throw new IllegalArgumentException(SERVICE_IMPORTED_CONFIGS + + " property must be set and non-empty"); + } } /** * Verify and obtain the interface list from the properties. * * @return A list with the interface names. - * @throws IllegalArgumentException When the properties do not contain the - * right values for and interface list. - * + * @throws IllegalArgumentException If the objectClass property is not set + * or is empty or if the package version property values are + * malformed. */ private List<String> verifyObjectClassProperty() { Object o = properties.get(Constants.OBJECTCLASS); - if (o == null) { - return Collections.EMPTY_LIST; - } if (!(o instanceof String[])) { throw new IllegalArgumentException( "objectClass value must be of type String[]"); } String[] objectClass = (String[]) o; + if (objectClass.length < 1) { + throw new IllegalArgumentException("objectClass is empty"); + } for (String interf : objectClass) { int index = interf.lastIndexOf('.'); if (index == -1) { @@ -269,19 +301,19 @@ public class EndpointDescription { } /** - * Returns the endpoint's URI. + * Returns the endpoint's id. * - * The URI is an opaque id for an endpoint in URI form. No two different - * endpoints must have the same URI, two Endpoint Descriptions with the same - * URI must represent the same endpoint. + * The id is an opaque id for an endpoint. No two different endpoints must + * have the same id. Two Endpoint Descriptions with the same id must + * represent the same endpoint. * - * The value of the URI is stored in the - * {@link RemoteConstants#ENDPOINT_URI} property. + * The value of the id is stored in the + * {@link RemoteConstants#ENDPOINT_ID} property. * - * @return The URI of the endpoint, never <code>null</code>. + * @return The id of the endpoint, never <code>null</code>. */ - public String getRemoteURI() { - return remoteUri; + public String getRemoteID() { + return remoteID; } /** @@ -344,14 +376,14 @@ public class EndpointDescription { * id for a service. * * The value of the remote service id is stored in the - * {@link RemoteConstants#ENDPOINT_ID} endpoint property. + * {@link RemoteConstants#ENDPOINT_SERVICE_ID} endpoint property. * * @return Service id of a service or 0 if this Endpoint Description does - * not relate to an OSGi service + * not relate to an OSGi service. * */ public long getRemoteServiceID() { - return remoteServiceId; + return remoteServiceID; } /** @@ -426,7 +458,7 @@ public class EndpointDescription { List<String> result = new ArrayList<String>(values.size()); for (Iterator< ? > iter = values.iterator(); iter.hasNext();) { Object v = iter.next(); - if ((v != null) && (v instanceof String)) { + if (v instanceof String) { result.add((String) v); } } @@ -464,7 +496,7 @@ public class EndpointDescription { * 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. + * id 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 @@ -490,7 +522,7 @@ public class EndpointDescription { * @return An integer which is a hash code value for this object. */ public int hashCode() { - return getRemoteURI().hashCode(); + return getRemoteID().hashCode(); } /** @@ -498,7 +530,7 @@ public class EndpointDescription { * * <p> * An Endpoint Description is considered to be <b>equal to</b> another - * Endpoint Description if their URIs are equal. + * Endpoint Description if their ids are equal. * * @param other The <code>EndpointDescription</code> object to be compared. * @return <code>true</code> if <code>object</code> is a @@ -512,13 +544,13 @@ public class EndpointDescription { if (!(other instanceof EndpointDescription)) { return false; } - return getRemoteURI().equals( - ((EndpointDescription) other).getRemoteURI()); + return getRemoteID().equals( + ((EndpointDescription) other).getRemoteID()); } /** - * Tests the properties of this <code>EndpointDescription</code> against the - * given filter using a case insensitive match. + * Tests the properties of this <code>EndpointDescription</code> against + * the given filter using a case insensitive match. * * @param filter The filter to test. * @return <code>true</code> If the properties of this @@ -548,9 +580,10 @@ public class EndpointDescription { } /** - * Unmodifiable Dictionary wrapper for a Map. + * Unmodifiable Dictionary wrapper for a Map. This class is also used by + * EndpointPermission. */ - private static class UnmodifiableDictionary<K, V> extends Dictionary<K, V> { + static class UnmodifiableDictionary<K, V> extends Dictionary<K, V> { private final Map<K, V> wrapped; UnmodifiableDictionary(Map<K, V> wrapped) { @@ -584,5 +617,9 @@ public class EndpointDescription { public int size() { return wrapped.size(); } + + public String toString() { + return wrapped.toString(); + } } } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java index 0bfdcd334b..84a7ba512e 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2000, 2009). All Rights Reserved. + * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,13 @@ package org.osgi.service.remoteserviceadmin; -// TODO Hacked from ServiePermission +import static org.osgi.service.remoteserviceadmin.RemoteConstants.*; 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; @@ -32,205 +31,166 @@ 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 java.util.TreeMap; -import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; /** - * <pre> - * ------------------------------------------------------------- - * THIS CLASS IS A PLACEHOLDER (COPIED FROM SERVICE PERMISSION)! - * ------------------------------------------------------------- - * </pre> - * - * A bundle's authority to register or get a service. + * A bundle's authority to export, import or read an Endpoint. * <ul> - * <li>The <code>register</code> action allows a bundle to register a service on - * the specified names. - * <li>The <code>get</code> action allows a bundle to detect a service and get - * it. + * <li>The <code>export</code> action allows a bundle to export a service as an + * Endpoint.</li> + * <li>The <code>import</code> action allows a bundle to import a service from + * an Endpoint.</li> + * <li>The <code>read</code> action allows a bundle to read references to an + * Endpoint.</li> * </ul> - * Permission to get a service is required in order to detect events regarding - * the service. Untrusted bundles should not be able to detect the presence of - * certain services unless they have the appropriate - * <code>EndpointPermission</code> to get the specific service. + * Permission to read an Endpoint is required in order to detect events + * regarding an Endpoint. Untrusted bundles should not be able to detect the + * presence of certain Endpoints unless they have the appropriate + * <code>EndpointPermission</code> to read the specific service. * * @ThreadSafe * @version $Revision$ */ -public final class EndpointPermission extends BasicPermission { - static final long serialVersionUID = -7662148639076511574L; +public final class EndpointPermission extends Permission { + static final long serialVersionUID = -7662148639076511574L; /** - * The action string <code>export</code>. + * The action string <code>read</code>. */ - public final static String EXPORT = "export"; + public final static String READ = "read"; /** - * The action string <code>import</code>. + * The action string <code>import</code>. The <code>import</code> action + * implies the <code>read</code> action. */ - public final static String IMPORT = "import"; + public final static String IMPORT = "import"; /** - * The action string <code>read</code>. + * The action string <code>export</code>. The <code>export</code> action + * implies the <code>read</code> action. */ - public final static String READ = "read"; + public final static String EXPORT = "export"; - private final static int ACTION_EXPORT = 0x00000001; - private final static int ACTION_IMPORT = 0x00000002; - private final static int ACTION_READ = 0x00000004; - private final static int ACTION_ALL = ACTION_EXPORT - | ACTION_IMPORT - | ACTION_READ; - final static int ACTION_NONE = 0; + private final static int ACTION_READ = 0x00000001; + private final static int ACTION_IMPORT = 0x00000002; + private final static int ACTION_EXPORT = 0x00000004; + private final static int ACTION_ALL = ACTION_EXPORT + | ACTION_IMPORT + | ACTION_READ; + final static int ACTION_NONE = 0; /** * The actions mask. */ - transient int action_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; + private volatile String actions = null; /** - * If this EndpointPermission was constructed with a filter, this holds a - * Filter matching object used to evaluate the filter in implies. + * The endpoint used by this EndpointPermission. Must be null if not + * constructed with a endpoint. */ - transient Filter filter; - + transient final EndpointDescription endpoint; + /** * 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 ".*". + * filter in implies. */ - private transient boolean wildcard; + private transient final Dictionary<String, Object> properties; /** - * If constructed with a name and the name ends with ".*", this contains the - * name without the final "*". + * If this EndpointPermission was not constructed with an + * EndpointDescription, this holds a Filter matching object used to evaluate + * the filter in implies or null for wildcard. */ - private transient String prefix; + transient Filter filter; /** - * Create a new EndpointPermission. + * Create a new EndpointPermission with the specified filter. * * <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. + * The filter will be evaluated against the endpoint properties of a + * requested EndpointPermission. * * <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. + * There are three possible actions: <code>read</code>, <code>import</code> + * and <code>export</code>. The <code>read</code> action allows the owner of + * this permission to see the presence of distributed services. The + * <code>import</code> action allows the owner of this permission to import + * an endpoint. The <code>export</code> action allows the owner of this + * permission to export a service. * - * @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"); - } + * @param filterString The filter string or "*" to match all + * endpoints. + * @param actions The actions <code>read</code>, <code>import</code>, or + * <code>export</code>. + * @throws IllegalArgumentException If the filter has an invalid syntax or + * the actions are not valid. + */ + public EndpointPermission(String filterString, String actions) { + this(filterString, parseActions(actions)); } /** * 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. + * by code that must perform <code>checkPermission</code>. + * <code>EndpointPermission</code> objects created with this constructor + * cannot be added to an <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) { + * @param endpoint The requested endpoint. + * @param localFrameworkUUID The UUID of the local framework. This is used + * to support matching the + * {@link RemoteConstants#ENDPOINT_FRAMEWORK_UUID + * endpoint.framework.uuid} endpoint property to the + * <code><<LOCAL>></code> value in the filter expression. + * @param actions The actions <code>read</code>, <code>import</code>, or + * <code>export</code>. + * @throws IllegalArgumentException If the endpoint is <code>null</code> or + * the actions are not valid. + */ + public EndpointPermission(EndpointDescription endpoint, + String localFrameworkUUID, 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"); + Map<String, Object> props; + if ((localFrameworkUUID != null) + && localFrameworkUUID.equals(endpoint.getRemoteFrameworkUUID())) { + props = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER); + props.putAll(endpoint.getProperties()); + props.put(ENDPOINT_FRAMEWORK_UUID, new String[] { + endpoint.getRemoteFrameworkUUID(), "<<LOCAL>>"}); + } + else { + props = endpoint.getProperties(); } + this.endpoint = endpoint; + this.properties = new EndpointDescription.UnmodifiableDictionary<String, Object>( + props); } /** - * Create a permission name from a EndpointDescription TODO Needs work + * Create a permission name from a EndpointDescription. * * @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"); + throw new IllegalArgumentException("invalid endpoint: null"); } - StringBuffer sb = new StringBuffer("(service.id="); - // TODO sb.append(endpoint.getProperty(Constants.SERVICE_ID)); + StringBuffer sb = new StringBuffer("(" + ENDPOINT_ID + "="); + sb.append(endpoint.getRemoteID()); sb.append(")"); return sb.toString(); } @@ -245,7 +205,7 @@ public final class EndpointPermission extends BasicPermission { super(name); setTransients(parseFilter(name), mask); this.endpoint = null; - this.objectClass = null; + this.properties = null; } /** @@ -259,16 +219,6 @@ public final class EndpointPermission extends BasicPermission { } 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); - } - } } /** @@ -304,34 +254,45 @@ public final class EndpointPermission extends BasicPermission { // 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') + if (i >= 5 && (a[i - 5] == 'i' || a[i - 5] == 'I') + && (a[i - 4] == 'm' || a[i - 4] == 'M') + && (a[i - 3] == 'p' || a[i - 3] == 'P') + && (a[i - 2] == 'o' || a[i - 2] == 'O') + && (a[i - 1] == 'r' || a[i - 1] == 'R') && (a[i] == 't' || a[i] == 'T')) { - matchlen = 3; - mask |= ACTION_EXPORT; + matchlen = 6; + mask |= ACTION_IMPORT | ACTION_READ; } 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; + if (i >= 5 && (a[i - 5] == 'e' || a[i - 5] == 'E') + && (a[i - 4] == 'x' || a[i - 4] == 'X') + && (a[i - 3] == 'p' || a[i - 3] == 'P') + && (a[i - 2] == 'o' || a[i - 2] == 'O') + && (a[i - 1] == 'r' || a[i - 1] == 'R') + && (a[i] == 't' || a[i] == 'T')) { + matchlen = 6; + mask |= ACTION_EXPORT | ACTION_READ; } else { - // parse error - throw new IllegalArgumentException("invalid permission: " - + actions); + if (i >= 3 && (a[i - 3] == 'r' || a[i - 3] == 'R') + && (a[i - 2] == 'e' || a[i - 2] == 'E') + && (a[i - 1] == 'a' || a[i - 1] == 'A') + && (a[i] == 'd' || a[i] == 'D')) { + matchlen = 4; + mask |= ACTION_READ; + + } + 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. + // like "ackbarfread". Also, skip to the comma. seencomma = false; while (i >= matchlen && !seencomma) { switch (a[i - matchlen]) { @@ -366,16 +327,17 @@ public final class EndpointPermission extends BasicPermission { * 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. + * @return a Filter for this bundle. * @throws IllegalArgumentException If the filter syntax is invalid. */ private static Filter parseFilter(String filterString) { + if (filterString == null) { + throw new IllegalArgumentException("invalid filter: null"); + } filterString = filterString.trim(); - if (filterString.charAt(0) != '(') { - return null; + if (filterString.equals("*")) { + return null; // wildcard } - try { return FrameworkUtil.createFilter(filterString); } @@ -428,46 +390,19 @@ public final class EndpointPermission extends BasicPermission { if ((effective & desired) != desired) { return false; } - /* we have name of "*" */ - if (wildcard && (prefix == null)) { - return true; - } - /* if we have a filter */ + /* if we have no 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; - } - } + if (f == null) { + // it's "*" + return true; } - return false; + return f.matchCase(requested.getProperties()); } /** * Returns the canonical string representation of the actions. Always - * returns present actions in the following order: <code>get</code>, - * <code>register</code>. + * returns present actions in the following canonical order: + * <code>read</code>, <code>import</code>, <code>export</code>. * * @return The canonical string representation of the actions. */ @@ -478,8 +413,8 @@ public final class EndpointPermission extends BasicPermission { boolean comma = false; int mask = action_mask; - if ((mask & ACTION_EXPORT) == ACTION_EXPORT) { - sb.append(EXPORT); + if ((mask & ACTION_READ) == ACTION_READ) { + sb.append(READ); comma = true; } @@ -489,6 +424,12 @@ public final class EndpointPermission extends BasicPermission { sb.append(IMPORT); } + if ((mask & ACTION_EXPORT) == ACTION_EXPORT) { + if (comma) + sb.append(','); + sb.append(EXPORT); + } + actions = result = sb.toString(); } @@ -509,12 +450,12 @@ public final class EndpointPermission extends BasicPermission { /** * Determines the equality of two EndpointPermission objects. * - * Checks that specified object has the same class name and action as this - * <code>EndpointPermission</code>. + * Checks that specified object has the same name, actions and endpoint 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 + * same name, actions and endpoint as this * <code>EndpointPermission</code> object; <code>false</code> * otherwise. */ @@ -527,13 +468,13 @@ public final class EndpointPermission extends BasicPermission { return false; } - EndpointPermission sp = (EndpointPermission) obj; + EndpointPermission ep = (EndpointPermission) obj; - return (action_mask == sp.action_mask) - && getName().equals(sp.getName()) - && ((endpoint == sp.endpoint) || ((endpoint != null) - && (sp.endpoint != null) && endpoint - .equals(sp.endpoint))); + return (action_mask == ep.action_mask) + && getName().equals(ep.getName()) + && ((endpoint == ep.endpoint) || ((endpoint != null) + && (ep.endpoint != null) && endpoint + .equals(ep.endpoint))); } /** @@ -561,8 +502,9 @@ public final class EndpointPermission extends BasicPermission { } // Write out the actions. The superclass takes care of the name // call getActions to make sure actions field is initialized - if (actions == null) + if (actions == null) { getActions(); + } s.defaultWriteObject(); } @@ -582,109 +524,8 @@ public final class EndpointPermission extends BasicPermission { * * @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(); - } + private Dictionary<String, Object> getProperties() { + return properties; } } @@ -696,35 +537,28 @@ public final class EndpointPermission extends BasicPermission { * @see java.security.PermissionCollection */ final class EndpointPermissionCollection extends PermissionCollection { - static final long serialVersionUID = 662615640374640621L; + 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; + private Map<String, EndpointPermission> permissions; /** - * Table of permissions with filter expressions. + * Boolean saying if "*" is in the collection. * * @serial * @GuardedBy this */ - private Map filterPermissions; + private boolean all_allowed; /** * Creates an empty EndpointPermissions object. */ public EndpointPermissionCollection() { - permissions = new HashMap(); + permissions = new HashMap<String, EndpointPermission>(); all_allowed = false; } @@ -748,39 +582,29 @@ final class EndpointPermissionCollection extends PermissionCollection { + "readonly PermissionCollection"); } - final EndpointPermission sp = (EndpointPermission) permission; - if (sp.endpoint != null) { + final EndpointPermission ep = (EndpointPermission) permission; + if (ep.endpoint != null) { throw new IllegalArgumentException("cannot add to collection: " - + sp); + + ep); } - final String name = sp.getName(); - final Filter f = sp.filter; + final String name = ep.getName(); 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; - } + Map<String, EndpointPermission> pc = permissions; final EndpointPermission existing = (EndpointPermission) pc .get(name); if (existing != null) { final int oldMask = existing.action_mask; - final int newMask = sp.action_mask; + final int newMask = ep.action_mask; if (oldMask != newMask) { pc.put(name, new EndpointPermission(name, oldMask | newMask)); } } else { - pc.put(name, sp); + pc.put(name, ep); } if (!all_allowed) { @@ -808,50 +632,27 @@ final class EndpointPermissionCollection extends PermissionCollection { if (requested.filter != null) { return false; } - int effective = EndpointPermission.ACTION_NONE; - Collection perms; + Collection<EndpointPermission> 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; + EndpointPermission ep = permissions.get("*"); + if (ep != null) { + effective |= ep.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(); + perms = permissions.values(); } - /* iterate one by one over filteredPermissions */ - for (Iterator iter = perms.iterator(); iter.hasNext();) { - if (((EndpointPermission) iter.next()).implies0(requested, - effective)) { + /* iterate one by one over permissions */ + for (Iterator<EndpointPermission> iter = perms.iterator(); iter + .hasNext();) { + if (iter.next().implies0(requested, effective)) { return true; } } @@ -859,85 +660,34 @@ final class EndpointPermissionCollection extends PermissionCollection { } /** - * 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()); - } + public synchronized Enumeration<Permission> elements() { + List<Permission> all = new ArrayList<Permission>(permissions.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) }; + new ObjectStreamField("permissions", HashMap.class), + new ObjectStreamField("all_allowed", Boolean.TYPE) }; private synchronized void writeObject(ObjectOutputStream out) throws IOException { - Hashtable hashtable = new Hashtable(permissions); ObjectOutputStream.PutField pfields = out.putFields(); - pfields.put("permissions", hashtable); + pfields.put("permissions", permissions); 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); + permissions = (HashMap<String, EndpointPermission>) gfields.get( + "permissions", new HashMap<String, EndpointPermission>()); all_allowed = gfields.get("all_allowed", false); - filterPermissions = (HashMap) gfields.get("filterPermissions", null); } } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java index 93e6bb0c24..cf2194ec12 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2009). All Rights Reserved. + * Copyright (c) OSGi Alliance (2009, 2010). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,10 +30,9 @@ public class RemoteConstants { * Service property identifying the configuration types supported by a * distribution provider. Registered by the distribution provider on one of * its services to indicate the supported configuration types. - * * <p> * The value of this property must be of type <code>String</code>, - * <code>String[]</code>, or <code>Collection</code> of <code>String</code>. + * <code>String[]</code>, or <code>Collection<String></code>. */ public static final String REMOTE_CONFIGS_SUPPORTED = "remote.configs.supported"; @@ -44,7 +43,7 @@ public class RemoteConstants { * * <p> * The value of this property must be of type <code>String</code>, - * <code>String[]</code>, or <code>Collection</code> of <code>String</code>. + * <code>String[]</code>, or <code>Collection<String></code>. */ public static final String REMOTE_INTENTS_SUPPORTED = "remote.intents.supported"; @@ -59,7 +58,7 @@ public class RemoteConstants { * <code>Dictionary</code> object passed to the * <code>BundleContext.registerService</code> method. The value of this * property must be of type <code>String</code>, <code>String[]</code>, or - * <code>Collection</code> of <code>String</code>. + * <code>Collection<String></code>. */ public static final String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; @@ -75,7 +74,7 @@ public class RemoteConstants { * <code>Dictionary</code> object passed to the * <code>BundleContext.registerService</code> method. The value of this * property must be of type <code>String</code>, <code>String[]</code>, or - * <code>Collection</code> of <code>String</code>. + * <code>Collection<String></code>. */ public static final String SERVICE_EXPORTED_INTENTS = "service.exported.intents"; @@ -94,7 +93,7 @@ public class RemoteConstants { * <code>Dictionary</code> object passed to the * <code>BundleContext.registerService</code> method. The value of this * property must be of type <code>String</code>, <code>String[]</code>, or - * <code>Collection</code> of <code>String</code>. + * <code>Collection<String></code>. */ public static final String SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra"; @@ -113,7 +112,7 @@ public class RemoteConstants { * <code>Dictionary</code> object passed to the * <code>BundleContext.registerService</code> method. The value of this * property must be of type <code>String</code>, <code>String[]</code>, or - * <code>Collection</code> of <code>String</code>. + * <code>Collection<String></code>. */ public static final String SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces"; @@ -139,7 +138,7 @@ public class RemoteConstants { * * <p> * The value of this property must be of type <code>String</code>, - * <code>String[]</code>, or <code>Collection</code> of <code>String</code>. + * <code>String[]</code>, or <code>Collection<String></code>. * * @see #SERVICE_EXPORTED_CONFIGS */ @@ -153,34 +152,30 @@ public class RemoteConstants { * provider that these intents are already implemented by the exported * service object.</li> * <li>A distribution provider must use this property to convey the combined - * intents of:</li> - * <ul> - * <li>The exporting service, and</li> - * <li>the intents that the exporting distribution provider adds, and</li> - * <li>the intents that the importing distribution provider adds.</li> + * intents of: The exporting service, and, the intents that the exporting + * distribution provider adds, and the intents that the importing + * distribution provider adds.</li> * </ul> - * <i></i> - * - * </ul> To export a service, a distribution provider must expand any - * qualified intents. Both the exporting and importing distribution - * providers must recognize all intents before a service can be distributed. + * To export a service, a distribution provider must expand any qualified + * intents. Both the exporting and importing distribution providers must + * recognize all intents before a service can be distributed. * * <p> * The value of this property must be of type <code>String</code>, - * <code>String[]</code>, or <code>Collection</code> of <code>String</code>. + * <code>String[]</code>, or <code>Collection<String></code>. */ public static final String SERVICE_INTENTS = "service.intents"; /* above are from Ch 13 Remote Service spec. */ /** - * Endpoint property identifying the URI for this endpoint. This service + * Endpoint property identifying the id for this endpoint. This service * property must always be set. * * <p> * The value of this property must be of type <code>String</code>. */ - public final static String ENDPOINT_URI = "endpoint.uri"; + public final static String ENDPOINT_ID = "endpoint.id"; /** * Endpoint property identifying the service id of the exported service. Can @@ -189,7 +184,7 @@ public class RemoteConstants { * <p> * The value of this property must be of type <code>Long</code>. */ - public final static String ENDPOINT_ID = "endpoint.id"; + public final static String ENDPOINT_SERVICE_ID = "endpoint.service.id"; /** * Endpoint property identifying the universally unique id of the exporting |