📄 classfile.java
字号:
} return null; } /** * Get information for static method without respect to return value. This * can only be used with existing classes. Only the class itself is checked * for a method matching the supplied name and argument list signature. * * @param name method name * @param sig encoded argument list signature * @return method information, or <code>null</code> if method not found */ public ClassItem getStaticMethod(String name, String sig) { // only check if loadable class if (m_curClass != null) { // check for match to method defined in class Method[] methods = getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(name) && method.isStatic()) { if (method.getSignature().startsWith(sig)) { ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem(name, this, method); m_itemMap.put(method, item); } return item; } } } } return null; } /** * Get all binding methods currently defined in class. Binding methods are * generally identified by a supplied prefix, but additional methods * can be specified the the combination of exact name and signature. This * is a little kludgy, but necessary to handle the "marshal" method added * to mapped classes. * * @param prefix identifying prefix for binding methods * @param matches pairs of method name and signature to be matched as * exceptions to the prefix matching * @return existing binding methods */ public ExistingMethod[] getBindingMethods(String prefix, String[] matches) { // return empty array if newly created class or unloadable class if (m_curClass == null) { return EMPTY_METHOD_ARRAY; } // check for binding methods defined in class Method[] methods = getMethods(); int count = 0; for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String name = method.getName(); if (name.startsWith(prefix)) { count++; } else { String sig = method.getSignature(); for (int j = 0; j < matches.length; j += 2) { if (name.equals(matches[j]) && sig.equals(matches[j+1])) { count++; break; } } } } // generate array of methods found if (count == 0) { return EMPTY_METHOD_ARRAY; } else { ExistingMethod[] exists = new ExistingMethod[count]; int fill = 0; for (int i = 0; i < methods.length; i++) { Method method = methods[i]; String name = method.getName(); boolean match = name.startsWith(prefix); if (!match) { String sig = method.getSignature(); for (int j = 0; j < matches.length; j += 2) { if (name.equals(matches[j]) && sig.equals(matches[j+1])) { match = true; break; } } } if (match) { ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem(name, this, method); m_itemMap.put(method, item); } exists[fill++] = new ExistingMethod(method, item, this); } } return exists; } } /** * Check accessible method. Check if a field or method in another class is * accessible from within this class. * * @param item field or method information * @return <code>true</code> if accessible, <code>false</code> if not */ public boolean isAccessible(ClassItem item) { if (item.getClassFile() == this) { return true; } else { int access = item.getAccessFlags(); if ((access & Constants.ACC_PUBLIC) != 0) { return true; } else if ((access & Constants.ACC_PRIVATE) != 0) { return false; } else if (getPackage().equals(item.getClassFile().getPackage())) { return true; } else if ((access & Constants.ACC_PROTECTED) != 0) { ClassFile target = item.getClassFile(); ClassFile ancestor = this; while ((ancestor = ancestor.getSuperFile()) != null) { if (ancestor == target) { return true; } } return false; } else { return false; } } } /** * Get generator for modifying class. * * @return generator for class * @throws JiBXException if class not modifiable */ private ClassGen getClassGen() throws JiBXException { if (m_genClass == null) { if (m_isWritable) { m_genClass = new ClassGen(m_curClass); m_genPool = m_genClass.getConstantPool(); m_instBuilder = new InstructionBuilder(m_genClass, m_genPool); m_isHashCurrent = false; } else { throw new JiBXException("Cannot modify class " + m_name); } } return m_genClass; } /** * Get constant pool generator for modifying class. * * @return constant pool generator for class * @throws JiBXException if class not modifiable */ public ConstantPoolGen getConstPoolGen() throws JiBXException { if (m_genPool == null) { getClassGen(); } return m_genPool; } /** * Get instruction builder for modifying class. * * @return instruction builder for class * @throws JiBXException if class not modifiable */ public InstructionBuilder getInstructionBuilder() throws JiBXException { if (m_instBuilder == null) { getClassGen(); } return m_instBuilder; } /** * Add method to class. * * @param method method to be added * @return added method information * @throws JiBXException on error in adding method */ public ClassItem addMethod(Method method) throws JiBXException { getClassGen().addMethod(method); setModified(); String mname = method.getName(); if (m_suffixMap != null && isSuffixName(mname)) { m_suffixMap.put(mname, method); } return new ClassItem(mname, this, method); } /** * Remove method from class. * * @param method method to be removed * @throws JiBXException on error in removing method */ public void removeMethod(Method method) throws JiBXException { getClassGen().removeMethod(method); setModified(); String mname = method.getName(); if (m_suffixMap != null && isSuffixName(mname)) { m_suffixMap.remove(mname); } } /** * Add field to class with initial <code>String</code> value. If a field * with the same name already exists, it is overwritten. * * @param type fully qualified class name of field type * @param name field name * @param access access flags for field * @param init initial value for field * @return field information * @throws JiBXException if unable to add field */ public ClassItem addField(String type, String name, int access, String init) throws JiBXException { deleteField(name); FieldGen fgen = new FieldGen(access, Type.getType(Utility.getSignature(type)), name, getConstPoolGen()); fgen.setInitValue(init); Field field = fgen.getField(); getClassGen().addField(field); m_isModified = true; m_isHashCurrent = false; return new ClassItem(name, this, field); } /** * Update class field with initial <code>String</code> value. If the field * already exists with the same characteristics it is left unchanged; * otherwise any existing field with the same name is overwritten. * * @param type fully qualified class name of field type * @param name field name * @param access access flags for field * @param init initial value for field * @return field information * @throws JiBXException if unable to add field */ public ClassItem updateField(String type, String name, int access, String init) throws JiBXException { // first check for match with existing field Field[] fields = m_curClass.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; if (field.getName().equals(name) && field.getAccessFlags() == access) { String sig = field.getSignature(); if (type.equals(Utility.signatureToString(sig, false))) { ConstantValue cval = field.getConstantValue(); if (cval != null) { int index = cval.getConstantValueIndex(); ConstantPool cp = m_curClass.getConstantPool(); Constant cnst = cp.getConstant(index); if (cnst instanceof ConstantString) { Object value = ((ConstantString)cnst). getConstantValue(cp); if (init.equals(value)) { return new ClassItem(name,this, field); } } } } } } // no exact match, so replace any existing field with same name deleteField(name); FieldGen fgen = new FieldGen(access, Type.getType(Utility.getSignature(type)), name, getConstPoolGen()); fgen.setInitValue(init); Field field = fgen.getField(); getClassGen().addField(field); m_isModified = true; m_isHashCurrent = false; return new ClassItem(name, this, field); } /** * Add field to class without initialization. If a field with the same name * already exists, it is overwritten. * * @param type fully qualified class name of field type * @param name field name * @param access access flags for field * @return field information * @throws JiBXException if unable to add field */ public ClassItem addField(String type, String name, int access) throws JiBXException { deleteField(name); FieldGen fgen = new FieldGen(access, Type.getType(Utility.getSignature(type)), name, getConstPoolGen()); Field field = fgen.getField(); getClassGen().addField(field); m_isModified = true; m_isHashCurrent = false; return new ClassItem(name, this, field); } /** * Add private field to class without initialization. If a field * with the same name already exists, it is overwritten. * * @param type fully qualified class name of field type * @param name field name * @return field information * @throws JiBXException if unable to add field */ public ClassItem addPrivateField(String type, String name) throws JiBXException { return addField(type, name, PRIVATEFIELD_ACCESS); } /** * Add default constructor to a class. The added default constructor just * calls the default constructor for the superclass. If the superclass * doesn't have a default constructor, this method is called recursively to * add one if possible. * * @return constructor information * @throws JiBXException if unable to add constructor */ public ClassItem addDefaultConstructor() throws JiBXException { if (m_defaultConstructor == null) { // check for default constructor in superclass ClassItem cons = m_superClass.getInitializerMethod("()V"); if (cons == null) { if (m_superClass.addDefaultConstructor() == null) { return null; } } else { cons.makeAccessible(this); } // add the public constructor method ExceptionMethodBuilder mb = new ExceptionMethodBuilder("<init>", Type.VOID, new Type[0], this, Constants.ACC_PUBLIC); // call the superclass constructor mb.appendLoadLocal(0); mb.appendCallInit(m_superClass.getName(), "()V"); // finish with return mb.appendReturn(); mb.codeComplete(false); m_defaultConstructor = mb.addMethod(); } return m_defaultConstructor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -