⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 entrylogger.java

📁 这是java2核心技术第七版的源代码
💻 JAVA
字号:
import java.lang.annotation.*;import java.lang.reflect.Proxy;import java.lang.reflect.InvocationHandler;import java.io.*;import java.util.*;import org.apache.bcel.*;import org.apache.bcel.Repository;import org.apache.bcel.classfile.*;import org.apache.bcel.classfile.FieldOrMethod;import org.apache.bcel.generic.*;import org.apache.bcel.util.*;/**   Adds "entering" logs to all methods of a class that have the LogEntry annotation.*/public class EntryLogger{   /**      Adds entry logging code to the given class      @param args the name of the class file to patch   */   public static void main(String[] args)   {      try      {         if (args.length == 0)             System.out.println("USAGE: java EntryLogger classname");         else         {            Attribute.addAttributeReader("RuntimeVisibleAnnotations",                new AnnotationsAttributeReader());            JavaClass jc = Repository.lookupClass(args[0]);            ClassGen cg = new ClassGen(jc);            EntryLogger el = new EntryLogger(cg);            el.convert();            File f = new File(Repository.lookupClassFile(cg.getClassName()).getPath());            cg.getJavaClass().dump(f.getPath());         }      }      catch (Exception e)      {         e.printStackTrace();      }   }   /**      Constructs an EntryLogger that inserts logging into annotated methods of a given class       @param cg the class   */   public EntryLogger(ClassGen cg)   {      this.cg = cg;      cpg = cg.getConstantPool();   }   /**      converts the class by inserting the logging calls.   */   public void convert() throws IOException   {      for (Method m : cg.getMethods())      {         AnnotationsAttribute attr             = (AnnotationsAttribute) getAttribute(m, "RuntimeVisibleAnnotations");         if (attr != null)         {            LogEntry logEntry = attr.getAnnotation(LogEntry.class);            if (logEntry != null)            {               String loggerName = logEntry.logger();               if (loggerName == null) loggerName = "";               cg.replaceMethod(m, insertLogEntry(m, loggerName));                           }         }      }   }   /**      Adds an "entering" call to the beginning of a method.      @param m the method      @param loggerName the name of the logger to call   */   private Method insertLogEntry(Method m, String loggerName)   {      MethodGen mg = new MethodGen(m, cg.getClassName(), cpg);      String className = cg.getClassName();      String methodName = mg.getMethod().getName();      System.out.printf("Adding logging instructions to %s.%s%n", className, methodName);           int getLoggerIndex = cpg.addMethodref(            "java.util.logging.Logger",            "getLogger",            "(Ljava/lang/String;)Ljava/util/logging/Logger;");      int enteringIndex = cpg.addMethodref(            "java.util.logging.Logger",            "entering",            "(Ljava/lang/String;Ljava/lang/String;)V");      InstructionList il = mg.getInstructionList();      InstructionList patch = new InstructionList();      patch.append(new PUSH(cpg, loggerName));      patch.append(new INVOKESTATIC(getLoggerIndex));      patch.append(new PUSH(cpg, className));      patch.append(new PUSH(cpg, methodName));      patch.append(new INVOKEVIRTUAL(enteringIndex));      InstructionHandle[] ihs = il.getInstructionHandles();      il.insert(ihs[0], patch);      mg.setMaxStack();      return mg.getMethod();   }   /**      Gets the attribute of a field or method with the given name.      @param fm the field or method      @param name the attribute name      @return the attribute, or null, if no attribute with the given name was found   */   public static Attribute getAttribute(FieldOrMethod fm, String name)   {      for (Attribute attr : fm.getAttributes())      {         int nameIndex = attr.getNameIndex();         ConstantPool cp = attr.getConstantPool();         String attrName = cp.constantToString(cp.getConstant(nameIndex));         if (attrName.equals(name))            return attr;      }      return null;   }   private ClassGen cg;   private ConstantPoolGen cpg;}/**   This is a pluggable reader for an annotations attribute for the BCEL framework.*/class AnnotationsAttributeReader implements org.apache.bcel.classfile.AttributeReader{   public Attribute createAttribute(int nameIndex, int length, DataInputStream in,      ConstantPool constantPool)   {      AnnotationsAttribute attribute = new AnnotationsAttribute(nameIndex, length, constantPool);      try       {         attribute.read(in, constantPool);         return attribute;      }      catch (IOException e)      {         e.printStackTrace();         return null;      }   }}/**   This attribute describes a set of annotations.    Only String-valued annotation attributes are supported.*/class AnnotationsAttribute extends Attribute{   /**      Reads this annotation.      @param nameIndex the index for the name of this attribute      @param length the number of bytes in this attribute      @param cp the constant pool   */   public AnnotationsAttribute (int nameIndex, int length, ConstantPool cp)   {      super(Constants.ATTR_UNKNOWN, nameIndex, length, cp);      annotations = new HashMap<String, Map<String, String>>();   }   /**      Reads this annotation.      @param in the input stream      @param cp the constant pool   */   public void read(DataInputStream in, ConstantPool cp)      throws IOException   {      short numAnnotations = in.readShort();      for (int i = 0; i < numAnnotations; i++)       {         short typeIndex = in.readShort();         String type = cp.constantToString(cp.getConstant(typeIndex));         Map<String, String> nvPairs = new HashMap<String, String>();         annotations.put(type, nvPairs);         short numElementValuePairs = in.readShort();         for (int j = 0; j < numElementValuePairs; j++)          {            short nameIndex = in.readShort();            String name = cp.constantToString(cp.getConstant(nameIndex));            byte tag = in.readByte();            if (tag == 's')             {               short constValueIndex = in.readShort();               String value = cp.constantToString(cp.getConstant(constValueIndex));               nvPairs.put(name, value);            }            else               throw new UnsupportedOperationException("Can only handle String attributes");         }                              }   }   public void dump(DataOutputStream out)      throws IOException   {      ConstantPoolGen cpg = new ConstantPoolGen(getConstantPool());      out.writeShort(getNameIndex());      out.writeInt(getLength());      out.writeShort(annotations.size());      for (Map.Entry<String, Map<String, String>> entry : annotations.entrySet())       {         String type = entry.getKey();         Map<String, String> nvPairs = entry.getValue();         out.writeShort(cpg.lookupUtf8(type));                  out.writeShort(nvPairs.size());         for (Map.Entry<String, String> nv : nvPairs.entrySet())          {            out.writeShort(cpg.lookupUtf8(nv.getKey()));            out.writeByte('s');            out.writeShort(cpg.lookupUtf8(nv.getValue()));         }      }   }   /**      Gets an annotation from this set of annotations.      @param annotationClass the class of the annotation to get      @return the annotation object, or null if no matching annotation is present   */   public <A extends Annotation> A getAnnotation(Class<A> annotationClass)   {      String key = "L" + annotationClass.getName() + ";";      final Map<String, String> nvPairs = annotations.get(key);      if (nvPairs == null) return null;      InvocationHandler handler = new         InvocationHandler()         {            public Object invoke(Object proxy, java.lang.reflect.Method m, Object[] args)                throws Throwable            {               return nvPairs.get(m.getName());            }         };         return (A) Proxy.newProxyInstance(         getClass().getClassLoader(),          new Class[] { annotationClass },          handler);   }   public void accept(org.apache.bcel.classfile.Visitor v)   {      throw new UnsupportedOperationException();   }      public Attribute copy(ConstantPool cp)   {      throw new UnsupportedOperationException();   }      public String toString ()   {      return annotations.toString();   }      private Map<String, Map<String, String>> annotations;}

⌨️ 快捷键说明

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