All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.osgi.service.application.ApplicationHandle Maven / Gradle / Ivy

/*
 * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 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.application;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;

import org.osgi.framework.Constants;

/**
 * ApplicationHandle is an OSGi service interface which represents an instance
 * of an application. It provides the functionality to query and manipulate the
 * lifecycle state of the represented application instance. It defines constants
 * for the lifecycle states.
 * 
 * @version $Id: 10f890813548235e11bb5cd7f9f1866dcb18d381 $
 */
public abstract class ApplicationHandle {
	/*
	 * NOTE: An implementor may also choose to replace this class in
	 * their distribution with a class that directly interfaces with the
	 * org.osgi.service.application implementation. This replacement class MUST NOT alter the
	 * public/protected signature of this class.
	 */

	/**
	 * The property key for the unique identifier (PID) of the application
	 * instance.
	 */
	public static final String APPLICATION_PID = Constants.SERVICE_PID;
	
	/**
	 * The property key for the pid of the corresponding application descriptor.
	 */
	public final static String APPLICATION_DESCRIPTOR	= "application.descriptor";
	
	/**
	 * The property key for the state of this application instance.
	 */
	public final static String APPLICATION_STATE		= "application.state";

	/**
	 * The property key for the supports exit value property of this application
	 * instance.
	 * 
	 * @since 1.1
	 */
	public final static String APPLICATION_SUPPORTS_EXITVALUE = "application.supports.exitvalue";

	/**
	 * The application instance is running. This is the initial state of a newly
	 * created application instance.
	 */
	public final static String RUNNING = "RUNNING";
	
  /**
   * The application instance is being stopped. This is the state of the
   * application instance during the execution of the {@code destroy()}
   * method.
   */
	public final static String STOPPING = "STOPPING";

	private final String instanceId;
	
	private final ApplicationDescriptor	descriptor;

