1 /* 2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package com.sun.org.apache.bcel.internal.classfile; 21 22 import java.io.DataInput; 23 import java.io.DataInputStream; 24 import java.io.DataOutputStream; 25 import java.io.IOException; 26 import java.util.HashMap; 27 import java.util.Map; 28 29 import com.sun.org.apache.bcel.internal.Const; 30 31 /** 32 * Abstract super class for <em>Attribute</em> objects. Currently the 33 * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>, 34 * <em>Exceptiontable</em>, <em>LineNumberTable</em>, 35 * <em>LocalVariableTable</em>, <em>InnerClasses</em> and 36 * <em>Synthetic</em> attributes are supported. The <em>Unknown</em> 37 * attribute stands for non-standard-attributes. 38 * 39 * @version $Id$ 40 * @see ConstantValue 41 * @see SourceFile 42 * @see Code 43 * @see Unknown 44 * @see ExceptionTable 45 * @see LineNumberTable 46 * @see LocalVariableTable 47 * @see InnerClasses 48 * @see Synthetic 49 * @see Deprecated 50 * @see Signature 51 * @LastModified: Jun 2019 52 */ 53 public abstract class Attribute implements Cloneable, Node { 54 55 private int name_index; // Points to attribute name in constant pool 56 private int length; // Content length of attribute field 57 private final byte tag; // Tag to distinguish subclasses 58 private ConstantPool constant_pool; 59 60 protected Attribute(final byte tag, final int name_index, final int length, final ConstantPool constant_pool) { 61 this.tag = tag; 62 this.name_index = name_index; 63 this.length = length; 64 this.constant_pool = constant_pool; 65 } 66 67 /** 68 * Called by objects that are traversing the nodes of the tree implicitely 69 * defined by the contents of a Java class. I.e., the hierarchy of methods, 70 * fields, attributes, etc. spawns a tree of objects. 71 * 72 * @param v Visitor object 73 */ 74 @Override 75 public abstract void accept(Visitor v); 76 77 /** 78 * Dump attribute to file stream in binary format. 79 * 80 * @param file Output file stream 81 * @throws IOException 82 */ 83 public void dump(final DataOutputStream file) throws IOException 84 { 85 file.writeShort(name_index); 86 file.writeInt(length); 87 } 88 89 private static final Map<String, Object> readers = new HashMap<>(); 90 91 /** 92 * Add an Attribute reader capable of parsing (user-defined) attributes 93 * named "name". You should not add readers for the standard attributes such 94 * as "LineNumberTable", because those are handled internally. 95 * 96 * @param name the name of the attribute as stored in the class file 97 * @param r the reader object 98 */ 99 public static void addAttributeReader(final String name, final UnknownAttributeReader r) 100 { 101 readers.put(name, r); 102 } 103 104 /** 105 * Remove attribute reader 106 * 107 * @param name the name of the attribute as stored in the class file 108 */ 109 public static void removeAttributeReader(final String name) 110 { 111 readers.remove(name); 112 } 113 114 /** 115 * Class method reads one attribute from the input data stream. This method 116 * must not be accessible from the outside. It is called by the Field and 117 * Method constructor methods. 118 * 119 * @see Field 120 * @see Method 121 * 122 * @param file Input stream 123 * @param constant_pool Array of constants 124 * @return Attribute 125 * @throws IOException 126 * @throws ClassFormatException 127 */ 128 public static Attribute readAttribute(final DataInputStream file, final ConstantPool constant_pool) 129 throws IOException, ClassFormatException 130 { 131 return readAttribute((DataInput) file, constant_pool); 132 } 133 134 /** 135 * Class method reads one attribute from the input data stream. This method 136 * must not be accessible from the outside. It is called by the Field and 137 * Method constructor methods. 138 * 139 * @see Field 140 * @see Method 141 * 142 * @param file Input stream 143 * @param constant_pool Array of constants 144 * @return Attribute 145 * @throws IOException 146 * @throws ClassFormatException 147 * @since 6.0 148 */ 149 public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool) 150 throws IOException, ClassFormatException 151 { 186 return new Code(name_index, length, file, constant_pool); 187 case Const.ATTR_EXCEPTIONS: 188 return new ExceptionTable(name_index, length, file, constant_pool); 189 case Const.ATTR_LINE_NUMBER_TABLE: 190 return new LineNumberTable(name_index, length, file, constant_pool); 191 case Const.ATTR_LOCAL_VARIABLE_TABLE: 192 return new LocalVariableTable(name_index, length, file, constant_pool); 193 case Const.ATTR_INNER_CLASSES: 194 return new InnerClasses(name_index, length, file, constant_pool); 195 case Const.ATTR_SYNTHETIC: 196 return new Synthetic(name_index, length, file, constant_pool); 197 case Const.ATTR_DEPRECATED: 198 return new Deprecated(name_index, length, file, constant_pool); 199 case Const.ATTR_PMG: 200 return new PMGClass(name_index, length, file, constant_pool); 201 case Const.ATTR_SIGNATURE: 202 return new Signature(name_index, length, file, constant_pool); 203 case Const.ATTR_STACK_MAP: 204 // old style stack map: unneeded for JDK5 and below; 205 // illegal(?) for JDK6 and above. So just delete with a warning. 206 System.err.println("Warning: Obsolete StackMap attribute ignored."); 207 return new Unknown(name_index, length, file, constant_pool); 208 case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: 209 return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool); 210 case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: 211 return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool); 212 case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: 213 return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool); 214 case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: 215 return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool); 216 case Const.ATTR_ANNOTATION_DEFAULT: 217 return new AnnotationDefault(name_index, length, file, constant_pool); 218 case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE: 219 return new LocalVariableTypeTable(name_index, length, file, constant_pool); 220 case Const.ATTR_ENCLOSING_METHOD: 221 return new EnclosingMethod(name_index, length, file, constant_pool); 222 case Const.ATTR_STACK_MAP_TABLE: 223 // read new style stack map: StackMapTable. The rest of the code 224 // calls this a StackMap for historical reasons. 225 return new StackMap(name_index, length, file, constant_pool); 226 case Const.ATTR_BOOTSTRAP_METHODS: 227 return new BootstrapMethods(name_index, length, file, constant_pool); 228 case Const.ATTR_METHOD_PARAMETERS: 229 return new MethodParameters(name_index, length, file, constant_pool); 230 default: 231 // Never reached 232 throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); 233 } 234 } 235 236 /** 237 * @return Name of attribute 238 * @since 6.0 239 */ 240 public String getName() 241 { 242 final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); 243 return c.getBytes(); 244 } 245 246 /** 247 * @return Length of attribute field in bytes. 248 */ 249 public final int getLength() 250 { 251 return length; 252 } 253 254 /** 255 * @param length length in bytes. 256 */ 257 public final void setLength(final int length) 258 { 259 this.length = length; 260 } 261 262 /** 263 * @param name_index of attribute. 264 */ 265 public final void setNameIndex(final int name_index) 266 { 267 this.name_index = name_index; 268 } 269 270 /** 271 * @return Name index in constant pool of attribute name. 272 */ 273 public final int getNameIndex() 274 { 275 return name_index; 276 } 277 278 /** 279 * @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method. 280 */ 281 public final byte getTag() 282 { 283 return tag; 284 } 285 286 /** 287 * @return Constant pool used by this object. 288 * @see ConstantPool 289 */ 290 public final ConstantPool getConstantPool() 291 { 292 return constant_pool; 293 } 294 295 /** 296 * @param constant_pool Constant pool to be used for this object. 297 * @see ConstantPool 298 */ 299 public final void setConstantPool(final ConstantPool constant_pool) 300 { 301 this.constant_pool = constant_pool; 302 } 303 304 /** 305 * Use copy() if you want to have a deep copy(), i.e., with all references 306 * copied correctly. 307 * 308 * @return shallow copy of this attribute 309 */ 310 @Override 311 public Object clone() 312 { 313 Attribute attr = null; 314 try 315 { 316 attr = (Attribute) super.clone(); 317 } 318 catch (final CloneNotSupportedException e) 319 { 320 throw new Error("Clone Not Supported"); // never happens 321 } 322 return attr; 323 } 324 325 /** 326 * @return deep copy of this attribute 327 */ 328 public abstract Attribute copy(ConstantPool _constant_pool); 329 330 /** 331 * @return attribute name. 332 */ 333 @Override 334 public String toString() 335 { 336 return Const.getAttributeName(tag); 337 } 338 } | 1 /* 2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package com.sun.org.apache.bcel.internal.classfile; 21 22 import java.io.DataInput; 23 import java.io.DataInputStream; 24 import java.io.DataOutputStream; 25 import java.io.IOException; 26 import java.util.HashMap; 27 import java.util.Map; 28 29 import com.sun.org.apache.bcel.internal.Const; 30 31 /** 32 * Abstract super class for <em>Attribute</em> objects. Currently the 33 * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>, 34 * <em>Exceptiontable</em>, <em>LineNumberTable</em>, 35 * <em>LocalVariableTable</em>, <em>InnerClasses</em> and 36 * <em>Synthetic</em> attributes are supported. The <em>Unknown</em> 37 * attribute stands for non-standard-attributes. 38 * 39 * @see ConstantValue 40 * @see SourceFile 41 * @see Code 42 * @see Unknown 43 * @see ExceptionTable 44 * @see LineNumberTable 45 * @see LocalVariableTable 46 * @see InnerClasses 47 * @see Synthetic 48 * @see Deprecated 49 * @see Signature 50 * @LastModified: Jan 2020 51 */ 52 public abstract class Attribute implements Cloneable, Node { 53 private static final boolean debug = false; 54 private int name_index; // Points to attribute name in constant pool 55 private int length; // Content length of attribute field 56 private final byte tag; // Tag to distinguish subclasses 57 private ConstantPool constant_pool; 58 59 private static final Map<String, Object> readers = new HashMap<>(); 60 61 /** 62 * Add an Attribute reader capable of parsing (user-defined) attributes 63 * named "name". You should not add readers for the standard attributes such 64 * as "LineNumberTable", because those are handled internally. 65 * 66 * @param name the name of the attribute as stored in the class file 67 * @param r the reader object 68 */ 69 public static void addAttributeReader(final String name, final UnknownAttributeReader r) 70 { 71 readers.put(name, r); 72 } 73 74 protected static void println(final String msg) { 75 if (debug) { 76 System.err.println(msg); 77 } 78 } 79 80 /** 81 * Class method reads one attribute from the input data stream. This method 82 * must not be accessible from the outside. It is called by the Field and 83 * Method constructor methods. 84 * 85 * @see Field 86 * @see Method 87 * 88 * @param file Input stream 89 * @param constant_pool Array of constants 90 * @return Attribute 91 * @throws IOException 92 * @throws ClassFormatException 93 * @since 6.0 94 */ 95 public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool) 96 throws IOException, ClassFormatException 97 { 132 return new Code(name_index, length, file, constant_pool); 133 case Const.ATTR_EXCEPTIONS: 134 return new ExceptionTable(name_index, length, file, constant_pool); 135 case Const.ATTR_LINE_NUMBER_TABLE: 136 return new LineNumberTable(name_index, length, file, constant_pool); 137 case Const.ATTR_LOCAL_VARIABLE_TABLE: 138 return new LocalVariableTable(name_index, length, file, constant_pool); 139 case Const.ATTR_INNER_CLASSES: 140 return new InnerClasses(name_index, length, file, constant_pool); 141 case Const.ATTR_SYNTHETIC: 142 return new Synthetic(name_index, length, file, constant_pool); 143 case Const.ATTR_DEPRECATED: 144 return new Deprecated(name_index, length, file, constant_pool); 145 case Const.ATTR_PMG: 146 return new PMGClass(name_index, length, file, constant_pool); 147 case Const.ATTR_SIGNATURE: 148 return new Signature(name_index, length, file, constant_pool); 149 case Const.ATTR_STACK_MAP: 150 // old style stack map: unneeded for JDK5 and below; 151 // illegal(?) for JDK6 and above. So just delete with a warning. 152 println("Warning: Obsolete StackMap attribute ignored."); 153 return new Unknown(name_index, length, file, constant_pool); 154 case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: 155 return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool); 156 case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: 157 return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool); 158 case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: 159 return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool); 160 case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: 161 return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool); 162 case Const.ATTR_ANNOTATION_DEFAULT: 163 return new AnnotationDefault(name_index, length, file, constant_pool); 164 case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE: 165 return new LocalVariableTypeTable(name_index, length, file, constant_pool); 166 case Const.ATTR_ENCLOSING_METHOD: 167 return new EnclosingMethod(name_index, length, file, constant_pool); 168 case Const.ATTR_STACK_MAP_TABLE: 169 // read new style stack map: StackMapTable. The rest of the code 170 // calls this a StackMap for historical reasons. 171 return new StackMap(name_index, length, file, constant_pool); 172 case Const.ATTR_BOOTSTRAP_METHODS: 173 return new BootstrapMethods(name_index, length, file, constant_pool); 174 case Const.ATTR_METHOD_PARAMETERS: 175 return new MethodParameters(name_index, length, file, constant_pool); 176 case Const.ATTR_MODULE: 177 return new Module(name_index, length, file, constant_pool); 178 case Const.ATTR_MODULE_PACKAGES: 179 return new ModulePackages(name_index, length, file, constant_pool); 180 case Const.ATTR_MODULE_MAIN_CLASS: 181 return new ModuleMainClass(name_index, length, file, constant_pool); 182 case Const.ATTR_NEST_HOST: 183 return new NestHost(name_index, length, file, constant_pool); 184 case Const.ATTR_NEST_MEMBERS: 185 return new NestMembers(name_index, length, file, constant_pool); 186 default: 187 // Never reached 188 throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); 189 } 190 } 191 192 /** 193 * Class method reads one attribute from the input data stream. This method 194 * must not be accessible from the outside. It is called by the Field and 195 * Method constructor methods. 196 * 197 * @see Field 198 * @see Method 199 * 200 * @param file Input stream 201 * @param constant_pool Array of constants 202 * @return Attribute 203 * @throws IOException 204 * @throws ClassFormatException 205 */ 206 public static Attribute readAttribute(final DataInputStream file, final ConstantPool constant_pool) 207 throws IOException, ClassFormatException 208 { 209 return readAttribute((DataInput) file, constant_pool); 210 } 211 212 /** 213 * Remove attribute reader 214 * 215 * @param name the name of the attribute as stored in the class file 216 */ 217 public static void removeAttributeReader(final String name) 218 { 219 readers.remove(name); 220 } 221 222 protected Attribute(final byte tag, final int name_index, final int length, final ConstantPool constant_pool) 223 { 224 this.tag = tag; 225 this.name_index = name_index; 226 this.length = length; 227 this.constant_pool = constant_pool; 228 } 229 230 /** 231 * Called by objects that are traversing the nodes of the tree implicitely 232 * defined by the contents of a Java class. I.e., the hierarchy of methods, 233 * fields, attributes, etc. spawns a tree of objects. 234 * 235 * @param v 236 * Visitor object 237 */ 238 @Override 239 public abstract void accept(Visitor v); 240 241 /** 242 * Use copy() if you want to have a deep copy(), i.e., with all references 243 * copied correctly. 244 * 245 * @return shallow copy of this attribute 246 */ 247 @Override 248 public Object clone() 249 { 250 Attribute attr = null; 251 try 252 { 253 attr = (Attribute) super.clone(); 254 } 255 catch (final CloneNotSupportedException e) 256 { 257 throw new Error("Clone Not Supported"); // never happens 258 } 259 return attr; 260 } 261 262 /** 263 * @return deep copy of this attribute 264 */ 265 public abstract Attribute copy(ConstantPool _constant_pool); 266 267 /** 268 * Dump attribute to file stream in binary format. 269 * 270 * @param file 271 * Output file stream 272 * @throws IOException 273 */ 274 public void dump(final DataOutputStream file) throws IOException 275 { 276 file.writeShort(name_index); 277 file.writeInt(length); 278 } 279 280 /** 281 * @return Constant pool used by this object. 282 * @see ConstantPool 283 */ 284 public final ConstantPool getConstantPool() 285 { 286 return constant_pool; 287 } 288 289 /** 290 * @return Length of attribute field in bytes. 291 */ 292 public final int getLength() 293 { 294 return length; 295 } 296 297 /** 298 * @return Name of attribute 299 * @since 6.0 300 */ 301 public String getName() 302 { 303 final ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8); 304 return c.getBytes(); 305 } 306 307 /** 308 * @return Name index in constant pool of attribute name. 309 */ 310 public final int getNameIndex() 311 { 312 return name_index; 313 } 314 315 /** 316 * @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method. 317 */ 318 public final byte getTag() 319 { 320 return tag; 321 } 322 323 /** 324 * @param constant_pool Constant pool to be used for this object. 325 * @see ConstantPool 326 */ 327 public final void setConstantPool(final ConstantPool constant_pool) 328 { 329 this.constant_pool = constant_pool; 330 } 331 332 /** 333 * @param length length in bytes. 334 */ 335 public final void setLength(final int length) 336 { 337 this.length = length; 338 } 339 340 /** 341 * @param name_index of attribute. 342 */ 343 public final void setNameIndex(final int name_index) 344 { 345 this.name_index = name_index; 346 } 347 348 /** 349 * @return attribute name. 350 */ 351 @Override 352 public String toString() 353 { 354 return Const.getAttributeName(tag); 355 } 356 } |