/* * #%L * Gravia :: Runtime :: API * %% * Copyright (C) 2013 - 2014 JBoss by Red Hat * %% * 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. * #L% */ package org.jboss.gravia.runtime; import java.io.File; import java.net.URL; import java.util.Dictionary; import java.util.List; import org.jboss.gravia.resource.Resource; import org.jboss.gravia.resource.ResourceIdentity; /** * An installed module in the Runtime. * * <p> * A module must have a unique {@link ResourceIdentity} in the Runtime. * * <p> * Gravia stays out of the business of resolving module's at runtime. Every module * has an associated {@link ClassLoader} when it is installed in the runtime already. * Modularity must be dealt with in the layer using the Gravia runtime. * * <p> * For example, a servlet container like Tomcat may choose to create one Module per web application. * Multiple modules may share the same class loader or may even all have the same class loader association. * This allows GRavia to run on a flat class path (e.g. a plain JUnit test) * * <p> * When installed it is also assigned a {@code long} identity, chosen by the Runtime. * This identity does not change during the lifecycle of a module. * Uninstalling and then reinstalling the module creates a new unique {@code long} identity. * * <p> * A module can be in one of six states: * <ul> * <li>{@link State#INSTALLED} * <li>{@link State#RESOLVED} * <li>{@link State#STARTING} * <li>{@link State#ACTIVE} * <li>{@link State#STOPPING} * <li>{@link State#UNINSTALLED} * </ul> * <p> * <p> * A module should only have active threads of execution when its state is one * of {@code STARTING},{@code ACTIVE}, or {@code STOPPING}. * An {@code UNINSTALLED} module can not be set to another state; * it can only be reached because references are kept somewhere. * * <p> * The Runtime is the only entity that is allowed to create {@code Module} * objects, and these objects are only valid within the Runtime that created * them. * * <p> * Modules have a natural ordering such that if two {@code Module}s have the * same {@link #getModuleId() module id} they are equal. A {@code Module} is * less than another {@code Module} if it has a lower {@link #getModuleId() * module id} and is greater if it has a higher module id. * * @author thomas.diesler@jboss.com * @since 27-Sep-2013 * * @ThreadSafe */ public interface Module { /** * A module can be in one of five states: */ enum State { /** * A module is in the {@code INSTALLED} state when it has been installed in the Runtime */ INSTALLED, /** * The module is in the process of starting. * <p> * A module is in the {@code STARTING} state when its {@link #start() * start} method is active. A module must be in this state when the module's * {@link ModuleActivator#start(ModuleContext)} is called. If the * {@code ModuleActivator.start(ModuleContext)} method completes without exception, then * the module has successfully started and must move to the {@code ACTIVE} * state. */ STARTING, /** * The module is now running. * <p> * A module is in the {@code ACTIVE} state when it has been successfully * started and activated. */ ACTIVE, /** * The module is in the process of stopping. * <p> * A module is in the {@code STOPPING} state when its {@link #stop() * stop} method is active. A module must be in this state when the module's * {@link ModuleActivator#stop(ModuleContext)} method is called. When the * {@code ModuleActivator.stop} method completes the module is stopped and * must move to the {@code RESOLVED} state. */ STOPPING, /** * The module is uninstalled and may not be used. */ UNINSTALLED } /** * Addapt this module to another type. * <p/> * All modules support * <ul> * <li>{@link Runtime}</li> * <li>{@link ClassLoader}</li> * <li>{@link Resource}</li> * <li>{@link ModuleContext}</li> * </ul> * @return Null if the module cannot be adapted to the requested type */ <A> A adapt(Class<A> type); /** * Get the identity of this module. */ ResourceIdentity getIdentity(); /** * Returns this module's unique identifier. Each module is assigned a unique * identifier by the Runtime when it was installed. * * <p> * A module's unique identifier has the following attributes: * <ul> * <li>Is unique and persistent. * <li>Is a {@code long}. * <li>Its value is not reused for another module, even after a module is uninstalled. * <li>Does not change while a module remains installed. * </ul> * * <p> * This method must continue to return this module's unique identifier while * this module is in the {@code UNINSTALLED} state. * * @return The unique runtime id of this module. */ long getModuleId(); /** * Returns this module's current state. * @see State */ State getState(); /** * Returns this module's {@link ModuleContext}. The returned * {@code ModuleContext} can be used by the caller to act on behalf of this * module. * * <p> * If this module is not in the {@link State#STARTING}, {@link State#ACTIVE}, or * {@link State#STOPPING} states, then this module has no valid {@code ModuleContext}. * * @return A {@code ModuleContext} for this module or {@code null} if this * module has no valid {@code ModuleContext}. */ ModuleContext getModuleContext(); /** * Returns this module's headers and values that where given on module installation. * * <p> * These values may be mapped to manifest headers, but this is not a requirement. * The module's header values do not change durint the lifecycle of the module. * * <p> * Header names are case-insensitive. The methods of the returned * {@code Dictionary} object must operate on header names in a * case-insensitive manner. * * <p> * This method must continue to return header information while * this module is in the {@code UNINSTALLED} state. * * @return An unmodifiable {@code Dictionary} object containing this * module's Manifest headers and values. */ Dictionary<String, String> getHeaders(); /** * Returns a URL to the entry at the specified path in this module. This * modules's class loader is not used to search for the entry. Only the * contents of this module are searched for the entry. * <p> * The specified path is always relative to the root of this module and may * begin with "/". A path value of "/" indicates the * root of this module. * * @param path The path name of the entry. * @return A URL to the entry, or {@code null} if no entry could be found. */ URL getEntry(String path); /** * Returns an Enumeration of all the paths ({@code String} objects) to * entries within this module whose longest sub-path matches the specified * path. This module's class loader is not used to search for entries. Only * the contents of this module are searched. * <p> * The specified path is always relative to the root of this module and may * begin with a "/". A path value of "/" indicates the * root of this module. * <p> * Returned paths indicating subdirectory paths end with a "/". * The returned paths are all relative to the root of this module and must * not begin with "/". * * @param path The path name for which to return entry paths. * @return A list of the entry paths ({@code String} objects). */ List<String> getEntryPaths(String path); /** * Returns entries in this module. This module's * class loader is not used to search for entries. Only the contents of this * module is searched for the specified entries. * * <p> * URLs for directory entries must have their path end with "/". * * @param path The path name in which to look. The path is always relative * to the root of this module and may begin with "/". A * path value of "/" indicates the root of this module. * @param filePattern The file name pattern for selecting entries in the * specified path. The pattern is only matched against the last * element of the entry path. If the entry is a directory then the * trailing "/" is not used for pattern matching. Substring * matching is supported, as specified in the Filter specification, * using the wildcard character ("*"). If null is * specified, this is equivalent to "*" and matches all * files. * @param recurse If {@code true}, recurse into subdirectories. Otherwise * only return entries from the specified path. * @return A list of URL objects for each matching entry. */ List<URL> findEntries(String path, String filePattern, boolean recurse); /** * Starts this module. * <p> * If this module's state is {@code UNINSTALLED} then an {@code IllegalStateException} is thrown. * <p> * The following steps are required to start this module: * <ol> * * <li>If this module is in the process of being activated or deactivated * then this method must wait for activation or deactivation to complete * before continuing. If this does not occur in a reasonable time, a * {@code ModuleException} is thrown to indicate this module was unable to * be started. * * <li>If this module's state is {@code ACTIVE} then this method returns immediately. * * <li>This module's state is set to {@code STARTING}. * * <li>A module event of type {@link ModuleEvent#STARTING} is fired. * * <li>The {@link ModuleActivator#start(ModuleContext)} method if one is specified, is called. * If the {@code ModuleActivator} is invalid or throws an exception then: * <ul> * <li>This module's state is set to {@code STOPPING}. * <li>A module event of type {@link ModuleEvent#STOPPING} is fired. * <li>Any services registered by this module must be unregistered. * <li>Any services used by this module must be released. * <li>Any listeners registered by this module must be removed. * <li>This module's state is set to {@code RESOLVED}. * <li>A module event of type {@link ModuleEvent#STOPPED} is fired. * <li>A {@code ModuleException} is then thrown. * </ul> * * <li>This module's state is set to {@code ACTIVE}. * * <li>A module event of type {@link ModuleEvent#STARTED} is fired. * </ol> * * @throws ModuleException If the module cannot be started */ void start() throws ModuleException; /** * Stops this module. * <p> * If this module's state is {@code UNINSTALLED} then an {@code IllegalStateException} is thrown. * <p> * The following steps are required to stop this module: * <ol> * * <li>If this module is in the process of being activated or deactivated * then this method must wait for activation or deactivation to complete * before continuing. If this does not occur in a reasonable time, a * {@code ModuleException} is thrown to indicate this module was unable to * be stopped. * * <li>If this module's state is not {@code ACTIVE} then this method returns immediately. * * <li>This module's state is set to {@code STOPPING}. * * <li>A module event of type {@link ModuleEvent#STOPPING} is fired. * * <li>The {@link ModuleActivator#stop(ModuleContext)} method of this module's {@code ModuleActivator}, * if one is specified, is called. If that method throws an exception, this method must continue to * stop this module and a {@code ModuleException} must be thrown after * completion of the remaining steps. * * <li>Any services registered by this module must be unregistered. * <li>Any services used by this module must be released. * <li>Any listeners registered by this module must be removed. * * <li>This module's state is set to {@code RESOLVED}. * * <li>A module event of type {@link ModuleEvent#STOPPED} is fired. * </ol> * * @throws ModuleException If the module cannot be started */ void stop() throws ModuleException; /** * Uninstalls this module. * * <p> * This method causes the Runtime to notify other modules that this module * is being uninstalled, and then puts this module into the * {@code UNINSTALLED} state. The Runtime must remove any resources * related to this module that it is able to remove. * * <p> * If this module's state is {@code UNINSTALLED} then an {@code IllegalStateException} is thrown. * * <p> * The following steps are required to uninstall a module: * <ol> * * <li>This module is stopped as described in the {@code Module.stop} method. * * <li>This module's state is set to {@code UNINSTALLED}. * * <li>A module event of type {@link ModuleEvent#UNINSTALLED} is fired. * </ol> */ void uninstall(); /** * Loads the specified class using this module's class loader. * * <p> * If this module's state is {@code UNINSTALLED}, then an * {@code IllegalStateException} is thrown. * * @param className The name of the class to load. * @return The Class object for the requested class. */ Class<?> loadClass(String className) throws ClassNotFoundException; /** * Creates a {@code File} object for a file in the persistent storage area * provided for this module by the Runtime. This method will return * {@code null} if the platform does not have file system support. * * <p> * A {@code File} object for the base directory of the persistent storage * area provided for this module by the Runtime can be obtained by calling * this method with an empty string as {@code filename}. * * <p> * If the Java Runtime Environment supports permissions, the Runtime will * ensure that this module has the {@code java.io.FilePermission} with * actions {@code read},{@code write},{@code delete} for all files * (recursively) in the persistent storage area provided for this module. * * @param filename A relative name to the file to be accessed. * @return A {@code File} object that represents the requested file or * {@code null} if the platform does not have file system support. * @throws IllegalStateException If this module has been uninstalled. */ File getDataFile(String filename); }