001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.util.ArrayList;
022:
023: public class CpBands extends BandSet {
024:
025: public SegmentConstantPool getConstantPool() {
026: return pool;
027: }
028:
029: private final SegmentConstantPool pool = new SegmentConstantPool(
030: this );
031:
032: private String[] cpClass;
033:
034: private String[] cpDescriptor;
035:
036: private double[] cpDouble;
037:
038: private String[] cpFieldClass;
039:
040: private String[] cpFieldDescriptor;
041:
042: private float[] cpFloat;
043:
044: private String[] cpIMethodClass;
045:
046: private String[] cpIMethodDescriptor;
047:
048: private int[] cpInt;
049:
050: private long[] cpLong;
051:
052: private String[] cpMethodClass;
053:
054: private String[] cpMethodDescriptor;
055:
056: private String[] cpSignature;
057:
058: private String[] cpString;
059:
060: private String[] cpUTF8;
061:
062: public CpBands(Segment segment) {
063: super (segment);
064: }
065:
066: public void unpack(InputStream in) throws IOException,
067: Pack200Exception {
068: parseCpUtf8(in);
069: parseCpInt(in);
070: parseCpFloat(in);
071: parseCpLong(in);
072: parseCpDouble(in);
073: parseCpString(in);
074: parseCpClass(in);
075: parseCpSignature(in);
076: parseCpDescriptor(in);
077: parseCpField(in);
078: parseCpMethod(in);
079: parseCpIMethod(in);
080: }
081:
082: /**
083: * Parses the constant pool class names, using {@link #cpClassCount} to
084: * populate {@link #cpClass} from {@link #cpUTF8}.
085: *
086: * @param in
087: * the input stream to read from
088: * @throws IOException
089: * if a problem occurs during reading from the underlying stream
090: * @throws Pack200Exception
091: * if a problem occurs with an unexpected value or unsupported
092: * codec
093: */
094: private void parseCpClass(InputStream in) throws IOException,
095: Pack200Exception {
096: int cpClassCount = header.getCpClassCount();
097: cpClass = parseReferences("cp_Class", in, Codec.UDELTA5,
098: cpClassCount, cpUTF8);
099: }
100:
101: /**
102: * Parses the constant pool descriptor definitions, using
103: * {@link #cpDescriptorCount} to populate {@link #cpDescriptor}. For ease
104: * of use, the cpDescriptor is stored as a string of the form <i>name:type</i>,
105: * largely to make it easier for representing field and method descriptors
106: * (e.g. <code>out:java.lang.PrintStream</code>) in a way that is
107: * compatible with passing String arrays.
108: *
109: * @param in
110: * the input stream to read from
111: * @throws IOException
112: * if a problem occurs during reading from the underlying stream
113: * @throws Pack200Exception
114: * if a problem occurs with an unexpected value or unsupported
115: * codec
116: */
117: private void parseCpDescriptor(InputStream in) throws IOException,
118: Pack200Exception {
119: int cpDescriptorCount = header.getCpDescriptorCount();
120: String[] cpDescriptorNames = parseReferences("cp_Descr_name",
121: in, Codec.DELTA5, cpDescriptorCount, cpUTF8);
122: String[] cpDescriptorTypes = parseReferences("cp_Descr_type",
123: in, Codec.UDELTA5, cpDescriptorCount, cpSignature);
124: cpDescriptor = new String[cpDescriptorCount];
125: for (int i = 0; i < cpDescriptorCount; i++) {
126: cpDescriptor[i] = cpDescriptorNames[i]
127: + ":" + cpDescriptorTypes[i]; //$NON-NLS-1$
128: }
129: }
130:
131: private void parseCpDouble(InputStream in) throws IOException,
132: Pack200Exception {
133: int cpDoubleCount = header.getCpDoubleCount();
134: cpDouble = new double[cpDoubleCount];
135: long[] hiBits = decodeBandLong("cp_Double_hi", in,
136: Codec.UDELTA5, cpDoubleCount);
137: long[] loBits = decodeBandLong("cp_Double_lo", in,
138: Codec.DELTA5, cpDoubleCount);
139: for (int i = 0; i < cpDoubleCount; i++) {
140: cpDouble[i] = Double.longBitsToDouble(hiBits[i] << 32
141: | loBits[i]);
142: }
143: }
144:
145: /**
146: * Parses the constant pool field definitions, using {@link #cpFieldCount}
147: * to populate {@link #cpFieldClass} and {@link #cpFieldDescriptor}.
148: *
149: * @param in
150: * the input stream to read from
151: * @throws IOException
152: * if a problem occurs during reading from the underlying stream
153: * @throws Pack200Exception
154: * if a problem occurs with an unexpected value or unsupported
155: * codec
156: */
157: private void parseCpField(InputStream in) throws IOException,
158: Pack200Exception {
159: int cpFieldCount = header.getCpFieldCount();
160: cpFieldClass = parseReferences("cp_Field_class", in,
161: Codec.DELTA5, cpFieldCount, cpClass);
162: cpFieldDescriptor = parseReferences("cp_Field_desc", in,
163: Codec.UDELTA5, cpFieldCount, cpDescriptor);
164: }
165:
166: private void parseCpFloat(InputStream in) throws IOException,
167: Pack200Exception {
168: int cpFloatCount = header.getCpFloatCount();
169: cpFloat = new float[cpFloatCount];
170: int floatBits[] = decodeBandInt("cp_Float", in, Codec.UDELTA5,
171: cpFloatCount);
172: for (int i = 0; i < cpFloatCount; i++) {
173: cpFloat[i] = Float.intBitsToFloat(floatBits[i]);
174: }
175: }
176:
177: /**
178: * Parses the constant pool interface method definitions, using
179: * {@link #cpIMethodCount} to populate {@link #cpIMethodClass} and
180: * {@link #cpIMethodDescriptor}.
181: *
182: * @param in
183: * the input stream to read from
184: * @throws IOException
185: * if a problem occurs during reading from the underlying stream
186: * @throws Pack200Exception
187: * if a problem occurs with an unexpected value or unsupported
188: * codec
189: */
190: private void parseCpIMethod(InputStream in) throws IOException,
191: Pack200Exception {
192: int cpIMethodCount = header.getCpIMethodCount();
193: cpIMethodClass = parseReferences("cp_Imethod_class", in,
194: Codec.DELTA5, cpIMethodCount, cpClass);
195: cpIMethodDescriptor = parseReferences("cp_Imethod_desc", in,
196: Codec.UDELTA5, cpIMethodCount, cpDescriptor);
197: }
198:
199: private void parseCpInt(InputStream in) throws IOException,
200: Pack200Exception {
201: int cpIntCount = header.getCpIntCount();
202: cpInt = decodeBandInt("cpInt", in, Codec.UDELTA5, cpIntCount);
203: }
204:
205: private void parseCpLong(InputStream in) throws IOException,
206: Pack200Exception {
207: int cpLongCount = header.getCpLongCount();
208: cpLong = parseFlags("cp_Long", in, cpLongCount, Codec.UDELTA5,
209: Codec.DELTA5);
210: }
211:
212: /**
213: * Parses the constant pool method definitions, using {@link #cpMethodCount}
214: * to populate {@link #cpMethodClass} and {@link #cpMethodDescriptor}.
215: *
216: * @param in
217: * the input stream to read from
218: * @throws IOException
219: * if a problem occurs during reading from the underlying stream
220: * @throws Pack200Exception
221: * if a problem occurs with an unexpected value or unsupported
222: * codec
223: */
224: private void parseCpMethod(InputStream in) throws IOException,
225: Pack200Exception {
226: int cpMethodCount = header.getCpMethodCount();
227: cpMethodClass = parseReferences("cp_Method_class", in,
228: Codec.DELTA5, cpMethodCount, cpClass);
229: cpMethodDescriptor = parseReferences("cp_Method_desc", in,
230: Codec.UDELTA5, cpMethodCount, cpDescriptor);
231: }
232:
233: /**
234: * Parses the constant pool signature classes, using
235: * {@link #cpSignatureCount} to populate {@link #cpSignature}. A signature
236: * form is akin to the bytecode representation of a class; Z for boolean, I
237: * for int, [ for array etc. However, although classes are started with L,
238: * the classname does not follow the form; instead, there is a separate
239: * array of classes. So an array corresponding to
240: * <code>public static void main(String args[])</code> has a form of
241: * <code>[L(V)</code> and a classes array of
242: * <code>[java.lang.String]</code>. The {@link #cpSignature} is a string
243: * representation identical to the bytecode equivalent
244: * <code>[Ljava/lang/String;(V)</code> TODO Check that the form is as
245: * above and update other types e.g. J
246: *
247: * @param in
248: * the input stream to read from
249: * @throws IOException
250: * if a problem occurs during reading from the underlying stream
251: * @throws Pack200Exception
252: * if a problem occurs with an unexpected value or unsupported
253: * codec
254: */
255: private void parseCpSignature(InputStream in) throws IOException,
256: Pack200Exception {
257: int cpSignatureCount = header.getCpSignatureCount();
258: String[] cpSignatureForm = parseReferences("cp_Signature_form",
259: in, Codec.DELTA5, cpSignatureCount, cpUTF8);
260: cpSignature = new String[cpSignatureCount];
261: int lCount = 0;
262: for (int i = 0; i < cpSignatureCount; i++) {
263: String form = cpSignatureForm[i];
264: char[] chars = form.toCharArray();
265: for (int j = 0; j < chars.length; j++) {
266: if (chars[j] == 'L') {
267: lCount++;
268: }
269: }
270: }
271: String[] cpSignatureClasses = parseReferences(
272: "cp_Signature_classes", in, Codec.UDELTA5, lCount,
273: cpClass);
274: int index = 0;
275: for (int i = 0; i < cpSignatureCount; i++) {
276: String form = cpSignatureForm[i];
277: int len = form.length();
278: StringBuffer signature = new StringBuffer(64);
279: ArrayList list = new ArrayList();
280: for (int j = 0; j < len; j++) {
281: char c = form.charAt(j);
282: signature.append(c);
283: if (c == 'L') {
284: String className = cpSignatureClasses[index];
285: list.add(className);
286: signature.append(className);
287: index++;
288: }
289: }
290: cpSignature[i] = signature.toString();
291: }
292: }
293:
294: /**
295: * Parses the constant pool strings, using {@link #cpStringCount} to
296: * populate {@link #cpString} from indexes into {@link #cpUTF8}.
297: *
298: * @param in
299: * the input stream to read from
300: * @throws IOException
301: * if a problem occurs during reading from the underlying stream
302: * @throws Pack200Exception
303: * if a problem occurs with an unexpected value or unsupported
304: * codec
305: */
306: private void parseCpString(InputStream in) throws IOException,
307: Pack200Exception {
308: int cpStringCount = header.getCpStringCount();
309: cpString = parseReferences("cp_String", in, Codec.UDELTA5,
310: cpStringCount, cpUTF8);
311: }
312:
313: private void parseCpUtf8(InputStream in) throws IOException,
314: Pack200Exception {
315: int cpUTF8Count = header.getCpUTF8Count();
316: cpUTF8 = new String[cpUTF8Count];
317: cpUTF8[0] = ""; //$NON-NLS-1$
318: int[] prefix = decodeBandInt("cpUTF8Prefix", in, Codec.DELTA5,
319: cpUTF8Count - 2);
320: int charCount = 0;
321: int bigSuffixCount = 0;
322: int[] suffix = decodeBandInt("cpUTF8Suffix", in,
323: Codec.UNSIGNED5, cpUTF8Count - 1);
324:
325: for (int i = 0; i < suffix.length; i++) {
326: if (suffix[i] == 0) {
327: bigSuffixCount++;
328: } else {
329: charCount += suffix[i];
330: }
331: }
332: char[] data = new char[charCount];
333: int[] dataBand = decodeBandInt("cp_Utf8_chars", in,
334: Codec.CHAR3, charCount);
335: for (int i = 0; i < data.length; i++) {
336: data[i] = (char) dataBand[i];
337: }
338:
339: // Read in the big suffix data
340: int[] bigSuffixCounts = decodeBandInt("cp_Utf8_big_suffix", in,
341: Codec.DELTA5, bigSuffixCount);
342: int[][] bigSuffixDataBand = decodeBandInt("cp_Utf8_big_chars",
343: in, Codec.DELTA5, bigSuffixCounts);
344:
345: // Convert big suffix data to characters
346: char bigSuffixData[][] = new char[bigSuffixCount][];
347: for (int i = 0; i < bigSuffixDataBand.length; i++) {
348: bigSuffixData[i] = new char[bigSuffixDataBand[i].length];
349: for (int j = 0; j < bigSuffixDataBand[i].length; j++) {
350: bigSuffixData[i][j] = (char) bigSuffixDataBand[i][j];
351: }
352: }
353: // Go through the strings
354: charCount = 0;
355: bigSuffixCount = 0;
356: for (int i = 1; i < cpUTF8Count; i++) {
357: String lastString = cpUTF8[i - 1];
358: if (suffix[i - 1] == 0) {
359: // The big suffix stuff hasn't been tested, and I'll be
360: // surprised if it works first time w/o errors ...
361: cpUTF8[i] = lastString.substring(0,
362: i > 1 ? prefix[i - 2] : 0)
363: + new String(bigSuffixData[bigSuffixCount++]);
364: } else {
365: cpUTF8[i] = lastString.substring(0,
366: i > 1 ? prefix[i - 2] : 0)
367: + new String(data, charCount, suffix[i - 1]);
368: charCount += suffix[i - 1];
369: }
370: }
371: }
372:
373: public String[] getCpClass() {
374: return cpClass;
375: }
376:
377: public String[] getCpDescriptor() {
378: return cpDescriptor;
379: }
380:
381: public double[] getCpDouble() {
382: return cpDouble;
383: }
384:
385: public String[] getCpFieldClass() {
386: return cpFieldClass;
387: }
388:
389: public String[] getCpFieldDescriptor() {
390: return cpFieldDescriptor;
391: }
392:
393: public float[] getCpFloat() {
394: return cpFloat;
395: }
396:
397: public String[] getCpIMethodClass() {
398: return cpIMethodClass;
399: }
400:
401: public String[] getCpIMethodDescriptor() {
402: return cpIMethodDescriptor;
403: }
404:
405: public int[] getCpInt() {
406: return cpInt;
407: }
408:
409: public long[] getCpLong() {
410: return cpLong;
411: }
412:
413: public String[] getCpMethodClass() {
414: return cpMethodClass;
415: }
416:
417: public String[] getCpMethodDescriptor() {
418: return cpMethodDescriptor;
419: }
420:
421: public String[] getCpSignature() {
422: return cpSignature;
423: }
424:
425: public String[] getCpString() {
426: return cpString;
427: }
428:
429: public String[] getCpUTF8() {
430: return cpUTF8;
431: }
432:
433: }
|