?? classfile.java
字號:
/*Copyright (c) 2003-2005, Dennis M. SosnoskiAll rights reserved.Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FORANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ONANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/package org.jibx.binding.classes;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URL;import java.net.URLClassLoader;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import org.apache.bcel.Constants;import org.apache.bcel.classfile.ClassParser;import org.apache.bcel.classfile.Code;import org.apache.bcel.classfile.CodeException;import org.apache.bcel.classfile.Constant;import org.apache.bcel.classfile.ConstantDouble;import org.apache.bcel.classfile.ConstantFloat;import org.apache.bcel.classfile.ConstantInteger;import org.apache.bcel.classfile.ConstantLong;import org.apache.bcel.classfile.ConstantPool;import org.apache.bcel.classfile.ConstantString;import org.apache.bcel.classfile.ConstantUtf8;import org.apache.bcel.classfile.ConstantValue;import org.apache.bcel.classfile.ExceptionTable;import org.apache.bcel.classfile.Field;import org.apache.bcel.classfile.FieldOrMethod;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Method;import org.apache.bcel.classfile.Synthetic;import org.apache.bcel.classfile.Utility;import org.apache.bcel.generic.ClassGen;import org.apache.bcel.generic.ConstantPoolGen;import org.apache.bcel.generic.FieldGen;import org.apache.bcel.generic.Type;import org.apache.bcel.util.ClassPath;import org.jibx.runtime.JiBXException;/** * Class file information. Wraps the actual class file data as well as * associated management information. * * @author Dennis M. Sosnoski * @version 1.0 */public class ClassFile{ // // Constants for code generation. public static final int PRIVATE_ACCESS = 0; public static final int PACKAGE_ACCESS = 1; public static final int PROTECTED_ACCESS = 2; public static final int PUBLIC_ACCESS = 3; public static final int SYNTHETIC_ACCESS_FLAG = 0x1000; protected static final int PRIVATEFIELD_ACCESS = Constants.ACC_PRIVATE | SYNTHETIC_ACCESS_FLAG; protected static final ExistingMethod[] EMPTY_METHOD_ARRAY = {}; protected static final byte[] EMPTY_BYTES = new byte[0]; public static final ClassItem[] EMPTY_CLASS_ITEMS = new ClassItem[0]; // // Class data. /** Singleton loader from classpath. */ private static ClassPath s_loader; /** Direct class loader. */ private static ClassLoader s_directLoader; // // Actual instance data. /** Fully qualified class name. */ private String m_name; /** Signature for class as type. */ private String m_signature; /** Class as type. */ private Type m_type; /** Directory root for class. */ private File m_root; /** Actual class file information. */ private File m_file; /** Class in same package as superclass flag. */ private boolean m_isSamePackage; /** File is writable flag. */ private boolean m_isWritable; /** Super class of this class (set by caller, since it may require additional information to find the class file). */ protected ClassFile m_superClass; /** Names of all interfaces directly implemented by this class. */ protected String[] m_interfaceNames; /** Class files of interfaces extended by interface. */ private ClassFile[] m_superInterfaces; /** All classes and interfaces of which this is an instance (lazy create, only if needed. */ private String[] m_instanceOfs; /** All methods defined by this class or interface (lazy create, only if needed. */ private Method[] m_methods; /** Base class information as loaded by BCEL. */ private JavaClass m_curClass; /** Modified class generator (lazy create, only if needed). */ private ClassGen m_genClass; /** Constant pool generator for modified class (lazy create, only if needed). */ private ConstantPoolGen m_genPool; /** Instruction factory for modified class (lazy create, only if needed). */ protected InstructionBuilder m_instBuilder; /** Map for method names with possibly generated suffixes (lazy create, only if needed). */ private HashMap m_suffixMap; /** Map to class item information. */ private HashMap m_itemMap; /** Flag for class modified. */ private boolean m_isModified; /** Usage count for this class. */ private int m_useCount; /** Hash code computation for class is current flag. */ private boolean m_isHashCurrent; /** Cached hash code value for class. */ private int m_hashCode; /** Depth of superclass hierarchy for class (lazy computation). */ private int m_inheritDepth; /** Suffix number for making method names unique (lazy computation). */ private int m_uniqueIndex; /** Added default constructor for class. */ private ClassItem m_defaultConstructor; /** * Constructor for class file loaded from a stream. Loads the class data * and prepares it for use. * * @param name fully qualified class name * @param path class file path * @param ins input stream for class file data * @throws JiBXException if unable to load class file */ public ClassFile(String name, String path, InputStream ins) throws JiBXException { init(name, path, ins); } /** * Constructor for preexisting class file. Loads the class data and * prepares it for use. * * @param name fully qualified class name * @param root directory root from class loading path list * @param file actual class file * @throws IOException if unable to open file * @throws JiBXException if error in reading class file */ public ClassFile(String name, File root, File file) throws IOException, JiBXException { init(name, root.getPath(), new FileInputStream(file)); m_root = root; m_file = file; m_isWritable = file.canWrite(); } /** * Constructor for preexisting class file from classpath. Loads the class * data and prepares it for use. * * @param name fully qualified class name * @throws IOException if unable to open file * @throws JiBXException if error in reading class file */ public ClassFile(String name) throws IOException, JiBXException { // try out class path first, then BCEL system path ClassPath.ClassFile cf = null; try { cf = s_loader.getClassFile(name); } catch (IOException ex) { try { cf = ClassPath.SYSTEM_CLASS_PATH.getClassFile(name); } catch (IOException ex1) { /* deliberately left empty */ } } if (cf == null) { throw new JiBXException("Class " + name + " not found in any classpath"); } else { init(name, cf.getPath(), cf.getInputStream()); } } /** * Constructor for synthetic placeholder classfile with no backing class * data. * * @param name fully qualified class name * @param sig corresponding class signature */ public ClassFile(String name, String sig) { m_name = name; m_signature = sig; m_type = Type.getType(sig); m_interfaceNames = new String[0]; m_superInterfaces = new ClassFile[0]; m_itemMap = new HashMap(); } /** * Constructor for new class file. Initializes the class data and * prepares it for use. * * @param name fully qualified class name * @param root directory root from class loading path list * @param sclas superclass of new class * @param access access flags for class * @param impls array of interfaces implemented by new class * @throws JiBXException on error loading interface information */ public ClassFile(String name, File root, ClassFile sclas, int access, String[] impls) throws JiBXException { String fname = name.replace('.', File.separatorChar)+".class"; File file = new File(root, fname); m_name = name; m_signature = Utility.getSignature(name); m_type = ClassItem.typeFromName(name); m_root = root; m_superClass = sclas; m_interfaceNames = impls; m_file = file; m_isWritable = true; m_genClass = new ClassGen(name, sclas.getName(), "", access | SYNTHETIC_ACCESS_FLAG, impls); m_genPool = m_genClass.getConstantPool(); int index = m_genPool.addUtf8("Synthetic"); m_genClass.addAttribute(new Synthetic(index, 0, EMPTY_BYTES, m_genPool.getConstantPool())); m_instBuilder = new InstructionBuilder(m_genClass, m_genPool); m_itemMap = new HashMap(); initInterface(); ClassCache.addClassFile(this); } /** * Internal initialization method. This is used to handle common * initialization for the constructors. * * @param name fully qualified class name * @param path class file path * @param ins input stream for class file data * @throws JiBXException if unable to load class file */ private void init(String name, String path, InputStream ins) throws JiBXException { m_name = name; m_signature = Utility.getSignature(name); m_type = ClassItem.typeFromName(name); m_itemMap = new HashMap(); if (path == null) { m_interfaceNames = new String[0]; } else { String fname = name.replace('.', File.separatorChar) + ".class"; ClassParser parser = new ClassParser(ins, fname); try { m_curClass = parser.parse(); m_interfaceNames = m_curClass.getInterfaceNames(); } catch (Exception ex) { throw new JiBXException("Error reading path " + path + " for class " + name); } } initInterface(); } /** * Retrieve superinterfaces for an interface class. These are collected at * initialization so that we can support getting the full set of methods * later without worrying about throwing an exception. * * @throws JiBXException on error loading interface information */ private void initInterface() throws JiBXException { if (isInterface() && m_interfaceNames.length > 0) { ClassFile[] supers = new ClassFile[m_interfaceNames.length]; for (int i = 0; i < m_interfaceNames.length; i++) { supers[i] = ClassCache.getClassFile(m_interfaceNames[i]); } m_superInterfaces = supers; } else { m_superInterfaces = new ClassFile[0]; } } /** * Check if class is an interface. This only checks existing classes, * assuming that no generated classes are interfaces. * * @return <code>true</code> if an interface, <code>false</code> if not */ public boolean isInterface() { return m_curClass != null && m_curClass.isInterface(); } /** * Check if class is abstract. This only checks existing classes, * assuming that no generated classes are abstract. * * @return <code>true</code> if an abstract class, <code>false</code> if not */ public boolean isAbstract() { return m_curClass != null && m_curClass.isAbstract(); } /** * Check if class is an array. This only checks existing classes, * assuming that no generated classes are arrays. *
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -