001: /* ===========================================================================
002: * $RCSfile: ClassItemInfo.java,v $
003: * ===========================================================================
004: *
005: * RetroGuard -- an obfuscation package for Java classfiles.
006: *
007: * Copyright (c) 1998-2006 Mark Welsh (markw@retrologic.com)
008: *
009: * This program can be redistributed and/or modified under the terms of the
010: * Version 2 of the GNU General Public License as published by the Free
011: * Software Foundation.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: */
019:
020: package COM.rl.obf.classfile;
021:
022: import java.io.*;
023: import java.util.*;
024: import COM.rl.util.*;
025:
026: /**
027: * Representation of a field or method from a class-file.
028: *
029: * @author Mark Welsh
030: */
031: abstract public class ClassItemInfo implements ClassConstants {
032: // Constants -------------------------------------------------------------
033:
034: // Fields ----------------------------------------------------------------
035: private int u2accessFlags;
036: private int u2nameIndex;
037: private int u2descriptorIndex;
038: protected int u2attributesCount;
039: protected AttrInfo attributes[];
040:
041: protected ClassFile cf;
042: private boolean isSynthetic = false;
043:
044: // Class Methods ---------------------------------------------------------
045:
046: // Instance Methods ------------------------------------------------------
047: protected ClassItemInfo(ClassFile cf) {
048: this .cf = cf;
049: }
050:
051: /** Is the field or method 'Synthetic'? */
052: public boolean isSynthetic() {
053: return isSynthetic;
054: }
055:
056: /** Return method/field name index into Constant Pool. */
057: protected int getNameIndex() {
058: return u2nameIndex;
059: }
060:
061: /** Set the method/field name index. */
062: protected void setNameIndex(int index) {
063: u2nameIndex = index;
064: }
065:
066: /** Return method/field descriptor index into Constant Pool. */
067: protected int getDescriptorIndex() {
068: return u2descriptorIndex;
069: }
070:
071: /** Set the method/field descriptor index. */
072: protected void setDescriptorIndex(int index) {
073: u2descriptorIndex = index;
074: }
075:
076: /** Return method/field string name. */
077: public String getName() throws Exception {
078: return ((Utf8CpInfo) cf.getCpEntry(u2nameIndex)).getString();
079: }
080:
081: /** Return descriptor string. */
082: public String getDescriptor() throws Exception {
083: return ((Utf8CpInfo) cf.getCpEntry(u2descriptorIndex))
084: .getString();
085: }
086:
087: /** Return access flags. */
088: public int getAccessFlags() throws Exception {
089: return u2accessFlags;
090: }
091:
092: /**
093: * Trim attributes from the classfile ('Code', 'Exceptions', 'ConstantValue'
094: * are preserved, all others except the list in the String[] are killed).
095: */
096: protected void trimAttrsExcept(String[] keepAttrs) throws Exception {
097: // Traverse all attributes, removing all except those on 'keep' list
098: for (int i = 0; i < attributes.length; i++) {
099: if (Tools.isInArray(attributes[i].getAttrName(), keepAttrs)) {
100: attributes[i].trimAttrsExcept(keepAttrs);
101: } else {
102: attributes[i] = null;
103: }
104: }
105:
106: // Delete the marked attributes
107: AttrInfo[] left = new AttrInfo[attributes.length];
108: int j = 0;
109: for (int i = 0; i < attributes.length; i++) {
110: if (attributes[i] != null) {
111: left[j++] = attributes[i];
112: }
113: }
114: attributes = new AttrInfo[j];
115: System.arraycopy(left, 0, attributes, 0, j);
116: u2attributesCount = j;
117: }
118:
119: /** Check for Utf8 references to constant pool and mark them. */
120: protected void markUtf8Refs(ConstantPool pool) throws Exception {
121: pool.incRefCount(u2nameIndex);
122: pool.incRefCount(u2descriptorIndex);
123: for (int i = 0; i < attributes.length; i++) {
124: attributes[i].markUtf8Refs(pool);
125: }
126: }
127:
128: /** List the constant pool entries references from this method or field. */
129: public Enumeration listCpRefs() throws Exception {
130: return null;
131: }
132:
133: /** Import the field or method data to internal representation. */
134: protected void read(DataInput din) throws Exception {
135: u2accessFlags = din.readUnsignedShort();
136: u2nameIndex = din.readUnsignedShort();
137: u2descriptorIndex = din.readUnsignedShort();
138: u2attributesCount = din.readUnsignedShort();
139: attributes = new AttrInfo[u2attributesCount];
140: for (int i = 0; i < u2attributesCount; i++) {
141: attributes[i] = AttrInfo.create(din, cf);
142: if (attributes[i].getAttrName().equals(ATTR_Synthetic)) {
143: isSynthetic = true;
144: }
145: }
146: }
147:
148: /** Export the representation to a DataOutput stream. */
149: public void write(DataOutput dout) throws Exception {
150: if (dout == null)
151: throw new IOException("No output stream was provided.");
152: dout.writeShort(u2accessFlags);
153: dout.writeShort(u2nameIndex);
154: dout.writeShort(u2descriptorIndex);
155: dout.writeShort(u2attributesCount);
156: for (int i = 0; i < u2attributesCount; i++) {
157: attributes[i].write(dout);
158: }
159: }
160: }
|