	/**
	 * Application instance identifier is specified by the container when the
	 * instance is created. The instance identifier must remain static for the 
	 * lifetime of the instance, it must remain the same even across framework
	 * restarts for the same application instance. This value must be the same
	 * as the {@code service.pid} service property of this application
	 * handle.
	 * 

* The instance identifier should follow the following scheme: * <application descriptor PID>.<index> * where <application descriptor PID> is the PID of the * corresponding {@code ApplicationDescriptor} and <index> * is a unique integer index assigned by the application container. * Even after destroying the application index the same index value should not * be reused in a reasonably long timeframe. * * @param instanceId the instance identifier of the represented application * instance. It must not be null. * * @param descriptor the {@code ApplicationDescriptor} of the represented * application instance. It must not be null. * * @throws NullPointerException if any of the arguments is null. */ protected ApplicationHandle(String instanceId, ApplicationDescriptor descriptor ) { if( (null == instanceId) || (null == descriptor) ) { throw new NullPointerException("Parameters must not be null!"); } this.instanceId = instanceId; this.descriptor = descriptor; try { delegate = new Delegate(); delegate.setApplicationHandle( this, descriptor.delegate ); } catch (Exception e) { // Too bad ... e.printStackTrace(); System.err .println("No implementation available for ApplicationDescriptor, property is: " + Delegate.cName); } } /** * Retrieves the {@code ApplicationDescriptor} to which this * {@code ApplicationHandle} belongs. * * @return The corresponding {@code ApplicationDescriptor} */ public final ApplicationDescriptor getApplicationDescriptor() { return descriptor; } /** * Get the state of the application instance. * * @return the state of the application. * * @throws IllegalStateException * if the application handle is unregistered */ public abstract String getState(); /** * Returns the exit value for the application instance. The timeout * specifies how the method behaves when the application has not yet * terminated. A negative, zero or positive value may be used. *

    *
  • negative - The method does not wait for termination. If the * application has not terminated then an {@code ApplicationException} * is thrown.
  • * *
  • zero - The method waits until the application terminates.
  • * *
  • positive - The method waits until the application terminates or the * timeout expires. If the timeout expires and the application has not * terminated then an {@code ApplicationException} is thrown.
  • *
*

* The default implementation throws an * {@code UnsupportedOperationException}. The application model should * override this method if exit values are supported. *

* * @param timeout The maximum time in milliseconds to wait for the * application to timeout. * @return The exit value for the application instance. The value is * application specific. * @throws UnsupportedOperationException If the application model does not * support exit values. * @throws InterruptedException If the thread is interrupted while waiting * for the timeout. * @throws ApplicationException If the application has not terminated. The * error code will be * {@link ApplicationException#APPLICATION_EXITVALUE_NOT_AVAILABLE}. * * @since 1.1 */ public Object getExitValue(long timeout) throws ApplicationException, InterruptedException{ throw new UnsupportedOperationException(); } /** * Returns the unique identifier of this instance. This value is also * available as a service property of this application handle's service.pid. * * @return the unique identifier of the instance */ public final String getInstanceId() { return instanceId; } /** * The application instance's lifecycle state can be influenced by this * method. It lets the application instance perform operations to stop * the application safely, e.g. saving its state to a permanent storage. *

* The method must check if the lifecycle transition is valid; a STOPPING * application cannot be stopped. If it is invalid then the method must * exit. Otherwise the lifecycle state of the application instance must be * set to STOPPING. Then the destroySpecific() method must be called to * perform any application model specific steps for safe stopping of the * represented application instance. *

* At the end the {@code ApplicationHandle} must be unregistered. * This method should free all the resources related to this * {@code ApplicationHandle}. *

* When this method is completed the application instance has already made * its operations for safe stopping, the ApplicationHandle has been * unregistered and its related resources has been freed. Further calls on * this application should not be made because they may have unexpected * results. * * @throws SecurityException * if the caller doesn't have "lifecycle" * {@code ApplicationAdminPermission} for the corresponding application. * * @throws IllegalStateException * if the application handle is unregistered */ public final void destroy() { try { delegate.destroy(); }catch( SecurityException se ) { descriptor.isLaunchableSpecific(); /* check whether the bundle was uninstalled */ /* if yes, throws IllegalStateException */ throw se; /* otherwise throw the caught SecurityException */ } destroySpecific(); } /** * Called by the destroy() method to perform application model specific * steps to stop and destroy an application instance safely. * * @throws IllegalStateException * if the application handle is unregistered */ protected abstract void destroySpecific(); Delegate delegate; /** * This class will load the class named * by the org.osgi.vendor.application.ApplicationHandle and delegate * method calls to an instance of the class. */ static class Delegate { static String cName; static Class implementation; static Method setApplicationHandle; static Method destroy; static { AccessController.doPrivileged(new PrivilegedAction() { public Object run(){ cName = System.getProperty("org.osgi.vendor.application.ApplicationHandle"); if (cName == null) { throw new NoClassDefFoundError("org.osgi.vendor.application.ApplicationHandle property must be set"); } try { implementation = Class.forName(cName); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.toString()); } try { setApplicationHandle = implementation.getMethod("setApplicationHandle", new Class[] {ApplicationHandle.class, Object.class}); destroy = implementation.getMethod("destroy", new Class[] {}); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.toString()); } return null; } }); } Object target; Delegate() throws Exception { target = AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws Exception { return implementation.newInstance(); } }); } void setApplicationHandle(ApplicationHandle d, ApplicationDescriptor.Delegate descriptor ) { try { try { setApplicationHandle.invoke(target, new Object[] {d, descriptor.target}); } catch (InvocationTargetException e) { throw e.getTargetException(); } } catch (Error e) { throw e; } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e); } } void destroy() { try { try { destroy.invoke(target, new Object[] {}); } catch (InvocationTargetException e) { throw e.getTargetException(); } } catch (Error e) { throw e; } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy