001: /* ===========================================================================
002: * $RCSfile: MemberValueInfo.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:
025: /**
026: * Representation of an annotation member's value entry.
027: *
028: * @author Mark Welsh
029: */
030: public class MemberValueInfo {
031: // Constants -------------------------------------------------------------
032:
033: // Fields ----------------------------------------------------------------
034: private int u1tag;
035: private int u2constValueIndex; // Union: const_value_index
036: private int u2typeNameIndex; // Union: enum_const_value
037: private int u2constNameIndex; // enum_const_value
038: private int u2classInfoIndex; // Union: class_info_index
039: private AnnotationInfo annotationValue; // Union: annotation_value
040: private int u2numValues; // Union: array_value
041: private MemberValueInfo[] values; // array_value
042:
043: // Class Methods ---------------------------------------------------------
044: public static MemberValueInfo create(DataInput din)
045: throws Exception {
046: MemberValueInfo mvi = new MemberValueInfo();
047: mvi.read(din);
048: return mvi;
049: }
050:
051: // Instance Methods ------------------------------------------------------
052: private MemberValueInfo() {
053: }
054:
055: /** Return tag, defining member type. */
056: protected int getTag() {
057: return u1tag;
058: }
059:
060: /** Check for Utf8 references to constant pool and mark them. */
061: protected void markUtf8Refs(ConstantPool pool) throws Exception {
062: switch (u1tag) {
063: case 'B':
064: case 'C':
065: case 'D':
066: case 'F':
067: case 'I':
068: case 'J':
069: case 'S':
070: case 'Z':
071: break;
072: case 's':
073: pool.incRefCount(u2constValueIndex);
074: break;
075: case 'e':
076: pool.incRefCount(u2typeNameIndex);
077: pool.incRefCount(u2constNameIndex);
078: break;
079: case 'c':
080: pool.incRefCount(u2classInfoIndex);
081: break;
082: case '@':
083: annotationValue.markUtf8Refs(pool);
084: break;
085: case '[':
086: for (int i = 0; i < u2numValues; i++) {
087: values[i].markUtf8Refs(pool);
088: }
089: break;
090: default:
091: throw new Exception(
092: "Illegal tag value in annotation attribute member_value structure: "
093: + u1tag);
094: }
095: }
096:
097: private void read(DataInput din) throws Exception {
098: u1tag = din.readUnsignedByte();
099: switch (u1tag) {
100: case 'B':
101: case 'C':
102: case 'D':
103: case 'F':
104: case 'I':
105: case 'J':
106: case 'S':
107: case 'Z':
108: case 's':
109: u2constValueIndex = din.readUnsignedShort();
110: break;
111: case 'e':
112: u2typeNameIndex = din.readUnsignedShort();
113: u2constNameIndex = din.readUnsignedShort();
114: break;
115: case 'c':
116: u2classInfoIndex = din.readUnsignedShort();
117: break;
118: case '@':
119: annotationValue = AnnotationInfo.create(din);
120: break;
121: case '[':
122: u2numValues = din.readUnsignedShort();
123: values = new MemberValueInfo[u2numValues];
124: for (int i = 0; i < u2numValues; i++) {
125: values[i] = MemberValueInfo.create(din);
126: }
127: break;
128: default:
129: throw new Exception(
130: "Illegal tag value in annotation attribute member_value structure: "
131: + u1tag);
132: }
133: }
134:
135: /** Export the representation to a DataOutput stream. */
136: public void write(DataOutput dout) throws Exception {
137: dout.writeByte(u1tag);
138: switch (u1tag) {
139: case 'B':
140: case 'C':
141: case 'D':
142: case 'F':
143: case 'I':
144: case 'J':
145: case 'S':
146: case 'Z':
147: case 's':
148: dout.writeShort(u2constValueIndex);
149: break;
150: case 'e':
151: dout.writeShort(u2typeNameIndex);
152: dout.writeShort(u2constNameIndex);
153: break;
154: case 'c':
155: dout.writeShort(u2classInfoIndex);
156: break;
157: case '@':
158: annotationValue.write(dout);
159: break;
160: case '[':
161: dout.writeShort(u2numValues);
162: for (int i = 0; i < u2numValues; i++) {
163: values[i].write(dout);
164: }
165: break;
166: default:
167: throw new Exception(
168: "Illegal tag value in annotation attribute member_value structure: "
169: + u1tag);
170: }
171: }
172:
173: /** Do necessary name remapping. */
174: protected void remap(ClassFile cf, NameMapper nm) throws Exception {
175: switch (u1tag) {
176: case 'B':
177: case 'C':
178: case 'D':
179: case 'F':
180: case 'I':
181: case 'J':
182: case 'S':
183: case 'Z':
184: case 's':
185: break;
186: case 'e':
187: break;
188: case 'c':
189: String oldDesc = cf.getUtf8(u2classInfoIndex);
190: String newDesc = nm.mapDescriptor(oldDesc);
191: u2classInfoIndex = cf
192: .remapUtf8To(newDesc, u2classInfoIndex);
193: break;
194: case '@':
195: annotationValue.remap(cf, nm);
196: break;
197: case '[':
198: for (int i = 0; i < u2numValues; i++) {
199: values[i].remap(cf, nm);
200: }
201: break;
202: default:
203: throw new Exception(
204: "Illegal tag value in annotation attribute member_value structure: "
205: + u1tag);
206: }
207: }
208:
209: /** Provide debugging dump of this object. */
210: public void dump(PrintStream ps, ClassFile cf) throws Exception {
211: ps.println("u1tag : " + u1tag);
212: }
213: }
|