📄 importsearchpolicy.java
字号:
else { throw new IllegalStateException("Module manager is already initialized"); } } /** * This method is part of the <tt>SearchPolicy</tt> interface; it * should not be called directly. This method finds a class * based on the import/export meta-data attached to the module. * It first attempts to validate the target module, if it cannot * be validated, then a <tt>ClassNotFoundException</tt> is thrown. * Once the module is validated, the module's imports are searched * for the target class, then the module's exports are searched. * If the class is found in either place, then it is returned; * otherwise, <tt>null</tt> is returned. * @param module the target module that is loading the class. * @param name the name of the class being loaded. * @return the class if found, <tt>null</tt> otherwise. * @throws java.lang.ClassNotFoundException if the target module * could not be validated. **/ public Class findClass(Module module, String name) throws ClassNotFoundException { // First, try to validate the originating module. try { validate(module); } catch (ValidationException ex) { throw new ClassNotFoundException(name); } // Get the package of the target class. String pkgName = (name.lastIndexOf('.') < 0) ? "" : name.substring(0, name.lastIndexOf('.')); // We delegate to the module's imports for finding the // desired class first, then we delegate to the module's // exports for finding the desired class. We do this because // implicitly a module imports everything that it exports. // To avoid code duplication, we use a simple array of // attribute names to loop through both of the imports // and exports meta-data searching for the desired class. for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++) { Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); // If the module doesn't import anything, then just // return null. if ((imports != null) && (imports.length > 0)) { for (int i = 0; i < imports.length; i++) { // Only check when the package of the class is // the same as the import package. if (imports[i][IDENTIFIER_IDX].equals(pkgName)) { Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX]; try { Class clazz = resolvingModule.getClassLoader().searchForClass(name); if (clazz != null) { return clazz; } } catch (Throwable th) { // Not much we can do here. } throw new ClassNotFoundException(name); } } } } return null; } /** * This method is part of the <tt>SearchPolicy</tt> interface; it * should not be called directly. This method finds a resource * based on the import/export meta-data attached to the module. * It first attempts to validate the target module, if it cannot * be validated, then it returns <tt>null</tt>. Once the module is * validated, the module's imports are searched for the target * resource, then the module's exports are searched. If the resource * is found in either place, then a <tt>URL</tt> to is is returned; * otherwise, <tt>null</tt> is returned. * @param module the target module that is loading the resource. * @param name the name of the resource being loaded. * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise. **/ public URL findResource(Module module, String name) throws ResourceNotFoundException { // First, try to validate the originating module. try { validate(module); } catch (ValidationException ex) { return null; } // Get the package of the target resource. // NOTE: The package of a resource is tricky to determine, since // resources do not follow the same naming conventions as classes. // This code is pessimistic and assumes that the package of a // resource is everything up to the last '/' character. By making // this choice, it will not be possible to load resources from // imports using relative resource names. For example, if a // bundle exports "foo" and an importer of "foo" tries to load // "/foo/bar/myresource.txt", this will not be found in the exporter // because the following algorithm assumes the package name is // "foo.bar", not just "foo". This only affects imported resources, // local resources will work as expected. String pkgName = (name.startsWith("/")) ? name.substring(1) : name; pkgName = (pkgName.lastIndexOf('/') < 0) ? "" : pkgName.substring(0, pkgName.lastIndexOf('/')); pkgName = pkgName.replace('/', '.'); // We delegate to the module's imports for finding the // desired class first, then we delegate to the module's // exports for finding the desired class. We do this because // implicitly a module imports everything that it exports. // To avoid code duplication, we use a simple array of // attribute names to loop through both of the imports // and exports meta-data searching for the desired class. for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++) { Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); // If the module doesn't import or export anything, // then just return null. if ((imports != null) && (imports.length > 0)) { for (int i = 0; i < imports.length; i++) { // Only check when the package of the resource is // the same as the import package. if (imports[i][IDENTIFIER_IDX].equals(pkgName)) { Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX]; try { URL url = resolvingModule.getClassLoader().searchForResource(name); if (url != null) { return url; } } catch (Throwable th) { // Not much we can do here. } throw new ResourceNotFoundException(name); } } } } return null; } private Map m_validateMap = new HashMap(); private Module m_rootModule = null; /** * This method validates the specified target module. If the module * is already validated, then this method returns immediately. This * method synchronizes on the associated module manager to ensure that * modules are not added or removed while the validation is occuring. * Each import and export for the target module are resolved by first * using the compatibility policy to create a list of candidate export * modules, then using the selection policy to choose among the * candidates. Each selected candidate is also recursively validated; * this process validates a transitive closure of all dependent modules. * After the selected candidate is validated, its propagated imports * are checked to make sure that they do not conflict with any existing * propagated imports. If no validation errors occur, then all dependent * modules are marked as validated, if they are not already validated. * If an error occurs, the valid state of all modules remains unchanged. * @param module the module to validate. * @throws org.ungoverned.moduleloader.search.ValidationException if * the module or any dependent modules could not be validated. **/ public void validate(Module module) throws ValidationException { if (getValidAttribute(module).booleanValue()) { return; } // Flag to indicate whether the bundle is valid or not. boolean isValid = true; // This list will be used to remember which bundles // were validated so that the validation events can // be fired outside of the synchronized block. List fireValidatedList = null; // Will hold the exception to be thrown or rethrown. ValidationException invalidException = null; // Synchronize on the module manager, because we don't want // anything to change while we are in the middle of this // operation. synchronized (m_mgr) { // If we are already validating this module, then // just return; this is necessary for cycles. if (m_validateMap.get(module) != null) { return; } // Add the module to the validation map; this // is necessary for cycles. m_validateMap.put(module, module); // Keep track of the root module that started // the validation request; this is necessary // for cycles. if (m_rootModule == null) { m_rootModule = module; } // Now perform the validation algorithm. Map propagateMap = new HashMap(); // Validation binds the module's imports to a specific exporting // module. A module also implicitly imports whatever it exports, // so exports are validated in the same fashion as imports. It // is possible, given the selection policy that a given export // may actually be satisfied by a different module (i.e., a // module is not guaranteed to be bound to what it exports). Since // the imports and exports meta-data are validated in the same // fashion, we will use the follow attribute array to loop and // validate both imports and exports using the same code. for (int attrIdx = 0; (isValid) && (attrIdx < m_searchAttrs.length); attrIdx++) { // Get the imports (exports are treated as imports to) // for the current module. Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]); // See if each import has available exporters. for (int impIdx = 0; impIdx < imports.length; impIdx++) { // Get all exporter candidates. Module[] candidates = getCompatibleModules( imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX]); // If there are no candidates, then prepare a // validation exception. if (candidates == null) { isValid = false; invalidException = new ValidationException( "Unable to validate module", module, imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX], false); break; } // Use selection policy to choose a single export candidate. Module exportingModule = m_selectPolicy.select( module, imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX], candidates, m_compatPolicy); // If there is no export module chosen, then prepare // a validation exception. if (exportingModule == null) { isValid = false; invalidException = new ValidationException( "Unable to validate module", module, imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX], false); break; } // Make sure that the export module is // also validated. try { validate(exportingModule); } catch (ValidationException ex) { // Prepare to rethrow the exception if // the exporter could not be validated. isValid = false; invalidException = ex; break; } // Keep track of all propagations from each module that this // module imports from. Verify that any given import always // comes form the same export module, otherwise there will be // class cast exceptions. Object[] propagates = getPropagatesAttribute(exportingModule); for (int propIdx = 0; propIdx < propagates.length; propIdx++) { // If the module does not import the propagated target, // then it can be safely ignored. if (doesImport(module, propagates[propIdx])) { Module sourceModule = (Module) propagateMap.get(propagates[propIdx]); // If the propagation source module has not already been // found, then remember the resolving module of the // exporting module as the source of the propagated // target. if (sourceModule == null) { propagateMap.put( propagates[propIdx], getImportResolvingModule( exportingModule, propagates[propIdx])); } // If the propagation source module is found, then check to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -