001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.harmony.unpack200; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.util.Arrays; 024import java.util.HashMap; 025import java.util.Map; 026 027import org.apache.commons.compress.harmony.pack200.Codec; 028import org.apache.commons.compress.harmony.pack200.Pack200Exception; 029import org.apache.commons.compress.harmony.unpack200.bytecode.CPClass; 030import org.apache.commons.compress.harmony.unpack200.bytecode.CPDouble; 031import org.apache.commons.compress.harmony.unpack200.bytecode.CPFieldRef; 032import org.apache.commons.compress.harmony.unpack200.bytecode.CPFloat; 033import org.apache.commons.compress.harmony.unpack200.bytecode.CPInteger; 034import org.apache.commons.compress.harmony.unpack200.bytecode.CPInterfaceMethodRef; 035import org.apache.commons.compress.harmony.unpack200.bytecode.CPLong; 036import org.apache.commons.compress.harmony.unpack200.bytecode.CPMethodRef; 037import org.apache.commons.compress.harmony.unpack200.bytecode.CPNameAndType; 038import org.apache.commons.compress.harmony.unpack200.bytecode.CPString; 039import org.apache.commons.compress.harmony.unpack200.bytecode.CPUTF8; 040 041/** 042 * Constant Pool bands. 043 */ 044public class CpBands extends BandSet { 045 046 private static final String EMPTY_STRING = ""; //$NON-NLS-1$ 047 048 private final SegmentConstantPool pool = new SegmentConstantPool(this); 049 050 private String[] cpClass; 051 052 private int[] cpClassInts; 053 private int[] cpDescriptorNameInts; 054 private int[] cpDescriptorTypeInts; 055 private String[] cpDescriptor; 056 private double[] cpDouble; 057 private String[] cpFieldClass; 058 private String[] cpFieldDescriptor; 059 private int[] cpFieldClassInts; 060 private int[] cpFieldDescriptorInts; 061 private float[] cpFloat; 062 private String[] cpIMethodClass; 063 private String[] cpIMethodDescriptor; 064 private int[] cpIMethodClassInts; 065 private int[] cpIMethodDescriptorInts; 066 private int[] cpInt; 067 private long[] cpLong; 068 private String[] cpMethodClass; 069 private String[] cpMethodDescriptor; 070 private int[] cpMethodClassInts; 071 private int[] cpMethodDescriptorInts; 072 private String[] cpSignature; 073 private int[] cpSignatureInts; 074 private String[] cpString; 075 private int[] cpStringInts; 076 private String[] cpUTF8; 077 private final Map<String, CPUTF8> stringsToCPUTF8 = new HashMap<>(); 078 079 private final Map<String, CPString> stringsToCPStrings = new HashMap<>(); 080 private final Map<Long, CPLong> longsToCPLongs = new HashMap<>(); 081 private final Map<Integer, CPInteger> integersToCPIntegers = new HashMap<>(); 082 private final Map<Float, CPFloat> floatsToCPFloats = new HashMap<>(); 083 private final Map<String, CPClass> stringsToCPClass = new HashMap<>(); 084 private final Map<Double, CPDouble> doublesToCPDoubles = new HashMap<>(); 085 private final Map<String, CPNameAndType> descriptorsToCPNameAndTypes = new HashMap<>(); 086 private Map<String, Integer> mapClass; 087 088 private Map<String, Integer> mapDescriptor; 089 private Map<String, Integer> mapUTF8; 090 // TODO: Not used 091 private Map<String, Integer> mapSignature; 092 093 private int intOffset; 094 095 private int floatOffset; 096 private int longOffset; 097 private int doubleOffset; 098 private int stringOffset; 099 private int classOffset; 100 private int signatureOffset; 101 private int descrOffset; 102 private int fieldOffset; 103 private int methodOffset; 104 private int imethodOffset; 105 106 public CpBands(final Segment segment) { 107 super(segment); 108 } 109 110 public CPClass cpClassValue(final int index) { 111 final String string = cpClass[index]; 112 final int utf8Index = cpClassInts[index]; 113 final int globalIndex = classOffset + index; 114 return stringsToCPClass.computeIfAbsent(string, k -> new CPClass(cpUTF8Value(utf8Index), globalIndex)); 115 } 116 117 public CPClass cpClassValue(final String string) { 118 CPClass cpString = stringsToCPClass.get(string); 119 if (cpString == null) { 120 final Integer index = mapClass.get(string); 121 if (index != null) { 122 return cpClassValue(index.intValue()); 123 } 124 cpString = new CPClass(cpUTF8Value(string, false), -1); 125 stringsToCPClass.put(string, cpString); 126 } 127 return cpString; 128 } 129 130 public CPDouble cpDoubleValue(final int index) { 131 return doublesToCPDoubles.computeIfAbsent(Double.valueOf(cpDouble[index]), k -> new CPDouble(k, index + doubleOffset)); 132 } 133 134 public CPFieldRef cpFieldValue(final int index) { 135 return new CPFieldRef(cpClassValue(cpFieldClassInts[index]), cpNameAndTypeValue(cpFieldDescriptorInts[index]), index + fieldOffset); 136 } 137 138 public CPFloat cpFloatValue(final int index) { 139 return floatsToCPFloats.computeIfAbsent(Float.valueOf(cpFloat[index]), k -> new CPFloat(Float.valueOf(cpFloat[index]), index + floatOffset)); 140 } 141 142 public CPInterfaceMethodRef cpIMethodValue(final int index) { 143 return new CPInterfaceMethodRef(cpClassValue(cpIMethodClassInts[index]), cpNameAndTypeValue(cpIMethodDescriptorInts[index]), index + imethodOffset); 144 } 145 146 public CPInteger cpIntegerValue(final int index) { 147 return integersToCPIntegers.computeIfAbsent(Integer.valueOf(cpInt[index]), k -> new CPInteger(k, index + intOffset)); 148 } 149 150 public CPLong cpLongValue(final int index) { 151 return longsToCPLongs.computeIfAbsent(Long.valueOf(cpLong[index]), k -> new CPLong(k, index + longOffset)); 152 } 153 154 public CPMethodRef cpMethodValue(final int index) { 155 return new CPMethodRef(cpClassValue(cpMethodClassInts[index]), cpNameAndTypeValue(cpMethodDescriptorInts[index]), index + methodOffset); 156 } 157 158 public CPNameAndType cpNameAndTypeValue(final int index) { 159 final String descriptor = cpDescriptor[index]; 160 return descriptorsToCPNameAndTypes.computeIfAbsent(descriptor, k -> { 161 final int nameIndex = cpDescriptorNameInts[index]; 162 final int descriptorIndex = cpDescriptorTypeInts[index]; 163 final CPUTF8 name = cpUTF8Value(nameIndex); 164 final CPUTF8 descriptorU = cpSignatureValue(descriptorIndex); 165 return new CPNameAndType(name, descriptorU, index + descrOffset); 166 }); 167 } 168 169 public CPNameAndType cpNameAndTypeValue(final String descriptor) { 170 CPNameAndType cpNameAndType = descriptorsToCPNameAndTypes.get(descriptor); 171 if (cpNameAndType == null) { 172 final Integer index = mapDescriptor.get(descriptor); 173 if (index != null) { 174 return cpNameAndTypeValue(index.intValue()); 175 } 176 final int colon = descriptor.indexOf(':'); 177 final String nameString = descriptor.substring(0, colon); 178 final String descriptorString = descriptor.substring(colon + 1); 179 180 final CPUTF8 name = cpUTF8Value(nameString, true); 181 final CPUTF8 descriptorU = cpUTF8Value(descriptorString, true); 182 cpNameAndType = new CPNameAndType(name, descriptorU, -1 + descrOffset); 183 descriptorsToCPNameAndTypes.put(descriptor, cpNameAndType); 184 } 185 return cpNameAndType; 186 } 187 188 public CPUTF8 cpSignatureValue(final int index) { 189 final int globalIndex; 190 if (cpSignatureInts[index] != -1) { 191 globalIndex = cpSignatureInts[index]; 192 } else { 193 globalIndex = index + signatureOffset; 194 } 195 return stringsToCPUTF8.computeIfAbsent(cpSignature[index], k -> new CPUTF8(k, globalIndex)); 196 } 197 198 public CPString cpStringValue(final int index) { 199 final String string = cpString[index]; 200 final int utf8Index = cpStringInts[index]; 201 final int globalIndex = stringOffset + index; 202 return stringsToCPStrings.computeIfAbsent(string, k -> new CPString(cpUTF8Value(utf8Index), globalIndex)); 203 } 204 205 public CPUTF8 cpUTF8Value(final int index) { 206 final String string = cpUTF8[index]; 207 CPUTF8 cputf8 = stringsToCPUTF8.get(string); 208 if (cputf8 == null) { 209 cputf8 = new CPUTF8(string, index); 210 stringsToCPUTF8.put(string, cputf8); 211 } else if (cputf8.getGlobalIndex() > index) { 212 cputf8.setGlobalIndex(index); 213 } 214 return cputf8; 215 } 216 217 public CPUTF8 cpUTF8Value(final String string) { 218 return cpUTF8Value(string, true); 219 } 220 221 public CPUTF8 cpUTF8Value(final String string, final boolean searchForIndex) { 222 CPUTF8 cputf8 = stringsToCPUTF8.get(string); 223 if (cputf8 == null) { 224 Integer index = null; 225 if (searchForIndex) { 226 index = mapUTF8.get(string); 227 } 228 if (index != null) { 229 return cpUTF8Value(index.intValue()); 230 } 231 if (searchForIndex) { 232 index = mapSignature.get(string); 233 } 234 if (index != null) { 235 return cpSignatureValue(index.intValue()); 236 } 237 cputf8 = new CPUTF8(string, -1); 238 stringsToCPUTF8.put(string, cputf8); 239 } 240 return cputf8; 241 } 242 243 public SegmentConstantPool getConstantPool() { 244 return pool; 245 } 246 247 public String[] getCpClass() { 248 return cpClass; 249 } 250 251 public String[] getCpDescriptor() { 252 return cpDescriptor; 253 } 254 255 public int[] getCpDescriptorNameInts() { 256 return cpDescriptorNameInts; 257 } 258 259 public int[] getCpDescriptorTypeInts() { 260 return cpDescriptorTypeInts; 261 } 262 263 public String[] getCpFieldClass() { 264 return cpFieldClass; 265 } 266 267 public String[] getCpIMethodClass() { 268 return cpIMethodClass; 269 } 270 271 public int[] getCpInt() { 272 return cpInt; 273 } 274 275 public long[] getCpLong() { 276 return cpLong; 277 } 278 279 public String[] getCpMethodClass() { 280 return cpMethodClass; 281 } 282 283 public String[] getCpMethodDescriptor() { 284 return cpMethodDescriptor; 285 } 286 287 public String[] getCpSignature() { 288 return cpSignature; 289 } 290 291 public String[] getCpUTF8() { 292 return cpUTF8; 293 } 294 295 /** 296 * Parses the constant pool class names, using {@link #cpClassCount} to populate {@link #cpClass} from {@link #cpUTF8}. 297 * 298 * @param in the input stream to read from 299 * @throws IOException if a problem occurs during reading from the underlying stream 300 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 301 */ 302 private void parseCpClass(final InputStream in) throws IOException, Pack200Exception { 303 final int cpClassCount = header.getCpClassCount(); 304 cpClassInts = decodeBandInt("cp_Class", in, Codec.UDELTA5, cpClassCount); 305 cpClass = new String[cpClassCount]; 306 mapClass = new HashMap<>(cpClassCount); 307 for (int i = 0; i < cpClassCount; i++) { 308 cpClass[i] = cpUTF8[cpClassInts[i]]; 309 mapClass.put(cpClass[i], Integer.valueOf(i)); 310 } 311 } 312 313 /** 314 * Parses the constant pool descriptor definitions, using {@link #cpDescriptorCount} to populate {@link #cpDescriptor}. For ease of use, the cpDescriptor is 315 * stored as a string of the form <em>name:type</em>, largely to make it easier for representing field and method descriptors (for example 316 * {@code out:java.lang.PrintStream}) in a way that is compatible with passing String arrays. 317 * 318 * @param in the input stream to read from 319 * @throws IOException if a problem occurs during reading from the underlying stream 320 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 321 */ 322 private void parseCpDescriptor(final InputStream in) throws IOException, Pack200Exception { 323 final int cpDescriptorCount = header.getCpDescriptorCount(); 324 cpDescriptorNameInts = decodeBandInt("cp_Descr_name", in, Codec.DELTA5, cpDescriptorCount); 325 cpDescriptorTypeInts = decodeBandInt("cp_Descr_type", in, Codec.UDELTA5, cpDescriptorCount); 326 final String[] cpDescriptorNames = getReferences(cpDescriptorNameInts, cpUTF8); 327 final String[] cpDescriptorTypes = getReferences(cpDescriptorTypeInts, cpSignature); 328 cpDescriptor = new String[cpDescriptorCount]; 329 mapDescriptor = new HashMap<>(cpDescriptorCount); 330 for (int i = 0; i < cpDescriptorCount; i++) { 331 cpDescriptor[i] = cpDescriptorNames[i] + ":" + cpDescriptorTypes[i]; //$NON-NLS-1$ 332 mapDescriptor.put(cpDescriptor[i], Integer.valueOf(i)); 333 } 334 } 335 336 private void parseCpDouble(final InputStream in) throws IOException, Pack200Exception { 337 final int cpDoubleCount = header.getCpDoubleCount(); 338 final long[] band = parseFlags("cp_Double", in, cpDoubleCount, Codec.UDELTA5, Codec.DELTA5); 339 cpDouble = new double[band.length]; 340 Arrays.setAll(cpDouble, i -> Double.longBitsToDouble(band[i])); 341 } 342 343 /** 344 * Parses the constant pool field definitions, using {@link #cpFieldCount} to populate {@link #cpFieldClass} and {@link #cpFieldDescriptor}. 345 * 346 * @param in the input stream to read from 347 * @throws IOException if a problem occurs during reading from the underlying stream 348 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 349 */ 350 private void parseCpField(final InputStream in) throws IOException, Pack200Exception { 351 final int cpFieldCount = header.getCpFieldCount(); 352 cpFieldClassInts = decodeBandInt("cp_Field_class", in, Codec.DELTA5, cpFieldCount); 353 cpFieldDescriptorInts = decodeBandInt("cp_Field_desc", in, Codec.UDELTA5, cpFieldCount); 354 cpFieldClass = new String[cpFieldCount]; 355 cpFieldDescriptor = new String[cpFieldCount]; 356 for (int i = 0; i < cpFieldCount; i++) { 357 cpFieldClass[i] = cpClass[cpFieldClassInts[i]]; 358 cpFieldDescriptor[i] = cpDescriptor[cpFieldDescriptorInts[i]]; 359 } 360 } 361 362 private void parseCpFloat(final InputStream in) throws IOException, Pack200Exception { 363 final int cpFloatCount = header.getCpFloatCount(); 364 final int[] floatBits = decodeBandInt("cp_Float", in, Codec.UDELTA5, cpFloatCount); 365 cpFloat = new float[cpFloatCount]; 366 for (int i = 0; i < cpFloatCount; i++) { 367 cpFloat[i] = Float.intBitsToFloat(floatBits[i]); 368 } 369 } 370 371 /** 372 * Parses the constant pool interface method definitions, using {@link #cpIMethodCount} to populate {@link #cpIMethodClass} and 373 * {@link #cpIMethodDescriptor}. 374 * 375 * @param in the input stream to read from 376 * @throws IOException if a problem occurs during reading from the underlying stream 377 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 378 */ 379 private void parseCpIMethod(final InputStream in) throws IOException, Pack200Exception { 380 final int cpIMethodCount = header.getCpIMethodCount(); 381 cpIMethodClassInts = decodeBandInt("cp_Imethod_class", in, Codec.DELTA5, cpIMethodCount); 382 cpIMethodDescriptorInts = decodeBandInt("cp_Imethod_desc", in, Codec.UDELTA5, cpIMethodCount); 383 cpIMethodClass = new String[cpIMethodCount]; 384 cpIMethodDescriptor = new String[cpIMethodCount]; 385 for (int i = 0; i < cpIMethodCount; i++) { 386 cpIMethodClass[i] = cpClass[cpIMethodClassInts[i]]; 387 cpIMethodDescriptor[i] = cpDescriptor[cpIMethodDescriptorInts[i]]; 388 } 389 } 390 391 private void parseCpInt(final InputStream in) throws IOException, Pack200Exception { 392 final int cpIntCount = header.getCpIntCount(); 393 cpInt = decodeBandInt("cpInt", in, Codec.UDELTA5, cpIntCount); 394 } 395 396 private void parseCpLong(final InputStream in) throws IOException, Pack200Exception { 397 final int cpLongCount = header.getCpLongCount(); 398 cpLong = parseFlags("cp_Long", in, cpLongCount, Codec.UDELTA5, Codec.DELTA5); 399 } 400 401 /** 402 * Parses the constant pool method definitions, using {@link #cpMethodCount} to populate {@link #cpMethodClass} and {@link #cpMethodDescriptor}. 403 * 404 * @param in the input stream to read from 405 * @throws IOException if a problem occurs during reading from the underlying stream 406 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 407 */ 408 private void parseCpMethod(final InputStream in) throws IOException, Pack200Exception { 409 final int cpMethodCount = header.getCpMethodCount(); 410 cpMethodClassInts = decodeBandInt("cp_Method_class", in, Codec.DELTA5, cpMethodCount); 411 cpMethodDescriptorInts = decodeBandInt("cp_Method_desc", in, Codec.UDELTA5, cpMethodCount); 412 cpMethodClass = new String[cpMethodCount]; 413 cpMethodDescriptor = new String[cpMethodCount]; 414 for (int i = 0; i < cpMethodCount; i++) { 415 cpMethodClass[i] = cpClass[cpMethodClassInts[i]]; 416 cpMethodDescriptor[i] = cpDescriptor[cpMethodDescriptorInts[i]]; 417 } 418 } 419 420 /** 421 * Parses the constant pool signature classes, using {@link #cpSignatureCount} to populate {@link #cpSignature}. A signature form is akin to the bytecode 422 * representation of a class; Z for boolean, I for int, [ for array etc. However, although classes are started with L, the class name does not follow the 423 * form; instead, there is a separate array of classes. So an array corresponding to {@code public static void main(String args[])} has a form of 424 * {@code [L(V)} and a classes array of {@code [java.lang.String]}. The {@link #cpSignature} is a string representation identical to the bytecode equivalent 425 * {@code [Ljava/lang/String;(V)} TODO Check that the form is as above and update other types for example J 426 * 427 * @param in the input stream to read from 428 * @throws IOException if a problem occurs during reading from the underlying stream 429 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 430 */ 431 private void parseCpSignature(final InputStream in) throws IOException, Pack200Exception { 432 final int cpSignatureCount = header.getCpSignatureCount(); 433 cpSignatureInts = decodeBandInt("cp_Signature_form", in, Codec.DELTA5, cpSignatureCount); 434 final String[] cpSignatureForm = getReferences(cpSignatureInts, cpUTF8); 435 cpSignature = new String[cpSignatureCount]; 436 mapSignature = new HashMap<>(); 437 int lCount = 0; 438 for (int i = 0; i < cpSignatureCount; i++) { 439 final String form = cpSignatureForm[i]; 440 final char[] chars = form.toCharArray(); 441 for (final char element : chars) { 442 if (element == 'L') { 443 cpSignatureInts[i] = -1; 444 lCount++; 445 } 446 } 447 } 448 final String[] cpSignatureClasses = parseReferences("cp_Signature_classes", in, Codec.UDELTA5, lCount, cpClass); 449 int index = 0; 450 for (int i = 0; i < cpSignatureCount; i++) { 451 final String form = cpSignatureForm[i]; 452 final int len = form.length(); 453 final StringBuilder signature = new StringBuilder(64); 454 for (int j = 0; j < len; j++) { 455 final char c = form.charAt(j); 456 signature.append(c); 457 if (c == 'L') { 458 final String className = cpSignatureClasses[index]; 459 signature.append(className); 460 index++; 461 } 462 } 463 cpSignature[i] = signature.toString(); 464 mapSignature.put(signature.toString(), Integer.valueOf(i)); 465 } 466// for (int i = 0; i < cpSignatureInts.length; i++) { 467// if (cpSignatureInts[i] == -1) { 468// cpSignatureInts[i] = search(cpUTF8, cpSignature[i]); 469// } 470// } 471 } 472 473 /** 474 * Parses the constant pool strings, using {@link #cpStringCount} to populate {@link #cpString} from indexes into {@link #cpUTF8}. 475 * 476 * @param in the input stream to read from 477 * @throws IOException if a problem occurs during reading from the underlying stream 478 * @throws Pack200Exception if a problem occurs with an unexpected value or unsupported codec 479 */ 480 private void parseCpString(final InputStream in) throws IOException, Pack200Exception { 481 final int cpStringCount = header.getCpStringCount(); 482 cpStringInts = decodeBandInt("cp_String", in, Codec.UDELTA5, cpStringCount); 483 cpString = new String[cpStringCount]; 484 Arrays.setAll(cpString, i -> cpUTF8[cpStringInts[i]]); 485 } 486 487 private void parseCpUtf8(final InputStream in) throws IOException, Pack200Exception { 488 final int cpUTF8Count = header.getCpUTF8Count(); 489 if (cpUTF8Count <= 0) { 490 throw new IOException("cpUTF8Count value must be greater than 0"); 491 } 492 final int[] prefix = decodeBandInt("cpUTF8Prefix", in, Codec.DELTA5, cpUTF8Count - 2); 493 int charCount = 0; 494 int bigSuffixCount = 0; 495 final int[] suffix = decodeBandInt("cpUTF8Suffix", in, Codec.UNSIGNED5, cpUTF8Count - 1); 496 497 for (final int element : suffix) { 498 if (element == 0) { 499 bigSuffixCount++; 500 } else { 501 charCount += element; 502 } 503 } 504 final int[] dataBand = decodeBandInt("cp_Utf8_chars", in, Codec.CHAR3, charCount); 505 final char[] data = new char[charCount]; 506 for (int i = 0; i < data.length; i++) { 507 data[i] = (char) dataBand[i]; 508 } 509 510 // Read in the big suffix data 511 final int[] bigSuffixCounts = decodeBandInt("cp_Utf8_big_suffix", in, Codec.DELTA5, bigSuffixCount); 512 final int[][] bigSuffixDataBand = new int[bigSuffixCount][]; 513 for (int i = 0; i < bigSuffixDataBand.length; i++) { 514 bigSuffixDataBand[i] = decodeBandInt("cp_Utf8_big_chars " + i, in, Codec.DELTA5, bigSuffixCounts[i]); 515 } 516 517 // Convert big suffix data to characters 518 final char[][] bigSuffixData = new char[bigSuffixCount][]; 519 for (int i = 0; i < bigSuffixDataBand.length; i++) { 520 bigSuffixData[i] = new char[bigSuffixDataBand[i].length]; 521 for (int j = 0; j < bigSuffixDataBand[i].length; j++) { 522 bigSuffixData[i][j] = (char) bigSuffixDataBand[i][j]; 523 } 524 } 525 526 // Initialize variables 527 mapUTF8 = new HashMap<>(cpUTF8Count + 1); 528 cpUTF8 = new String[cpUTF8Count]; 529 cpUTF8[0] = EMPTY_STRING; 530 mapUTF8.put(EMPTY_STRING, Integer.valueOf(0)); 531 532 // Go through the strings 533 charCount = 0; 534 bigSuffixCount = 0; 535 for (int i = 1; i < cpUTF8Count; i++) { 536 final String lastString = cpUTF8[i - 1]; 537 if (suffix[i - 1] == 0) { 538 // The big suffix stuff hasn't been tested, and I'll be 539 // surprised if it works first time w/o errors ... 540 cpUTF8[i] = lastString.substring(0, i > 1 ? prefix[i - 2] : 0) + new String(bigSuffixData[bigSuffixCount++]); 541 } else { 542 cpUTF8[i] = lastString.substring(0, i > 1 ? prefix[i - 2] : 0) + new String(data, charCount, suffix[i - 1]); 543 charCount += suffix[i - 1]; 544 } 545 mapUTF8.put(cpUTF8[i], Integer.valueOf(i)); 546 } 547 } 548 549 @Override 550 public void read(final InputStream in) throws IOException, Pack200Exception { 551 parseCpUtf8(in); 552 parseCpInt(in); 553 parseCpFloat(in); 554 parseCpLong(in); 555 parseCpDouble(in); 556 parseCpString(in); 557 parseCpClass(in); 558 parseCpSignature(in); 559 parseCpDescriptor(in); 560 parseCpField(in); 561 parseCpMethod(in); 562 parseCpIMethod(in); 563 564 intOffset = cpUTF8.length; 565 floatOffset = intOffset + cpInt.length; 566 longOffset = floatOffset + cpFloat.length; 567 doubleOffset = longOffset + cpLong.length; 568 stringOffset = doubleOffset + cpDouble.length; 569 classOffset = stringOffset + cpString.length; 570 signatureOffset = classOffset + cpClass.length; 571 descrOffset = signatureOffset + cpSignature.length; 572 fieldOffset = descrOffset + cpDescriptor.length; 573 methodOffset = fieldOffset + cpFieldClass.length; 574 imethodOffset = methodOffset + cpMethodClass.length; 575 } 576 577 @Override 578 public void unpack() { 579 580 } 581 582}