📄 importsearchpolicy.java
字号:
/* * ModuleLoader - A generic, policy-driven class loader. * Copyright (c) 2004, Richard S. Hall * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of the ungoverned.org nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Contact: Richard S. Hall (heavy@ungoverned.org) * Contributor(s): ***/package org.ungoverned.moduleloader.search;import java.net.URL;import java.util.*;import org.ungoverned.moduleloader.*;/** * <p> * This class implements a <tt>ModuleLoader</tt> search policy to support * modules that import and export classes and resources from/to one another. * Modules import from other modules by specifying a set of import identifiers * and associated version numbers. Modules export their classes and * resources by specifying a set of export identifiers and associated * versions. Exports for a given module are also treated as imports for that module, * meaning that it is possible for a module that exports classes to not use * the classes it exports, but to actually use classes that are exported from * another module. This search policy requires the following meta-data * attributes be attached to each module: * </p> * <ul> * <li><tt>ImportSearchPolicy.EXPORTS_ATTR</tt> - the "<tt>exports</tt>" * meta-data attribute is used to declare the module's exports, * </li> * <li><tt>ImportSearchPolicy.IMPORTS_ATTR</tt> - the "<tt>imports</tt>" * meta-data attribute is used to declare the module's imports, * </li> * <li><tt>ImportSearchPolicy.PROPAGATES_ATTR</tt> - the "<tt>propagates</tt>" * meta-data attribute is used to declare which imports are exposed or * "propagated" to clients of the module's exports, and * </li> * <li><tt>ImportSearchPolicy.VALID_ATTR</tt> - the "<tt>valid</tt>" * meta-data attribute signifies the current <i>validation</i> status * of the module (this will be defined more fully below). * </li> * </ul> * <p> * The value of the <tt>ImportSearchPolicy.EXPORTS_ATTR</tt> attribute is * an array of <tt>Object</tt> arrays, i.e., <tt>Object[][]</tt>. Each element * in the array signifies a particular export that is offered by this * associated module. Each element is an array triple of * <tt>Object</tt>, where the index into this triple is: * </p> * <ul> * <li><tt>ImportSearchPolicy.IDENTIFIER_IDX</tt> - the first element * is the export identifier object, used to identify the * export target. The export identifier does not have any special * meaning to the search policy and any value is allowed. A * typical identifier might be the package name of the exported classes, * such as <tt>javax.servlet</tt>. * </li> * <li><tt>ImportSearchPolicy.VERSION_IDX</tt> - the second element * is the export version number. The version number does not have * any special meaning to the search policy and any value is allowed. * A typical version number might be major, minor, and release number. * </li> * <li><tt>ImportSearchPolicy.RESOLVING_MODULE_IDX</tt> - the third element * is the resolving module for this export; since exports are treated like * imports, it is possible that the resolving module will not be the * exporting module itself. This value is filled in automatically by the * search policy and is initially <tt>null</tt>. * </li> * </ul> * </p> * <p> * The value of the <tt>ImportSearchPolicy.IMPORTS_ATTR</tt> attribute is * essentially the same as the <tt>ImportSearchPolicy.EXPORTS_ATTR</tt> defined * above; the only difference is that the array of versioned identifiers denote * import targets rather than exports. * </p> * <p> * The value of the <tt>ImportSearchPolicy.PROPAGATES_ATTR</tt> attribute is * an array of <tt>Object</tt>s, i.e., <tt>Object[]</tt>. Each element in the * array is an identifier of a propagated import target from the * <tt>ImportSearchPolicy.IMPORTS_ATTR</tt> attribute. Only identifiers for * import targets are candidates for inclusion and the version number is * unnecessary since it is assumed from the corresponding import target. * </p> * <p> * The value of the <tt>ImportSearchPolicy.VALID_ATTR</tt> attribute is a * <tt>Boolean</tt>. The value is initially set to <tt>Boolean.FALSE</tt> * and indicates that the module has not yet been validated. After the module * is validated, the value is set to <tt>Boolean.TRUE</tt>. The search policy * automatically adds this attribute to all modules and maintains its value. * </p> * <p> * These meta-data attributes help the search policy enforce consistency * using a process called <i>validation</i>; validation ensures that classes * and resources are only loaded from a module whose imports are satisfied. * Therefore, a <i>valid</i> module is a module whose imports are satisfied and * an <i>invalid</i> module is a module whose imports are not yet satisfied. * An invalid module may be invalid for two reasons: * </p> * <p> * <ol> * <li>Its imports are not available or</li> * <li>It has not yet been validated.</li> * </ol> * </p> * <p> * These two possibilities arise due to the fact that module validation * is not performed until it is necessary (i.e., lazy evaluation). A module * is automatically validated when an attempt is made to get classes or * resources from it, although it is possible to manually validate a module. * For a given module, called <tt>M</tt>, the validation process attempts to * find an exporting module for every import target of <tt>M</tt>. If an * exporter is not found for a specific import target, then the validation of * module <tt>M</tt> fails. If an exporting module is found, then this module * is also validated, if it is not already. As a result, the validation of * module <tt>M</tt> depends on the validation of the transitive closure of * all modules on which <tt>M</tt> depends. It is also possible for modules * to exhibit dependency cycles; circular dependencies are allowed. * Initially, a module's <tt>VALID_ATTR</tt> is set to <tt>Boolean.FALSE</tt>, * but after the module is successfully validated, this attribute is set to * <tt>Boolean.TRUE</tt>. * </p> * <p> * Besides ensuring that every import target is resolved to an appropriate * exporting module, the validation process also attempts to maintain * consistency along "propagation" chains. Propagation occurs when a module * imports classes that are also visible from its own exports; for example, * an HTTP server implementation may import classes from <tt>javax.servlet</tt> * and export classes that have methods that use the type <tt>javax.servlet.Servlet</tt> * in their signatures. Monitoring these types of occurences is important * to uncover import source and version conflicts when multiple sources or * versions of an import target are available within one virtual machine. When * a module <tt>M</tt> is validated, the propagation information of each * module that resolves the imports of <tt>M</tt> is checked to ensure * that they do not propagate conflicting sources of <tt>M</tt>'s * imports; specifically, it is verified that all propagators of a * particular import target have the same source module for that import * target. * </p> * <p> * To facilitate applicability in as many scenarios as possible, this search * policy delegates some decisions via additional policy interfaces. The following * two policy interfaces must be specified by the code that instantiates the * <tt>ImportSearchPolicy</tt> object: * </p> * <ul> * <li><tt>CompatibilityPolicy</tt> - this policy is used to determine * whether import/export version numbers are compatible. * </li> * <li><tt>SelectionPolicy</tt> - this policy is used to resolve a specific * import target when multiple candidate exporting modules exist. * </li> * </ul> * <p> * Once an instance is created with definitions of the above policy interfaces, * this search policy will operate largely self-contained. There are a few utility * methods for manually validating modules, adding validation listeners, and * access meta-data attributes, but for the most part these are not necessary * except for implementing more sophisticated infrastructure. * </p> * <p> * The follow snippet of code illustrates a typical usage scenario for * this search policy: * </p> * <pre> * ... * ImportSearchPolicy searchPolicy = * new ImportSearchPolicy( * new MyCompatibilityPolicy(), new MySelectionPolicy()); * ModuleManager mgr = new ModuleManager(searchPolicy); * ... * Object[][] exports = new Object[][] { * { "org.apache.jasper", "2.1.0", null } * }; * Object[][] imports = new Object[][] { * { "javax.servlet", "2.3.1", null } * }; * Object[][] attributes = new Object[][] { * new Object[] { ImportSearchPolicy.EXPORTS_ATTR, exports }, * new Object[] { ImportSearchPolicy.IMPORTS_ATTR, imports }, * new Object[] { ImportSearchPolicy.PROPAGATES_ATTR, new Object[] { "javax.servlet" } } * }; * ResourceSource[] resSources = new ResourceSource[] { * new JarResourceSource(file1) * new JarResourceSource(file2) * }; * Module module = mgr.addModule(id, attributes, resSources, null); * ClassLoader loader = module.getClassLoader(); * // Assuming that all imports are satisfied... * Class clazz = loader.loadClass("org.foo.MyClass"); * ... * </pre> * <p> * The above code snippet illustrates creating a module with one export and one * import, where the import is also propagated via the module's export. The module * has multiple resource sources, but no library sources. * </p> * @see org.ungoverned.moduleloader.SearchPolicy * @see org.ungoverned.moduleloader.Module * @see org.ungoverned.moduleloader.ModuleClassLoader * @see org.ungoverned.moduleloader.ModuleManager**/public class ImportSearchPolicy implements SearchPolicy, ModuleListener{ /** * This is the name of the "exports" meta-data attribute that * should be attached to each module. The value of this attribute * is of type <tt>Object[][]</tt> and is described in the overview * documentation for this class. **/ public static final String EXPORTS_ATTR = "exports"; /** * This is the name of the "imports" meta-data attribute that * should be attached to each module. The value of this attribute * is of type <tt>Object[][]</tt> and is described in the overview * documentation for this class. **/ public static final String IMPORTS_ATTR = "imports"; /** * This is the name of the "propagates" meta-data attribute that * should be attached to each module. The value of this attribute * is of type <tt>Object[]</tt> and is described in the overview * documentation for this class. **/ public static final String PROPAGATES_ATTR = "propagates"; /** * This is the name of the "valid" meta-data attribute that is * automatically attached to each module. The value of this attribute * is of type <tt>Boolean</tt> and is described in the overview * documentation for this class. **/ public static final String VALID_ATTR = "valid"; /** * This is the index used to retrieve the import or export identifier * from a given element of the <tt>EXPORTS_ATTR</tt> or the <tt>IMPORTS_ATTR</tt> * attribute. **/ public static final int IDENTIFIER_IDX = 0; /** * This is the index used to retrieve the import or export version number * from a given element of the <tt>EXPORTS_ATTR</tt> or the <tt>IMPORTS_ATTR</tt> * attribute. **/ public static final int VERSION_IDX = 1; /** * This is the index used to retrieve the resolving module for an import * or export target from a given element of the <tt>EXPORTS_ATTR</tt> or * the <tt>IMPORTS_ATTR</tt> attribute. **/ public static final int RESOLVING_MODULE_IDX = 2; private ModuleManager m_mgr = null; private CompatibilityPolicy m_compatPolicy = null; private SelectionPolicy m_selectPolicy = null; private ValidationListener[] m_listeners = null; private String[] m_searchAttrs = { IMPORTS_ATTR, EXPORTS_ATTR }; private static final ValidationListener[] m_noListeners = new ValidationListener[0]; /** * Constructs an import search policy instance with the supplied * compatibility and selection policies. * @param compatPolicy the compatibility policy implementation to be used * by the search policy. * @param selectPolicy the selection policy implementation to be used * by the search policy. **/ public ImportSearchPolicy( CompatibilityPolicy compatPolicy, SelectionPolicy selectPolicy) { m_compatPolicy = compatPolicy; m_selectPolicy = selectPolicy; m_listeners = m_noListeners; } /** * Returns the compatibility policy used by this import search policy instance. * @return the compatibility policy of this import search policy instance. **/ public CompatibilityPolicy getCompatibilityPolicy() { return m_compatPolicy; } /** * Returns the selection policy used by this import search policy instance. * @return the selection policy of this import search policy instance. **/ public SelectionPolicy getSelectionPolicy() { return m_selectPolicy; } // JavaDoc comment copied from SearchPolicy. public void setModuleManager(ModuleManager mgr) throws IllegalStateException { if (m_mgr == null) { m_mgr = mgr; m_mgr.addModuleListener(this); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -