From 56e4e96278a4421de5c4d1bd43ff0cf96f9fad03 Mon Sep 17 00:00:00 2001 From: rfeng Date: Tue, 1 Dec 2009 21:59:20 +0000 Subject: Update to the latest OSGi remoteserviceadmin apis git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@885958 13f79535-47bb-0310-9956-ffa450edef68 --- .../modules/node-impl-osgi/META-INF/MANIFEST.MF | 4 +- .../remoteserviceadmin/EndpointDescription.java | 472 ---------- .../osgi/remoteserviceadmin/EndpointListener.java | 127 --- .../remoteserviceadmin/EndpointPermission.java | 959 --------------------- .../osgi/remoteserviceadmin/ExportReference.java | 43 - .../remoteserviceadmin/ExportRegistration.java | 67 -- .../osgi/remoteserviceadmin/ImportReference.java | 42 - .../remoteserviceadmin/ImportRegistration.java | 65 -- .../osgi/remoteserviceadmin/RemoteConstants.java | 170 ---- .../remoteserviceadmin/RemoteServiceAdmin.java | 119 --- .../RemoteServiceAdminEvent.java | 166 ---- .../RemoteServiceAdminListener.java | 31 - .../remoteserviceadmin/impl/EndpointHelper.java | 10 +- .../impl/EndpointIntrospector.java | 2 +- .../impl/ExportReferenceImpl.java | 6 +- .../impl/ExportRegistrationImpl.java | 8 +- .../impl/ImportReferenceImpl.java | 6 +- .../impl/ImportRegistrationImpl.java | 10 +- .../impl/OSGiServiceExporter.java | 12 +- .../impl/OSGiServiceImporter.java | 6 +- .../impl/RemoteServiceAdminImpl.java | 62 +- .../impl/TopologyManagerImpl.java | 24 +- .../discovery/impl/AbstractDiscoveryService.java | 8 +- .../discovery/impl/DomainDiscoveryService.java | 2 +- .../discovery/impl/LocalDiscoveryService.java | 16 +- .../remoteserviceadmin/EndpointDescription.java | 540 ++++++++++++ .../remoteserviceadmin/EndpointListener.java | 126 +++ .../remoteserviceadmin/EndpointPermission.java | 943 ++++++++++++++++++++ .../remoteserviceadmin/ExportReference.java | 45 + .../remoteserviceadmin/ExportRegistration.java | 71 ++ .../remoteserviceadmin/ImportReference.java | 44 + .../remoteserviceadmin/ImportRegistration.java | 67 ++ .../remoteserviceadmin/RemoteConstants.java | 216 +++++ .../remoteserviceadmin/RemoteServiceAdmin.java | 129 +++ .../RemoteServiceAdminEvent.java | 178 ++++ .../RemoteServiceAdminListener.java | 44 + 36 files changed, 2496 insertions(+), 2344 deletions(-) delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointDescription.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointListener.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointPermission.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportReference.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportRegistration.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportReference.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportRegistration.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteConstants.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdmin.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminEvent.java delete mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminListener.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointListener.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportReference.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportRegistration.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportReference.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportRegistration.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdmin.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminEvent.java create mode 100644 sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminListener.java (limited to 'sca-java-2.x/trunk/modules') diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/META-INF/MANIFEST.MF b/sca-java-2.x/trunk/modules/node-impl-osgi/META-INF/MANIFEST.MF index c0e7f7dd2d..82b79149f8 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/META-INF/MANIFEST.MF +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/META-INF/MANIFEST.MF @@ -32,7 +32,6 @@ Import-Package: javax.xml.namespace, org.apache.tuscany.sca.node;version="2.0.0", org.apache.tuscany.sca.node.configuration;version="2.0.0", org.apache.tuscany.sca.node.impl;version="2.0.0", - org.apache.tuscany.sca.osgi.remoteserviceadmin;version="2.0.0", org.apache.tuscany.sca.policy;version="2.0.0", org.apache.tuscany.sca.provider;version="2.0.0", org.apache.tuscany.sca.runtime;version="2.0.0", @@ -45,9 +44,10 @@ Import-Package: javax.xml.namespace, org.osgi.service.component;version="1.1.0";resolution:=optional, org.osgi.service.event;version="1.2.0", org.osgi.service.packageadmin;version="1.2.0";resolution:=optional, + org.osgi.service.remoteserviceadmin;version="1.0.0", org.osgi.util.tracker;version="1.3.0";resolution:=optional Bundle-SymbolicName: org.apache.tuscany.sca.node.osgi.impl Bundle-DocURL: http://www.apache.org/ Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 Bundle-ActivationPolicy: lazy -Export-Package: org.apache.tuscany.sca.osgi.remoteserviceadmin;version="2.0.0" +Export-Package: org.osgi.service.remoteserviceadmin;version="1.0.0" diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointDescription.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointDescription.java deleted file mode 100644 index 9fda882738..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointDescription.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Dictionary; -import java.util.Enumeration; -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; -import org.osgi.framework.ServiceReference; -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 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. - * - * 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. - * - * @Immutable - * @version $Revision$ - */ - -public class EndpointDescription { - private final Map properties; - private final List interfaces; - private final long remoteServiceId; - private final String remoteFrameworkUUID; - private final String remoteUri; - - /** - * Create an Endpoint Description based on a Map. - * - * @param properties The map to create the Endpoint Description from. - * @throws IllegalArgumentException When the properties are not proper for - * an Endpoint Description - */ - - public EndpointDescription(Map properties) { - this(properties, null); - } - - /** - * Create an Endpoint Description based on a reference and optionally a map - * of additional properties. The properties on the original service take - * precedence over the ones in the map. - * - * @param reference A service reference that can be exported - * @param properties Additional properties to add. Can be null. - * @throws IllegalArgumentException When the properties are not proper for - * an Endpoint Description - */ - public EndpointDescription(ServiceReference reference, Map properties) { - this(properties, reference); - if (reference == null) { - throw new NullPointerException("reference must not be null"); - } - } - - private EndpointDescription(Map map, ServiceReference reference) { - Map props = new TreeMap(String.CASE_INSENSITIVE_ORDER); - - if (map != null) { - try { - props.putAll(map); - } catch (ClassCastException e) { - IllegalArgumentException iae = new IllegalArgumentException("non-String key in properties"); - iae.initCause(e); - throw iae; - } - if (props.size() < map.size()) { - throw new IllegalArgumentException("duplicate keys with different cases in properties"); - } - } - - if (reference != null) { - for (String key : reference.getPropertyKeys()) { - if (!props.containsKey(key)) { - props.put(key, reference.getProperty(key)); - } - } - } - - properties = Collections.unmodifiableMap(props); - /* properties must be initialized before calling the following methods */ - interfaces = verifyInterfacesProperty(); - remoteServiceId = verifyLongProperty(RemoteConstants.SERVICE_REMOTE_ID); - remoteFrameworkUUID = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID); - remoteUri = verifyStringProperty(RemoteConstants.SERVICE_REMOTE_URI); - } - - /** - * 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. - * - */ - private List verifyInterfacesProperty() { - Object o = properties.get(Constants.OBJECTCLASS); - if (o == null) { - return Collections.EMPTY_LIST; - } - if (!(o instanceof String[])) { - throw new IllegalArgumentException("objectClass must be a String[]"); - } - String[] objectClass = (String[])o; - for (String interf : objectClass) { - try { - getInterfaceVersion(interf); - } catch (IllegalArgumentException e) { - IllegalArgumentException iae = new IllegalArgumentException("Improper version for interface " + interf); - iae.initCause(e); - throw iae; - } - } - return Collections.unmodifiableList(Arrays.asList(objectClass)); - } - - /** - * 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. - */ - private long verifyLongProperty(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); - } - try { - return Long.parseLong((String)r); - } catch (NumberFormatException e) { - IllegalArgumentException iae = - new IllegalArgumentException("Required property cannot be parsed as a long: " + propName); - iae.initCause(e); - throw iae; - } - } - - /** - * Returns the endpoint's URI. - * - * 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 value of the URI is stored in the - * {@link RemoteConstants#SERVICE_REMOTE_URI} property. - * - * @return The URI of the endpoint, never null. - */ - public String getRemoteURI() { - return remoteUri; - } - - /** - * Provide the list of interfaces implemented by the exported service. - * - * If this Endpoint Description does not map to a service, then this List - * must be empty. - * - * The value of the interfaces is derived from the objectClass - * property. - * - * @return The read only list of Java interface names accessible by this - * endpoint. - */ - public List getInterfaces() { - return interfaces; - } - - /** - * Provide the version of the given interface. - * - * The version is encoded by prefixing the given interface name with - * endpoint.version., and then using this as a property key. - * For example: - * - *
-     * endpoint.version.com.acme.Foo
-     * 
- * - * The value of this property is in String format and will be converted to a - * Version object by this method. - * - * @param name The name of the interface for which a version is requested - * @return The version of the given interface or null if the - * interface has no version in this Endpoint Description - */ - public Version getInterfaceVersion(String name) { - String version = (String)properties.get("endpoint.version." + name); - return Version.parseVersion(version); - } - - /** - * Returns the service id for the service exported through this endpoint. - * - * 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. - * - * @return Service id of a service or 0 if this Endpoint Description does - * not relate to an OSGi service - * - */ - public long getRemoteServiceID() { - return remoteServiceId; - } - - /** - * Returns the configuration types. - * - * A distribution provider exports a service with an endpoint. This endpoint - * uses some kind of communications protocol with a set of configuration - * parameters. There are many different types but each endpoint is - * configured by only one configuration type. However, a distribution - * provider can be aware of different configuration types and provide - * synonyms to increase the change a receiving distribution provider can - * create a connection to this endpoint. - * - * This value represents the - * {@link RemoteConstants#SERVICE_IMPORTED_CONFIGS} - * - * @return An unmodifiable list of the configuration types used for the - * associated endpoint and optionally synonyms. - */ - public List getConfigurationTypes() { - return getStringPlusProperty(RemoteConstants.SERVICE_IMPORTED_CONFIGS); - } - - /** - * Return the list of intents implemented by this endpoint. - * - * The intents are based on the service.intents on an imported service, - * except for any intents that are additionally provided by the importing - * distribution provider. All qualified intents must have been expanded. - * - * The property the intents come from is - * {@link RemoteConstants#SERVICE_INTENTS} - * - * @return An unmodifiable list of expanded intents that are provided by - * this endpoint. - */ - public List getIntents() { - return getStringPlusProperty(RemoteConstants.SERVICE_INTENTS); - } - - /** - * Reads a 'String+' property from the properties map, which may be of type - * String, String[] or Collection and returns it as an unmodifiable - * List. - * - * @param key The property - * @return An unmodifiable list - * @throws Illegal - */ - private List getStringPlusProperty(String key) { - Object value = properties.get(key); - if (value == null) { - return Collections.EMPTY_LIST; - } - - if (value instanceof String) { - return Collections.singletonList((String)value); - } - - if (value instanceof String[]) { - String[] values = (String[])value; - List result = new ArrayList(values.length); - for (String v : values) { - if (v != null) { - result.add(v); - } - } - return result; - } - - if (value instanceof Collection) { - Collection values = (Collection)value; - List result = new ArrayList(values.size()); - for (Iterator iter = values.iterator(); iter.hasNext();) { - Object v = iter.next(); - if ((v != null) && (v instanceof String)) { - result.add((String)v); - } - } - return result; - } - - return Collections.EMPTY_LIST; - } - - /** - * Return the framework UUID for the remote service, if present. - * - * The property the framework UUID comes 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 unmodifiable map referring to the properties of this Endpoint - * Description. - */ - public Map getProperties() { - return properties; - } - - /** - * 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. - * - * @return The hashcode of this endpoint. - */ - public int hashCode() { - return getRemoteURI().hashCode(); - } - - /** - * Two endpoints are equal if their URIs are equal. - * - * @return - */ - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof EndpointDescription)) { - return false; - } - return getRemoteURI().equals(((EndpointDescription)other).getRemoteURI()); - } - - /** - * TODO - * - * @param filter - * @return - * @throws InvalidSyntaxException - */ - public boolean match(String filter) throws InvalidSyntaxException { - Filter f = FrameworkUtil.createFilter(filter); - Dictionary d = new UnmodifiableDictionary(properties); - return f.matchCase(d); - } - - /** - * Unmodifiable wrapper for Dictionary. - */ - private static class UnmodifiableDictionary extends Dictionary { - private final Map wrapped; - - UnmodifiableDictionary(Map wrapped) { - this.wrapped = wrapped; - } - - public Enumeration elements() { - return (Enumeration)Collections.enumeration(wrapped.values()); - } - - public V get(Object key) { - return wrapped.get(key); - } - - public boolean isEmpty() { - return wrapped.isEmpty(); - } - - public Enumeration keys() { - return (Enumeration)Collections.enumeration(wrapped.keySet()); - } - - public V put(K key, V value) { - throw new UnsupportedOperationException(); - } - - public V remove(Object key) { - throw new UnsupportedOperationException(); - } - - public int size() { - return wrapped.size(); - } - } -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointListener.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointListener.java deleted file mode 100644 index 316cac081b..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointListener.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -/** - * 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 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 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 - * protocol, then it sends an End Point Description to all the End Point - * Listener services that are registered (except its own) that have specified an - * interest in that endpoint. - * - * Endpoint Listener services can express their scope with the service - * property {@link #ENDPOINT_LISTENER_SCOPE}. This service property is a list - * of filters. An Endpoint Description should only be given to a Endpoint - * Listener when there is at least one filter that matches the Endpoint - * Description properties. given to it. - * - * This filter model is quite flexible. For example, a discovery bundle is only - * interested in locally originating Endpoint Descriptions. The following filter - * ensure that it only sees local endpoints. - * - *
- *   (org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72)
- * 
- * - * In the same vein, a manager that is only interested in remote Endpoint - * Descriptions can use a filter like: - * - *
- *   (!(org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72))
- * 
- * - * Where in both cases, the given UUID is the UUID of the local framework that - * can be found in the Framework properties. - * - * The Endpoint Listener's scope maps very well to the service hooks. A - * 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. - * - * In general, when an Endpoint Description is discovered, it should be - * dispatched to all registered Endpoint Listener services. If a new Endpoint - * Listener is registered, it should be informed about all currently known - * Endpoints that match its scope. If a getter of the Endpoint Listener service - * is unregistered, then all its registered Endpoint Description objects must be - * removed. - * - * The Endpoint Listener models a best effort approach. Participating - * bundles should do their utmost to keep the listeners up to date, but - * implementers should realize that many endpoints come through unreliable - * discovery processes. - * - * - * @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 String+. - */ - 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 matchedFilter 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 null. - */ - void endpointAdded(EndpointDescription endpoint, String matchedFilter); - - /** - * 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 null. - */ - void endpointRemoved(EndpointDescription endpoint, String matchedFilter); -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointPermission.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointPermission.java deleted file mode 100644 index 1e12547ab5..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/EndpointPermission.java +++ /dev/null @@ -1,959 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -// TODO Hacked from ServiePermission - -/* - * Copyright (c) OSGi Alliance (2000, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -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; - -/** - *
- * -------------------------------------------------------------
- * THIS CLASS IS A PLACEHOLDER (COPIED FROM SERVICE PERMISSION)!
- * -------------------------------------------------------------
- * 
- * - * A bundle's authority to register or get a service. - *
    - *
  • The register action allows a bundle to register a service - * on the specified names. - *
  • The get action allows a bundle to detect a service and - * get it. - *
