001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024 025import org.apache.bcel.Const; 026import org.apache.bcel.util.Args; 027 028/** 029 * This attribute exists for local or anonymous classes and ... there can be only one. 030 * 031 * @since 6.0 032 */ 033public class EnclosingMethod extends Attribute { 034 035 // Pointer to the CONSTANT_Class_info structure representing the 036 // innermost class that encloses the declaration of the current class. 037 private int classIndex; 038 039 // If the current class is not immediately enclosed by a method or 040 // constructor, then the value of the method_index item must be zero. 041 // Otherwise, the value of the method_index item must point to a 042 // CONSTANT_NameAndType_info structure representing the name and the 043 // type of a method in the class referenced by the class we point 044 // to in the class_index. *It is the compiler responsibility* to 045 // ensure that the method identified by this index is the closest 046 // lexically enclosing method that includes the local/anonymous class. 047 private int methodIndex; 048 049 // Ctors - and code to read an attribute in. 050 EnclosingMethod(final int nameIndex, final int len, final DataInput input, final ConstantPool cpool) throws IOException { 051 this(nameIndex, len, input.readUnsignedShort(), input.readUnsignedShort(), cpool); 052 } 053 054 private EnclosingMethod(final int nameIndex, final int len, final int classIndex, final int methodIndex, final ConstantPool cpool) { 055 super(Const.ATTR_ENCLOSING_METHOD, nameIndex, Args.require(len, 4, "EnclosingMethod attribute length"), cpool); 056 this.classIndex = Args.requireU2(classIndex, 0, cpool.getLength(), "EnclosingMethod class index"); 057 this.methodIndex = Args.requireU2(methodIndex, "EnclosingMethod method index"); 058 } 059 060 @Override 061 public void accept(final Visitor v) { 062 v.visitEnclosingMethod(this); 063 } 064 065 @Override 066 public Attribute copy(final ConstantPool constantPool) { 067 return (Attribute) clone(); 068 } 069 070 @Override 071 public final void dump(final DataOutputStream file) throws IOException { 072 super.dump(file); 073 file.writeShort(classIndex); 074 file.writeShort(methodIndex); 075 } 076 077 public final ConstantClass getEnclosingClass() { 078 return super.getConstantPool().getConstant(classIndex, Const.CONSTANT_Class, ConstantClass.class); 079 } 080 081 // Accessors 082 public final int getEnclosingClassIndex() { 083 return classIndex; 084 } 085 086 public final ConstantNameAndType getEnclosingMethod() { 087 if (methodIndex == 0) { 088 return null; 089 } 090 return super.getConstantPool().getConstant(methodIndex, Const.CONSTANT_NameAndType, ConstantNameAndType.class); 091 } 092 093 public final int getEnclosingMethodIndex() { 094 return methodIndex; 095 } 096 097 public final void setEnclosingClassIndex(final int idx) { 098 classIndex = idx; 099 } 100 101 public final void setEnclosingMethodIndex(final int idx) { 102 methodIndex = idx; 103 } 104}