/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.
*/
/** Object representing one module, possibly installed. * Responsible for opening of module JAR file; reading * manifest; parsing basic information such as dependencies; * and creating a classloader for use by the installer. * Methods not defined in ModuleInfo must be called from within * the module manager's read mutex as a rule. * @author Jesse Glick * @since 2.1 the class was made public abstract
*/ publicabstractclass Module extends ModuleInfo {
/** manager which owns this module */ protectedfinal ModuleManager mgr; /** event logging (should not be much here) */ protectedfinal Events events; /** associated history object * @see <a href="@org-netbeans-core-startup@/org/netbeans/core/startup/ModuleHistory.html">ModuleHistory</a>
*/ privatefinal Object history; /** true if currently enabled; manipulated by ModuleManager */ privateboolean enabled; /** whether it is supposed to be automatically loaded when required */ privatefinalboolean autoload; /** */ protectedboolean reloadable; /** if true, this module is eagerly turned on whenever it can be */ privatefinalboolean eager; /** currently active module classloader */ protected ClassLoader classloader;
// Access from ModuleManager: void setEnabled(boolean enabled) { /* #13647: actually can happen if loading of bootstrap modules is rolled back: */ if (isFixed() && ! enabled) thrownew IllegalStateException("Cannot disable a fixed module: " + this); // NOI18N this.enabled = enabled;
}
/** Normally a module once created and managed is valid * (that is, either installed or not, but at least managed). * If it is deleted any remaining references to it become * invalid.
*/ publicboolean isValid() { return mgr.get(getCodeNameBase()) == this;
}
/** Is this module automatically loaded? * If so, no information about its state is kept * permanently beyond the existence of its JAR file; * it is enabled when some real module needs it to be, * and disabled when this is no longer the case. * @see <a href="https://bz.apache.org/netbeans/show_bug.cgi?id=9779">#9779</a>
*/ publicboolean isAutoload() { return autoload;
}
/** Is this module eagerly enabled? * If so, no information about its state is kept permanently. * It is turned on whenever it can be, i.e. whenever it meets all of * its dependencies. This may be used to implement "bridge" modules with * simple functionality that just depend on two normal modules. * A module may not be simultaneously eager and autoload. * @see <a href="https://bz.apache.org/netbeans/show_bug.cgi?id=17501">#17501</a> * @since org.netbeans.core/1 1.3
*/ publicboolean isEager() { return eager;
}
/** Get an associated arbitrary attribute. * Right now, simply provides the main attributes of the manifest. * In the future some of these could be suppressed (if only of dangerous * interest, e.g. Class-Path) or enhanced with other information available * from the core (if needed).
*/
@Override public Object getAttribute(String attr) { return getManifest().getMainAttributes().getValue(attr);
}
@Override public String getCodeName() { return data().getCodeName();
}
public @Override String[] getProvides() { return data().getProvides();
} /** Test whether the module provides a given token or not. * @since JST-PENDING again used from NbProblemDisplayer
*/ publicfinalboolean provides(String token) {
String[] provides = getProvides(); if (provides == null) { returnfalse;
} for (int i = 0; i < provides.length; i++) { if (provides[i].equals(token)) { returntrue;
}
} returnfalse;
}
@Override public SpecificationVersion getSpecificationVersion() { return data().getSpecificationVersion();
}
@Override public String getImplementationVersion() { return data().getImplementationVersion();
}
@Override public String getBuildVersion() { return data().getBuildVersion();
}
public @Override boolean owns(Class<?> clazz) {
ClassLoader cl = clazz.getClassLoader(); if (cl instanceof Util.ModuleProvider) { return ((Util.ModuleProvider) cl).getModule() == this;
} if (cl != classloader) { returnfalse;
}
String _codeName = findClasspathModuleCodeName(clazz); if (_codeName != null) { return _codeName.equals(getCodeName());
} returntrue; // not sure...
}
static String findClasspathModuleCodeName(Class<?> clazz) { // #157798: in JNLP or otherwise classpath mode, all modules share a CL.
CodeSource src = clazz.getProtectionDomain().getCodeSource(); if (src != null) { try {
URL loc = src.getLocation(); if (loc.toString().matches(".+\\.jar")) { // URLClassLoader inconsistency.
loc = new URL("jar:" + loc + "!/");
}
URL manifest = new URL(loc, "META-INF/MANIFEST.MF");
InputStream is = manifest.openStream(); try { returnnew Manifest(is).getMainAttributes().getValue("OpenIDE-Module");
} finally {
is.close();
}
} catch (IOException x) {
Logger.getLogger(Module.class.getName()).log(Level.FINE, null, x);
}
} returnnull;
}
/** Get all packages exported by this module to other modules. * @return a list (possibly empty) of exported packages, or null to export everything * @since org.netbeans.core/1 > 1.4 * @see "#19621"
*/ public PackageExport[] getPublicPackages() { return data().getPublicPackages();
}
/** Checks whether we use friends attribute and if so, then * whether the name of module is listed there.
*/ boolean isDeclaredAsFriend (Module module) {
Set<String> friendNames = data().getFriendNames(); if (friendNames == null) { returntrue;
} return friendNames.contains(module.getCodeNameBase());
}
/** Parse information from the current manifest. * Includes code name, specification version, and dependencies. * If anything is in an invalid format, throws an exception with * some kind of description of the problem.
*/ protectedvoid parseManifest() throws InvalidException {
data();
}
/** Get all JARs loaded by this module. * Includes the module itself, any locale variants of the module, * any extensions specified with Class-Path, any locale variants * of those extensions. * The list will be in classpath order (patches first). * Currently the temp JAR is provided in the case of test modules, to prevent * sporadic ZIP file exceptions when background threads (like Java parsing) tries * to open libraries found in the library path. * JARs already present in the classpath are <em>not</em> listed. * @return a list of JARs
*/ publicabstract List<File> getAllJars();
/** Is this module supposed to be easily reloadable? * If so, it is suitable for testing inside the IDE. * Controls whether a copy of the JAR file is made before * passing it to the classloader, which can affect locking * and refreshing of the JAR.
*/ publicboolean isReloadable() { return reloadable;
}
/** Set whether this module is supposed to be reloadable. * Has no immediate effect, only impacts what happens the * next time it is enabled (after having been disabled if * necessary). * Must be called from within a write mutex. * @param r whether the module should be considered reloadable
*/ publicabstractvoid setReloadable(boolean r);
/** Reload this module. Access from ModuleManager. * If an exception is thrown, the module is considered * to be in an invalid state. * @since JST-PENDING: needed from ModuleSystem
*/ publicabstractvoid reload() throws IOException;
// impl of ModuleInfo method public @Override ClassLoader getClassLoader() throws IllegalArgumentException { if (!enabled) { thrownew IllegalArgumentException("Not enabled: " + getCodeNameBase()); // NOI18N
} assert classloader != null : "Should have had a non-null loader for " + this; return classloader;
}
// Access from ModuleManager: /** Turn on the classloader. Passed a list of parent modules to use. * The parents should already have had their classloaders initialized.
*/ protectedabstractvoid classLoaderUp(Set<Module> parents) throws IOException;
/** Turn off the classloader and release all resources. */ protectedabstractvoid classLoaderDown(); /** Should be called after turning off the classloader of one or more modules & GC'ing. */ protectedabstractvoid cleanup();
/** Notify the module that it is being deleted. */ protectedabstractvoid destroy();
/** Get the JAR this module is packaged in. * May be null for modules installed specially, e.g. * automatically from the classpath. * @see #isFixed
*/ public File getJarFile() { returnnull;
}
/** Get the JAR manifest. * Should never be null, even if disabled. * Might change if a module is reloaded. * It is not guaranteed that change events will be fired * for changes in this property.
*/ publicabstract Manifest getManifest();
/** * Release memory storage for the JAR manifest, if applicable.
*/ publicvoid releaseManifest() {}
/** Get a set of {@link org.openide.modules.Dependency} objects representing missed dependencies. * This module is examined to see * why it would not be installable. * If it is enabled, there are no problems. * If it is in fact installable (possibly only * by also enabling some other managed modules which are currently disabled), and * all of its non-module dependencies are met, the returned set will be empty. * Otherwise it will contain a list of reasons why this module cannot be installed: * non-module dependencies which are not met; and module dependencies on modules * which either do not exist in the managed set, or are the wrong version, * or themselves cannot be installed * for some reason or another (which may be separately examined). * Note that in the (illegal) situation of two or more modules forming a cyclic * dependency cycle, none of them will be installable, and the missing dependencies * for each will be stated as the dependencies on the others. Again other modules * dependent on modules in the cycle will list failed dependencies on the cyclic modules. * Missing package dependencies are not guaranteed to be reported unless an install * of the module has already been attempted, and failed due to them. * The set may also contain {@link InvalidException}s representing known failures * of the module to be installed, e.g. due to classloader problems, missing runtime * resources, or failed ad-hoc dependencies. Again these are not guaranteed to be * reported unless an install has already been attempted and failed due to them.
*/ public Set<Object> getProblems() { // cannot use Union2<Dependency,InvalidException> without being binary-incompatible if (! isValid()) thrownew IllegalStateException("Not valid: " + this); // NOI18N if (isEnabled()) return Collections.emptySet();
Set<Object> problems = new HashSet<Object>(); for (Union2<Dependency,InvalidException> problem : mgr.missingDependencies(this)) { if (problem.hasFirst()) {
problems.add(problem.first());
} else {
problems.add(problem.second());
}
} return problems;
}
/** Get the history object representing what has happened to this module before. * @see <a href="@org-netbeans-core-startup@/org/netbeans/core/startup/ModuleHistory.html">ModuleHistory</a>
*/ publicfinal Object getHistory() { return history;
}
/** Finds out if a module has been assigned with a specific start level. * Start level is only useful for OSGi bundles. Otherwise it is always zero. * * @return -1, if no specific level is assigned, non-negative integer if so * @since 2.43
*/ publicfinalint getStartLevel() { return getStartLevelImpl();
}
int getStartLevelImpl() { return -1;
}
/** String representation for debugging. */ public @Override String toString() {
String s = "Module:" + getCodeNameBase(); // NOI18N if (!isValid()) s += "[invalid]"; // NOI18N return s;
}
/** Locates resource in this module. May search only the main JAR * of the module (which is what it does in case of OSGi bundles). * Should be as lightweight as possible - e.g. if it is OK to not * initialize something in the module while performing this method, * the something should not be initialized (e.g. OSGi bundles are * not resolved). * * @param resources path to the resources we are looking for * @since 2.49
*/ public Enumeration<URL> findResources(String resources) { try { // #149136
ClassLoader cl = getClassLoader();
if (cl instanceof ProxyClassLoader) { return ((ProxyClassLoader) cl).findResources(resources);
} //TODO: other ClassLoaders - what can we expect here? can fallback to getResources for JVM classloaders, and nothing else should be here? thrownew IllegalStateException("Unexpected ClassLoader: " + cl + ".");
} catch (Exception x) {
Exceptions.printStackTrace(x); return Enumerations.empty();
}
}
/** To be overriden to empty in FixedModule & co. */ void refineDependencies(Set<Dependency> dependencies) { // Permit the concrete installer to make some changes:
mgr.refineDependencies(this, dependencies);
}
/** Is this module a wrapper around OSGi? * @return true, if the module is build around OSGi * @since 2.51
*/ publicfinalboolean isNetigso() { return isNetigsoImpl();
}
/** * Release references to the ClassLoader. Package-private for now as only (?) FixedModule * should retain the CL instance.
*/ void releaseClassLoader() { this.classloader = null;
}
/** Struct representing a package exported from a module. * @since org.netbeans.core/1 > 1.4 * @see Module#getPublicPackages
*/ publicstaticfinalclass PackageExport { /** Package to export, in the form <code>org/netbeans/modules/foo/</code>. */ publicfinal String pkg; /** If true, export subpackages also. */ publicfinalboolean recursive; /** Create a package export struct with the named parameters. */ public PackageExport(String pkg, boolean recursive) { this.pkg = pkg; this.recursive = recursive;
} public @Override String toString() { return"PackageExport[" + pkg + (recursive ? "**/" : "") + "]"; // NOI18N
} public @Override boolean equals(Object obj) { if (!(obj instanceof PackageExport)) { returnfalse;
} final PackageExport other = (PackageExport) obj; return pkg.equals(other.pkg) && recursive == other.recursive;
} public @Override int hashCode() { return pkg.hashCode();
}
staticvoid write(DataOutput dos, PackageExport[] arr) throws IOException { if (arr == null) {
dos.writeInt(0); return;
}
dos.writeInt(arr.length); for (PackageExport pe : arr) {
dos.writeUTF(pe.pkg);
dos.writeBoolean(pe.recursive);
}
}
static PackageExport[] read(DataInput is) throws IOException { int cnt = is.readInt(); if (cnt == 0) { returnnull;
}
PackageExport[] arr = new PackageExport[cnt]; for (int i = 0; i < cnt; i++) {
String pkg = is.readUTF(); boolean recursive = is.readBoolean();
arr[i] = new PackageExport(pkg, recursive);
} return arr;
}
}
}
¤ Dauer der Verarbeitung: 0.38 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.