|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | /* | 
|  |  * Licensed to the Apache Software Foundation (ASF) under one or more | 
|  |  * contributor license agreements.  See the NOTICE file distributed with | 
|  |  * this work for additional information regarding copyright ownership. | 
|  |  * The ASF licenses this file to You under the Apache License, Version 2.0 | 
|  |  * (the "License"); you may not use this file except in compliance with | 
|  |  * the License.  You may obtain a copy of the License at | 
|  |  * | 
|  |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  |  * | 
|  |  * Unless required by applicable law or agreed to in writing, software | 
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  |  * See the License for the specific language governing permissions and | 
|  |  * limitations under the License. | 
|  |  */ | 
|  |  | 
|  | package com.sun.org.apache.bcel.internal.classfile; | 
|  |  | 
|  | import java.io.DataInput; | 
|  | import java.io.DataOutputStream; | 
|  | import java.io.IOException; | 
|  |  | 
|  | import com.sun.org.apache.bcel.internal.Const; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | public final class Code extends Attribute { | 
|  |  | 
|  |     private int max_stack;  | 
|  |     private int max_locals;  | 
|  |     private byte[] code;  | 
|  |     private CodeException[] exception_table;  | 
|  |     private Attribute[] attributes;  | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public Code(final Code c) { | 
|  |         this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c | 
|  |                 .getExceptionTable(), c.getAttributes(), c.getConstantPool()); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool) | 
|  |             throws IOException { | 
|  |          | 
|  |         this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, | 
|  |                 (CodeException[]) null, (Attribute[]) null, constant_pool); | 
|  |         final int code_length = file.readInt(); | 
|  |         code = new byte[code_length];  | 
|  |         file.readFully(code); | 
|  |          | 
|  |  | 
|  |          */ | 
|  |         final int exception_table_length = file.readUnsignedShort(); | 
|  |         exception_table = new CodeException[exception_table_length]; | 
|  |         for (int i = 0; i < exception_table_length; i++) { | 
|  |             exception_table[i] = new CodeException(file); | 
|  |         } | 
|  |          | 
|  |  | 
|  |          */ | 
|  |         final int attributes_count = file.readUnsignedShort(); | 
|  |         attributes = new Attribute[attributes_count]; | 
|  |         for (int i = 0; i < attributes_count; i++) { | 
|  |             attributes[i] = Attribute.readAttribute(file, constant_pool); | 
|  |         } | 
|  |          | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         super.setLength(length); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public Code(final int name_index, final int length, final int max_stack, final int max_locals, final byte[] code, | 
|  |             final CodeException[] exception_table, final Attribute[] attributes, final ConstantPool constant_pool) { | 
|  |         super(Const.ATTR_CODE, name_index, length, constant_pool); | 
|  |         this.max_stack = max_stack; | 
|  |         this.max_locals = max_locals; | 
|  |         this.code = code != null ? code : new byte[0]; | 
|  |         this.exception_table = exception_table != null ? exception_table : new CodeException[0]; | 
|  |         this.attributes = attributes != null ? attributes : new Attribute[0]; | 
|  |         super.setLength(calculateLength());  | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public void accept( final Visitor v ) { | 
|  |         v.visitCode(this); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public final void dump( final DataOutputStream file ) throws IOException { | 
|  |         super.dump(file); | 
|  |         file.writeShort(max_stack); | 
|  |         file.writeShort(max_locals); | 
|  |         file.writeInt(code.length); | 
|  |         file.write(code, 0, code.length); | 
|  |         file.writeShort(exception_table.length); | 
|  |         for (final CodeException exception : exception_table) { | 
|  |             exception.dump(file); | 
|  |         } | 
|  |         file.writeShort(attributes.length); | 
|  |         for (final Attribute attribute : attributes) { | 
|  |             attribute.dump(file); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public final Attribute[] getAttributes() { | 
|  |         return attributes; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public LineNumberTable getLineNumberTable() { | 
|  |         for (final Attribute attribute : attributes) { | 
|  |             if (attribute instanceof LineNumberTable) { | 
|  |                 return (LineNumberTable) attribute; | 
|  |             } | 
|  |         } | 
|  |         return null; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public LocalVariableTable getLocalVariableTable() { | 
|  |         for (final Attribute attribute : attributes) { | 
|  |             if (attribute instanceof LocalVariableTable) { | 
|  |                 return (LocalVariableTable) attribute; | 
|  |             } | 
|  |         } | 
|  |         return null; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final byte[] getCode() { | 
|  |         return code; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public final CodeException[] getExceptionTable() { | 
|  |         return exception_table; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final int getMaxLocals() { | 
|  |         return max_locals; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final int getMaxStack() { | 
|  |         return max_stack; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private int getInternalLength() { | 
|  |         return 2 + 2 + 4  | 
|  |                 + code.length  | 
|  |                 + 2  | 
|  |                 + 8 * (exception_table == null ? 0 : exception_table.length)  | 
|  |                 + 2 /* attributes count */; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private int calculateLength() { | 
|  |         int len = 0; | 
|  |         if (attributes != null) { | 
|  |             for (final Attribute attribute : attributes) { | 
|  |                 len += attribute.getLength() + 6 /*attribute header size*/; | 
|  |             } | 
|  |         } | 
|  |         return len + getInternalLength(); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setAttributes( final Attribute[] attributes ) { | 
|  |         this.attributes = attributes != null ? attributes : new Attribute[0]; | 
|  |         super.setLength(calculateLength());  | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setCode( final byte[] code ) { | 
|  |         this.code = code != null ? code : new byte[0]; | 
|  |         super.setLength(calculateLength());  | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setExceptionTable( final CodeException[] exception_table ) { | 
|  |         this.exception_table = exception_table != null ? exception_table : new CodeException[0]; | 
|  |         super.setLength(calculateLength());  | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setMaxLocals( final int max_locals ) { | 
|  |         this.max_locals = max_locals; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final void setMaxStack( final int max_stack ) { | 
|  |         this.max_stack = max_stack; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public final String toString( final boolean verbose ) { | 
|  |         final StringBuilder buf = new StringBuilder(100);  | 
|  |         buf.append("Code(max_stack = ").append(max_stack).append(", max_locals = ").append( | 
|  |                 max_locals).append(", code_length = ").append(code.length).append(")\n").append( | 
|  |                 Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose)); | 
|  |         if (exception_table.length > 0) { | 
|  |             buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n"); | 
|  |             for (final CodeException exception : exception_table) { | 
|  |                 buf.append(exception.toString(super.getConstantPool(), verbose)).append("\n"); | 
|  |             } | 
|  |         } | 
|  |         if (attributes.length > 0) { | 
|  |             buf.append("\nAttribute(s) = "); | 
|  |             for (final Attribute attribute : attributes) { | 
|  |                 buf.append("\n").append(attribute); | 
|  |             } | 
|  |         } | 
|  |         return buf.toString(); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public final String toString() { | 
|  |         return toString(true); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     @Override | 
|  |     public Attribute copy( final ConstantPool _constant_pool ) { | 
|  |         final Code c = (Code) clone(); | 
|  |         if (code != null) { | 
|  |             c.code = new byte[code.length]; | 
|  |             System.arraycopy(code, 0, c.code, 0, code.length); | 
|  |         } | 
|  |         c.setConstantPool(_constant_pool); | 
|  |         c.exception_table = new CodeException[exception_table.length]; | 
|  |         for (int i = 0; i < exception_table.length; i++) { | 
|  |             c.exception_table[i] = exception_table[i].copy(); | 
|  |         } | 
|  |         c.attributes = new Attribute[attributes.length]; | 
|  |         for (int i = 0; i < attributes.length; i++) { | 
|  |             c.attributes[i] = attributes[i].copy(_constant_pool); | 
|  |         } | 
|  |         return c; | 
|  |     } | 
|  | } |