dynamicclassloader.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,097 行 · 第 1/4 页
JAVA
2,097 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.loader;import com.caucho.config.ConfigException;import com.caucho.lifecycle.Lifecycle;import com.caucho.loader.enhancer.EnhancerRuntimeException;import com.caucho.make.AlwaysModified;import com.caucho.make.DependencyContainer;import com.caucho.make.Make;import com.caucho.make.MakeContainer;import com.caucho.management.server.*;import com.caucho.server.util.CauchoSystem;import com.caucho.util.ByteBuffer;import com.caucho.util.L10N;import com.caucho.util.TimedCache;import com.caucho.vfs.Dependency;import com.caucho.vfs.JarPath;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import java.io.FilePermission;import java.io.IOException;import java.io.InputStream;import java.net.*;import java.security.*;import java.lang.instrument.*;import java.util.ArrayList;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import java.util.jar.Attributes;import java.util.jar.Manifest;import java.util.logging.Level;import java.util.logging.Logger;import java.util.regex.Pattern;/** * Class loader which checks for changes in class files and automatically * picks up new jars. * * <p>DynamicClassLoaders can be chained creating one virtual class loader. * From the perspective of the JDK, it's all one classloader. Internally, * the class loader chain searches like a classpath. */public class DynamicClassLoader extends java.net.URLClassLoader implements Dependency, Make, DynamicClassLoaderMXBean{ private static L10N _L; private static Logger _log; private final static URL NULL_URL; private final static URL []NULL_URL_ARRAY = new URL[0]; private static long _globalDependencyCheckInterval = 2000L; private static boolean _isJarCacheEnabled; private String _id; private final boolean _isVerbose; private int _verboseDepth; // List of resource loaders private ArrayList<Loader> _loaders = new ArrayList<Loader>(); private JarLoader _jarLoader; private PathLoader _pathLoader; private ArrayList<Path> _nativePath = new ArrayList<Path>(); // List of cached classes private Hashtable<String,ClassEntry> _entryCache; private TimedCache<String,URL> _resourceCache; // Dependencies private DependencyContainer _dependencies = new DependencyContainer(); private boolean _isEnableDependencyCheck = false; // Makes private MakeContainer _makeList; // If true, use the servlet spec's hack to give the parent priority // for some classes, but the child priority for other classes. private boolean _useServletHack; // List of packages where the parent has priority. private String []_parentPriorityPackages; // List of packages where this has priority. private String []_priorityPackages; // Array of listeners // XXX: There's still some questions of what kind of reference this // should be. It either needs to be a WeakReference or // a normal reference. Anything in between makes no sense. // // server/10w3 indicates that it needs to be a regular reference private ArrayList<ClassLoaderListener> _listeners; // The security manager for the loader private SecurityManager _securityManager; // List of permissions allowed in this context private ArrayList<Permission> _permissions; // The security code source for the loader private CodeSource _codeSource; // Any enhancer private ArrayList<ClassFileTransformer> _classFileTransformerList; private URL []_urls = NULL_URL_ARRAY; private WeakCloseListener _closeListener; // Lifecycle private final Lifecycle _lifecycle = new Lifecycle(); private boolean _hasNewLoader = true; private long _lastNullCheck; /** * Create a new class loader. * * @param parent parent class loader */ public DynamicClassLoader(ClassLoader parent) { this(parent, true); } /** * Create a new class loader. * * @param parent parent class loader */ public DynamicClassLoader(ClassLoader parent, boolean enableDependencyCheck) { super(NULL_URL_ARRAY, getInitParent(parent)); parent = getParent(); _securityManager = System.getSecurityManager(); _isEnableDependencyCheck = enableDependencyCheck; _dependencies.setCheckInterval(_globalDependencyCheckInterval); for (; parent != null; parent = parent.getParent()) { if (parent instanceof DynamicClassLoader) { DynamicClassLoader loader = (DynamicClassLoader) parent; loader.init(); addPermissions(loader.getPermissions()); // loader.addListener(this); _dependencies.add(loader); _dependencies.setCheckInterval(loader.getDependencyCheckInterval()); _useServletHack = loader._useServletHack; break; } } if (System.getProperty("resin.verbose.classpath") != null) { _isVerbose = true; int depth = 0; while (parent != null) { depth++; parent = parent.getParent(); } _verboseDepth = depth; } else _isVerbose = false; } /** * Returns the initialization parent, i.e. the parent if given * or the context class loader if not given. */ private static ClassLoader getInitParent(ClassLoader parent) { if (parent != null) return parent; else return Thread.currentThread().getContextClassLoader(); } /** * Returns true if jar entries should be cached. */ public static boolean isJarCacheEnabled() { return _isJarCacheEnabled; } /** * Returns true if jar entries should be cached. */ public static void setJarCacheEnabled(boolean isEnabled) { _isJarCacheEnabled = isEnabled; } private void verbose(String name, String msg) { if (_isVerbose) { for (int i = _verboseDepth; _verboseDepth > 0; _verboseDepth--) System.err.print(' '); System.err.println(toString() + " " + name + " " + msg); } } /** * Returns the global dependency check interval. */ public static long getGlobalDependencyCheckInterval() { return _globalDependencyCheckInterval; } /** * Sets the global dependency check interval. */ public static void setGlobalDependencyCheckInterval(long interval) { _globalDependencyCheckInterval = interval; } /** * Sets the name. */ public void setId(String id) { _id = id; } /** * Gets the name. */ public String getId() { return _id; } /** * Returns true if the class loader is closed. */ public boolean isDestroyed() { return _lifecycle.isDestroyed(); } /** * Adds a resource loader to the end of the list. */ public void addLoader(Loader loader) { int p = _loaders.indexOf(loader); // overriding loaders are inserted before the loader they override // server/10ih if (p >= 0) { Loader oldLoader = _loaders.get(p); if (oldLoader != loader) addLoader(loader, p); } else addLoader(loader, _loaders.size()); _hasNewLoader = true; } /** * Adds a resource loader. */ public void addLoader(Loader loader, int offset) { if (_lifecycle.isDestroyed()) throw new IllegalStateException(L().l("can't add loaders after initialization")); if (log().isLoggable(Level.FINEST)) log().finest(this + " adding loader " + loader); _loaders.add(offset, loader); if (loader.getLoader() == null) loader.setLoader(this); if (loader instanceof Dependency) _dependencies.add((Dependency) loader); if (loader instanceof Make) { if (_makeList == null) _makeList = new MakeContainer(); _makeList.add((Make) loader); } if (loader instanceof ClassLoaderListener) addListener(new WeakLoaderListener((ClassLoaderListener) loader)); _hasNewLoader = true; } public ArrayList<Loader> getLoaders() { return _loaders; } /** * Adds jars based on a manifest classpath. */ public void addJarManifestClassPath(Path path) throws IOException { Path contextPath; Path manifestPath; if (path.isDirectory()) { manifestPath = path.lookup("META-INF/MANIFEST.MF"); contextPath = path; } else { JarPath jar = JarPath.create(path); manifestPath = jar.lookup("META-INF/MANIFEST.MF"); contextPath = path.getParent(); } if (manifestPath.canRead()) { ReadStream is = manifestPath.openRead(); try { Manifest manifest = new Manifest(is); Attributes main = manifest.getMainAttributes(); String classPath = main.getValue("Class-Path"); addManifestClassPath(classPath, contextPath); } catch (IOException e) { log().log(Level.WARNING, e.toString(), e); return; } finally { is.close(); } } } /** * Adds jars based on a manifest classpath. */ public void addManifestClassPath(String classPath, Path pwd) { if (classPath == null) return; String []urls = Pattern.compile("[\\s,]+").split(classPath); if (urls == null) return; for (int i = 0; i < urls.length; i++) { String url = urls[i]; if (url.equals("")) continue; addJar(pwd.lookup(url)); } } /** * Adds a native path. */ public void addNative(Path path) { _nativePath.add(path); } /** * Adds a jar loader. */ public void addJar(Path jar) { addRoot(jar); } /** * Adds a root loader. */ public void addRoot(Path root) { if (_lifecycle.isDestroyed()) throw new IllegalStateException(L().l("can't add roots after closing")); URL url = pathToURL(root); if (containsURL(url)) { log().finer(this + " skipping duplicate URL " + url); return; } if (root instanceof JarPath || root.getPath().endsWith(".jar") || root.getPath().endsWith(".zip")) { if (_jarLoader == null) { _jarLoader = new JarLoader(); addLoader(_jarLoader); } _jarLoader.addJar(root); } else { SimpleLoader loader = new SimpleLoader(); loader.setPath(root); if (! _loaders.contains(loader)) addLoader(loader); } addURL(root); } /** * Adds a jar loader. */ public void addPathClass(String className, Path path) { if (_pathLoader == null) { _pathLoader = new PathLoader(); // ejb/0i00 _loaders.add(0, _pathLoader); } _pathLoader.put(className, path); } /** * Adds the URL to the URLClassLoader. */ public boolean addURL(Path path) { URL url = pathToURL(path); if (url == null) return false; else if (containsURL(url)) return false; else { addURL(url); return true; } } /** * Adds the URL to the URLClassLoader. */ public boolean containsURL(Path path) { URL url = pathToURL(path); if (url == null) return false; else return containsURL(url); } private URL pathToURL(Path path) { try { if (path.getScheme().equals("memory")) return null; if (path.getScheme().equals("jar")) { } else if (path.getFullPath().endsWith(".jar")) { } else if (! path.getURL().endsWith("/")) path = path.lookup("./"); return new URL(path.getURL()); } catch (MalformedURLException e) { log().warning(e.toString()); } catch (Exception e) { log().log(Level.WARNING, e.toString(), e); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?