/* Copyright (c) 2006-2009 Jan S. Rellermeyer * Systems Group, * Department of Computer Science, ETH Zurich. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of ETH Zurich nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package ch.ethz.iks.r_osgi; import java.io.IOException; import org.osgi.framework.Filter; import ch.ethz.iks.r_osgi.channels.ChannelEndpointManager; /** * <p> * RemoteOSGiService provides transparent access to services on remote service * platforms. It uses SLP as underlying discovery protocol. Local services can * be registered for remoting, applications can register listeners for * <code>ServiceTypes</code> to be informed whenever matching services have been * discovered. * </p> * <p> * As soon as a service has been discovered and the listener has been informed, * the application can fetch the service. In the default case, the service * interface is transferred to the receiving peer together with an optional * smart proxy class and optional injections. The service then builds a proxy * bundle and registers it with the local framework so that the application can * get a service reference as if the service was local. Internally, all methods * of the service interface are implemented as remote method calls. * </p> * <p> * Services can define smart proxies to move some parts of the code to the * client. This is done by an abstract class. All implemented method will be * executed on the client, abstract methods will be implemented by remote method * calls. Moving parts of the code to the client can be useful for saving * service provider platform's resources. * </p> * <p> * Injections are used if the service interface uses classes as method arguments * that are not expected to be present on client side. These classes will be * automatically injected into the proxy bundle. The registrator can manually * inject additional classes. * </p> * <p> * With version 0.5, there is also the possibility to register a service with * the MIGRATE_BUNDLE policy. In this case, the bundle that provides the service * is moved to the requesting peer. * </p> * * @author Jan S. Rellermeyer, ETH Zurich * @since 0.1 */ public interface RemoteOSGiService { // public constants for service registrations /** * Default proxy prefix. */ String R_OSGi_PROXY_PREFIX = System.getProperty("ch.ethz.iks.r_osgi.proxyprefix", "ch.ethz.iks.r_osgi.genproxy.endpoint."); /** * this property has to be set in order to release a service for remote * access. Currently, the following two policies are supported. * * @since 0.5 */ String R_OSGi_REGISTRATION = "service.remote.registration"; //$NON-NLS-1$ /** * Can be set to use a smart proxy. Smart proxies have to be abstract * classes implementing the service interface. All abstract methods are * implemented as remote calls, implemented methods remain untouched. This * allows to perform some of the work on client side (inside of implemented * methods). The value of this property in the service property dictionary * has to be a the name of a class. * * @since 0.5 */ String SMART_PROXY = "service.remote.smartproxy"; //$NON-NLS-1$ /** * For special purposes, the service can decide to inject other classes into * the proxy bundle that is dynamically created on the client side. For * instance, if types are use as arguments of method calls that are not part * of the standard execution environment and the service does not want to * rely on assumption that the corresponding classes are present on client * side, it can inject these classes. The value of this property in the * service property dictionary has to be an array of <code>Class</code> * objects. * * @since 0.5 */ String INJECTIONS = "service.remote.injections"; //$NON-NLS-1$ /** * property for registration of a service UI component that gived the user a * presentation of the service. The value of the property in the service * property dictionary has to be a name of a class implementing * <code>org.service.proposition.remote.ServiceUIComponent</code>. When this * property is set, the presentation is injected into the bundle and the * R-OSGi ServiceUI can display the presentation when the service is * discovered. * * @since 0.5 */ String PRESENTATION = "service.presentation"; //$NON-NLS-1$ /** * the property key for the host name of the remote service. This constant * is set by R-OSGi when a service is transferred to a remote peer. So to * find out whether a service is provided by an R-OSGi proxy, check for the * presence of this key in the service properties. * * @since 1.0 */ String SERVICE_URI = "service.uri"; //$NON-NLS-1$ /** * connect to a remote OSGi framework. Has to be called prior to any service * access. Causes the frameworks to exchange leases and start the transport * of remote events. * * @param endpoint * the endpoint to connect to. * @return the array of remote service references of the services that the * remote frameworks offers. * @throws RemoteOSGiException * in case of connection errors. * if the connection attempt fails. * @throws IOException * @since 0.6 */ RemoteServiceReference[] connect(final URI endpoint) throws RemoteOSGiException, IOException; /** * disconnect from a connected host. * * @param endpoint * the URI of the remote host. * @throws RemoteOSGiException * if something goes wrong. */ void disconnect(final URI endpoint) throws RemoteOSGiException; /** * get a remote service reference for a given URI. * * @param serviceURI * the uri of the service. Has to be a channel URI including a * fragment, which is the service ID on the other peer. * @return the remote service reference, or <code>null</code>, if the * service is not present. */ RemoteServiceReference getRemoteServiceReference(final URI serviceURI); /** * get remote service references for all services on a certain peer that * match the given criteria. * * @param endpointAddress * the URI of the peer. * @param clazz * a service interface class, or <code>null</code> for all * services. * @param filter * a filter string, or <code>null</code> * @return an array of remote service references, or <code>null</code> if no * services match. */ RemoteServiceReference[] getRemoteServiceReferences( final URI endpointAddress, final String clazz, final Filter filter); /** * get the a remote service. If there is no proxy bundle for the service so * far, it is generated. * * @param ref * the remote service reference. * @return the service belonging to the service url or null, if no such * service is present. */ Object getRemoteService(final RemoteServiceReference ref); /** * get a copy of the bundle that has registered the remote service. * * @param ref * the remote service reference * @param timeout * number of milliseconds to wait for the service to be * registered after the bundle has been started. A value of 0 * means indefinite time, a negative value means don't wait at * all. * @return the service object or null if the timeout is exceeded and the * service has not appeared. * @throws InterruptedException */ Object getRemoteServiceBundle(final RemoteServiceReference ref, final int timeout) throws InterruptedException; /** * unget the service. The proxy bundle will be uninstalled. The service will * be no longer available, unless it is retrieved through * {@link #getRemoteService(RemoteServiceReference)} again. * * @param remoteServiceReference * thre remote service reference. */ void ungetRemoteService(final RemoteServiceReference remoteServiceReference); /** * get the endpoint manager for a channel to a given remote peer. * * @param remoteEndpointAddress * the endpoint address of the remote peer. * @return the endpoint manager, or <code>null</code> if no such channel * exists. */ ChannelEndpointManager getEndpointManager(final URI remoteEndpointAddress); /** * make an asynchronous remote call to a service * * @param service * the URI of the service * @param methodSignature * the signature of the method to call * @param args * the arguments to pass * @param callback * a callback to be called when the result is available */ void asyncRemoteCall(final URI service, final String methodSignature, final Object[] args, final AsyncRemoteCallCallback callback); /** * get the port on which the corresponding NetworkChannelFactory for the * given protocol listens for incoming connections. * * @param protocol * the protocol identifier string. E.g., "r-osgi" for the default * TCP-based transport * @return the port number or -1 if the protocol is not supported. */ int getListeningPort(final String protocol); }