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