- * 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 - * EndpointPermission to get the specific service. - * - * @ThreadSafe - * @version $Revision$ - */ - -public final class EndpointPermission extends BasicPermission { - static final long serialVersionUID = -7662148639076511574L; - /** - * The action string get. - */ - public final static String EXPORT = "export"; - /** - * The action string register. - */ - 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. - * - *

- * The name of the service is specified as a fully qualified class name. - * Wildcards may be used. - * - *

-     * name ::= <class name> | <class name ending in ".*"> | *
-     * 
- * - * Examples: - * - *
-     * org.osgi.service.http.HttpService
-     * org.osgi.service.http.*
-     * *
-     * 
- * - * For the get action, the name can also be a filter - * expression. The filter gives access to the service properties as well as - * the following attributes: - *
    - *
  • 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.
  • - *
  • location - The location of the bundle publishing the service.
  • - *
  • id - The bundle ID of the bundle publishing the service.
  • - *
  • name - The symbolic name of the bundle publishing the service.
  • - *
- * 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. - * - *

- * There are two possible actions: get and - * register. The get permission allows the - * owner of this permission to obtain a service with this name. The - * register permission allows the bundle to register a - * service under that name. - * - * @param name - * The service class name - * @param actions - * get,register (canonical order) - * @throws IllegalArgumentException - * If the specified name is a filter expression and either the - * specified action is not get 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 EndpointPermission object to be - * used by code that must perform checkPermission for the - * get action. EndpointPermission objects - * created with this constructor cannot be added to a - * EndpointPermission permission collection. - * - * @param endpoint - * The requested service. - * @param actions - * The action get. - * @throws IllegalArgumentException - * If the specified action is not get or - * reference is null. - * @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 null 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 EndpointPermission object "implies" the - * specified permission. - * - * @param p - * The target permission to check. - * @return true if the specified permission is implied by - * this object; false 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 true if the specified permission is implied by - * this object; false 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: get, - * register. - * - * @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 PermissionCollection object for storing - * EndpointPermission objects. - * - * @return A new PermissionCollection object suitable for storing - * EndpointPermission 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 - * EndpointPermission. - * - * @param obj - * The object to test for equality. - * @return true if obj is a EndpointPermission, and has the - * same class name and actions as this - * EndpointPermission object; false - * 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 <@link EndpointPermission#implies(Permission)>. - * - * @return a dictionary of properties for this permission. - */ - private Dictionary/**/getProperties() { - Dictionary/**/result = properties; - if (result != null) { - return result; - } - if (endpoint == null) { - result = new Hashtable/**/(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(); - } - } -} - -/** - * Stores a set of EndpointPermission permissions. - * - * @see java.security.Permission - * @see java.security.Permissions - * @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 EndpointPermissionCollection 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 - * permission. - * - * @param permission - * The Permission object to compare. - * @return true if permission is a proper - * subset of a permission in the set; false - * 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 EndpointPermission - * 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/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportReference.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportReference.java deleted file mode 100644 index dd6b71a021..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportReference.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -import org.osgi.framework.ServiceReference; - -/** - * An Export Reference associates a service with a local endpoint. - * - * The Export Reference can be used to reference an exported service. When the - * service is no longer exported, all methods must return null; - * - * @ThreadSafe - */ -public interface ExportReference { - /** - * Return the service being exported. - * - * @return The service being exported, must be null when this - * registration is unregistered. - */ - ServiceReference getExportedService(); - - /** - * Return the Endpoint Description that is created for this registration. - * - * @return the local Endpoint Description - */ - EndpointDescription getEndpointDescription(); -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportRegistration.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportRegistration.java deleted file mode 100644 index 231d742220..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ExportRegistration.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -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 RemoteServiceAdmin#exportService(ServiceReference,java.util.Map)} method. - * - * When this Export Registration has been unregistered, the methods must all - * return null. - * - * @ThreadSafe - */ -public interface ExportRegistration { - /** - * Return the Export Reference for the exported service. - * - * @return An Export Reference for this registration - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - ExportReference getExportReference() throws IllegalStateException; - - /** - * Delete the local endpoint and disconnect any remote distribution - * providers. After this method returns, all the methods must return - * null. - * - * 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 Throwable 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 - * null. - * - * 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 null if no exception occurred. - */ - Throwable getException(); -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportReference.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportReference.java deleted file mode 100644 index ead03edd58..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportReference.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -import org.osgi.framework.ServiceReference; - -/** - * An Import Reference associates an active proxy service to a remote endpoint. - * - * The Import Reference can be used to reference an imported service. When the - * service is no longer imported, all methods must return null; - * - * @ThreadSafe - */ -public interface ImportReference { - /** - * Answer the associated Service Reference for the proxy to the endpoint. - * - * @return A Service Reference to the proxy for the endpoint. - */ - ServiceReference getImportedService(); - - /** - * Answer the associated remote Endpoint Description. - * - * @return A Endpoint Description for the remote endpoint. - */ - EndpointDescription getImportedEndpointDescription(); -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportRegistration.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportRegistration.java deleted file mode 100644 index 28dcc213c9..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/ImportRegistration.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -/** - * 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 RemoteServiceAdmin#importService} - * method. - * - * @ThreadSafe - */ -public interface ImportRegistration { - /** - * Answer the associated Export Reference. - * - * @return An Import Reference for this registration - * @throws IllegalStateException Thrown when this object was not properly initialized, see {@link #getException()} - */ - ImportReference getImportedReference(); - - /** - * 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 Throwable 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 - * null. - * - * 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 null if no exception occurred. - */ - Throwable getException(); - -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteConstants.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteConstants.java deleted file mode 100644 index 63ce2ed042..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteConstants.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -/** - * 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() { - } - - /** - * 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 String+ - * - * @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 String+. - * - * @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"; - - /** - * A list of intents that the distribution provider must implement to - * distribute the service. Intents listed in this property are reserved for - * intents that are critical for the code to function correctly, for - * example, ordering of messages. These intents should not be configurable. - * - * The value of this property is of type String+. - */ - 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 String+. - */ - 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 synonymous or alternatives. - * In principle, a distribution provider should create an endpoint for each - * recognized configuration type, the deployer is responsible that synonyms - * do not clash. - * - * Each configuration type has an associated specification that describes - * how the configuration data for the exported service is represented in an - * OSGi framework. - * - * The value of this property is of type String+. - */ - public final static String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; - - /** - * Must be set by a distribution provider to true when it - * registers the end-point proxy as an imported service. Can be used by a - * bundle to prevent it from getting an imported service. - * - * The value of this property is not defined, setting it is sufficient. - */ - 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 String+. - */ - public final static 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 String+. - */ - 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. - */ - public final static String SERVICE_REMOTE_URI = "service.remote.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. - */ - public final 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. - */ - public final static String SERVICE_REMOTE_FRAMEWORK_UUID = "service.remote.framework.id"; -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdmin.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdmin.java deleted file mode 100644 index b79cfbe330..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdmin.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -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 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. - * - * - * - * @ThreadSafe - */ -public interface RemoteServiceAdmin { - - /** - * 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 properties are case sensitive. A value in - * the properties 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 null, this - * should be treated as an empty map. - * @return An Export Registration that combines the Endpoint Description and - * the Service Reference or null 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/* */exportService(ServiceReference ref, Map/* */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. - * - * 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 null if the endpoint - * could not be imported - */ - ImportRegistration importService(EndpointDescription endpoint); - - /** - * Answer the currently active Export References. - * - * @return A collection of Export Registrations that are currently active. - * @throws SecurityException When the caller no - * {@link EndpointPermission#READ} could be obtained - */ - Collection/* */getExportedServices(); - - /** - * Answer the currently active Import References. - * - * @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 - */ - Collection/* */getImportedEndpoints(); - -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminEvent.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminEvent.java deleted file mode 100644 index 71f914b085..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminEvent.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -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 ImportReference importReference; - private final ExportReference exportReference; - 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 null. - * @param importReference The importReference, can be null. - * @param exportReference The exportReference, can be null. - * @param exception Any exceptions encountered, can be null - */ - RemoteServiceAdminEvent(int type, - Bundle source, - ImportReference importReference, - ExportReference exportReference, - Throwable exception) { - this.type = type; - this.source = source; - this.importReference = importReference; - this.exportReference = exportReference; - 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 null. - * @param exportRegistration The exportRegistration, can not be - * null. - * @param exception Any exceptions encountered, can be null - */ - public RemoteServiceAdminEvent(int type, Bundle source, ExportReference 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 null. - * @param importRegistration The importRegistration, can not be - * null. - * @param exception Any exceptions encountered, can be null - */ - public RemoteServiceAdminEvent(int type, Bundle source, ImportReference importRegistration, Throwable exception) { - this(type, source, importRegistration, null, exception); - } - - /** - * @return the importRegistration or null - */ - public ImportReference getImportReference() { - return importReference; - } - - /** - * @return the exportRegistration or null - */ - public ExportReference getExportReference() { - return exportReference; - } - - /** - * @return the exception or null - */ - public Throwable getException() { - return exception; - } - - /** - * @return the type - */ - public int getType() { - return type; - } - - /** - * @return the source - */ - public Bundle getSource() { - return source; - } -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminListener.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminListener.java deleted file mode 100644 index 40f68a4ba8..0000000000 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/RemoteServiceAdminListener.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2008, 2009). 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tuscany.sca.osgi.remoteserviceadmin; - -/** - * A Remote Service Admin Listener is notified asynchronously of any export or - * import registrations and unregistrations. - * - * @ThreadSafe - */ - -public interface RemoteServiceAdminListener { - /** - * Receive a Remote Service Admin event. - * @param event - */ - void remoteAdminEvent(RemoteServiceAdminEvent event); -} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointHelper.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointHelper.java index 6d29a0c51a..ccea9281df 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointHelper.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointHelper.java @@ -28,10 +28,10 @@ import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.implementation.osgi.OSGiProperty; import org.apache.tuscany.sca.interfacedef.Interface; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.RemoteConstants; /** * Implementation of {@link EndpointDescription} @@ -55,7 +55,7 @@ public class EndpointHelper { if (!endpoint.isRemote()) { String uuid = OSGiHelper.getFrameworkUUID(bundleContext); - props.put(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID, uuid); + props.put(RemoteConstants.ENDPOINT_FRAMEWORK_UUID, uuid); } for (Object ext : endpoint.getService().getExtensions()) { @@ -65,8 +65,8 @@ public class EndpointHelper { } } - props.put(RemoteConstants.SERVICE_REMOTE_ID, props.get(Constants.SERVICE_ID)); - props.put(RemoteConstants.SERVICE_REMOTE_URI, endpoint.getURI()); + props.put(RemoteConstants.ENDPOINT_ID, props.get(Constants.SERVICE_ID)); + props.put(RemoteConstants.ENDPOINT_URI, endpoint.getURI()); // FIXME: [rfeng] How to pass in the remote service id from the endpoint XML props.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, new String[] {"org.osgi.sca"}); props.put(Endpoint.class.getName(), endpoint); diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java index 9247978b23..bfc5b97ee8 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java @@ -70,7 +70,6 @@ import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; import org.apache.tuscany.sca.osgi.service.discovery.impl.LocalDiscoveryService; import org.apache.tuscany.sca.osgi.service.discovery.impl.LocalDiscoveryService.ExtenderConfiguration; import org.apache.tuscany.sca.policy.Intent; @@ -80,6 +79,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.osgi.util.tracker.ServiceTracker; /** diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportReferenceImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportReferenceImpl.java index a36f388bf6..473e5742e9 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportReferenceImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportReferenceImpl.java @@ -19,9 +19,9 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportReference; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; /** * @@ -44,7 +44,7 @@ public class ExportReferenceImpl implements ExportReference { return exportedService; } - public EndpointDescription getEndpointDescription() { + public EndpointDescription getExportedEndpoint() { return endpointDescription; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportRegistrationImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportRegistrationImpl.java index c31b1b1c70..9b31931b6c 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportRegistrationImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ExportRegistrationImpl.java @@ -20,10 +20,10 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; import org.apache.tuscany.sca.node.Node; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportReference; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportRegistration; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.ExportRegistration; /** * Implementation of {@link ExportRegistration} @@ -60,7 +60,7 @@ public class ExportRegistrationImpl implements ExportRegistration { } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportRegistration#close() + * @see org.osgi.remoteserviceadmin.ExportRegistration#close() */ public void close() { if (node != null) { diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportReferenceImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportReferenceImpl.java index 453d9a8020..8ecc696795 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportReferenceImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportReferenceImpl.java @@ -19,9 +19,9 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportReference; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ImportReference; /** * @@ -45,7 +45,7 @@ public class ImportReferenceImpl implements ImportReference { return importedService; } - public EndpointDescription getImportedEndpointDescription() { + public EndpointDescription getImportedEndpoint() { return endpointDescription; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportRegistrationImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportRegistrationImpl.java index e89a05233b..2526f70a6b 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportRegistrationImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/ImportRegistrationImpl.java @@ -20,10 +20,10 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; import org.apache.tuscany.sca.node.Node; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportReference; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportRegistration; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ImportReference; +import org.osgi.service.remoteserviceadmin.ImportRegistration; /** * @@ -59,7 +59,7 @@ public class ImportRegistrationImpl implements ImportRegistration { } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportRegistration#close() + * @see org.osgi.remoteserviceadmin.ImportRegistration#close() */ public void close() { if (node != null) { @@ -78,7 +78,7 @@ public class ImportRegistrationImpl implements ImportRegistration { return node; } - public ImportReference getImportedReference() { + public ImportReference getImportReference() { return importReference; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceExporter.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceExporter.java index 479ae54e42..fc4d3971cf 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceExporter.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceExporter.java @@ -19,13 +19,13 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; -import static org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID; -import static org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants.SERVICE_REMOTE_ID; import static org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.EndpointHelper.createEndpointDescription; import static org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper.createOSGiProperty; import static org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper.getFrameworkUUID; import static org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper.getOSGiProperties; import static org.osgi.framework.Constants.SERVICE_ID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID; import java.util.ArrayList; import java.util.Collections; @@ -38,10 +38,10 @@ import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.contribution.Contribution; import org.apache.tuscany.sca.node.configuration.NodeConfiguration; import org.apache.tuscany.sca.node.impl.NodeImpl; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportRegistration; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportRegistration; import org.osgi.util.tracker.ServiceTrackerCustomizer; /** @@ -85,10 +85,10 @@ public class OSGiServiceExporter extends AbstractOSGiServiceHandler implements S ComponentService service = component.getServices().get(0); service.getExtensions().addAll(getOSGiProperties(registry, reference)); service.getExtensions().add(createOSGiProperty(registry, - SERVICE_REMOTE_FRAMEWORK_UUID, + ENDPOINT_FRAMEWORK_UUID, getFrameworkUUID(reference.getBundle() .getBundleContext()))); - service.getExtensions().add(createOSGiProperty(registry, SERVICE_REMOTE_ID, reference + service.getExtensions().add(createOSGiProperty(registry, ENDPOINT_ID, reference .getProperty(SERVICE_ID))); // FIXME: Configure the domain and node URI diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceImporter.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceImporter.java index 93b03d8075..66d4349feb 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceImporter.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiServiceImporter.java @@ -27,11 +27,11 @@ import org.apache.tuscany.sca.contribution.Contribution; import org.apache.tuscany.sca.node.Node; import org.apache.tuscany.sca.node.configuration.NodeConfiguration; import org.apache.tuscany.sca.node.impl.NodeImpl; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportRegistration; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ImportRegistration; /** * Watching and exporting OSGi services @@ -88,7 +88,7 @@ public class OSGiServiceImporter extends AbstractOSGiServiceHandler { } public void unimportService(ImportRegistration importRegistration) { - Node node = (Node)importRegistration.getImportedReference().getImportedService().getProperty("sca.node"); + Node node = (Node)importRegistration.getImportReference().getImportedService().getProperty("sca.node"); node.stop(); } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/RemoteServiceAdminImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/RemoteServiceAdminImpl.java index 28b2d864aa..994fb29e9b 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/RemoteServiceAdminImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/RemoteServiceAdminImpl.java @@ -27,12 +27,6 @@ import java.util.Hashtable; import java.util.List; import java.util.Map; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportRegistration; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportRegistration; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdminEvent; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdminListener; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -42,6 +36,14 @@ import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportReference; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; import org.osgi.util.tracker.ServiceTracker; /** @@ -56,8 +58,8 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic private OSGiServiceExporter exporter; private OSGiServiceImporter importer; - private Collection importedEndpoints = new ArrayList(); - private Collection exportedServices = new ArrayList(); + private Collection importRegistrations = new ArrayList(); + private Collection exportedRegistrations = new ArrayList(); public RemoteServiceAdminImpl(BundleContext context) { this.context = context; @@ -97,14 +99,14 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic listeners.close(); listeners = null; } - for (ExportRegistration exportRegistration : exportedServices) { + for (ExportRegistration exportRegistration : exportedRegistrations) { exportRegistration.close(); } - exportedServices.clear(); - for (ImportRegistration importRegistration : importedEndpoints) { + exportedRegistrations.clear(); + for (ImportRegistration importRegistration : importRegistrations) { importRegistration.close(); } - importedEndpoints.clear(); + importRegistrations.clear(); if (importer != null) { importer.stop(); importer = null; @@ -116,13 +118,13 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin#exportService(org.osgi.framework.ServiceReference, + * @see org.osgi.remoteserviceadmin.RemoteServiceAdmin#exportService(org.osgi.framework.ServiceReference, * java.util.Map) */ public List exportService(ServiceReference ref, Map properties) { List exportRegistrations = exporter.exportService(ref, properties); if (exportRegistrations != null) { - exportedServices.addAll(exportRegistrations); + exportRegistrations.addAll(exportedRegistrations); fireExportEvents(ref.getBundle(), exportRegistrations); } return exportRegistrations; @@ -131,8 +133,8 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic private void fireExportEvents(Bundle source, List exportRegistrations) { for (ExportRegistration registration : exportRegistrations) { RemoteServiceAdminEvent rsaEvent = - new RemoteServiceAdminEvent(RemoteServiceAdminEvent.EXPORT_REGISTRATION, source, registration.getExportReference(), - registration.getException()); + new RemoteServiceAdminEvent(RemoteServiceAdminEvent.EXPORT_REGISTRATION, source, registration + .getExportReference(), registration.getException()); EventAdmin eventAdmin = getEventAdmin(); if (eventAdmin != null) { eventAdmin.postEvent(wrap(rsaEvent)); @@ -215,9 +217,9 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic props.put("export.reference", rsaEvent.getExportReference()); EndpointDescription ep = null; if (rsaEvent.getImportReference() != null) { - ep = rsaEvent.getImportReference().getImportedEndpointDescription(); + ep = rsaEvent.getImportReference().getImportedEndpoint(); } else { - ep = rsaEvent.getExportReference().getEndpointDescription(); + ep = rsaEvent.getExportReference().getExportedEndpoint(); } props.put("service.remote.id", ep.getRemoteServiceID()); props.put("service.remote.uuid", ep.getRemoteFrameworkUUID()); @@ -231,8 +233,8 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic private void fireImportEvents(Bundle source, ImportRegistration registration) { RemoteServiceAdminEvent rsaEvent = - new RemoteServiceAdminEvent(RemoteServiceAdminEvent.IMPORT_REGISTRATION, source, registration.getImportedReference(), registration - .getException()); + new RemoteServiceAdminEvent(RemoteServiceAdminEvent.IMPORT_REGISTRATION, source, registration + .getImportReference(), registration.getException()); EventAdmin eventAdmin = getEventAdmin(); if (eventAdmin != null) { eventAdmin.postEvent(wrap(rsaEvent)); @@ -244,28 +246,36 @@ public class RemoteServiceAdminImpl implements RemoteServiceAdmin, ManagedServic } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin#getExportedServices() + * @see org.osgi.remoteserviceadmin.RemoteServiceAdmin#getExportedServices() */ - public Collection getExportedServices() { + public Collection getExportedServices() { + Collection exportedServices = new ArrayList(); + for (ExportRegistration registration : exportedRegistrations) { + exportedServices.add(registration.getExportReference()); + } return exportedServices; } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin#getImportedEndpoints() + * @see org.osgi.remoteserviceadmin.RemoteServiceAdmin#getImportedEndpoints() */ - public Collection getImportedEndpoints() { + public Collection getImportedEndpoints() { + Collection importedEndpoints = new ArrayList(); + for (ImportRegistration registration : importRegistrations) { + importedEndpoints.add(registration.getImportReference()); + } return importedEndpoints; } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin#importService(org.apache.tuscany.sca.dosgi.discovery.EndpointDescription) + * @see org.osgi.remoteserviceadmin.RemoteServiceAdmin#importService(org.apache.tuscany.sca.dosgi.discovery.EndpointDescription) */ public ImportRegistration importService(EndpointDescription endpoint) { Bundle bundle = (Bundle)endpoint.getProperties().get(Bundle.class.getName()); ImportRegistration importReg = importer.importService(bundle, endpoint); if (importReg != null) { fireImportEvents(bundle, importReg); - importedEndpoints.add(importReg); + importRegistrations.add(importReg); } return importReg; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java index 1967fa6e4a..31f4f4c0b3 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java @@ -20,8 +20,8 @@ package org.apache.tuscany.sca.osgi.remoteserviceadmin.impl; import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EXPORTED_INTERFACES; -import static org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS; -import static org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED; import java.util.Collection; import java.util.Dictionary; @@ -37,13 +37,6 @@ import java.util.logging.Logger; import org.apache.tuscany.sca.common.java.collection.CollectionMap; import org.apache.tuscany.sca.core.LifeCycleListener; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointListener; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ExportRegistration; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.ImportRegistration; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdmin; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdminEvent; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteServiceAdminListener; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -52,6 +45,13 @@ import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.hooks.service.ListenerHook; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.EndpointListener; +import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; @@ -178,7 +178,7 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList } else { for (Object ra : admins) { RemoteServiceAdmin remoteAdmin = (RemoteServiceAdmin)ra; - List exportRegistrations = remoteAdmin.exportService(reference, null); + Collection exportRegistrations = remoteAdmin.exportService(reference, null); if (exportRegistrations != null && !exportRegistrations.isEmpty()) { exportedServices.putValues(reference, exportRegistrations); } @@ -329,7 +329,7 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointListener#addEndpoint(org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription, + * @see org.osgi.remoteserviceadmin.EndpointListener#addEndpoint(org.osgi.service.remoteserviceadmin.EndpointDescription, * java.lang.String) */ public void endpointAdded(EndpointDescription endpoint, String matchedFilter) { @@ -337,7 +337,7 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList } /** - * @see org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointListener#removeEndpoint(org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription) + * @see org.osgi.remoteserviceadmin.EndpointListener#removeEndpoint(org.osgi.service.remoteserviceadmin.EndpointDescription) */ public void endpointRemoved(EndpointDescription endpoint, String matchedFilter) { unimportService(endpoint); diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java index 5b0b311d7a..6f0144a71e 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java @@ -19,7 +19,7 @@ package org.apache.tuscany.sca.osgi.service.discovery.impl; -import static org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointListener.ENDPOINT_LISTENER_SCOPE; +import static org.osgi.service.remoteserviceadmin.EndpointListener.ENDPOINT_LISTENER_SCOPE; import java.util.ArrayList; import java.util.Collection; @@ -37,15 +37,15 @@ import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.LifeCycleListener; import org.apache.tuscany.sca.node.NodeFactory; import org.apache.tuscany.sca.node.impl.NodeFactoryImpl; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointListener; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants; import org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.EndpointListener; +import org.osgi.service.remoteserviceadmin.RemoteConstants; import org.osgi.util.tracker.ServiceTracker; /** diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java index bf70c98634..0efa0cd20b 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java @@ -27,11 +27,11 @@ import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.assembly.Implementation; import org.apache.tuscany.sca.core.UtilityExtensionPoint; import org.apache.tuscany.sca.implementation.osgi.OSGiImplementation; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; import org.apache.tuscany.sca.runtime.DomainRegistryFactory; import org.apache.tuscany.sca.runtime.EndpointListener; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.service.remoteserviceadmin.EndpointDescription; /** * Discovery service based on the distributed SCA domain diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java index 11dcd56272..90fe3f8fd1 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java @@ -36,8 +36,6 @@ import org.apache.tuscany.sca.deployment.Deployer; import org.apache.tuscany.sca.implementation.osgi.SCAConfig; import org.apache.tuscany.sca.implementation.osgi.ServiceDescription; import org.apache.tuscany.sca.implementation.osgi.ServiceDescriptions; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.EndpointDescription; -import org.apache.tuscany.sca.osgi.remoteserviceadmin.RemoteConstants; import org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper; import org.oasisopen.sca.ServiceRuntimeException; import org.osgi.framework.Bundle; @@ -46,6 +44,8 @@ import org.osgi.framework.BundleEvent; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.InvalidSyntaxException; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.RemoteConstants; import org.osgi.util.tracker.BundleTracker; import org.osgi.util.tracker.BundleTrackerCustomizer; import org.osgi.util.tracker.ServiceTracker; @@ -88,14 +88,14 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B private EndpointDescription createEndpointDescription(ServiceDescription sd) { Map props = new HashMap(sd.getProperties()); props.put(Constants.OBJECTCLASS, sd.getInterfaces().toArray(new String[sd.getInterfaces().size()])); - if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_ID)) { - props.put(RemoteConstants.SERVICE_REMOTE_ID, String.valueOf(System.currentTimeMillis())); + if (!props.containsKey(RemoteConstants.ENDPOINT_ID)) { + props.put(RemoteConstants.ENDPOINT_ID, String.valueOf(System.currentTimeMillis())); } - if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID)) { - props.put(RemoteConstants.SERVICE_REMOTE_FRAMEWORK_UUID, OSGiHelper.getFrameworkUUID(context)); + if (!props.containsKey(RemoteConstants.ENDPOINT_FRAMEWORK_UUID)) { + props.put(RemoteConstants.ENDPOINT_FRAMEWORK_UUID, OSGiHelper.getFrameworkUUID(context)); } - if (!props.containsKey(RemoteConstants.SERVICE_REMOTE_URI)) { - props.put(RemoteConstants.SERVICE_REMOTE_URI, UUID.randomUUID().toString()); + if (!props.containsKey(RemoteConstants.ENDPOINT_URI)) { + props.put(RemoteConstants.ENDPOINT_URI, UUID.randomUUID().toString()); } EndpointDescription sed = new EndpointDescription(props); 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 new file mode 100644 index 0000000000..c83a79337f --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointDescription.java @@ -0,0 +1,540 @@ +/* + * Copyright (c) OSGi Alliance (2008, 2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_INTERACE_VERSION_; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_URI; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED_CONFIGS; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_INTENTS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.Enumeration; +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; +import org.osgi.framework.ServiceReference; +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 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. + * + * 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. + * + * @Immutable + * @version $Revision$ + */ + +public class EndpointDescription { + private final Map properties; + private final List interfaces; + private final long remoteServiceId; + private final String remoteFrameworkUUID; + private final String remoteUri; + + /** + * Create an Endpoint Description based on a Map. + * + * @param properties The map to create the Endpoint Description from. + * @throws IllegalArgumentException When the properties are not proper for + * an Endpoint Description + */ + + public EndpointDescription(Map properties) { + this(properties, null); + if (properties == null) { + throw new NullPointerException("properties must not be null"); + } + } + + /** + * Create an Endpoint Description based on a reference and optionally a map + * of additional properties. The properties on the original service take + * precedence over the ones in the map. + * + * @param reference A service reference that can be exported + * @param properties Additional properties to add. Can be null. + * @throws IllegalArgumentException When the properties are not proper for + * an Endpoint Description + */ + public EndpointDescription(ServiceReference reference, + Map properties) { + this(properties, reference); + if (reference == null) { + throw new NullPointerException("reference must not be null"); + } + } + + private EndpointDescription(Map map, + ServiceReference reference) { + Map props = new TreeMap( + String.CASE_INSENSITIVE_ORDER); + + if (map != null) { + try { + props.putAll(map); + } + catch (ClassCastException e) { + IllegalArgumentException iae = new IllegalArgumentException( + "non-String key in properties"); + iae.initCause(e); + throw iae; + } + if (props.size() < map.size()) { + throw new IllegalArgumentException( + "duplicate keys with different cases in properties"); + } + } + + if (reference != null) { + for (String key : reference.getPropertyKeys()) { + if (!props.containsKey(key)) { + props.put(key, reference.getProperty(key)); + } + } + } + + properties = Collections.unmodifiableMap(props); + /* properties must be initialized before calling the following methods */ + interfaces = verifyObjectClassProperty(); + remoteServiceId = verifyLongProperty(ENDPOINT_ID); + remoteFrameworkUUID = verifyStringProperty(ENDPOINT_FRAMEWORK_UUID); + remoteUri = verifyStringProperty(ENDPOINT_URI); + } + + /** + * 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. + * + */ + private List verifyObjectClassProperty() { + Object o = properties.get(Constants.OBJECTCLASS); + if (o == null) { + return Collections.EMPTY_LIST; + } + if (!(o instanceof String[])) { + throw new IllegalArgumentException( + "objectClass must be of type String[]"); + } + String[] objectClass = (String[]) o; + for (String interf : objectClass) { + try { + getInterfaceVersion(interf); + } + catch (IllegalArgumentException e) { + IllegalArgumentException iae = new IllegalArgumentException( + "Improper version for interface " + interf); + iae.initCause(e); + throw iae; + } + } + return Collections.unmodifiableList(Arrays.asList(objectClass)); + } + + /** + * 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. + */ + private long verifyLongProperty(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); + } + try { + return Long.parseLong((String) r); + } + catch (NumberFormatException e) { + IllegalArgumentException iae = new IllegalArgumentException( + "Required property cannot be parsed as a long: " + propName); + iae.initCause(e); + throw iae; + } + } + + /** + * Returns the endpoint's URI. + * + * 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 value of the URI is stored in the + * {@link RemoteConstants#ENDPOINT_URI} property. + * + * @return The URI of the endpoint, never null. + */ + public String getRemoteURI() { + return remoteUri; + } + + /** + * Provide the list of interfaces implemented by the exported service. + * + * If this Endpoint Description does not map to a service, then this List + * must be empty. + * + * The value of the interfaces is derived from the objectClass + * property. + * + * @return The read only list of Java interface names accessible by this + * endpoint. + */ + public List getInterfaces() { + return interfaces; + } + + /** + * Provide the version of the given interface. + * + * The version is encoded by prefixing the given interface name with + * endpoint.interface.version., and then using this as an + * endpoint property key. For example: + * + *

+     * endpoint.interface.version.com.acme.Foo
+     * 
+ * + * The value of this property is in String format and will be converted to a + * Version object by this method. + * + * @param name The name of the interface for which a version is requested. + * @return The version of the given interface or null if the + * interface has no version in this Endpoint Description. + * @throws IllegalArgumentException If the version property value is not + * String. + */ + public Version getInterfaceVersion(String name) { + String key = ENDPOINT_INTERACE_VERSION_ + name; + Object version = properties.get(key); + // [rfeng] Check for existence of the property + if (version == null) { + return null; + } + // [rfeng] + if (!(version instanceof String)) { + throw new IllegalArgumentException(key + + " property is not a String"); + } + return Version.parseVersion((String) version); + } + + /** + * Returns the service id for the service exported through this endpoint. + * + * 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. + * + * The value of the remote service id is stored in the + * {@link RemoteConstants#ENDPOINT_ID} endpoint property. + * + * @return Service id of a service or 0 if this Endpoint Description does + * not relate to an OSGi service + * + */ + public long getRemoteServiceID() { + return remoteServiceId; + } + + /** + * Returns the configuration types. + * + * A distribution provider exports a service with an endpoint. This endpoint + * uses some kind of communications protocol with a set of configuration + * parameters. There are many different types but each endpoint is + * configured by only one configuration type. However, a distribution + * provider can be aware of different configuration types and provide + * synonyms to increase the change a receiving distribution provider can + * create a connection to this endpoint. + * + * This value of the configuration types is stored in the + * {@link RemoteConstants#SERVICE_IMPORTED_CONFIGS} service property. + * + * @return An unmodifiable list of the configuration types used for the + * associated endpoint and optionally synonyms. + */ + public List getConfigurationTypes() { + return getStringPlusProperty(SERVICE_IMPORTED_CONFIGS); + } + + /** + * Return the list of intents implemented by this endpoint. + * + * The intents are based on the service.intents on an imported service, + * except for any intents that are additionally provided by the importing + * distribution provider. All qualified intents must have been expanded. + * + * This value of the intents is stored in the + * {@link RemoteConstants#SERVICE_INTENTS} service property. + * + * @return An unmodifiable list of expanded intents that are provided by + * this endpoint. + */ + public List getIntents() { + return getStringPlusProperty(SERVICE_INTENTS); + } + + /** + * Reads a 'String+' property from the properties map, which may be of type + * String, String[] or Collection and returns it as an unmodifiable + * List. + * + * @param key The property + * @return An unmodifiable list + */ + private List getStringPlusProperty(String key) { + Object value = properties.get(key); + if (value == null) { + return Collections.EMPTY_LIST; + } + + if (value instanceof String) { + return Collections.singletonList((String) value); + } + + if (value instanceof String[]) { + String[] values = (String[]) value; + List result = new ArrayList(values.length); + for (String v : values) { + if (v != null) { + result.add(v); + } + } + return Collections.unmodifiableList(result); + } + + if (value instanceof Collection< ? >) { + Collection< ? > values = (Collection< ? >) value; + List result = new ArrayList(values.size()); + for (Iterator< ? > iter = values.iterator(); iter.hasNext();) { + Object v = iter.next(); + if ((v != null) && (v instanceof String)) { + result.add((String) v); + } + } + return Collections.unmodifiableList(result); + } + + return Collections.EMPTY_LIST; + } + + /** + * Return the framework UUID for the remote service, if present. + * + * The value of the remote framework uuid is stored in the + * {@link RemoteConstants#ENDPOINT_FRAMEWORK_UUID} endpoint property. + * + * @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 unmodifiable map referring to the properties of this Endpoint + * Description. + */ + public Map getProperties() { + return properties; + } + + /** + * 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 (this.equals(other)) { + return true; + } + + if (getRemoteFrameworkUUID() == null) { + return false; + } + + return (this.getRemoteServiceID() == other.getRemoteServiceID()) + && this.getRemoteFrameworkUUID().equals( + other.getRemoteFrameworkUUID()); + } + + /** + * Returns a hash code value for the object. + * + * @return An integer which is a hash code value for this object. + */ + public int hashCode() { + return getRemoteURI().hashCode(); + } + + /** + * Compares this EndpointDescription object to another object. + * + *

+ * An Endpoint Description is considered to be equal to another + * Endpoint Description if their URIs are equal. + * + * @param other The EndpointDescription object to be compared. + * @return true if object is a + * EndpointDescription and is equal to this object; + * false otherwise. + */ + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof EndpointDescription)) { + return false; + } + return getRemoteURI().equals( + ((EndpointDescription) other).getRemoteURI()); + } + + /** + * Tests the properties of this EndpointDescription against the + * given filter using a case insensitive match. + * + * @param filter The filter to test. + * @return true If the properties of this + * EndpointDescription match the filter, + * false otherwise. + * @throws IllegalArgumentException If filter contains an + * invalid filter string that cannot be parsed. + */ + public boolean matches(String filter) { + Filter f; + try { + f = FrameworkUtil.createFilter(filter); + } + catch (InvalidSyntaxException e) { + IllegalArgumentException iae = new IllegalArgumentException(e + .getMessage()); + iae.initCause(e); + throw iae; + } + Dictionary d = new UnmodifiableDictionary( + properties); + /* + * we can use matchCase here since properties already supports case + * insensitive key lookup. + */ + return f.matchCase(d); + } + + /** + * Unmodifiable wrapper for Dictionary. + */ + private static class UnmodifiableDictionary extends Dictionary { + private final Map wrapped; + + UnmodifiableDictionary(Map wrapped) { + this.wrapped = wrapped; + } + + public Enumeration elements() { + return Collections.enumeration(wrapped.values()); + } + + public V get(Object key) { + return wrapped.get(key); + } + + public boolean isEmpty() { + return wrapped.isEmpty(); + } + + public Enumeration keys() { + return Collections.enumeration(wrapped.keySet()); + } + + public V put(K key, V value) { + throw new UnsupportedOperationException(); + } + + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + public int size() { + return wrapped.size(); + } + } +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointListener.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointListener.java new file mode 100644 index 0000000000..9a56c53f4f --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointListener.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +/** + * 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 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 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 + * protocol, then it sends an End Point Description to all the End Point + * Listener services that are registered (except its own) that have specified an + * interest in that endpoint. + * + * Endpoint Listener services can express their scope with the service + * property {@link #ENDPOINT_LISTENER_SCOPE}. This service property is a list of + * filters. An Endpoint Description should only be given to a Endpoint Listener + * when there is at least one filter that matches the Endpoint Description + * properties. given to it. + * + * This filter model is quite flexible. For example, a discovery bundle is only + * interested in locally originating Endpoint Descriptions. The following filter + * ensure that it only sees local endpoints. + * + *

+ *   (org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72)
+ * 
+ * + * In the same vein, a manager that is only interested in remote Endpoint + * Descriptions can use a filter like: + * + *
+ *   (!(org.osgi.framework.uuid=72dc5fd9-5f8f-4f8f-9821-9ebb433a5b72))
+ * 
+ * + * Where in both cases, the given UUID is the UUID of the local framework that + * can be found in the Framework properties. + * + * The Endpoint Listener's scope maps very well to the service hooks. A 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. + * + * In general, when an Endpoint Description is discovered, it should be + * dispatched to all registered Endpoint Listener services. If a new Endpoint + * Listener is registered, it should be informed about all currently known + * Endpoints that match its scope. If a getter of the Endpoint Listener service + * is unregistered, then all its registered Endpoint Description objects must be + * removed. + * + * The Endpoint Listener models a best effort approach. Participating + * bundles should do their utmost to keep the listeners up to date, but + * implementers should realize that many endpoints come through unreliable + * discovery processes. + * + * + * @ThreadSafe + * @version $Revision$ + */ +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 String+. + */ + 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 matchedFilter 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 null. + */ + void endpointAdded(EndpointDescription endpoint, String matchedFilter); + + /** + * 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 null. + */ + void endpointRemoved(EndpointDescription endpoint, String matchedFilter); +} 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 new file mode 100644 index 0000000000..0bfdcd334b --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/EndpointPermission.java @@ -0,0 +1,943 @@ +/* + * Copyright (c) OSGi Alliance (2000, 2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +// TODO Hacked from ServiePermission + +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; + +/** + *
+ * -------------------------------------------------------------
+ * THIS CLASS IS A PLACEHOLDER (COPIED FROM SERVICE PERMISSION)!
+ * -------------------------------------------------------------
+ * 
+ * + * A bundle's authority to register or get a service. + *
    + *
  • The register action allows a bundle to register a service on + * the specified names. + *
  • The get action allows a bundle to detect a service and get + * it. + *
+ * 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 + * EndpointPermission to get the specific service. + * + * @ThreadSafe + * @version $Revision$ + */ + +public final class EndpointPermission extends BasicPermission { + static final long serialVersionUID = -7662148639076511574L; + /** + * The action string export. + */ + public final static String EXPORT = "export"; + /** + * The action string import. + */ + public final static String IMPORT = "import"; + /** + * The action string read. + */ + public final static String READ = "read"; + + 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; + + /** + * 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. + * + *

+ * The name of the service is specified as a fully qualified class name. + * Wildcards may be used. + * + *

+	 * name ::= <class name> | <class name ending in ".*"> | *
+	 * 
+ * + * Examples: + * + *
+	 * org.osgi.service.http.HttpService
+	 * org.osgi.service.http.*
+	 * *
+	 * 
+ * + * For the get action, the name can also be a filter + * expression. The filter gives access to the service properties as well as + * the following attributes: + *
    + *
  • 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.
  • + *
  • location - The location of the bundle publishing the service.
  • + *
  • id - The bundle ID of the bundle publishing the service.
  • + *
  • name - The symbolic name of the bundle publishing the service.
  • + *
+ * 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. + * + *

+ * There are two possible actions: get and + * register. The get permission allows the owner + * of this permission to obtain a service with this name. The + * register permission allows the bundle to register a service + * under that name. + * + * @param name The service class name + * @param actions get,register (canonical order) + * @throws IllegalArgumentException If the specified name is a filter + * expression and either the specified action is not + * get 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 EndpointPermission object to be used + * by code that must perform checkPermission for the + * get action. EndpointPermission objects created + * with this constructor cannot be added to a + * EndpointPermission permission collection. + * + * @param endpoint The requested service. + * @param actions The action get. + * @throws IllegalArgumentException If the specified action is not + * get or reference is null. + * @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 null 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 EndpointPermission object "implies" the + * specified permission. + * + * @param p The target permission to check. + * @return true if the specified permission is implied by this + * object; false 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 true if the specified permission is implied by this + * object; false 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: get, + * register. + * + * @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 PermissionCollection object for storing + * EndpointPermission objects. + * + * @return A new PermissionCollection object suitable for + * storing EndpointPermission 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 + * EndpointPermission. + * + * @param obj The object to test for equality. + * @return true if obj is a EndpointPermission, and has the + * same class name and actions as this + * EndpointPermission object; false + * 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 <@link EndpointPermission#implies(Permission)>. + * + * @return a dictionary of properties for this permission. + */ + private Dictionary/* */getProperties() { + Dictionary/* */result = properties; + if (result != null) { + return result; + } + if (endpoint == null) { + result = new Hashtable/* */(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(); + } + } +} + +/** + * Stores a set of EndpointPermission permissions. + * + * @see java.security.Permission + * @see java.security.Permissions + * @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 + * EndpointPermissionCollection 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 + * permission. + * + * @param permission The Permission object to compare. + * @return true if permission is a proper subset + * of a permission in the set; false 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 EndpointPermission 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/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportReference.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportReference.java new file mode 100644 index 0000000000..03b3235c59 --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportReference.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +import org.osgi.framework.ServiceReference; + +/** + * An Export Reference associates a service with a local endpoint. + * + * The Export Reference can be used to reference an exported service. When the + * service is no longer exported, all methods must return null; + * + * @ThreadSafe + * @version $Revision$ + */ +public interface ExportReference { + /** + * Return the service being exported. + * + * @return The service being exported, must be null when this + * registration is unregistered. + */ + ServiceReference getExportedService(); + + /** + * Return the Endpoint Description that is created for this registration. + * + * @return the local Endpoint Description + */ + EndpointDescription getExportedEndpoint(); +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportRegistration.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportRegistration.java new file mode 100644 index 0000000000..e8c6c66cbf --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ExportRegistration.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +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 RemoteServiceAdmin#exportService(ServiceReference,java.util.Map)} + * method. + * + * When this Export Registration has been unregistered, the methods must all + * return null. + * + * @ThreadSafe + * @version $Revision$ + */ +public interface ExportRegistration { + /** + * Return the Export Reference for the exported service. + * + * @return An Export Reference for this registration + * @throws IllegalStateException Thrown when this object was not properly + * initialized, see {@link #getException()} + */ + ExportReference getExportReference(); + + /** + * Delete the local endpoint and disconnect any remote distribution + * providers. After this method returns, all the methods must return + * null. + * + * 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 Throwable 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 + * null. + * + * 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 null if no exception occurred. + */ + Throwable getException(); +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportReference.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportReference.java new file mode 100644 index 0000000000..5fa5673341 --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportReference.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +import org.osgi.framework.ServiceReference; + +/** + * An Import Reference associates an active proxy service to a remote endpoint. + * + * The Import Reference can be used to reference an imported service. When the + * service is no longer imported, all methods must return null; + * + * @ThreadSafe + * @version $Revision$ + */ +public interface ImportReference { + /** + * Answer the associated Service Reference for the proxy to the endpoint. + * + * @return A Service Reference to the proxy for the endpoint. + */ + ServiceReference getImportedService(); + + /** + * Answer the associated remote Endpoint Description. + * + * @return A Endpoint Description for the remote endpoint. + */ + EndpointDescription getImportedEndpoint(); +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportRegistration.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportRegistration.java new file mode 100644 index 0000000000..1fc1c6f6ba --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/ImportRegistration.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +/** + * 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 RemoteServiceAdmin#importService} + * method. + * + * @ThreadSafe + * @version $Revision$ + */ +public interface ImportRegistration { + /** + * Answer the associated Export Reference. + * + * @return An Import Reference for this registration + * @throws IllegalStateException Thrown when this object was not properly + * initialized, see {@link #getException()} + */ + ImportReference getImportReference(); + + /** + * 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 Throwable 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 + * null. + * + * 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 null if no exception occurred. + */ + Throwable getException(); + +} 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 new file mode 100644 index 0000000000..a44c03ea0e --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteConstants.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +/** + * Provide the definition of the constants used in the Remote Services API. + * + * @Immutable + * @version $Revision$ + */ +public class RemoteConstants { + private 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. + * + *

+ * The value of this property must be of type String, + * String[], or Collection of String. + */ + public static final String REMOTE_CONFIGS_SUPPORTED = "remote.configs.supported"; + + /** + * Service property identifying the intents supported by a distribution + * provider. Registered by the distribution provider on one of its services + * to indicate the vocabulary of implemented intents. + * + *

+ * The value of this property must be of type String, + * String[], or Collection of String. + */ + public static final String REMOTE_INTENTS_SUPPORTED = "remote.intents.supported"; + + /** + * Service property identifying the configuration types that should be used + * to export the service. Each configuration type represents the + * configuration parameters for an endpoint. A distribution provider should + * create an endpoint for each configuration type that it supports. + * + *

+ * This property may be supplied in the properties + * Dictionary object passed to the + * BundleContext.registerService method. The value of this + * property must be of type String, String[], or + * Collection of String. + */ + public static final String SERVICE_EXPORTED_CONFIGS = "service.exported.configs"; + + /** + * Service property identifying the 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. + * + *

+ * This property may be supplied in the properties + * Dictionary object passed to the + * BundleContext.registerService method. The value of this + * property must be of type String, String[], or + * Collection of String. + */ + public static final String SERVICE_EXPORTED_INTENTS = "service.exported.intents"; + + /** + * Service property identifying the extra intents that the distribution + * provider must implement to distribute the service. This property is + * merged with the service.exported.intents property before the + * distribution provider interprets the listed intents; it has therefore the + * same semantics but the property should be configurable so the + * administrator can choose the intents based on the topology. Bundles + * should therefore make this property configurable, for example through the + * Configuration Admin service. + * + *

+ * This property may be supplied in the properties + * Dictionary object passed to the + * BundleContext.registerService method. The value of this + * property must be of type String, String[], or + * Collection of String. + */ + public static final String SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra"; + + /** + * Service property marking the service for export. It defines the + * interfaces under which this service can be exported. This list must be a + * subset of the types under which the service was registered. The single + * value of an asterisk ("*", \u002A) indicates all the + * interface types under which the service was registered excluding the + * non-interface types. It is strongly recommended to only export interface + * types and not concrete classes due to the complexity of creating proxies + * for some type of concrete classes. + * + *

+ * This property may be supplied in the properties + * Dictionary object passed to the + * BundleContext.registerService method. The value of this + * property must be of type String, String[], or + * Collection of String. + */ + public static final String SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces"; + + /** + * Service property identifying the service as imported. This service + * property must be set by a distribution provider to any value when it + * registers the endpoint proxy as an imported service. A bundle can use + * this property to filter out imported services. + * + *

+ * The value of this property may be of any type. + */ + public static final String SERVICE_IMPORTED = "service.imported"; + + /** + * Service property identifying the configuration types used to import the + * service. 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. If multiple configuration types are listed in this property, + * then they must be synonyms for exactly the same remote endpoint that is + * used to export this service. + * + *

+ * The value of this property must be of type String, + * String[], or Collection of String. + * + * @see #SERVICE_EXPORTED_CONFIGS + */ + public static final String SERVICE_IMPORTED_CONFIGS = "service.imported.configs"; + + /** + * Service property identifying the intents that this service implement. + * This property has a 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.
  • + *
  • A distribution provider must use this property to convey the combined + * intents of:
  • + *
      + *
    • The exporting service, and
    • + *
    • the intents that the exporting distribution provider adds, and
    • + *
    • the intents that the importing distribution provider adds.
    • + *
    + * + * + *
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. + * + *

+ * The value of this property must be of type String, + * String[], or Collection of String. + */ + 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 + * property must always be set. + * + *

+ * The value of this property must be of type String. + */ + public final static String ENDPOINT_URI = "endpoint.uri"; + + /** + * Endpoint property identifying the service id of the exported service. Can + * be absent or 0 if the corresponding endpoint is not for an OSGi service. + * + *

+ * The value of this property must be of type Long. + */ + public final static String ENDPOINT_ID = "endpoint.id"; + + /** + * Endpoint property identifying the universally unique id of the exporting + * framework. Can be absent if the corresponding endpoint is not for an OSGi + * service. + * + *

+ * The value of this property must be of type String. + */ + public final static String ENDPOINT_FRAMEWORK_UUID = "endpoint.framework.uuid"; + + /** + * Prefix for an endpoint property identifying the interface Java package + * version for an interface For example, the property + * endpoint.interface.version.com.acme.Foo=1.3 describes the version for the + * com.acme.Foo interface. This endpoint property for an interface does not + * have to be set. If not set, the value must be assumed to be 0. + * + *

+ * The value of this property must be of type String. + */ + public final static String ENDPOINT_INTERACE_VERSION_ = "endpoint.interface.version."; + +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdmin.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdmin.java new file mode 100644 index 0000000000..0b436c361a --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdmin.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +import java.util.Collection; +import java.util.Map; + +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 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. + * + * @ThreadSafe + * @version $Revision$ + */ +public interface RemoteServiceAdmin { + + /** + * 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. + * + * TODO Peter to update for case insensitive properties + * + * The properties on a Service Reference are case insensitive while the + * properties on a properties are case sensitive. A value in + * the properties must therefore override any case variant in + * the properties of the Service Reference. + * + *

+ * If the caller does not have the appropriate + * EndpointPermission[endpoint,EXPORT] for an endpoint, and the + * Java Runtime Environment supports permissions, then the + * {@link ExportRegistration#getException() getException} method on the + * corresponding returned {@link ExportRegistration} will return a + * SecurityException. + * + * @param reference 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 null, this should + * be treated as an empty map. + * + * TODO Peter The return description does not mesh with returning a + * list! Why a list and not just one? + * @return An Export Registration that combines the Endpoint Description and + * the Service Reference or null if the service could + * not be exported. + * @throws IllegalArgumentException If any of the properties has a value + * that is not syntactically correct or if the service properties + * and the overlaid properties do not contain a + * {@link RemoteConstants#SERVICE_EXPORTED_INTERFACES} entry. + * @throws UnsupportedOperationException If any of the intents expressed + * through the properties is not supported by the distribution + * provider. + */ + Collection exportService(ServiceReference reference, + Map properties); + + /** + * 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. + * + * @param endpoint The Endpoint Description to be used for import. + * @return An Import Registration that combines the Endpoint Description and + * the Service Reference or null if the endpoint could + * not be imported. + * @throws SecurityException If the caller does not have the appropriate + * EndpointPermission[endpoint,IMPORT] for the + * endpoint, and the Java Runtime Environment supports permissions. + */ + ImportRegistration importService(EndpointDescription endpoint); + + /** + * Return the currently active Export References. + * + *

+ * If the caller does not have the appropriate + * EndpointPermission[endpoint,READ] for an endpoint, and the + * Java Runtime Environment supports permissions, then returned collection + * will not contain a reference to the exported endpoint. + * + * @return A Collection of {@link ExportReference}s that are + * currently active. + */ + Collection getExportedServices(); + + /** + * Return the currently active Import References. + * + *

+ * If the caller does not have the appropriate + * EndpointPermission[endpoint,READ] for an endpoint, and the + * Java Runtime Environment supports permissions, then returned collection + * will not contain a reference to the imported endpoint. + * + * @return A Collection of {@link ImportReference}s that are + * currently active. + */ + Collection getImportedEndpoints(); + +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminEvent.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminEvent.java new file mode 100644 index 0000000000..8f4ac717c8 --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminEvent.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +import org.osgi.framework.Bundle; + +/** + * Provides the event information for a Remote Admin event. + * + * @Immutable + * @version $Revision$ + */ +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 ImportReference importReference; + private final ExportReference exportReference; + 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 null. + * @param importReference The importReference, can be null. + * @param exportReference The exportReference, can be null. + * @param exception Any exceptions encountered, can be null + */ + private RemoteServiceAdminEvent(int type, Bundle source, + ImportReference importReference, ExportReference exportReference, + Throwable exception) { + if (source == null) { + throw new NullPointerException("source must not be null"); + } + this.type = type; + this.source = source; + this.importReference = importReference; + this.exportReference = exportReference; + this.exception = exception; + } + + /** + * Create a Remote Service Admin Event for an export notification. + * + * @param type The event type. + * @param source The source bundle, must not be null. + * @param exportReference The exportReference, can not be null. + * @param exception Any exceptions encountered, can be null. + */ + public RemoteServiceAdminEvent(int type, Bundle source, + ExportReference exportReference, Throwable exception) { + this(type, source, null, exportReference, exception); + } + + /** + * Create a Remote Service Admin Event for an import notification. + * + * @param type The event type. + * @param source The source bundle, must not be null. + * @param importReference The importReference, can not be null. + * @param exception Any exceptions encountered, can be null. + */ + public RemoteServiceAdminEvent(int type, Bundle source, + ImportReference importReference, Throwable exception) { + this(type, source, importReference, null, exception); + } + + /** + * Return the Import Reference for this event. + * + * @return The Import Reference or null. + */ + public ImportReference getImportReference() { + return importReference; + } + + /** + * Return the Export Reference for this event. + * + * @return The Export Reference or null. + */ + public ExportReference getExportReference() { + return exportReference; + } + + /** + * Return the exception for this event. + * + * @return The exception or null. + */ + public Throwable getException() { + return exception; + } + + /** + * Return the type of this event. + * + * @return The type of this event. + */ + public int getType() { + return type; + } + + /** + * Return the bundle source of this event. + * + * @return The bundle source of this event. + */ + public Bundle getSource() { + return source; + } +} diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminListener.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminListener.java new file mode 100644 index 0000000000..0030b870c7 --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/osgi/service/remoteserviceadmin/RemoteServiceAdminListener.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) OSGi Alliance (2009). 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.service.remoteserviceadmin; + +/** + * A {@link RemoteServiceAdminEvent} listener is notified asynchronously of any + * export or import registrations and unregistrations. + * + *

+ * If the Java Runtime Environment supports permissions, then filtering is done. + * RemoteServiceAdminEvent objects are only delivered to the + * listener if the bundle which defines the listener object's class has the + * appropriate EndpointPermission[endpoint,READ] for the endpoint + * referenced by the event. + * + * + * @see RemoteServiceAdminEvent + * @ThreadSafe + * @version $Revision$ + */ + +public interface RemoteServiceAdminListener { + /** + * Receive notification of any export or import registrations and + * unregistrations. + * + * @param event The {@link RemoteServiceAdminEvent} object. + */ + void remoteAdminEvent(RemoteServiceAdminEvent event); +} -- cgit v1.2.3