/* * Copyright (c) OSGi Alliance (2012, 2013). 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.subsystem; import java.io.InputStream; import java.util.Collection; import java.util.Locale; import java.util.Map; import org.osgi.annotation.versioning.ProviderType; import org.osgi.framework.BundleContext; import org.osgi.framework.Version; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.resource.Resource; /** * A subsystem is a collection of resources constituting a logical, possibly * isolated, unit of functionality. * * <p> * A subsystem may be <i>scoped</i> or <i>unscoped</i>. Scoped subsystems are * isolated by implicit or explicit sharing policies. Unscoped subsystems are * not isolated and, therefore, have no sharing policy. There are three standard * {@link SubsystemConstants#SUBSYSTEM_TYPE types} of subsystems. * <ul> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION Application} - An * implicitly scoped subsystem. Nothing is exported, and imports are computed * based on any unsatisfied content requirements.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_COMPOSITE Composite} - An * explicitly scoped subsystem. The sharing policy is defined by metadata within * the subsystem archive.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_FEATURE Feature} - An unscoped * subsystem.</li> * </ul> * Conceptually, a subsystem may be thought of as existing in an isolated region * along with zero or more other subsystems. Each region has one and only one * scoped subsystem, which dictates the sharing policy. The region may, however, * have many unscoped subsystems. It is, therefore, possible to have shared * constituents across multiple subsystems within a region. Associated with each * region is a bundle whose context may be {@link #getBundleContext() retrieved} * from any subsystem within that region. This context may be used to monitor * activity occurring within the region. * * <p> * A subsystem may have {@link #getChildren() children} and, unless it's the * root subsystem, must have at least one {@link #getParents() parent}. * Subsystems become children of the subsystem in which they are installed. * Unscoped subsystems have more than one parent if they are installed in more * than one subsystem within the same region. The subsystem graph may be thought * of as an <a * href="http://en.wikipedia.org/wiki/Directed_acyclic_graph">acyclic * digraph</a> with one and only one source vertex, which is the root subsystem. * The edges have the child as the head and parent as the tail. * * <p> * A subsystem has several identifiers. * <ul> * <li>{@link #getLocation() Location} - An identifier specified by the client * as part of installation. It is guaranteed to be unique within the same * framework.</li> * <li>{@link #getSubsystemId() ID} - An identifier generated by the * implementation as part of installation. It is guaranteed to be unique within * the same framework.</li> * <li>{@link #getSymbolicName() Symbolic Name}/{@link #getVersion() Version} - * The combination of symbolic name and version is guaranteed to be unique * within the same region. Although {@link #getType() type} is not formally part * of the identity, two subsystems with the same symbolic names and versions but * different types are not considered to be equal.</li> * </ul> * A subsystem has a well-defined {@link State life cycle}. Which stage a * subsystem is in may be obtained from the subsystem's {@link #getState() * state} and is dependent on which life cycle operation is currently active or * was last invoked. * * <p> * A subsystem archive is a ZIP file having an {@code .esa} extension and * containing metadata describing the subsystem. The form of the metadata may be * a subsystem or deployment manifest, as well as any content resource files. * The manifests are optional and will be computed if not present. The subsystem * manifest headers may be {@link #getSubsystemHeaders(Locale) retrieved} in raw * or localized forms. There are five standard * {@link IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE types} of resources that * may be included in a subsystem. * <ul> * <li>{@link IdentityNamespace#TYPE_BUNDLE Bundle} - A bundle that is not a * fragment.</li> * <li>{@link IdentityNamespace#TYPE_FRAGMENT Fragment} - A fragment bundle.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION Application * Subsystem} - An application subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_COMPOSITE Composite Subsystem} - * A composite subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_FEATURE Feature Subsystem} - A * feature subsystem.</li> * </ul> * Resources contained by a subsystem are called {@link #getConstituents() * constituents}. There are several ways a resource may become a constituent of * a subsystem: * <ul> * <li>A resource is listed as part of the subsystem's content.</li> * <li>A subsystem resource is a child of the subsystem.</li> * <li>The subsystem has a provision policy of accept dependencies.</li> * <li>A bundle resource is installed using the region bundle context.</li> * <li>A bundle resource is installed using the bundle context of another * resource contained by the subsystem.</li> * </ul> * * <p> * In addition to invoking one of the install methods, a subsystem instance may * be obtained through the service registry. Each installed subsystem has a * corresponding service registration. A subsystem service has the following * properties. * * <ul> * <li>{@link SubsystemConstants#SUBSYSTEM_ID_PROPERTY ID} - The ID of the * subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_SYMBOLICNAME_PROPERTY Symbolic Name} * - The symbolic name of the subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_VERSION_PROPERTY Version} - The * version of the subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_TYPE_PROPERTY Type} - The type of the * subsystem.</li> * <li>{@link SubsystemConstants#SUBSYSTEM_STATE_PROPERTY State} - The state of * the subsystem.</li> * </ul> * * <p> * Because a subsystem must be used to install other subsystems, a root * subsystem is provided as a starting point. The root subsystem may only be * obtained as a service and has the following characteristics. * * <ul> * <li>The ID is {@code 0}.</li> * <li>The symbolic name is * {@link SubsystemConstants#ROOT_SUBSYSTEM_SYMBOLICNAME * org.osgi.service.subsystem.root}.</li> * <li>The version matches this specification's version.</li> * <li>It has no parents.</li> * <li>All existing bundles, including the system and subsystem implementation * bundles, are constituents.</li> * <li>The type is {@link SubsystemConstants#SUBSYSTEM_TYPE_APPLICATION * osgi.subsystem.application} with no imports.</li> * <li>The provision policy is * {@link SubsystemConstants#PROVISION_POLICY_ACCEPT_DEPENDENCIES * acceptDependencies}.</li> * </ul> * * @ThreadSafe * @author $Id: 46dbc3d05b6c0fcd6962ffe433b62cbd284c3d0d $ */ @ProviderType public interface Subsystem { /** * An enumeration of the possible states of a subsystem. * * <p> * These states are a reflection of what constituent resources are permitted * to do and not an aggregation of constituent resource states. */ public static enum State { /** * The subsystem is in the process of installing. * <p> * A subsystem is in the {@code INSTALLING} state when the * {@link Subsystem#install(String, InputStream) install} method of its * parent is active, and attempts are being made to install its content * resources. If the install method completes without exception, then * the subsystem has successfully installed and must move to the * {@link #INSTALLED} state. Otherwise, the subsystem has failed to * install and must move to the {@link #INSTALL_FAILED} state. */ INSTALLING, /** * The subsystem is installed but not yet resolved. * <p> * A subsystem is in the {@code INSTALLED} state when it has been * installed in a parent subsystem but is not or cannot be resolved. * This state is visible if the dependencies of the subsystem's content * resources cannot be resolved. */ INSTALLED, /** * The subsystem failed to install. * <p> * A subsystem is in the {@code INSTALL_FAILED} state when an * unrecoverable error occurred during installation. The subsystem is in * an unusable state but references to the subsystem object may still be * available and used for introspection. */ INSTALL_FAILED, /** * The subsystem is in the process of resolving. * <p> * A subsystem is in the {@code RESOLVING} state when the * {@link Subsystem#start() start} method is active, and attempts are * being made to resolve its content resources. If the resolve method * completes without exception, then the subsystem has successfully * resolved and must move to the {@link #RESOLVED} state. Otherwise, the * subsystem has failed to resolve and must move to the INSTALLED state. */ RESOLVING, /** * The subsystem is resolved and able to be started. * <p> * A subsystem is in the {@code RESOLVED} state when all of its content * resources are resolved. Note that the subsystem is not active yet. */ RESOLVED, /** * The subsystem is in the process of starting. * <p> * A subsystem is in the {@code STARTING} state when its * {@link Subsystem#start() start} method is active, and attempts are * being made to start its content and dependencies. If the start method * completes without exception, then the subsystem has successfully * started and must move to the {@link #ACTIVE} state. Otherwise, the * subsystem has failed to start and must move to the {@link #RESOLVED} * state. */ STARTING, /** * The subsystem is now running. * <p> * A subsystem is in the {@code ACTIVE} state when its content and * dependencies have been successfully started. */ ACTIVE, /** * The subsystem is in the process of stopping. * <p> * A subsystem is in the {@code STOPPING} state when its * {@link Subsystem#stop() stop} method is active, and attempts are * being made to stop its content and dependencies. When the stop method * completes, the subsystem is stopped and must move to the * {@link #RESOLVED} state. */ STOPPING, /** * The subsystem is in the process of uninstalling. * <p> * A subsystem is in the {@code UNINSTALLING} state when its * {@link Subsystem#uninstall() uninstall} method is active, and * attempts are being made to uninstall its constituent and * dependencies. When the uninstall method completes, the subsystem is * uninstalled and must move to the {@link #UNINSTALLED} state. */ UNINSTALLING, /** * The subsystem is uninstalled and may not be used. * <p> * The {@code UNINSTALLED} state is only visible after a subsystem's * constituent and dependencies are uninstalled. The subsystem is in an * unusable state but references to the subsystem object may still be * available and used for introspection. */ UNINSTALLED } /** * Returns the bundle context of the region within which this subsystem * resides. * <p> * The bundle context offers the same perspective of any resource contained * by a subsystem within the region. It may be used, for example, to monitor * events internal to the region as well as external events visible to the * region. All subsystems within the same region have the same bundle * context. If this subsystem is in a state where the bundle context would * be invalid, {@code null} is returned. * * @return The bundle context of the region within which this subsystem * resides or {@code null} if this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLED UNINSTALLED}. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,CONTEXT], and the runtime * supports permissions. */ public BundleContext getBundleContext(); /** * Returns the child subsystems of this subsystem. * * @return The child subsystems of this subsystem. The returned collection * is an unmodifiable snapshot of all subsystems that are installed * in this subsystem. The collection will be empty if no subsystems * are installed in this subsystem. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLED UNINSTALLED}. */ public Collection<Subsystem> getChildren(); /** * Returns the headers for this subsystem's subsystem manifest. * <p> * Each key in the map is a header name and the value of the key is the * corresponding header value. Because header names are case-insensitive, * the methods of the map must treat the keys in a case-insensitive manner. * If the header name is not found, {@code null} is returned. Both original * and derived headers will be included in the map. * <p> * This method must continue to return the headers while this subsystem is * in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @param locale The locale for which translations are desired. The header * values are translated according to the specified locale. If the * specified locale is {@code null} or not supported, the raw values * are returned. If the translation for a particular header is not * found, the raw value is returned. * @return The headers for this subsystem's subsystem manifest. The returned * map is unmodifiable. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,METADATA], and the runtime * supports permissions. */ public Map<String, String> getSubsystemHeaders(Locale locale); /** * Returns the location identifier of this subsystem. * <p> * The location identifier is the {@code location} that was passed to the * {@link #install(String, InputStream) install} method of the * {@link #getParents() parent} subsystem. It is unique within the * framework. * <p> * This method must continue to return this subsystem's headers while this * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The location identifier of this subsystem. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,METADATA], and the runtime * supports permissions. */ public String getLocation(); /** * Returns the parent subsystems of this subsystem. * * @return The parent subsystems of this subsystem. The returned collection * is an unmodifiable snapshot of all subsystems in which this * subsystem is installed. The collection will be empty for the root * subsystem; otherwise, it must contain at least one parent. Scoped * subsystems always have only one parent. Unscoped subsystems may * have multiple parents. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLED UNINSTALLED}. */ public Collection<Subsystem> getParents(); /** * Returns the constituent resources of this subsystem. * * @return The constituent resources of this subsystem. The returned * collection is an unmodifiable snapshot of the constituent * resources of this subsystem. If this subsystem has no * constituents, the collection will be empty. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLED UNINSTALLED}. */ public Collection<Resource> getConstituents(); /** * Returns the headers for this subsystem's deployment manifest. * <p> * Each key in the map is a header name and the value of the key is the * corresponding header value. Because header names are case-insensitive, * the methods of the map must treat the keys in a case-insensitive manner. * If the header name is not found, {@code null} is returned. Both original * and derived headers will be included in the map. * <p> * This method must continue to return the headers while this subsystem is * in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The headers for this subsystem's deployment manifest. The * returned map is unmodifiable. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,METADATA], and the runtime * supports permissions. * @since 1.1 */ public Map<String, String> getDeploymentHeaders(); /** * Returns the current state of this subsystem. * <p> * This method must continue to return this subsystem's state while this * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The current state of this subsystem. */ public State getState(); /** * Returns the identifier of this subsystem. * <p> * The identifier is a monotonically increasing, non-negative integer * automatically generated at installation time and guaranteed to be unique * within the framework. The identifier of the root subsystem is zero. * <p> * This method must continue to return this subsystem's identifier while * this subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The identifier of this subsystem. */ public long getSubsystemId(); /** * Returns the symbolic name of this subsystem. * <p> * The subsystem symbolic name conforms to the same grammar rules as the * bundle symbolic name and is derived from one of the following, in order. * <ul> * <li>The value of the {@link SubsystemConstants#SUBSYSTEM_SYMBOLICNAME * Subsystem-SymbolicName} header, if specified.</li> * <li>The subsystem URI if passed as the {@code location} along with the * {@code content} to the {@link #install(String, InputStream) install} * method.</li> * <li>Optionally generated in an implementation specific way.</li> * </ul> * The combination of subsystem symbolic name and {@link #getVersion() * version} is unique within a region. The symbolic name of the root * subsystem is {@link SubsystemConstants#ROOT_SUBSYSTEM_SYMBOLICNAME * org.osgi.service.subsystem.root}. * <p> * This method must continue to return this subsystem's symbolic name while * this subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The symbolic name of this subsystem. */ public String getSymbolicName(); /** * Returns the {@link SubsystemConstants#SUBSYSTEM_TYPE type} of this * subsystem. * <p> * This method must continue to return this subsystem's type while this * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The type of this subsystem. */ public String getType(); /** * Returns the {@link SubsystemConstants#SUBSYSTEM_VERSION version} of this * subsystem. * <p> * The subsystem version conforms to the same grammar rules as the bundle * version and is derived from one of the following, in order. * <ul> * <li>The value of the {@link SubsystemConstants#SUBSYSTEM_VERSION * Subsystem-Version} header, if specified.</li> * <li>The subsystem URI if passed as the {@code location} along with the * {@code content} to the {@link #install(String, InputStream) install} * method.</li> * <li>Defaults to {@code 0.0.0}.</li> * </ul> * The combination of subsystem {@link #getSymbolicName() symbolic name} and * version is unique within a region. The version of the root subsystem * matches this specification's version. * <p> * This method must continue to return this subsystem's version while this * subsystem is in the {@link State#INSTALL_FAILED INSTALL_FAILED} or * {@link State#UNINSTALLED UNINSTALLED} states. * * @return The version of this subsystem. */ public Version getVersion(); /** * Installs a subsystem from the specified location identifier. * <p> * This method performs the same function as calling * {@link #install(String, InputStream)} with the specified location * identifier and {@code null} as the content. * * @param location The location identifier of the subsystem to install. * @return The installed subsystem. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED * INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING}, * {@link State#UNINSTALLED UNINSTALLED}. * @throws SubsystemException If the installation failed. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and * the runtime supports permissions. * @see #install(String, InputStream) */ public Subsystem install(String location); /** * Installs a subsystem from the specified content. * <p> * The specified location will be used as an identifier of the subsystem. * Every installed subsystem is uniquely identified by its location, which * is typically in the form of a URI. If the specified location conforms to * the {@code subsystem-uri} grammar, the required symbolic name and * optional version information will be used as default values. * <p> * If the specified content is {@code null}, a new input stream must be * created from which to read the subsystem by interpreting, in an * implementation dependent manner, the specified location. * <p> * A subsystem installation must be persistent. That is, an installed * subsystem must remain installed across Framework and VM restarts. * <p> * All references to changing the state of this subsystem include both * changing the state of the subsystem object as well as the state property * of the subsystem service registration. * <p> * The following steps are required to install a subsystem. * <ol> * <li>If an installed subsystem with the specified location identifier * already exists, return the installed subsystem.</li> * <li>Read the specified content in order to determine the symbolic name, * version, and type of the installing subsystem. If an error occurs while * reading the content, an installation failure results.</li> * <li>If an installed subsystem with the same symbolic name and version * already exists within this subsystem's region, complete the installation * with one of the following. * <ul> * <li>If the installing and installed subsystems' types are not equal, an * installation failure results.</li> * <li>If the installing and installed subsystems' types are equal, and the * installed subsystem is already a child of this subsystem, return the * installed subsystem.</li> * <li>If the installing and installed subsystems' types are equal, and the * installed subsystem is not already a child of this subsystem, add the * installed subsystem as a child of this subsystem, increment the installed * subsystem's reference count by one, and return the installed subsystem.</li> * </ul> * <li>Create a new subsystem based on the specified location and content.</li> * <li>If the subsystem is scoped, install and start a new region context * bundle.</li> * <li>Change the state to {@link State#INSTALLING INSTALLING} and register * a new subsystem service.</li> * <li>Discover the subsystem's content resources. If any mandatory resource * is missing, an installation failure results.</li> * <li>Discover the dependencies required by the content resources. If any * mandatory dependency is missing, an installation failure results.</li> * <li>Using a framework {@code ResolverHook}, disable runtime resolution * for the resources.</li> * <li>For each resource, increment the reference count by one. If the * reference count is one, install the resource. If an error occurs while * installing a resource, an install failure results with that error as the * cause.</li> * <li>If the subsystem is scoped, enable the import sharing policy.</li> * <li>Enable runtime resolution for the resources.</li> * <li>Change the state of the subsystem to {@link State#INSTALLED * INSTALLED}.</li> * <li>Return the new subsystem.</li> * </ol> * <p> * Implementations should be sensitive to the potential for long running * operations and periodically check the current thread for interruption. An * interrupted thread should result in a {@link SubsystemException} with an * InterruptedException as the cause and be treated as an installation * failure. * <p> * All installation failure flows include the following, in order. * <ol> * <li>Change the state to {@link State#INSTALL_FAILED INSTALL_FAILED}.</li> * <li>Change the state to {@link State#UNINSTALLING UNINSTALLING}.</li> * <li>All content and dependencies which may have been installed by the * installing process must be uninstalled.</li> * <li>Change the state to {@link State#UNINSTALLED UNINSTALLED}.</li> * <li>Unregister the subsystem service.</li> * <li>If the subsystem is a scoped subsystem then, uninstall the region * context bundle.</li> * <li>Throw a {@link SubsystemException} with the cause of the installation * failure.</li> * </ol> * * @param location The location identifier of the subsystem to be installed. * @param content The input stream from which this subsystem will be read or * {@code null} to indicate the input stream must be created from the * specified location identifier. The input stream will always be * closed when this method completes, even if an exception is thrown. * @return The installed subsystem. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED * INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING}, * {@link State#UNINSTALLED UNINSTALLED}. * @throws SubsystemException If the installation failed. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and * the runtime supports permissions. */ public Subsystem install(String location, InputStream content); /** * Installs a subsystem from the specified content according to the * specified deployment manifest. * <p> * This method installs a subsystem using the provided deployment manifest * instead of the one in the archive, if any, or a computed one. If the * deployment manifest is {@code null}, the behavior is exactly the same as * in the {@link #install(String, InputStream)} method. Implementations must * support deployment manifest input streams in the format described by * section 134.2 of the Subsystem Service Specification. If the deployment * manifest does not conform to the subsystem manifest (see 134.15.2), the * installation fails. * * @param location The location identifier of the subsystem to be installed. * @param content The input stream from which this subsystem will be read or * {@code null} to indicate the input stream must be created from the * specified location identifier. The input stream will always be * closed when this method completes, even if an exception is thrown. * @param deploymentManifest The deployment manifest to use in lieu of the * one in the archive, if any, or a computed one. * @return The installed subsystem. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED * INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING}, * {@link State#UNINSTALLED UNINSTALLED}. * @throws SubsystemException If the installation failed. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and * the runtime supports permissions. * @since 1.1 */ public Subsystem install(String location, InputStream content, InputStream deploymentManifest); /** * Starts this subsystem. * <p> * The following table shows which actions are associated with each state. * An action of {@code Wait} means this method will block until a state * transition occurs, upon which the new state will be evaluated in order to * determine how to proceed. If a state transition does not occur in a * reasonable time while waiting then no action is taken and a * SubsystemException is thrown to indicate the subsystem was unable to be * started. An action of {@code Return} means this method returns * immediately without taking any other action. * </p> * <table> * <tr> * <th>State</th> * <th width="4">Action</th> * </tr> * <tr> * <td>{@link State#INSTALLING INSTALLING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#INSTALLED INSTALLED}</td> * <td>{@code Resolve}, {@code Start}</td> * </tr> * <tr> * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td> * <td>{@code IllegalStateException}</td> * </tr> * <tr> * <td>{@link State#RESOLVING RESOLVING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#RESOLVED RESOLVED}</td> * <td>{@code Start}</td> * </tr> * <tr> * <td>{@link State#STARTING STARTING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#ACTIVE ACTIVE}</td> * <td>{@code Return}</td> * </tr> * <tr> * <td>{@link State#STOPPING STOPPING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#UNINSTALLING UNINSTALLING}</td> * <td>{@code IllegalStateException}</td> * </tr> * <tr> * <td>{@link State#UNINSTALLED UNINSTALLED}</td> * <td>{@code IllegalStateException}</td> * </tr> * </table> * <p> * All references to changing the state of this subsystem include both * changing the state of the subsystem object as well as the state property * of the subsystem service registration. * <p> * A subsystem must be persistently started. That is, a started subsystem * must be restarted across Framework and VM restarts, even if a start * failure occurs. * <p> * The following steps are required to start this subsystem. * <ol> * <li>Set the subsystem <i>autostart setting</i> to <i>started</i>.</li> * <li>If this subsystem is in the {@link State#RESOLVED RESOLVED} state, * proceed to step 7.</li> * <li>Change the state to {@link State#RESOLVING RESOLVING}.</li> * <li>Resolve the content resources. A resolution failure results in a * start failure with a state of {@link State#INSTALLED INSTALLED}.</li> * <li>Change the state to {@link State#RESOLVED RESOLVED}.</li> * <li>If this subsystem is scoped, enable the export sharing policy.</li> * <li>Change the state to {@link State#STARTING STARTING}.</li> * <li>For each eligible resource, increment the active use count by one. If * the active use count is one, start the resource. All dependencies must be * started before any content resource, and content resources must be * started according to the specified * {@link SubsystemConstants#START_ORDER_DIRECTIVE start order}. If an error * occurs while starting a resource, a start failure results with that error * as the cause.</li> * <li>Change the state to {@link State#ACTIVE ACTIVE}.</li> * </ol> * <p> * Implementations should be sensitive to the potential for long running * operations and periodically check the current thread for interruption. An * interrupted thread should be treated as a start failure with an * {@code InterruptedException} as the cause. * <p> * All start failure flows include the following, in order. * <ol> * <li>If the subsystem state is {@link State#STARTING STARTING} then change * the state to {@link State#STOPPING STOPPING} and stop all resources that * were started as part of this operation.</li> * <li>Change the state to either {@link State#INSTALLED INSTALLED} or * {@link State#RESOLVED RESOLVED}.</li> * <li>Throw a SubsystemException with the specified cause.</li> * </ol> * * @throws SubsystemException If this subsystem fails to start. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLING UNINSTALLING}, or * {@link State#UNINSTALLED UNINSTALLED}, or if the state of at * least one of this subsystem's parents is not in * {@link State#STARTING STARTING}, {@link State#ACTIVE ACTIVE}. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,EXECUTE], and the runtime * supports permissions. */ public void start(); /** * Stops this subsystem. * <p> * The following table shows which actions are associated with each state. * An action of {@code Wait} means this method will block until a state * transition occurs, upon which the new state will be evaluated in order to * determine how to proceed. If a state transition does not occur in a * reasonable time while waiting then no action is taken and a * SubsystemException is thrown to indicate the subsystem was unable to be * stopped. An action of {@code Return} means this method returns * immediately without taking any other action. * </p> * <table> * <tr> * <th>State</th> * <th width="4">Action</th> * </tr> * <tr> * <td>{@link State#INSTALLING INSTALLING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#INSTALLED INSTALLED}</td> * <td>{@code Return}</td> * <td> * <tr> * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td> * <td>{@code IllegalStateException}</td> * <td> * <tr> * <td>{@link State#RESOLVING RESOLVING}</td> * <td>{@code Wait}</td> * <td> * <tr> * <td>{@link State#RESOLVED RESOLVED}</td> * <td>{@code Return}</td> * <td> * <tr> * <td>{@link State#STARTING STARTING}</td> * <td>{@code Wait}</td> * <td> * <tr> * <td>{@link State#ACTIVE ACTIVE}</td> * <td>{@code Stop}</td> * <td> * <tr> * <td>{@link State#STOPPING STOPPING}</td> * <td>{@code Wait}</td> * <td> * <tr> * <td>{@link State#UNINSTALLING UNINSTALLING}</td> * <td>{@code IllegalStateException}</td> * <td> * <tr> * <td>{@link State#UNINSTALLED UNINSTALLED}</td> * <td>{@code IllegalStateException}</td> * <td> * </table> * <p> * A subsystem must be persistently stopped. That is, a stopped subsystem * must remain stopped across Framework and VM restarts. * <p> * All references to changing the state of this subsystem include both * changing the state of the subsystem object as well as the state property * of the subsystem service registration. * <p> * The following steps are required to stop this subsystem. * <ol> * <li>Set the subsystem <i>autostart setting</i> to <i>stopped</i>.</li> * <li>Change the state to {@link State#STOPPING STOPPING}.</li> * <li>For each eligible resource, decrement the active use count by one. If * the active use count is zero, stop the resource. All content resources * must be stopped before any dependencies, and content resources must be * stopped in reverse {@link SubsystemConstants#START_ORDER_DIRECTIVE start * order}.</li> * <li>Change the state to {@link State#RESOLVED RESOLVED}.</li> * </ol> * With regard to error handling, once this subsystem has transitioned to * the {@link State#STOPPING STOPPING} state, every part of each step above * must be attempted. Errors subsequent to the first should be logged. Once * the stop process has completed, a SubsystemException must be thrown with * the initial error as the specified cause. * <p> * Implementations should be sensitive to the potential for long running * operations and periodically check the current thread for interruption, in * which case a SubsystemException with an InterruptedException as the cause * should be thrown. If an interruption occurs while waiting, this method * should terminate immediately. Once the transition to the * {@link State#STOPPING STOPPING} state has occurred, however, this method * must not terminate due to an interruption until the stop process has * completed. * * @throws SubsystemException If this subsystem fails to stop cleanly. * @throws IllegalStateException If this subsystem's state is in * {@link State#INSTALL_FAILED INSTALL_FAILED}, * {@link State#UNINSTALLING UNINSTALLING}, or * {@link State#UNINSTALLED UNINSTALLED}. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,EXECUTE], and the runtime * supports permissions. */ public void stop(); /** * Uninstalls this subsystem. * <p> * The following table shows which actions are associated with each state. * An action of {@code Wait} means this method will block until a state * transition occurs, upon which the new state will be evaluated in order to * determine how to proceed. If a state transition does not occur in a * reasonable time while waiting then no action is taken and a * SubsystemException is thrown to indicate the subsystem was unable to be * uninstalled. An action of {@code Return} means this method returns * immediately without taking any other action. * <table> * <tr> * <th>State</th> * <th width="4">Action</th> * </tr> * <tr> * <td>{@link State#INSTALLING INSTALLING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#INSTALLED INSTALLED}</td> * <td>{@code Uninstall}</td> * </tr> * <tr> * <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#RESOLVING RESOLVING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#RESOLVED RESOLVED}</td> * <td>{@code Uninstall}</td> * </tr> * <tr> * <td>{@link State#STARTING STARTING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#ACTIVE ACTIVE}</td> * <td>{@code Stop}, {@code Uninstall}</td> * </tr> * <tr> * <td>{@link State#STOPPING STOPPING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#UNINSTALLING UNINSTALLING}</td> * <td>{@code Wait}</td> * </tr> * <tr> * <td>{@link State#UNINSTALLED UNINSTALLED}</td> * <td>{@code Return}</td> * </tr> * </table> * <p> * All references to changing the state of this subsystem include both * changing the state of the subsystem object as well as the state property * of the subsystem service registration. * <p> * The following steps are required to uninstall this subsystem after being * stopped if necessary. * <ol> * <li>Change the state to {@link State#INSTALLED INSTALLED}.</li> * <li>Change the state to {@link State#UNINSTALLING UNINSTALLING}.</li> * <li>For each referenced resource, decrement the reference count by one. * If the reference count is zero, uninstall the resource. All content * resources must be uninstalled before any dependencies.</li> * <li>Change the state to {@link State#UNINSTALLED UNINSTALLED}.</li> * <li>Unregister the subsystem service.</li> * <li>If the subsystem is scoped, uninstall the region context bundle.</li> * </ol> * With regard to error handling, once this subsystem has transitioned to * the {@link State#UNINSTALLING UNINSTALLING} state, every part of each * step above must be attempted. Errors subsequent to the first should be * logged. Once the uninstall process has completed, a * {@code SubsystemException} must be thrown with the specified cause. * <p> * Implementations should be sensitive to the potential for long running * operations and periodically check the current thread for interruption, in * which case a {@code SubsystemException} with an * {@code InterruptedException} as the cause should be thrown. If an * interruption occurs while waiting, this method should terminate * immediately. Once the transition to the {@link State#UNINSTALLING * UNINSTALLING} state has occurred, however, this method must not terminate * due to an interruption until the uninstall process has completed. * * @throws SubsystemException If this subsystem fails to uninstall cleanly. * @throws SecurityException If the caller does not have the appropriate * {@link SubsystemPermission}[this,LIFECYCLE], and the runtime * supports permissions. */ public void uninstall(); }