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.Arrays; 023import java.util.HashMap; 024import java.util.HashSet; 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<String> defaultAttributeNames = new HashSet<>(); 039 040 private final Set<CPUTF8> cp_Utf8 = new TreeSet<>(); 041 private final Set<CPInt> cp_Int = new TreeSet<>(); 042 private final Set<CPFloat> cp_Float = new TreeSet<>(); 043 private final Set<CPLong> cp_Long = new TreeSet<>(); 044 private final Set<CPDouble> cp_Double = new TreeSet<>(); 045 private final Set<CPString> cp_String = new TreeSet<>(); 046 private final Set<CPClass> cp_Class = new TreeSet<>(); 047 private final Set<CPSignature> cp_Signature = new TreeSet<>(); 048 private final Set<CPNameAndType> cp_Descr = new TreeSet<>(); 049 private final Set<CPMethodOrField> cp_Field = new TreeSet<>(); 050 private final Set<CPMethodOrField> cp_Method = new TreeSet<>(); 051 private final Set<CPMethodOrField> cp_Imethod = new TreeSet<>(); 052 053 private final Map<String, CPUTF8> stringsToCpUtf8 = new HashMap<>(); 054 private final Map<String, CPNameAndType> stringsToCpNameAndType = new HashMap<>(); 055 private final Map<String, CPClass> stringsToCpClass = new HashMap<>(); 056 private final Map<String, CPSignature> stringsToCpSignature = new HashMap<>(); 057 private final Map<String, CPMethodOrField> stringsToCpMethod = new HashMap<>(); 058 private final Map<String, CPMethodOrField> stringsToCpField = new HashMap<>(); 059 private final Map<String, CPMethodOrField> stringsToCpIMethod = new HashMap<>(); 060 061 private final Map<Object, CPConstant<?>> 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<Character> chars = new ArrayList<>(); 108 final List<Integer> bigSuffix = new ArrayList<>(); 109 final List<Character> 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 Arrays.setAll(cpUtf8Chars, i -> chars.get(i).charValue()); 142 for (int i = 0; i < cpUtf8BigSuffix.length; i++) { 143 final int numBigChars = bigSuffix.get(i).intValue(); 144 cpUtf8BigSuffix[i] = numBigChars; 145 cpUtf8BigChars[i] = new int[numBigChars]; 146 Arrays.setAll(cpUtf8BigChars[i], j -> bigChars.remove(0).charValue()); 147 } 148 149 byte[] encodedBand = encodeBandInt("cpUtf8Prefix", cpUtf8Prefix, Codec.DELTA5); 150 out.write(encodedBand); 151 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Prefix[" + cpUtf8Prefix.length + "]"); 152 153 encodedBand = encodeBandInt("cpUtf8Suffix", cpUtf8Suffix, Codec.UNSIGNED5); 154 out.write(encodedBand); 155 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Suffix[" + cpUtf8Suffix.length + "]"); 156 157 encodedBand = encodeBandInt("cpUtf8Chars", cpUtf8Chars, Codec.CHAR3); 158 out.write(encodedBand); 159 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8Chars[" + cpUtf8Chars.length + "]"); 160 161 encodedBand = encodeBandInt("cpUtf8BigSuffix", cpUtf8BigSuffix, Codec.DELTA5); 162 out.write(encodedBand); 163 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigSuffix[" + cpUtf8BigSuffix.length + "]"); 164 165 for (int i = 0; i < cpUtf8BigChars.length; i++) { 166 encodedBand = encodeBandInt("cpUtf8BigChars " + i, cpUtf8BigChars[i], Codec.DELTA5); 167 out.write(encodedBand); 168 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpUtf8BigChars" + i + "[" 169 + cpUtf8BigChars[i].length + "]"); 170 } 171 } 172 173 private void addCharacters(final List<Character> chars, final char[] charArray) { 174 for (char element : charArray) { 175 chars.add(Character.valueOf(element)); 176 } 177 } 178 179 private void writeCpInt(final OutputStream out) throws IOException, Pack200Exception { 180 PackingUtils.log("Writing " + cp_Int.size() + " Integer entries..."); 181 final int[] cpInt = new int[cp_Int.size()]; 182 int i = 0; 183 for (final CPInt integer : cp_Int) { 184 cpInt[i] = integer.getInt(); 185 i++; 186 } 187 final byte[] encodedBand = encodeBandInt("cp_Int", cpInt, Codec.UDELTA5); 188 out.write(encodedBand); 189 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Int[" + cpInt.length + "]"); 190 } 191 192 private void writeCpFloat(final OutputStream out) throws IOException, Pack200Exception { 193 PackingUtils.log("Writing " + cp_Float.size() + " Float entries..."); 194 final int[] cpFloat = new int[cp_Float.size()]; 195 int i = 0; 196 for (final CPFloat fl : cp_Float) { 197 cpFloat[i] = Float.floatToIntBits(fl.getFloat()); 198 i++; 199 } 200 final byte[] encodedBand = encodeBandInt("cp_Float", cpFloat, Codec.UDELTA5); 201 out.write(encodedBand); 202 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Float[" + cpFloat.length + "]"); 203 } 204 205 private void writeCpLong(final OutputStream out) throws IOException, Pack200Exception { 206 PackingUtils.log("Writing " + cp_Long.size() + " Long entries..."); 207 final int[] highBits = new int[cp_Long.size()]; 208 final int[] loBits = new int[cp_Long.size()]; 209 int i = 0; 210 for (final CPLong lng : cp_Long) { 211 final long l = lng.getLong(); 212 highBits[i] = (int) (l >> 32); 213 loBits[i] = (int) l; 214 i++; 215 } 216 byte[] encodedBand = encodeBandInt("cp_Long_hi", highBits, Codec.UDELTA5); 217 out.write(encodedBand); 218 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_hi[" + highBits.length + "]"); 219 220 encodedBand = encodeBandInt("cp_Long_lo", loBits, Codec.DELTA5); 221 out.write(encodedBand); 222 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Long_lo[" + loBits.length + "]"); 223 } 224 225 private void writeCpDouble(final OutputStream out) throws IOException, Pack200Exception { 226 PackingUtils.log("Writing " + cp_Double.size() + " Double entries..."); 227 final int[] highBits = new int[cp_Double.size()]; 228 final int[] loBits = new int[cp_Double.size()]; 229 int i = 0; 230 for (final CPDouble dbl : cp_Double) { 231 final long l = Double.doubleToLongBits(dbl.getDouble()); 232 highBits[i] = (int) (l >> 32); 233 loBits[i] = (int) l; 234 i++; 235 } 236 byte[] encodedBand = encodeBandInt("cp_Double_hi", highBits, Codec.UDELTA5); 237 out.write(encodedBand); 238 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_hi[" + highBits.length + "]"); 239 240 encodedBand = encodeBandInt("cp_Double_lo", loBits, Codec.DELTA5); 241 out.write(encodedBand); 242 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Double_lo[" + loBits.length + "]"); 243 } 244 245 private void writeCpString(final OutputStream out) throws IOException, Pack200Exception { 246 PackingUtils.log("Writing " + cp_String.size() + " String entries..."); 247 final int[] cpString = new int[cp_String.size()]; 248 int i = 0; 249 for (final CPString cpStr : cp_String) { 250 cpString[i] = cpStr.getIndexInCpUtf8(); 251 i++; 252 } 253 final byte[] encodedBand = encodeBandInt("cpString", cpString, Codec.UDELTA5); 254 out.write(encodedBand); 255 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpString[" + cpString.length + "]"); 256 } 257 258 private void writeCpClass(final OutputStream out) throws IOException, Pack200Exception { 259 PackingUtils.log("Writing " + cp_Class.size() + " Class entries..."); 260 final int[] cpClass = new int[cp_Class.size()]; 261 int i = 0; 262 for (final CPClass cpCl : cp_Class) { 263 cpClass[i] = cpCl.getIndexInCpUtf8(); 264 i++; 265 } 266 final byte[] encodedBand = encodeBandInt("cpClass", cpClass, Codec.UDELTA5); 267 out.write(encodedBand); 268 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpClass[" + cpClass.length + "]"); 269 } 270 271 private void writeCpSignature(final OutputStream out) throws IOException, Pack200Exception { 272 PackingUtils.log("Writing " + cp_Signature.size() + " Signature entries..."); 273 final int[] cpSignatureForm = new int[cp_Signature.size()]; 274 final List<CPClass> classes = new ArrayList<>(); 275 int i = 0; 276 for (final CPSignature cpS : cp_Signature) { 277 classes.addAll(cpS.getClasses()); 278 cpSignatureForm[i] = cpS.getIndexInCpUtf8(); 279 i++; 280 } 281 final int[] cpSignatureClasses = new int[classes.size()]; 282 Arrays.setAll(cpSignatureClasses, j -> classes.get(j).getIndex()); 283 284 byte[] encodedBand = encodeBandInt("cpSignatureForm", cpSignatureForm, Codec.DELTA5); 285 out.write(encodedBand); 286 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cpSignatureForm[" + cpSignatureForm.length + "]"); 287 288 encodedBand = encodeBandInt("cpSignatureClasses", cpSignatureClasses, Codec.UDELTA5); 289 out.write(encodedBand); 290 PackingUtils 291 .log("Wrote " + encodedBand.length + " bytes from cpSignatureClasses[" + cpSignatureClasses.length + "]"); 292 } 293 294 private void writeCpDescr(final OutputStream out) throws IOException, Pack200Exception { 295 PackingUtils.log("Writing " + cp_Descr.size() + " Descriptor entries..."); 296 final int[] cpDescrName = new int[cp_Descr.size()]; 297 final int[] cpDescrType = new int[cp_Descr.size()]; 298 int i = 0; 299 for (final CPNameAndType nameAndType : cp_Descr) { 300 cpDescrName[i] = nameAndType.getNameIndex(); 301 cpDescrType[i] = nameAndType.getTypeIndex(); 302 i++; 303 } 304 305 byte[] encodedBand = encodeBandInt("cp_Descr_Name", cpDescrName, Codec.DELTA5); 306 out.write(encodedBand); 307 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Name[" + cpDescrName.length + "]"); 308 309 encodedBand = encodeBandInt("cp_Descr_Type", cpDescrType, Codec.UDELTA5); 310 out.write(encodedBand); 311 PackingUtils.log("Wrote " + encodedBand.length + " bytes from cp_Descr_Type[" + cpDescrType.length + "]"); 312 } 313 314 private void writeCpMethodOrField(final Set<CPMethodOrField> cp, final OutputStream out, final String name) 315 throws IOException, Pack200Exception { 316 PackingUtils.log("Writing " + cp.size() + " Method and Field entries..."); 317 final int[] cp_methodOrField_class = new int[cp.size()]; 318 final int[] cp_methodOrField_desc = new int[cp.size()]; 319 int i = 0; 320 for (final CPMethodOrField mOrF : cp) { 321 cp_methodOrField_class[i] = mOrF.getClassIndex(); 322 cp_methodOrField_desc[i] = mOrF.getDescIndex(); 323 i++; 324 } 325 byte[] encodedBand = encodeBandInt(name + "_class", cp_methodOrField_class, Codec.DELTA5); 326 out.write(encodedBand); 327 PackingUtils.log( 328 "Wrote " + encodedBand.length + " bytes from " + name + "_class[" + cp_methodOrField_class.length + "]"); 329 330 encodedBand = encodeBandInt(name + "_desc", cp_methodOrField_desc, Codec.UDELTA5); 331 out.write(encodedBand); 332 PackingUtils 333 .log("Wrote " + encodedBand.length + " bytes from " + name + "_desc[" + cp_methodOrField_desc.length + "]"); 334 } 335 336 /** 337 * All input classes for the segment have now been read in, so this method is called so that this class can 338 * calculate/complete anything it could not do while classes were being read. 339 */ 340 public void finaliseBands() { 341 addCPUtf8(""); 342 removeSignaturesFromCpUTF8(); 343 addIndices(); 344 segmentHeader.setCp_Utf8_count(cp_Utf8.size()); 345 segmentHeader.setCp_Int_count(cp_Int.size()); 346 segmentHeader.setCp_Float_count(cp_Float.size()); 347 segmentHeader.setCp_Long_count(cp_Long.size()); 348 segmentHeader.setCp_Double_count(cp_Double.size()); 349 segmentHeader.setCp_String_count(cp_String.size()); 350 segmentHeader.setCp_Class_count(cp_Class.size()); 351 segmentHeader.setCp_Signature_count(cp_Signature.size()); 352 segmentHeader.setCp_Descr_count(cp_Descr.size()); 353 segmentHeader.setCp_Field_count(cp_Field.size()); 354 segmentHeader.setCp_Method_count(cp_Method.size()); 355 segmentHeader.setCp_Imethod_count(cp_Imethod.size()); 356 } 357 358 private void removeSignaturesFromCpUTF8() { 359 cp_Signature.forEach(signature -> { 360 final String sigStr = signature.getUnderlyingString(); 361 final CPUTF8 utf8 = signature.getSignatureForm(); 362 final String form = utf8.getUnderlyingString(); 363 if (!sigStr.equals(form)) { 364 removeCpUtf8(sigStr); 365 } 366 }); 367 } 368 369 private void addIndices() { 370 for (Set<? extends ConstantPoolEntry> set : Arrays.asList(cp_Utf8, cp_Int, cp_Float, cp_Long, cp_Double, 371 cp_String, cp_Class, cp_Signature, cp_Descr, cp_Field, cp_Method, cp_Imethod)) { 372 int j = 0; 373 for (final ConstantPoolEntry entry : set) { 374 entry.setIndex(j); 375 j++; 376 } 377 } 378 final Map<CPClass, Integer> classNameToIndex = new HashMap<>(); 379 cp_Field.forEach(mOrF -> { 380 final CPClass cpClassName = mOrF.getClassName(); 381 final Integer index = classNameToIndex.get(cpClassName); 382 if (index == null) { 383 classNameToIndex.put(cpClassName, Integer.valueOf(1)); 384 mOrF.setIndexInClass(0); 385 } else { 386 final int theIndex = index.intValue(); 387 mOrF.setIndexInClass(theIndex); 388 classNameToIndex.put(cpClassName, Integer.valueOf(theIndex + 1)); 389 } 390 }); 391 classNameToIndex.clear(); 392 final Map<CPClass, Integer> classNameToConstructorIndex = new HashMap<>(); 393 cp_Method.forEach(mOrF -> { 394 final CPClass cpClassName = mOrF.getClassName(); 395 final Integer index = classNameToIndex.get(cpClassName); 396 if (index == null) { 397 classNameToIndex.put(cpClassName, Integer.valueOf(1)); 398 mOrF.setIndexInClass(0); 399 } else { 400 final int theIndex = index.intValue(); 401 mOrF.setIndexInClass(theIndex); 402 classNameToIndex.put(cpClassName, Integer.valueOf(theIndex + 1)); 403 } 404 if (mOrF.getDesc().getName().equals("<init>")) { 405 final Integer constructorIndex = classNameToConstructorIndex.get(cpClassName); 406 if (constructorIndex == null) { 407 classNameToConstructorIndex.put(cpClassName, Integer.valueOf(1)); 408 mOrF.setIndexInClassForConstructor(0); 409 } else { 410 final int theIndex = constructorIndex.intValue(); 411 mOrF.setIndexInClassForConstructor(theIndex); 412 classNameToConstructorIndex.put(cpClassName, Integer.valueOf(theIndex + 1)); 413 } 414 } 415 }); 416 } 417 418 private void removeCpUtf8(final String string) { 419 final CPUTF8 utf8 = stringsToCpUtf8.get(string); 420 if ((utf8 != null) && (stringsToCpClass.get(string) == null)) { // don't remove if strings are also in cpclass 421 stringsToCpUtf8.remove(string); 422 cp_Utf8.remove(utf8); 423 } 424 } 425 426 void addCPUtf8(final String utf8) { 427 getCPUtf8(utf8); 428 } 429 430 public CPUTF8 getCPUtf8(final String utf8) { 431 if (utf8 == null) { 432 return null; 433 } 434 CPUTF8 cpUtf8 = stringsToCpUtf8.get(utf8); 435 if (cpUtf8 == null) { 436 cpUtf8 = new CPUTF8(utf8); 437 cp_Utf8.add(cpUtf8); 438 stringsToCpUtf8.put(utf8, cpUtf8); 439 } 440 return cpUtf8; 441 } 442 443 public CPSignature getCPSignature(final String signature) { 444 if (signature == null) { 445 return null; 446 } 447 CPSignature cpS = stringsToCpSignature.get(signature); 448 if (cpS == null) { 449 final List<CPClass> cpClasses = new ArrayList<>(); 450 CPUTF8 signatureUTF8; 451 if (signature.length() > 1 && signature.indexOf('L') != -1) { 452 final List<String> classes = new ArrayList<>(); 453 final char[] chars = signature.toCharArray(); 454 final StringBuilder signatureString = new StringBuilder(); 455 for (int i = 0; i < chars.length; i++) { 456 signatureString.append(chars[i]); 457 if (chars[i] == 'L') { 458 final StringBuilder className = new StringBuilder(); 459 for (int j = i + 1; j < chars.length; j++) { 460 final char c = chars[j]; 461 if (!Character.isLetter(c) && !Character.isDigit(c) && (c != '/') && (c != '$') 462 && (c != '_')) { 463 classes.add(className.toString()); 464 i = j - 1; 465 break; 466 } 467 className.append(c); 468 } 469 } 470 } 471 removeCpUtf8(signature); 472 for (String className : classes) { 473 CPClass cpClass = null; 474 if (className != null) { 475 className = className.replace('.', '/'); 476 cpClass = stringsToCpClass.get(className); 477 if (cpClass == null) { 478 final CPUTF8 cpUtf8 = getCPUtf8(className); 479 cpClass = new CPClass(cpUtf8); 480 cp_Class.add(cpClass); 481 stringsToCpClass.put(className, cpClass); 482 } 483 } 484 cpClasses.add(cpClass); 485 } 486 487 signatureUTF8 = getCPUtf8(signatureString.toString()); 488 } else { 489 signatureUTF8 = getCPUtf8(signature); 490 } 491 cpS = new CPSignature(signature, signatureUTF8, cpClasses); 492 cp_Signature.add(cpS); 493 stringsToCpSignature.put(signature, cpS); 494 } 495 return cpS; 496 } 497 498 public CPClass getCPClass(String className) { 499 if (className == null) { 500 return null; 501 } 502 className = className.replace('.', '/'); 503 CPClass cpClass = stringsToCpClass.get(className); 504 if (cpClass == null) { 505 final CPUTF8 cpUtf8 = getCPUtf8(className); 506 cpClass = new CPClass(cpUtf8); 507 cp_Class.add(cpClass); 508 stringsToCpClass.put(className, cpClass); 509 } 510 if (cpClass.isInnerClass()) { 511 segment.getClassBands().currentClassReferencesInnerClass(cpClass); 512 } 513 return cpClass; 514 } 515 516 public void addCPClass(final String className) { 517 getCPClass(className); 518 } 519 520 public CPNameAndType getCPNameAndType(final String name, final String signature) { 521 final String descr = name + ":" + signature; 522 CPNameAndType nameAndType = stringsToCpNameAndType.get(descr); 523 if (nameAndType == null) { 524 nameAndType = new CPNameAndType(getCPUtf8(name), getCPSignature(signature)); 525 stringsToCpNameAndType.put(descr, nameAndType); 526 cp_Descr.add(nameAndType); 527 } 528 return nameAndType; 529 } 530 531 public CPMethodOrField getCPField(final CPClass cpClass, final String name, final String desc) { 532 final String key = cpClass.toString() + ":" + name + ":" + desc; 533 CPMethodOrField cpF = stringsToCpField.get(key); 534 if (cpF == null) { 535 final CPNameAndType nAndT = getCPNameAndType(name, desc); 536 cpF = new CPMethodOrField(cpClass, nAndT); 537 cp_Field.add(cpF); 538 stringsToCpField.put(key, cpF); 539 } 540 return cpF; 541 } 542 543 public CPConstant<?> getConstant(final Object value) { 544 CPConstant<?> constant = objectsToCPConstant.get(value); 545 if (constant == null) { 546 if (value instanceof Integer) { 547 constant = new CPInt(((Integer) value).intValue()); 548 cp_Int.add((CPInt) constant); 549 } else if (value instanceof Long) { 550 constant = new CPLong(((Long) value).longValue()); 551 cp_Long.add((CPLong) constant); 552 } else if (value instanceof Float) { 553 constant = new CPFloat(((Float) value).floatValue()); 554 cp_Float.add((CPFloat) constant); 555 } else if (value instanceof Double) { 556 constant = new CPDouble(((Double) value).doubleValue()); 557 cp_Double.add((CPDouble) constant); 558 } else if (value instanceof String) { 559 constant = new CPString(getCPUtf8((String) value)); 560 cp_String.add((CPString) constant); 561 } else if (value instanceof Type) { 562 String className = ((Type) value).getClassName(); 563 if (className.endsWith("[]")) { 564 className = "[L" + className.substring(0, className.length() - 2); 565 while (className.endsWith("[]")) { 566 className = "[" + className.substring(0, className.length() - 2); 567 } 568 className += ";"; 569 } 570 constant = getCPClass(className); 571 } 572 objectsToCPConstant.put(value, constant); 573 } 574 return constant; 575 } 576 577 public CPMethodOrField getCPMethod(final CPClass cpClass, final String name, final String desc) { 578 final String key = cpClass.toString() + ":" + name + ":" + desc; 579 CPMethodOrField cpM = stringsToCpMethod.get(key); 580 if (cpM == null) { 581 final CPNameAndType nAndT = getCPNameAndType(name, desc); 582 cpM = new CPMethodOrField(cpClass, nAndT); 583 cp_Method.add(cpM); 584 stringsToCpMethod.put(key, cpM); 585 } 586 return cpM; 587 } 588 589 public CPMethodOrField getCPIMethod(final CPClass cpClass, final String name, final String desc) { 590 final String key = cpClass.toString() + ":" + name + ":" + desc; 591 CPMethodOrField cpIM = stringsToCpIMethod.get(key); 592 if (cpIM == null) { 593 final CPNameAndType nAndT = getCPNameAndType(name, desc); 594 cpIM = new CPMethodOrField(cpClass, nAndT); 595 cp_Imethod.add(cpIM); 596 stringsToCpIMethod.put(key, cpIM); 597 } 598 return cpIM; 599 } 600 601 public CPMethodOrField getCPField(final String owner, final String name, final String desc) { 602 return getCPField(getCPClass(owner), name, desc); 603 } 604 605 public CPMethodOrField getCPMethod(final String owner, final String name, final String desc) { 606 return getCPMethod(getCPClass(owner), name, desc); 607 } 608 609 public CPMethodOrField getCPIMethod(final String owner, final String name, final String desc) { 610 return getCPIMethod(getCPClass(owner), name, desc); 611 } 612 613 public boolean existsCpClass(final String className) { 614 final CPClass cpClass = stringsToCpClass.get(className); 615 return cpClass != null; 616 } 617 618}