enhancermanager.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 383 行

JAVA
383
字号
/* * 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.enhancer;import com.caucho.bytecode.ByteCodeClassMatcher;import com.caucho.bytecode.ByteCodeClassScanner;import com.caucho.bytecode.ByteCodeParser;import com.caucho.bytecode.JClass;import com.caucho.bytecode.JavaClass;import com.caucho.bytecode.JavaClassLoader;import com.caucho.java.WorkDir;import com.caucho.java.gen.GenClass;import com.caucho.java.gen.JavaClassGenerator;import com.caucho.loader.*;import com.caucho.util.CharBuffer;import com.caucho.util.L10N;import com.caucho.util.Log;import com.caucho.vfs.*;import java.io.*;import java.lang.instrument.*;import java.lang.reflect.*;import java.util.ArrayList;import java.security.*;import java.util.logging.Level;import java.util.logging.Logger;/** * Manages the enhancement */public class EnhancerManager implements ClassFileTransformer{  private static final L10N L = new L10N(EnhancerManager.class);  private static final Logger log = Log.open(EnhancerManager.class);  private static EnvironmentLocal<EnhancerManager> _localEnhancer =    new EnvironmentLocal<EnhancerManager>();  private EnhancerManager _parent;  private DynamicClassLoader _loader;  private Path _workPath;  private JavaClassLoader _jClassLoader = new JavaClassLoader();  private JavaClassGenerator _javaGen = new JavaClassGenerator();    private ArrayList<ClassEnhancer> _classEnhancerList    = new ArrayList<ClassEnhancer>();    private EnhancerManager(ClassLoader loader)  {    for (;	 loader != null && ! (loader instanceof DynamicClassLoader);	 loader = loader.getParent()) {    }    _loader = (DynamicClassLoader) loader;    if (loader != null)      _parent = getLocalEnhancer(loader.getParent());    /*    if (_parent != null) {      _classEnhancerList.addAll(_parent._classEnhancerList);    }    */  }  public static EnhancerManager create()  {    return create(Thread.currentThread().getContextClassLoader());  }  public static EnhancerManager create(ClassLoader loader)  {    EnhancerManager enhancer = _localEnhancer.getLevel(loader);    if (enhancer == null) {      enhancer = new EnhancerManager(loader);      _localEnhancer.set(enhancer, loader);      for (; loader != null; loader = loader.getParent()) {	if (loader instanceof DynamicClassLoader) {	  ((DynamicClassLoader) loader).addTransformer(enhancer);	  break;	}      }    }    return enhancer;  }  public static EnhancerManager getLocalEnhancer(ClassLoader loader)  {    return _localEnhancer.get(loader);  }  /**   * Returns the JClassLoader.   */  public JavaClassLoader getJavaClassLoader()  {    return _jClassLoader;  }  /**   * Gets the work path.   */  public Path getWorkPath()  {    if (_workPath != null)      return _workPath;    else      return WorkDir.getLocalWorkDir(_loader);  }  /**   * Sets the work path.   */  public void setWorkPath(Path workPath)  {    _workPath = workPath;  }  /**   * Gets the work path.   */  public final Path getPreWorkPath()  {    return getWorkPath().lookup("pre-enhance");  }  /**   * Gets the work path.   */  public final Path getPostWorkPath()  {    return getWorkPath().lookup("post-enhance");  }  /**   * Adds a class enhancer.   */  public void addClassEnhancer(ClassEnhancer classEnhancer)  {    _classEnhancerList.add(classEnhancer);  }  /**   * Adds a class annotation.   */  public void addClass(ClassEnhancerConfig config)  {    config.setEnhancerManager(this);    _classEnhancerList.add(config);  }    /**   * Returns the enhanced .class or null if no enhancement.   */  public byte[] transform(ClassLoader loader,			  String className,			  Class oldClass,			  ProtectionDomain domain,			  byte []buffer)  {    if (isClassMatch(className)) {      try {	ClassLoader tempLoader	  = ((DynamicClassLoader) loader).getNewTempClassLoader();	DynamicClassLoader workLoader	  = SimpleLoader.create(tempLoader, getPostWorkPath());	workLoader.setServletHack(true);	boolean isModified = true;	Thread thread = Thread.currentThread();	ClassLoader oldLoader = thread.getContextClassLoader();		try {	  Class cl = Class.forName(className.replace('/', '.'),				   false,				   workLoader);	  thread.setContextClassLoader(tempLoader);	  	  Method init = cl.getMethod("_caucho_init", new Class[] { Path.class });	  Method modified = cl.getMethod("_caucho_is_modified", new Class[0]);	  init.invoke(null, Vfs.lookup());	  isModified = (Boolean) modified.invoke(null);	} catch (Exception e) {	  log.log(Level.FINEST, e.toString(), e);	} catch (Throwable e) {	  log.log(Level.FINER, e.toString(), e);	} finally {	  thread.setContextClassLoader(oldLoader);	}	if (! isModified) {	  try {	    return load(className);	  } catch (Exception e) {	    log.log(Level.FINER, e.toString(), e);	  }	}		ByteCodeParser parser = new ByteCodeParser();	parser.setClassLoader(_jClassLoader);		ByteArrayInputStream is;	is = new ByteArrayInputStream(buffer, 0, buffer.length);      	JavaClass jClass = parser.parse(is);	return enhance(jClass);      } catch (RuntimeException e) {	throw e;      } catch (Exception e) {	throw new EnhancerRuntimeException(e);      }    }    return null;  }  /**   * Enhances the given class.   */  public byte []enhance(JClass jClass)    throws ClassNotFoundException  {    String className = jClass.getName().replace('/', '.');    String extClassName = className + "__ResinExt";    try {      EnhancerPrepare prepare = new EnhancerPrepare();      prepare.setWorkPath(getWorkPath());      prepare.setClassLoader(_loader);      for (ClassEnhancer enhancer : _classEnhancerList) {	if (enhancer.shouldEnhance(className)) {	  prepare.addEnhancer(enhancer);	}      }      //prepare.renameClass(className, extClassName);      prepare.renameClass(className, className);    } catch (Exception e) {      log.log(Level.FINE, e.toString(), e);      throw new ClassNotFoundException(e.toString());    }    boolean hasEnhancer = false;    GenClass genClass = new GenClass(extClassName);    genClass.setSuperClassName(className);    for (ClassEnhancer enhancer : _classEnhancerList) {      if (enhancer.shouldEnhance(className)) {	try {	  hasEnhancer = true;	  enhancer.enhance(genClass, jClass, extClassName);	} catch (RuntimeException e) {	  throw e;	} catch (Exception e) {	  throw new RuntimeException(e);	}      }    }    // XXX: class-wide enhancements need to go first    try {      if (hasEnhancer) {	_javaGen.setWorkDir(getPreWorkPath());	_javaGen.generate(genClass);	_javaGen.compilePendingJava();      }      EnhancerFixup fixup = new EnhancerFixup();      fixup.setJavaClassLoader(_jClassLoader);      fixup.setClassLoader(_loader);      fixup.setWorkPath(getWorkPath());      for (ClassEnhancer enhancer : _classEnhancerList) {	if (enhancer.shouldEnhance(className)) {	  fixup.addEnhancer(enhancer);	}      }            fixup.fixup(className, extClassName);      return load(className);    } catch (RuntimeException e) {      e.printStackTrace();            throw e;    } catch (Exception e) {      e.printStackTrace();      log.log(Level.FINE, e.toString(), e);            throw new ClassNotFoundException(e.getMessage());    }    // return null;  }  private byte []load(String className)    throws IOException  {    Path path = getPostWorkPath().lookup(className.replace('.', '/') + ".class");    byte []buffer = new byte[(int) path.getLength()];          ReadStream is = path.openRead();    try {      is.readAll(buffer, 0, buffer.length);    } finally {      is.close();    }    return buffer;  }  /**   * Returns true for a matching class.   */  public boolean isClassMatch(String className)  {    if (className.lastIndexOf('$') >= 0) {      int p = className.lastIndexOf('$');      char ch = 0;      if (p + 1 < className.length())	ch = className.charAt(p + 1);      if ('0' <= ch && ch <= '9')	return false;    }    else if (className.indexOf('+') > 0	     || className.indexOf('-') > 0)      return false;        for (int i = 0; i < _classEnhancerList.size(); i++) {      if (_classEnhancerList.get(i).shouldEnhance(className)) {	return true;      }    }    return false;  }  public String toString()  {    return getClass().getSimpleName() + "[" + _classEnhancerList + "]";  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?