blob: 1ea1f698ed67f4d6e20929204fa98c8d10675067 [file] [log] [blame]
/*
* 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 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 $Revision: 1.6 $
*/
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.
* <p>
* The instance identifier should follow the following scheme:
* &lt;<i>application descriptor PID</i>&gt;.&lt;<i>index</i>&gt;
* where &lt;<i>application descriptor PID</i>&gt; is the PID of the
* corresponding {@code ApplicationDescriptor} and &lt;<i>index</i>&gt;
* 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;
}
/**
* 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.
* <ul>
* <li> negative - The method does not wait for termination. If the
* application has not terminated then an {@code ApplicationException}
* is thrown.</li>
*
* <li> zero - The method waits until the application terminates.</li>
*
* <li> 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.</li>
* </ul>
* <p>
* The default implementation throws an
* {@code UnsupportedOperationException}. The application model should
* override this method if exit values are supported.
* </p>
*
* @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.
* <p>
* 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.
* <p>
* At the end the {@code ApplicationHandle} must be unregistered.
* This method should free all the resources related to this
* {@code ApplicationHandle}.
* <p>
* 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() {
if (STOPPING.equals(getState()))
return;
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new ApplicationAdminPermission(getApplicationDescriptor(), ApplicationAdminPermission.LIFECYCLE_ACTION));
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();
}