1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 import java.io.*;
  25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  26 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
  27 import com.sun.org.apache.bcel.internal.ExceptionConstants;
  28 
  29 /**
  30  * MULTIANEWARRAY - Create new mutidimensional array of references
  31  * <PRE>Stack: ..., count1, [count2, ...] -&gt; ..., arrayref</PRE>
  32  *
  33  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  34  */
  35 public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, ExceptionThrower {
  36   private short dimensions;
  37 
  38   /**
  39    * Empty constructor needed for the Class.newInstance() statement in
  40    * Instruction.readInstruction(). Not to be used otherwise.
  41    */
  42   MULTIANEWARRAY() {}
  43 
  44   public MULTIANEWARRAY(int index, short dimensions) {
  45     super(com.sun.org.apache.bcel.internal.Constants.MULTIANEWARRAY, index);
  46 
  47     if(dimensions < 1)
  48       throw new ClassGenException("Invalid dimensions value: " + dimensions);
  49 
  50     this.dimensions = dimensions;
  51     length = 4;
  52   }
  53 
  54   /**
  55    * Dump instruction as byte code to stream out.
  56    * @param out Output stream
  57    */
  58   public void dump(DataOutputStream out) throws IOException {
  59     out.writeByte(opcode);
  60     out.writeShort(index);
  61     out.writeByte(dimensions);
  62   }
  63 
  64   /**
  65    * Read needed data (i.e., no. dimension) from file.
  66    */
  67   protected void initFromFile(ByteSequence bytes, boolean wide)
  68        throws IOException
  69   {
  70     super.initFromFile(bytes, wide);
  71     dimensions = bytes.readByte();
  72     length     = 4;
  73   }
  74 
  75   /**
  76    * @return number of dimensions to be created
  77    */
  78   public final short getDimensions() { return dimensions; }
  79 
  80   /**
  81    * @return mnemonic for instruction
  82    */
  83   public String toString(boolean verbose) {
  84     return super.toString(verbose) + " " + index + " " + dimensions;
  85   }
  86 
  87   /**
  88    * @return mnemonic for instruction with symbolic references resolved
  89    */
  90   public String toString(ConstantPool cp) {
  91     return super.toString(cp) + " " + dimensions;
  92   }
  93 
  94   /**
  95    * Also works for instructions whose stack effect depends on the
  96    * constant pool entry they reference.
  97    * @return Number of words consumed from stack by this instruction
  98    */
  99   public int consumeStack(ConstantPoolGen cpg) { return dimensions; }
 100 
 101   public Class[] getExceptions() {
 102     Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
 103 
 104     System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0,
 105                      cs, 0, ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
 106 
 107     cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length+1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION;
 108     cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]   = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
 109 
 110     return cs;
 111   }
 112 
 113   public ObjectType getLoadClassType(ConstantPoolGen cpg) {
 114     Type t = getType(cpg);
 115 
 116     if (t instanceof ArrayType){
 117       t = ((ArrayType) t).getBasicType();
 118     }
 119 
 120     return (t instanceof ObjectType)? (ObjectType) t : null;
 121   }
 122 
 123   /**
 124    * Call corresponding visitor method(s). The order is:
 125    * Call visitor methods of implemented interfaces first, then
 126    * call methods according to the class hierarchy in descending order,
 127    * i.e., the most specific visitXXX() call comes last.
 128    *
 129    * @param v Visitor object
 130    */
 131   public void accept(Visitor v) {
 132     v.visitLoadClass(this);
 133     v.visitAllocationInstruction(this);
 134     v.visitExceptionThrower(this);
 135     v.visitTypedInstruction(this);
 136     v.visitCPInstruction(this);
 137     v.visitMULTIANEWARRAY(this);
 138   }
 139 }