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 + -
显示快捷键?