blob: 13087fbd8dff1b17ba69055dff5b5ef2a5804100 [file] [log] [blame]
/*
* Copyright (c) OSGi Alliance (2012). 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.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>{@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
* @noimplement
* @version $Id: 73028a6997272cbac7e90ae00eb0f28afd14c8ee $
*/
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 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.<br/>
* - If the installing and installed subsystems' types are not equal, an
* installation failure results.<br/>
* - If the installing and installed subsystems' types are equal, and the
* installed subsystem is already a child of this subsystem, return the
* installed subsystem.<br/>
* - 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>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>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);
/**
* 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}<br/>
* {@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}<br/>
* {@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();
}