001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with this 004 * work for additional information regarding copyright ownership. The ASF 005 * licenses this file to You under the Apache License, Version 2.0 (the 006 * "License"); you may not use this file except in compliance with the License. 007 * 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, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations under 015 * the License. 016 */ 017package org.apache.commons.compress.harmony.pack200; 018 019import java.io.IOException; 020import java.io.OutputStream; 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Map; 027import java.util.Set; 028import java.util.TreeSet; 029 030import org.objectweb.asm.Type; 031 032/** 033 * Pack200 Constant Pool Bands 034 */ 035public class CpBands extends BandSet { 036 037 // Don't need to include default attribute names in the constant pool bands 038 private final Set defaultAttributeNames = new HashSet(); 039 040 private final Set cp_Utf8 = new TreeSet(); 041 private final Set cp_Int = new TreeSet(); 042 private final Set cp_Float = new TreeSet(); 043 private final Set cp_Long = new TreeSet(); 044 private final Set cp_Double = new TreeSet(); 045 private final Set cp_String = new TreeSet(); 046 private final Set cp_Class = new TreeSet(); 047 private final Set cp_Signature = new TreeSet(); 048 private final Set cp_Descr = new TreeSet(); 049 private final Set cp_Field = new TreeSet(); 050 private final Set cp_Method = new TreeSet(); 051 private final Set cp_Imethod = new TreeSet(); 052 053 private final Map stringsToCpUtf8 = new HashMap(); 054 private final Map stringsToCpNameAndType = new HashMap(); 055 private final Map stringsToCpClass = new HashMap(); 056 private final Map stringsToCpSignature = new HashMap(); 057 private final Map stringsToCpMethod = new HashMap(); 058 private final Map stringsToCpField = new HashMap(); 059 private final Map stringsToCpIMethod = new HashMap(); 060 061 private final Map objectsToCPConstant = new HashMap(); 062 063 private final Segment segment; 064 065 public CpBands(final Segment segment, final int effort) { 066 super(effort, segment.getSegmentHeader()); 067 this.segment = segment; 068 defaultAttributeNames.add("AnnotationDefault"); 069 defaultAttributeNames.add("RuntimeVisibleAnnotations"); 070 defaultAttributeNames.add("RuntimeInvisibleAnnotations"); 071 defaultAttributeNames.add("RuntimeVisibleParameterAnnotations"); 072 defaultAttributeNames.add("RuntimeInvisibleParameterAnnotations"); 073 defaultAttributeNames.add("Code"); 074 defaultAttributeNames.add("LineNumberTable"); 075 defaultAttributeNames.add("LocalVariableTable"); 076 defaultAttributeNames.add("LocalVariableTypeTable"); 077 defaultAttributeNames.add("ConstantValue"); 078 defaultAttributeNames.add("Deprecated"); 079 defaultAttributeNames.add("EnclosingMethod"); 080 defaultAttributeNames.add("Exceptions"); 081 defaultAttributeNames.add("InnerClasses"); 082 defaultAttributeNames.add("Signature"); 083 defaultAttributeNames.add("SourceFile"); 084 } 085 086 @Override 087 public void pack(final OutputStream out) throws IOException, Pack200Exception { 088 PackingUtils.log("Writing constant pool bands..."); 089 writeCpUtf8(out); 090 writeCpInt(out); 091 writeCpFloat(out); 092 writeCpLong(out); 093 writeCpDouble(out); 094 writeCpString(out); 095 writeCpClass(out); 096 writeCpSignature(out); 097 writeCpDescr(out); 098 writeCpMethodOrField(cp_Field, out, "cp_Field"); 099 writeCpMethodOrField(cp_Method, out, "cp_Method"); 100 writeCpMethodOrField(cp_Imethod, out, "cp_Imethod"); 101 } 102 103 private void writeCpUtf8(final OutputStream out) throws IOException, Pack200Exception { 104 PackingUtils.log("Writing " + cp_Utf8.size() + " UTF8 entries..."); 105 final int[] cpUtf8Prefix = new int[cp_Utf8.size() - 2]; 106 final int[] cpUtf8Suffix = new int[cp_Utf8.size() - 1]; 107 final List chars = new ArrayList(); 108 final List bigSuffix = new ArrayList(); 109 final List bigChars = new ArrayList(); 110 final Object[] cpUtf8Array = cp_Utf8.toArray(); 111 final String first = ((CPUTF8) cpUtf8Array[1]).getUnderlyingString(); 112 cpUtf8Suffix[0] = first.length(); 113 addCharacters(chars, first.toCharArray()); 114 for (int i = 2; i < cpUtf8Array.length; i++) { 115 final char[] previous = ((CPUTF8) cpUtf8Array[i - 1]).getUnderlyingString().toCharArray(); 116 String currentStr = ((CPUTF8) cpUtf8Array[i]).getUnderlyingString(); 117 final char[] current = currentStr.toCharArray(); 118 int prefix = 0; 119 for (int j = 0; j < previous.length; j++) { 120 if (previous[j] != current[j]) { 121 break; 122 } 123 prefix++; 124 } 125 cpUtf8Prefix[i - 2] = prefix; 126 currentStr = currentStr.substring(prefix); 127 final char[] suffix = currentStr.toCharArray(); 128 if (suffix.length > 1000) { // big suffix (1000 is arbitrary - can we 129 // do better?) 130 cpUtf8Suffix[i - 1] = 0; 131 bigSuffix.add(Integer.valueOf(suffix.length)); 132 addCharacters(bigChars, suffix); 133 } else { 134 cpUtf8Suffix[i - 1] = suffix.length; 135 addCharacters(chars, suffix); 136 } 137 } 138 final int[] cpUtf8Chars = new int[chars.size()]; 139 final int[] cpUtf8BigSuffix = new int[bigSuffix.size()]; 140 final int[][] cpUtf8BigChars = new int[bigSuffix.size()][]; 141 for (int i = 0; i < cpUtf8Chars.length; i++) { 142 cpUtf8Chars[i] = ((Character) chars.get(i)).charValue(); 143 } 144 for (int i = 0; i < cpUtf8BigSuffix.length; i++) { 145 final int numBigChars = ((Integer) bigSuffix.get(i)).intValue(); 146 cpUtf8BigSuffix[i] = numBigChars; 147 cpUtf8BigChars[i] = new int[numBigChars]; 148 for (int j = 0; j < numBigChars; j++) { 149 cpUtf8BigChars[i][j] = ((Character) bigChars.remove(0)).charValue(); 150 } 151 } 152 153 byte[] encodedBand = encodeBandInt("cpUtf8Prefix", cpUtf8Prefix, Codec.DELTA5); 154 out.write(encodedBand); 155 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Prefix[" + cpUtf8Prefix.length + "]"); 156 157 encodedBand = encodeBandInt("cpUtf8Suffix", cpUtf8Suffix, Codec.UNSIGNED5); 158 out.write(encodedBand); 159 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Suffix[" + cpUtf8Suffix.length + "]"); 160 161 encodedBand = encodeBandInt("cpUtf8Chars", cpUtf8Chars, Codec.CHAR3); 162 out.write(encodedBand); 163 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Chars[" + cpUtf8Chars.length + "]"); 164 165 encodedBand = encodeBandInt("cpUtf8BigSuffix", cpUtf8BigSuffix, Codec.DELTA5); 166 out.write(encodedBand); 167 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigSuffix[" + cpUtf8BigSuffix.length + "]"); 168 169 for (int i = 0; i < cpUtf8BigChars.length; i++) { 170 encodedBand = encodeBandInt("cpUtf8BigChars " + i, cpUtf8BigChars[i], Codec.DELTA5); 171 out.write(encodedBand); 172 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigChars" + i + "[" 173 + cpUtf8BigChars[i].length + "]"); 174 } 175 } 176 177 private void addCharacters(final List chars, final char[] charArray) { 178 for (int i = 0; i < charArray.length; i++) { 179 chars.add(Character.valueOf(charArray[i])); 180 } 181 } 182 183 private void writeCpInt(final OutputStream out) throws IOException, Pack200Exception { 184 PackingUtils.log("Writing " + cp_Int.size() + " Integer entries..."); 185 final int[] cpInt = new int[cp_Int.size()]; 186 int i = 0; 187 for (final Iterator iterator = cp_Int.iterator(); iterator.hasNext();) { 188 final CPInt integer = (CPInt) iterator.next(); 189 cpInt[i] = integer.getInt(); 190 i++; 191 } 192 final byte[] encodedBand = encodeBandInt("cp_Int", cpInt, Codec.UDELTA5); 193 out.write(encodedBand); 194 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Int[" + cpInt.length + "]"); 195 } 196 197 private void writeCpFloat(final OutputStream out) throws IOException, Pack200Exception { 198 PackingUtils.log("Writing " + cp_Float.size() + " Float entries..."); 199 final int[] cpFloat = new int[cp_Float.size()]; 200 int i = 0; 201 for (final Iterator iterator = cp_Float.iterator(); iterator.hasNext();) { 202 final CPFloat fl = (CPFloat) iterator.next(); 203 cpFloat[i] = Float.floatToIntBits(fl.getFloat()); 204 i++; 205 } 206 final byte[] encodedBand = encodeBandInt("cp_Float", cpFloat, Codec.UDELTA5); 207 out.write(encodedBand); 208 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Float[" + cpFloat.length + "]"); 209 } 210 211 private void writeCpLong(final OutputStream out) throws IOException, Pack200Exception { 212 PackingUtils.log("Writing " + cp_Long.size() + " Long entries..."); 213 final int[] highBits = new int[cp_Long.size()]; 214 final int[] loBits = new int[cp_Long.size()]; 215 int i = 0; 216 for (final Iterator iterator = cp_Long.iterator(); iterator.hasNext();) { 217 final CPLong lng = (CPLong) iterator.next(); 218 final long l = lng.getLong(); 219 highBits[i] = (int) (l >> 32); 220 loBits[i] = (int) l; 221 i++; 222 } 223 byte[] encodedBand = encodeBandInt("cp_Long_hi", highBits, Codec.UDELTA5); 224 out.write(encodedBand); 225 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_hi[" + highBits.length + "]"); 226 227 encodedBand = encodeBandInt("cp_Long_lo", loBits, Codec.DELTA5); 228 out.write(encodedBand); 229 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_lo[" + loBits.length + "]"); 230 } 231 232 private void writeCpDouble(final OutputStream out) throws IOException, Pack200Exception { 233 PackingUtils.log("Writing " + cp_Double.size() + " Double entries..."); 234 final int[] highBits = new int[cp_Double.size()]; 235 final int[] loBits = new int[cp_Double.size()]; 236 int i = 0; 237 for (final Iterator iterator = cp_Double.iterator(); iterator.hasNext();) { 238 final CPDouble dbl = (CPDouble) iterator.next(); 239 final long l = Double.doubleToLongBits(dbl.getDouble()); 240 highBits[i] = (int) (l >> 32); 241 loBits[i] = (int) l; 242 i++; 243 } 244 byte[] encodedBand = encodeBandInt("cp_Double_hi", highBits, Codec.UDELTA5); 245 out.write(encodedBand); 246 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_hi[" + highBits.length + "]"); 247 248 encodedBand = encodeBandInt("cp_Double_lo", loBits, Codec.DELTA5); 249 out.write(encodedBand); 250 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_lo[" + loBits.length + "]"); 251 } 252 253 private void writeCpString(final OutputStream out) throws IOException, Pack200Exception { 254 PackingUtils.log("Writing " + cp_String.size() + " String entries..."); 255 final int[] cpString = new int[cp_String.size()]; 256 int i = 0; 257 for (final Iterator iterator = cp_String.iterator(); iterator.hasNext();) { 258 final CPString cpStr = (CPString) iterator.next(); 259 cpString[i] = cpStr.getIndexInCpUtf8(); 260 i++; 261 } 262 final byte[] encodedBand = encodeBandInt("cpString", cpString, Codec.UDELTA5); 263 out.write(encodedBand); 264 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpString[" + cpString.length + "]"); 265 } 266 267 private void writeCpClass(final OutputStream out) throws IOException, Pack200Exception { 268 PackingUtils.log("Writing " + cp_Class.size() + " Class entries..."); 269 final int[] cpClass = new int[cp_Class.size()]; 270 int i = 0; 271 for (final Iterator iterator = cp_Class.iterator(); iterator.hasNext();) { 272 final CPClass cpCl = (CPClass) iterator.next(); 273 cpClass[i] = cpCl.getIndexInCpUtf8(); 274 i++; 275 } 276 final byte[] encodedBand = encodeBandInt("cpClass", cpClass, Codec.UDELTA5); 277 out.write(encodedBand); 278 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpClass[" + cpClass.length + "]"); 279 } 280 281 private void writeCpSignature(final OutputStream out) throws IOException, Pack200Exception { 282 PackingUtils.log("Writing " + cp_Signature.size() + " Signature entries..."); 283 final int[] cpSignatureForm = new int[cp_Signature.size()]; 284 final List classes = new ArrayList(); 285 int i = 0; 286 for (final Iterator iterator = cp_Signature.iterator(); iterator.hasNext();) { 287 final CPSignature cpS = (CPSignature) iterator.next(); 288 classes.addAll(cpS.getClasses()); 289 cpSignatureForm[i] = cpS.getIndexInCpUtf8(); 290 i++; 291 } 292 final int[] cpSignatureClasses = new int[classes.size()]; 293 for (int j = 0; j < cpSignatureClasses.length; j++) { 294 cpSignatureClasses[j] = ((CPClass) classes.get(j)).getIndex(); 295 } 296 297 byte[] encodedBand = encodeBandInt("cpSignatureForm", cpSignatureForm, Codec.DELTA5); 298 out.write(encodedBand); 299 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpSignatureForm[" + cpSignatureForm.length + "]"); 300 301 encodedBand = encodeBandInt("cpSignatureClasses", cpSignatureClasses, Codec.UDELTA5); 302 out.write(encodedBand); 303 PackingUtils 304 .log("Wrote " + encodedBand.length + " bytes from cpSignatureClasses[" + cpSignatureClasses.length + "]"); 305 } 306 307 private void writeCpDescr(final OutputStream out) throws IOException, Pack200Exception { 308 PackingUtils.log("Writing " + cp_Descr.size() + " Descriptor entries..."); 309 final int[] cpDescrName = new int[cp_Descr.size()]; 310 final int[] cpDescrType = new int[cp_Descr.size()]; 311 int i = 0; 312 for (final Iterator iterator = cp_Descr.iterator(); iterator.hasNext();) { 313 final CPNameAndType nameAndType = (CPNameAndType) iterator.next(); 314 cpDescrName[i] = nameAndType.getNameIndex(); 315 cpDescrType[i] = nameAndType.getTypeIndex(); 316 i++; 317 } 318 319 byte[] encodedBand = encodeBandInt("cp_Descr_Name", cpDescrName, Codec.DELTA5); 320 out.write(encodedBand); 321 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Name[" + cpDescrName.length + "]"); 322 323 encodedBand = encodeBandInt("cp_Descr_Type", cpDescrType, Codec.UDELTA5); 324 out.write(encodedBand); 325 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Type[" + cpDescrType.length + "]"); 326 } 327 328 private void writeCpMethodOrField(final Set cp, final OutputStream out, final String name) 329 throws IOException, Pack200Exception { 330 PackingUtils.log("Writing " + cp.size() + " Method and Field entries..."); 331 final int[] cp_methodOrField_class = new int[cp.size()]; 332 final int[] cp_methodOrField_desc = new int[cp.size()]; 333 int i = 0; 334 for (final Iterator iterator = cp.iterator(); iterator.hasNext();) { 335 final CPMethodOrField mOrF = (CPMethodOrField) iterator.next(); 336 cp_methodOrField_class[i] = mOrF.getClassIndex(); 337 cp_methodOrField_desc[i] = mOrF.getDescIndex(); 338 i++; 339 } 340 byte[] encodedBand = encodeBandInt(name + "_class", cp_methodOrField_class, Codec.DELTA5); 341 out.write(encodedBand); 342 PackingUtils.log( 343 "Wrote " + encodedBand.length + " bytes from " + name + "_class[" + cp_methodOrField_class.length + "]"); 344 345 encodedBand = encodeBandInt(name + "_desc", cp_methodOrField_desc, Codec.UDELTA5); 346 out.write(encodedBand); 347 PackingUtils 348 .log("Wrote " + encodedBand.length + " bytes from " + name + "_desc[" + cp_methodOrField_desc.length + "]"); 349 } 350 351 /** 352 * All input classes for the segment have now been read in, so this method is called so that this class can 353 * calculate/complete anything it could not do while classes were being read. 354 */ 355 public void finaliseBands() { 356 addCPUtf8(""); 357 removeSignaturesFromCpUTF8(); 358 addIndices(); 359 segmentHeader.setCp_Utf8_count(cp_Utf8.size()); 360 segmentHeader.setCp_Int_count(cp_Int.size()); 361 segmentHeader.setCp_Float_count(cp_Float.size()); 362 segmentHeader.setCp_Long_count(cp_Long.size()); 363 segmentHeader.setCp_Double_count(cp_Double.size()); 364 segmentHeader.setCp_String_count(cp_String.size()); 365 segmentHeader.setCp_Class_count(cp_Class.size()); 366 segmentHeader.setCp_Signature_count(cp_Signature.size()); 367 segmentHeader.setCp_Descr_count(cp_Descr.size()); 368 segmentHeader.setCp_Field_count(cp_Field.size()); 369 segmentHeader.setCp_Method_count(cp_Method.size()); 370 segmentHeader.setCp_Imethod_count(cp_Imethod.size()); 371 } 372 373 private void removeSignaturesFromCpUTF8() { 374 for (final Iterator iterator = cp_Signature.iterator(); iterator.hasNext();) { 375 final CPSignature signature = (CPSignature) iterator.next(); 376 final String sigStr = signature.getUnderlyingString(); 377 final CPUTF8 utf8 = signature.getSignatureForm(); 378 final String form = utf8.getUnderlyingString(); 379 if (!sigStr.equals(form)) { 380 removeCpUtf8(sigStr); 381 } 382 } 383 } 384 385 private void addIndices() { 386 final Set[] sets = {cp_Utf8, cp_Int, cp_Float, cp_Long, cp_Double, cp_String, cp_Class, cp_Signature, cp_Descr, 387 cp_Field, cp_Method, cp_Imethod}; 388 for (int i = 0; i < sets.length; i++) { 389 int j = 0; 390 for (final Iterator iterator = sets[i].iterator(); iterator.hasNext();) { 391 final ConstantPoolEntry entry = (ConstantPoolEntry) iterator.next(); 392 entry.setIndex(j); 393 j++; 394 } 395 } 396 final Map classNameToIndex = new HashMap(); 397 for (final Iterator iterator = cp_Field.iterator(); iterator.hasNext();) { 398 final CPMethodOrField mOrF = (CPMethodOrField) iterator.next(); 399 final CPClass className = mOrF.getClassName(); 400 final Integer index = (Integer) classNameToIndex.get(className); 401 if (index == null) { 402 classNameToIndex.put(className, Integer.valueOf(1)); 403 mOrF.setIndexInClass(0); 404 } else { 405 final int theIndex = index.intValue(); 406 mOrF.setIndexInClass(theIndex); 407 classNameToIndex.put(className, Integer.valueOf(theIndex + 1)); 408 } 409 } 410 classNameToIndex.clear(); 411 final Map classNameToConstructorIndex = new HashMap(); 412 for (final Iterator iterator = cp_Method.iterator(); iterator.hasNext();) { 413 final CPMethodOrField mOrF = (CPMethodOrField) iterator.next(); 414 final CPClass className = mOrF.getClassName(); 415 final Integer index = (Integer) classNameToIndex.get(className); 416 if (index == null) { 417 classNameToIndex.put(className, Integer.valueOf(1)); 418 mOrF.setIndexInClass(0); 419 } else { 420 final int theIndex = index.intValue(); 421 mOrF.setIndexInClass(theIndex); 422 classNameToIndex.put(className, Integer.valueOf(theIndex + 1)); 423 } 424 if (mOrF.getDesc().getName().equals("<init>")) { 425 final Integer constructorIndex = (Integer) classNameToConstructorIndex.get(className); 426 if (constructorIndex == null) { 427 classNameToConstructorIndex.put(className, Integer.valueOf(1)); 428 mOrF.setIndexInClassForConstructor(0); 429 } else { 430 final int theIndex = constructorIndex.intValue(); 431 mOrF.setIndexInClassForConstructor(theIndex); 432 classNameToConstructorIndex.put(className, Integer.valueOf(theIndex + 1)); 433 } 434 } 435 } 436 } 437 438 private void removeCpUtf8(final String string) { 439 final CPUTF8 utf8 = (CPUTF8) stringsToCpUtf8.get(string); 440 if ((utf8 != null) && (stringsToCpClass.get(string) == null)) { // don't remove if strings are also in cpclass 441 stringsToCpUtf8.remove(string); 442 cp_Utf8.remove(utf8); 443 } 444 } 445 446 void addCPUtf8(final String utf8) { 447 getCPUtf8(utf8); 448 } 449 450 public CPUTF8 getCPUtf8(final String utf8) { 451 if (utf8 == null) { 452 return null; 453 } 454 CPUTF8 cpUtf8 = (CPUTF8) stringsToCpUtf8.get(utf8); 455 if (cpUtf8 == null) { 456 cpUtf8 = new CPUTF8(utf8); 457 cp_Utf8.add(cpUtf8); 458 stringsToCpUtf8.put(utf8, cpUtf8); 459 } 460 return cpUtf8; 461 } 462 463 public CPSignature getCPSignature(final String signature) { 464 if (signature == null) { 465 return null; 466 } 467 CPSignature cpS = (CPSignature) stringsToCpSignature.get(signature); 468 if (cpS == null) { 469 final List cpClasses = new ArrayList(); 470 CPUTF8 signatureUTF8; 471 if (signature.length() > 1 && signature.indexOf('L') != -1) { 472 final List classes = new ArrayList(); 473 final char[] chars = signature.toCharArray(); 474 final StringBuffer signatureString = new StringBuffer(); 475 for (int i = 0; i < chars.length; i++) { 476 signatureString.append(chars[i]); 477 if (chars[i] == 'L') { 478 final StringBuffer className = new StringBuffer(); 479 for (int j = i + 1; j < chars.length; j++) { 480 final char c = chars[j]; 481 if (!Character.isLetter(c) && !Character.isDigit(c) && (c != '/') && (c != '$') 482 && (c != '_')) { 483 classes.add(className.toString()); 484 i = j - 1; 485 break; 486 } 487 className.append(c); 488 } 489 } 490 } 491 removeCpUtf8(signature); 492 for (final Iterator iterator2 = classes.iterator(); iterator2.hasNext();) { 493 String className = (String) iterator2.next(); 494 CPClass cpClass = null; 495 if (className != null) { 496 className = className.replace('.', '/'); 497 cpClass = (CPClass) stringsToCpClass.get(className); 498 if (cpClass == null) { 499 final CPUTF8 cpUtf8 = getCPUtf8(className); 500 cpClass = new CPClass(cpUtf8); 501 cp_Class.add(cpClass); 502 stringsToCpClass.put(className, cpClass); 503 } 504 } 505 cpClasses.add(cpClass); 506 } 507 508 signatureUTF8 = getCPUtf8(signatureString.toString()); 509 } else { 510 signatureUTF8 = getCPUtf8(signature); 511 } 512 cpS = new CPSignature(signature, signatureUTF8, cpClasses); 513 cp_Signature.add(cpS); 514 stringsToCpSignature.put(signature, cpS); 515 } 516 return cpS; 517 } 518 519 public CPClass getCPClass(String className) { 520 if (className == null) { 521 return null; 522 } 523 className = className.replace('.', '/'); 524 CPClass cpClass = (CPClass) stringsToCpClass.get(className); 525 if (cpClass == null) { 526 final CPUTF8 cpUtf8 = getCPUtf8(className); 527 cpClass = new CPClass(cpUtf8); 528 cp_Class.add(cpClass); 529 stringsToCpClass.put(className, cpClass); 530 } 531 if (cpClass.isInnerClass()) { 532 segment.getClassBands().currentClassReferencesInnerClass(cpClass); 533 } 534 return cpClass; 535 } 536 537 public void addCPClass(final String className) { 538 getCPClass(className); 539 } 540 541 public CPNameAndType getCPNameAndType(final String name, final String signature) { 542 final String descr = name + ":" + signature; 543 CPNameAndType nameAndType = (CPNameAndType) stringsToCpNameAndType.get(descr); 544 if (nameAndType == null) { 545 nameAndType = new CPNameAndType(getCPUtf8(name), getCPSignature(signature)); 546 stringsToCpNameAndType.put(descr, nameAndType); 547 cp_Descr.add(nameAndType); 548 } 549 return nameAndType; 550 } 551 552 public CPMethodOrField getCPField(final CPClass cpClass, final String name, final String desc) { 553 final String key = cpClass.toString() + ":" + name + ":" + desc; 554 CPMethodOrField cpF = (CPMethodOrField) stringsToCpField.get(key); 555 if (cpF == null) { 556 final CPNameAndType nAndT = getCPNameAndType(name, desc); 557 cpF = new CPMethodOrField(cpClass, nAndT); 558 cp_Field.add(cpF); 559 stringsToCpField.put(key, cpF); 560 } 561 return cpF; 562 } 563 564 public CPConstant getConstant(final Object value) { 565 CPConstant constant = (CPConstant) objectsToCPConstant.get(value); 566 if (constant == null) { 567 if (value instanceof Integer) { 568 constant = new CPInt(((Integer) value).intValue()); 569 cp_Int.add(constant); 570 } else if (value instanceof Long) { 571 constant = new CPLong(((Long) value).longValue()); 572 cp_Long.add(constant); 573 } else if (value instanceof Float) { 574 constant = new CPFloat(((Float) value).floatValue()); 575 cp_Float.add(constant); 576 } else if (value instanceof Double) { 577 constant = new CPDouble(((Double) value).doubleValue()); 578 cp_Double.add(constant); 579 } else if (value instanceof String) { 580 constant = new CPString(getCPUtf8((String) value)); 581 cp_String.add(constant); 582 } else if (value instanceof Type) { 583 String className = ((Type) value).getClassName(); 584 if (className.endsWith("[]")) { 585 className = "[L" + className.substring(0, className.length() - 2); 586 while (className.endsWith("[]")) { 587 className = "[" + className.substring(0, className.length() - 2); 588 } 589 className += ";"; 590 } 591 constant = getCPClass(className); 592 } 593 objectsToCPConstant.put(value, constant); 594 } 595 return constant; 596 } 597 598 public CPMethodOrField getCPMethod(final CPClass cpClass, final String name, final String desc) { 599 final String key = cpClass.toString() + ":" + name + ":" + desc; 600 CPMethodOrField cpM = (CPMethodOrField) stringsToCpMethod.get(key); 601 if (cpM == null) { 602 final CPNameAndType nAndT = getCPNameAndType(name, desc); 603 cpM = new CPMethodOrField(cpClass, nAndT); 604 cp_Method.add(cpM); 605 stringsToCpMethod.put(key, cpM); 606 } 607 return cpM; 608 } 609 610 public CPMethodOrField getCPIMethod(final CPClass cpClass, final String name, final String desc) { 611 final String key = cpClass.toString() + ":" + name + ":" + desc; 612 CPMethodOrField cpIM = (CPMethodOrField) stringsToCpIMethod.get(key); 613 if (cpIM == null) { 614 final CPNameAndType nAndT = getCPNameAndType(name, desc); 615 cpIM = new CPMethodOrField(cpClass, nAndT); 616 cp_Imethod.add(cpIM); 617 stringsToCpIMethod.put(key, cpIM); 618 } 619 return cpIM; 620 } 621 622 public CPMethodOrField getCPField(final String owner, final String name, final String desc) { 623 return getCPField(getCPClass(owner), name, desc); 624 } 625 626 public CPMethodOrField getCPMethod(final String owner, final String name, final String desc) { 627 return getCPMethod(getCPClass(owner), name, desc); 628 } 629 630 public CPMethodOrField getCPIMethod(final String owner, final String name, final String desc) { 631 return getCPIMethod(getCPClass(owner), name, desc); 632 } 633 634 public boolean existsCpClass(final String className) { 635 final CPClass cpClass = (CPClass) stringsToCpClass.get(className); 636 return cpClass != null; 637 } 638 639}