001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License. 
016     *
017     */
018    package org.apache.bcel.generic;
019    
020    import java.io.DataOutputStream;
021    import java.io.IOException;
022    import org.apache.bcel.ExceptionConstants;
023    import org.apache.bcel.classfile.ConstantPool;
024    import org.apache.bcel.util.ByteSequence;
025    
026    /** 
027     * MULTIANEWARRAY - Create new mutidimensional array of references
028     * <PRE>Stack: ..., count1, [count2, ...] -&gt; ..., arrayref</PRE>
029     *
030     * @version $Id: MULTIANEWARRAY.java 1152072 2011-07-29 01:54:05Z dbrosius $
031     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
032     */
033    public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction,
034            ExceptionThrower {
035    
036        private static final long serialVersionUID = -7439639244808941662L;
037        private short dimensions;
038    
039    
040        /**
041         * Empty constructor needed for the Class.newInstance() statement in
042         * Instruction.readInstruction(). Not to be used otherwise.
043         */
044        MULTIANEWARRAY() {
045        }
046    
047    
048        public MULTIANEWARRAY(int index, short dimensions) {
049            super(org.apache.bcel.Constants.MULTIANEWARRAY, index);
050            if (dimensions < 1) {
051                throw new ClassGenException("Invalid dimensions value: " + dimensions);
052            }
053            this.dimensions = dimensions;
054            length = 4;
055        }
056    
057    
058        /**
059         * Dump instruction as byte code to stream out.
060         * @param out Output stream
061         */
062        @Override
063        public void dump( DataOutputStream out ) throws IOException {
064            out.writeByte(opcode);
065            out.writeShort(index);
066            out.writeByte(dimensions);
067        }
068    
069    
070        /**
071         * Read needed data (i.e., no. dimension) from file.
072         */
073        @Override
074        protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
075            super.initFromFile(bytes, wide);
076            dimensions = bytes.readByte();
077            length = 4;
078        }
079    
080    
081        /**
082         * @return number of dimensions to be created
083         */
084        public final short getDimensions() {
085            return dimensions;
086        }
087    
088    
089        /**
090         * @return mnemonic for instruction
091         */
092        @Override
093        public String toString( boolean verbose ) {
094            return super.toString(verbose) + " " + index + " " + dimensions;
095        }
096    
097    
098        /**
099         * @return mnemonic for instruction with symbolic references resolved
100         */
101        @Override
102        public String toString( ConstantPool cp ) {
103            return super.toString(cp) + " " + dimensions;
104        }
105    
106    
107        /**
108         * Also works for instructions whose stack effect depends on the
109         * constant pool entry they reference.
110         * @return Number of words consumed from stack by this instruction
111         */
112        @Override
113        public int consumeStack( ConstantPoolGen cpg ) {
114            return dimensions;
115        }
116    
117    
118        public Class<?>[] getExceptions() {
119            Class<?>[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
120            System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
121                    ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
122            cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION;
123            cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
124            return cs;
125        }
126    
127    
128        public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
129            Type t = getType(cpg);
130            if (t instanceof ArrayType) {
131                t = ((ArrayType) t).getBasicType();
132            }
133            return (t instanceof ObjectType) ? (ObjectType) t : null;
134        }
135    
136    
137        /**
138         * Call corresponding visitor method(s). The order is:
139         * Call visitor methods of implemented interfaces first, then
140         * call methods according to the class hierarchy in descending order,
141         * i.e., the most specific visitXXX() call comes last.
142         *
143         * @param v Visitor object
144         */
145        @Override
146        public void accept( Visitor v ) {
147            v.visitLoadClass(this);
148            v.visitAllocationInstruction(this);
149            v.visitExceptionThrower(this);
150            v.visitTypedInstruction(this);
151            v.visitCPInstruction(this);
152            v.visitMULTIANEWARRAY(this);
153        }
154    }