Save This Page
Home » javassist-sources » javassist » bytecode » [javadoc | source]
    1   /*
    2    * Javassist, a Java-bytecode translator toolkit.
    3    * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
    4    *
    5    * The contents of this file are subject to the Mozilla Public License Version
    6    * 1.1 (the "License"); you may not use this file except in compliance with
    7    * the License.  Alternatively, the contents of this file may be used under
    8    * the terms of the GNU Lesser General Public License Version 2.1 or later.
    9    *
   10    * Software distributed under the License is distributed on an "AS IS" basis,
   11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   12    * for the specific language governing rights and limitations under the
   13    * License.
   14    */
   15   
   16   package javassist.bytecode;
   17   
   18   import javassist.ClassPool;
   19   import javassist.CtClass;
   20   import javassist.CtPrimitiveType;
   21   import javassist.NotFoundException;
   22   import java.util.Map;
   23   
   24   /**
   25    * A support class for dealing with descriptors.
   26    *
   27    * <p>See chapter 4.3 in "The Java Virtual Machine Specification (2nd ed.)"
   28    */
   29   public class Descriptor {
   30       /**
   31        * Converts a class name into the internal representation used in
   32        * the JVM.
   33        *
   34        * <p>Note that <code>toJvmName(toJvmName(s))</code> is equivalent
   35        * to <code>toJvmName(s)</code>.
   36        */
   37       public static String toJvmName(String classname) {
   38           return classname.replace('.', '/');
   39       }
   40   
   41       /**
   42        * Converts a class name from the internal representation used in
   43        * the JVM to the normal one used in Java.
   44        * This method does not deal with an array type name such as
   45        * "[Ljava/lang/Object;" and "[I;".  For such names, use
   46        * <code>toClassName()</code>.
   47        *
   48        * @see #toClassName(String)
   49        */
   50       public static String toJavaName(String classname) {
   51           return classname.replace('/', '.');
   52       }
   53   
   54       /**
   55        * Returns the internal representation of the class name in the
   56        * JVM.
   57        */
   58       public static String toJvmName(CtClass clazz) {
   59           if (clazz.isArray())
   60               return of(clazz);
   61           else
   62               return toJvmName(clazz.getName());
   63       }
   64   
   65       /**
   66        * Converts to a Java class name from a descriptor.
   67        *
   68        * @param descriptor        type descriptor.
   69        */
   70       public static String toClassName(String descriptor) {
   71           int arrayDim = 0;
   72           int i = 0;
   73           char c = descriptor.charAt(0);
   74           while (c == '[') {
   75               ++arrayDim;
   76               c = descriptor.charAt(++i);
   77           }
   78   
   79           String name;
   80           if (c == 'L') {
   81               int i2 = descriptor.indexOf(';', i++);
   82               name = descriptor.substring(i, i2).replace('/', '.');
   83               i = i2;
   84           }
   85           else if (c == 'V')
   86               name =  "void";
   87           else if (c == 'I')
   88               name = "int";
   89           else if (c == 'B')
   90               name = "byte";
   91           else if (c == 'J')
   92               name = "long";
   93           else if (c == 'D')
   94               name = "double";
   95           else if (c == 'F')
   96               name = "float";
   97           else if (c == 'C')
   98               name = "char";
   99           else if (c == 'S')
  100               name = "short";
  101           else if (c == 'Z')
  102               name = "boolean";
  103           else
  104               throw new RuntimeException("bad descriptor: " + descriptor);
  105   
  106           if (i + 1 != descriptor.length())
  107               throw new RuntimeException("multiple descriptors?: " + descriptor);
  108   
  109           if (arrayDim == 0)
  110               return name;
  111           else {
  112               StringBuffer sbuf = new StringBuffer(name);
  113               do {
  114                   sbuf.append("[]");
  115               } while (--arrayDim > 0);
  116   
  117               return sbuf.toString();
  118           }
  119       }
  120   
  121       /**
  122        * Converts to a descriptor from a Java class name
  123        */
  124       public static String of(String classname) {
  125           if (classname.equals("void"))
  126               return "V";
  127           else if (classname.equals("int"))
  128               return "I";
  129           else if (classname.equals("byte"))
  130               return "B";
  131           else if (classname.equals("long"))
  132               return "J";
  133           else if (classname.equals("double"))
  134               return "D";
  135           else if (classname.equals("float"))
  136               return "F";
  137           else if (classname.equals("char"))
  138               return "C";
  139           else if (classname.equals("short"))
  140               return "S";
  141           else if (classname.equals("boolean"))
  142               return "Z";
  143           else
  144               return "L" + toJvmName(classname) + ";";
  145       }
  146   
  147       /**
  148        * Substitutes a class name
  149        * in the given descriptor string.
  150        *
  151        * @param desc    descriptor string
  152        * @param oldname replaced JVM class name
  153        * @param newname substituted JVM class name
  154        *
  155        * @see Descriptor#toJvmName(String)
  156        */
  157       public static String rename(String desc, String oldname, String newname) {
  158           if (desc.indexOf(oldname) < 0)
  159               return desc;
  160   
  161           StringBuffer newdesc = new StringBuffer();
  162           int head = 0;
  163           int i = 0;
  164           for (;;) {
  165               int j = desc.indexOf('L', i);
  166               if (j < 0)
  167                   break;
  168               else if (desc.startsWith(oldname, j + 1)
  169                        && desc.charAt(j + oldname.length() + 1) == ';') {
  170                   newdesc.append(desc.substring(head, j));
  171                   newdesc.append('L');
  172                   newdesc.append(newname);
  173                   newdesc.append(';');
  174                   head = i = j + oldname.length() + 2;
  175               }
  176               else {
  177                   i = desc.indexOf(';', j) + 1;
  178                   if (i < 1)
  179                       break; // ';' was not found.
  180               }
  181           }
  182   
  183           if (head == 0)
  184               return desc;
  185           else {
  186               int len = desc.length();
  187               if (head < len)
  188                   newdesc.append(desc.substring(head, len));
  189   
  190               return newdesc.toString();
  191           }
  192       }
  193   
  194       /**
  195        * Substitutes class names in the given descriptor string
  196        * according to the given <code>map</code>.
  197        *
  198        * @param map a map between replaced and substituted
  199        *            JVM class names.
  200        * @see Descriptor#toJvmName(String)
  201        */
  202       public static String rename(String desc, Map map) {
  203           if (map == null)
  204               return desc;
  205   
  206           StringBuffer newdesc = new StringBuffer();
  207           int head = 0;
  208           int i = 0;
  209           for (;;) {
  210               int j = desc.indexOf('L', i);
  211               if (j < 0)
  212                   break;
  213   
  214               int k = desc.indexOf(';', j);
  215               if (k < 0)
  216                   break;
  217   
  218               i = k + 1;
  219               String name = desc.substring(j + 1, k);
  220               String name2 = (String)map.get(name);
  221               if (name2 != null) {
  222                   newdesc.append(desc.substring(head, j));
  223                   newdesc.append('L');
  224                   newdesc.append(name2);
  225                   newdesc.append(';');
  226                   head = i;
  227               }
  228           }
  229   
  230           if (head == 0)
  231               return desc;
  232           else {
  233               int len = desc.length();
  234               if (head < len)
  235                   newdesc.append(desc.substring(head, len));
  236   
  237               return newdesc.toString();
  238           }
  239       }
  240   
  241       /**
  242        * Returns the descriptor representing the given type.
  243        */
  244       public static String of(CtClass type) {
  245           StringBuffer sbuf = new StringBuffer();
  246           toDescriptor(sbuf, type);
  247           return sbuf.toString();
  248       }
  249   
  250       private static void toDescriptor(StringBuffer desc, CtClass type) {
  251           if (type.isArray()) {
  252               desc.append('[');
  253               try {
  254                   toDescriptor(desc, type.getComponentType());
  255               }
  256               catch (NotFoundException e) {
  257                   desc.append('L');
  258                   String name = type.getName();
  259                   desc.append(toJvmName(name.substring(0, name.length() - 2)));
  260                   desc.append(';');
  261               }
  262           }
  263           else if (type.isPrimitive()) {
  264               CtPrimitiveType pt = (CtPrimitiveType)type;
  265               desc.append(pt.getDescriptor());
  266           }
  267           else { // class type
  268               desc.append('L');
  269               desc.append(type.getName().replace('.', '/'));
  270               desc.append(';');
  271           }
  272       }
  273   
  274       /**
  275        * Returns the descriptor representing a constructor receiving
  276        * the given parameter types.
  277        *
  278        * @param paramTypes parameter types
  279        */
  280       public static String ofConstructor(CtClass[] paramTypes) {
  281           return ofMethod(CtClass.voidType, paramTypes);
  282       }
  283   
  284       /**
  285        * Returns the descriptor representing a method that receives
  286        * the given parameter types and returns the given type.
  287        *
  288        * @param returnType return type
  289        * @param paramTypes parameter types
  290        */
  291       public static String ofMethod(CtClass returnType, CtClass[] paramTypes) {
  292           StringBuffer desc = new StringBuffer();
  293           desc.append('(');
  294           if (paramTypes != null) {
  295               int n = paramTypes.length;
  296               for (int i = 0; i < n; ++i)
  297                   toDescriptor(desc, paramTypes[i]);
  298           }
  299   
  300           desc.append(')');
  301           if (returnType != null)
  302               toDescriptor(desc, returnType);
  303   
  304           return desc.toString();
  305       }
  306   
  307       /**
  308        * Returns the descriptor representing a list of parameter types.
  309        * For example, if the given parameter types are two <code>int</code>,
  310        * then this method returns <code>"(II)"</code>.
  311        *
  312        * @param paramTypes parameter types
  313        */
  314       public static String ofParameters(CtClass[] paramTypes) {
  315           return ofMethod(null, paramTypes);
  316       }
  317   
  318       /**
  319        * Appends a parameter type to the parameter list represented
  320        * by the given descriptor.
  321        *
  322        * <p><code>classname</code> must not be an array type.
  323        *
  324        * @param classname parameter type (not primitive type)
  325        * @param desc      descriptor
  326        */
  327       public static String appendParameter(String classname, String desc) {
  328           int i = desc.indexOf(')');
  329           if (i < 0)
  330               return desc;
  331           else {
  332               StringBuffer newdesc = new StringBuffer();
  333               newdesc.append(desc.substring(0, i));
  334               newdesc.append('L');
  335               newdesc.append(classname.replace('.', '/'));
  336               newdesc.append(';');
  337               newdesc.append(desc.substring(i));
  338               return newdesc.toString();
  339           }
  340       }
  341   
  342       /**
  343        * Inserts a parameter type at the beginning of the parameter
  344        * list represented
  345        * by the given descriptor.
  346        *
  347        * <p><code>classname</code> must not be an array type.
  348        *
  349        * @param classname parameter type (not primitive type)
  350        * @param desc      descriptor
  351        */
  352       public static String insertParameter(String classname, String desc) {
  353           if (desc.charAt(0) != '(')
  354               return desc;
  355           else
  356               return "(L" + classname.replace('.', '/') + ';'
  357                      + desc.substring(1);
  358       }
  359   
  360       /**
  361        * Appends a parameter type to the parameter list represented
  362        * by the given descriptor.  The appended parameter becomes
  363        * the last parameter.
  364        *
  365        * @param type      the type of the appended parameter.
  366        * @param descriptor      the original descriptor.
  367        */
  368       public static String appendParameter(CtClass type, String descriptor) {
  369           int i = descriptor.indexOf(')');
  370           if (i < 0)
  371               return descriptor;
  372           else {
  373               StringBuffer newdesc = new StringBuffer();
  374               newdesc.append(descriptor.substring(0, i));
  375               toDescriptor(newdesc, type);
  376               newdesc.append(descriptor.substring(i));
  377               return newdesc.toString();
  378           }
  379       }
  380   
  381       /**
  382        * Inserts a parameter type at the beginning of the parameter
  383        * list represented
  384        * by the given descriptor.
  385        *
  386        * @param type              the type of the inserted parameter.
  387        * @param descriptor        the descriptor of the method.
  388        */
  389       public static String insertParameter(CtClass type,
  390                                            String descriptor) {
  391           if (descriptor.charAt(0) != '(')
  392               return descriptor;
  393           else
  394               return "(" + of(type) + descriptor.substring(1);
  395       }
  396   
  397       /**
  398        * Changes the return type included in the given descriptor.
  399        *
  400        * <p><code>classname</code> must not be an array type.
  401        *
  402        * @param classname return type
  403        * @param desc      descriptor
  404        */
  405       public static String changeReturnType(String classname, String desc) {
  406           int i = desc.indexOf(')');
  407           if (i < 0)
  408               return desc;
  409           else {
  410               StringBuffer newdesc = new StringBuffer();
  411               newdesc.append(desc.substring(0, i + 1));
  412               newdesc.append('L');
  413               newdesc.append(classname.replace('.', '/'));
  414               newdesc.append(';');
  415               return newdesc.toString();
  416           }
  417       }
  418   
  419       /**
  420        * Returns the <code>CtClass</code> objects representing the parameter
  421        * types specified by the given descriptor.
  422        *
  423        * @param desc descriptor
  424        * @param cp   the class pool used for obtaining
  425        *             a <code>CtClass</code> object.
  426        */
  427       public static CtClass[] getParameterTypes(String desc, ClassPool cp)
  428           throws NotFoundException
  429       {
  430           if (desc.charAt(0) != '(')
  431               return null;
  432           else {
  433               int num = numOfParameters(desc);
  434               CtClass[] args = new CtClass[num];
  435               int n = 0;
  436               int i = 1;
  437               do {
  438                   i = toCtClass(cp, desc, i, args, n++);
  439               } while (i > 0);
  440               return args;
  441           }
  442       }
  443   
  444       /**
  445        * Returns true if the list of the parameter types of desc1 is equal to
  446        * that of desc2.
  447        * For example, "(II)V" and "(II)I" are equal.
  448        */
  449       public static boolean eqParamTypes(String desc1, String desc2) {
  450           if (desc1.charAt(0) != '(')
  451               return false;
  452   
  453           for (int i = 0; true; ++i) {
  454               char c = desc1.charAt(i);
  455               if (c != desc2.charAt(i))
  456                   return false;
  457   
  458               if (c == ')')
  459                   return true;
  460           }
  461       }
  462   
  463       /**
  464        * Returns the signature of the given descriptor.  The signature does
  465        * not include the return type.  For example, the signature of "(I)V"
  466        * is "(I)".
  467        */
  468       public static String getParamDescriptor(String decl) {
  469           return decl.substring(0, decl.indexOf(')') + 1);
  470       }
  471   
  472       /**
  473        * Returns the <code>CtClass</code> object representing the return
  474        * type specified by the given descriptor.
  475        *
  476        * @param desc descriptor
  477        * @param cp   the class pool used for obtaining
  478        *             a <code>CtClass</code> object.
  479        */
  480       public static CtClass getReturnType(String desc, ClassPool cp)
  481           throws NotFoundException
  482       {
  483           int i = desc.indexOf(')');
  484           if (i < 0)
  485               return null;
  486           else {
  487               CtClass[] type = new CtClass[1];
  488               toCtClass(cp, desc, i + 1, type, 0);
  489               return type[0];
  490           }
  491       }
  492   
  493       /**
  494        * Returns the number of the prameters included in the given
  495        * descriptor.
  496        *
  497        * @param desc descriptor
  498        */
  499       public static int numOfParameters(String desc) {
  500           int n = 0;
  501           int i = 1;
  502           for (;;) {
  503               char c = desc.charAt(i);
  504               if (c == ')')
  505                   break;
  506   
  507               while (c == '[')
  508                   c = desc.charAt(++i);
  509   
  510               if (c == 'L') {
  511                   i = desc.indexOf(';', i) + 1;
  512                   if (i <= 0)
  513                       throw new IndexOutOfBoundsException("bad descriptor");
  514               }
  515               else
  516                   ++i;
  517   
  518               ++n;
  519           }
  520   
  521           return n;
  522       }
  523   
  524       /**
  525        * Returns a <code>CtClass</code> object representing the type
  526        * specified by the given descriptor.
  527        *
  528        * <p>This method works even if the package-class separator is
  529        * not <code>/</code> but <code>.</code> (period).  For example,
  530        * it accepts <code>Ljava.lang.Object;</code>
  531        * as well as <code>Ljava/lang/Object;</code>.
  532        *
  533        * @param desc descriptor.
  534        * @param cp   the class pool used for obtaining
  535        *             a <code>CtClass</code> object.
  536        */
  537       public static CtClass toCtClass(String desc, ClassPool cp)
  538           throws NotFoundException
  539       {
  540           CtClass[] clazz = new CtClass[1];
  541           int res = toCtClass(cp, desc, 0, clazz, 0);
  542           if (res >= 0)
  543               return clazz[0];
  544           else {
  545               // maybe, you forgot to surround the class name with
  546               // L and ;.  It violates the protocol, but I'm tolerant...
  547               return cp.get(desc.replace('/', '.'));
  548           }
  549       }
  550   
  551       private static int toCtClass(ClassPool cp, String desc, int i,
  552                                    CtClass[] args, int n)
  553           throws NotFoundException
  554       {
  555           int i2;
  556           String name;
  557   
  558           int arrayDim = 0;
  559           char c = desc.charAt(i);
  560           while (c == '[') {
  561               ++arrayDim;
  562               c = desc.charAt(++i);
  563           }
  564   
  565           if (c == 'L') {
  566               i2 = desc.indexOf(';', ++i);
  567               name = desc.substring(i, i2++).replace('/', '.');
  568           }
  569           else {
  570               CtClass type = toPrimitiveClass(c);
  571               if (type == null)
  572                   return -1; // error
  573   
  574               i2 = i + 1;
  575               if (arrayDim == 0) {
  576                   args[n] = type;
  577                   return i2; // neither an array type or a class type
  578               }
  579               else
  580                   name = type.getName();
  581           }
  582   
  583           if (arrayDim > 0) {
  584               StringBuffer sbuf = new StringBuffer(name);
  585               while (arrayDim-- > 0)
  586                   sbuf.append("[]");
  587   
  588               name = sbuf.toString();
  589           }
  590   
  591           args[n] = cp.get(name);
  592           return i2;
  593       }
  594   
  595       static CtClass toPrimitiveClass(char c) {
  596           CtClass type = null;
  597           switch (c) {
  598           case 'Z' :
  599               type = CtClass.booleanType;
  600               break;
  601           case 'C' :
  602               type = CtClass.charType;
  603               break;
  604           case 'B' :
  605               type = CtClass.byteType;
  606               break;
  607           case 'S' :
  608               type = CtClass.shortType;
  609               break;
  610           case 'I' :
  611               type = CtClass.intType;
  612               break;
  613           case 'J' :
  614               type = CtClass.longType;
  615               break;
  616           case 'F' :
  617               type = CtClass.floatType;
  618               break;
  619           case 'D' :
  620               type = CtClass.doubleType;
  621               break;
  622           case 'V' :
  623               type = CtClass.voidType;
  624               break;
  625           }
  626   
  627           return type;
  628       }
  629   
  630       /**
  631        * Computes the dimension of the array represented by the given
  632        * descriptor.  For example, if the descriptor is <code>"[[I"</code>,
  633        * then this method returns 2.
  634        *
  635        * @param desc the descriptor.
  636        * @return 0        if the descriptor does not represent an array type.
  637        */
  638       public static int arrayDimension(String desc) {
  639           int dim = 0;
  640           while (desc.charAt(dim) == '[')
  641               ++dim;
  642   
  643           return dim;
  644       }
  645   
  646       /**
  647        * Returns the descriptor of the type of the array component.
  648        * For example, if the given descriptor is
  649        * <code>"[[Ljava/lang/String;"</code> and the given dimension is 2,
  650        * then this method returns <code>"Ljava/lang/String;"</code>.
  651        *
  652        * @param desc the descriptor.
  653        * @param dim  the array dimension.
  654        */
  655       public static String toArrayComponent(String desc, int dim) {
  656           return desc.substring(dim);
  657       }
  658   
  659       /**
  660        * Computes the data size specified by the given descriptor.
  661        * For example, if the descriptor is "D", this method returns 2.
  662        *
  663        * <p>If the descriptor represents a method type, this method returns
  664        * (the size of the returned value) - (the sum of the data sizes
  665        * of all the parameters).  For example, if the descriptor is
  666        * <code>"(I)D"</code>, then this method returns 1 (= 2 - 1).
  667        *
  668        * @param desc descriptor
  669        */
  670       public static int dataSize(String desc) {
  671           return dataSize(desc, true);
  672       }
  673   
  674       /**
  675        * Computes the data size of parameters.
  676        * If one of the parameters is double type, the size of that parameter
  677        * is 2 words.  For example, if the given descriptor is
  678        *  <code>"(IJ)D"</code>, then this method returns 3.  The size of the
  679        * return type is not computed.
  680        * 
  681        * @param desc      a method descriptor.
  682        */
  683       public static int paramSize(String desc) {
  684           return -dataSize(desc, false);
  685       }
  686   
  687       private static int dataSize(String desc, boolean withRet) {
  688           int n = 0;
  689           char c = desc.charAt(0);
  690           if (c == '(') {
  691               int i = 1;
  692               for (;;) {
  693                   c = desc.charAt(i);
  694                   if (c == ')') {
  695                       c = desc.charAt(i + 1);
  696                       break;
  697                   }
  698   
  699                   boolean array = false;
  700                   while (c == '[') {
  701                       array = true;
  702                       c = desc.charAt(++i);
  703                   }
  704   
  705                   if (c == 'L') {
  706                       i = desc.indexOf(';', i) + 1;
  707                       if (i <= 0)
  708                           throw new IndexOutOfBoundsException("bad descriptor");
  709                   }
  710                   else
  711                       ++i;
  712   
  713                   if (!array && (c == 'J' || c == 'D'))
  714                       n -= 2;
  715                   else
  716                       --n;
  717               }
  718           }
  719   
  720           if (withRet)
  721               if (c == 'J' || c == 'D')
  722                   n += 2;
  723               else if (c != 'V')
  724                   ++n;
  725   
  726           return n;
  727       }
  728   
  729       /**
  730        * Returns a human-readable representation of the
  731        * given descriptor.  For example, <code>Ljava/lang/Object;</code>
  732        * is converted into <code>java.lang.Object</code>.
  733        * <code>(I[I)V</code> is converted into <code>(int, int[])</code>
  734        * (the return type is ignored). 
  735        */
  736       public static String toString(String desc) {
  737           return PrettyPrinter.toString(desc);
  738       }
  739   
  740       static class PrettyPrinter {
  741           static String toString(String desc) {
  742               StringBuffer sbuf = new StringBuffer();
  743               if (desc.charAt(0) == '(') {
  744                   int pos = 1;
  745                   sbuf.append('(');
  746                   while (desc.charAt(pos) != ')') {
  747                       if (pos > 1)
  748                           sbuf.append(',');
  749   
  750                       pos = readType(sbuf, pos, desc);
  751                   }
  752   
  753                   sbuf.append(')');
  754               }
  755               else
  756                   readType(sbuf, 0, desc);
  757   
  758               return sbuf.toString();
  759           }
  760   
  761           static int readType(StringBuffer sbuf, int pos, String desc) {
  762               char c = desc.charAt(pos);
  763               int arrayDim = 0;
  764               while (c == '[') {
  765                   arrayDim++;
  766                   c = desc.charAt(++pos);
  767               }
  768   
  769               if (c == 'L')
  770                   while (true) {
  771                       c = desc.charAt(++pos);
  772                       if (c == ';')
  773                           break;
  774   
  775                       if (c == '/')
  776                           c = '.';
  777   
  778                       sbuf.append(c);
  779                   }
  780               else {
  781                   CtClass t = toPrimitiveClass(c);
  782                   sbuf.append(t.getName());
  783               }
  784   
  785               while (arrayDim-- > 0)
  786                   sbuf.append("[]");
  787   
  788               return pos + 1;
  789           }
  790       }
  791   
  792       /**
  793        * An Iterator over a descriptor.
  794        */
  795       public static class Iterator {
  796           private String desc;
  797           private int index, curPos;
  798           private boolean param;
  799   
  800           /**
  801            * Constructs an iterator.
  802            *
  803            * @param s         descriptor.
  804            */
  805           public Iterator(String s) {
  806               desc = s;
  807               index = curPos = 0;
  808               param = false;
  809           }
  810   
  811           /**
  812            * Returns true if the iteration has more elements.
  813            */
  814           public boolean hasNext() {
  815               return index < desc.length();
  816           }
  817   
  818           /**
  819            * Returns true if the current element is a parameter type.
  820            */
  821           public boolean isParameter() { return param; }
  822   
  823           /**
  824            * Returns the first character of the current element.
  825            */
  826           public char currentChar() { return desc.charAt(curPos); }
  827   
  828           /**
  829            * Returns true if the current element is double or long type.
  830            */
  831           public boolean is2byte() {
  832               char c = currentChar();
  833               return c == 'D' || c == 'J';
  834           }
  835   
  836           /**
  837            * Returns the position of the next type character.
  838            * That type character becomes a new current element.
  839            */
  840           public int next() {
  841               int nextPos = index;
  842               char c = desc.charAt(nextPos);
  843               if (c == '(') {
  844                   ++index;
  845                   c = desc.charAt(++nextPos);
  846                   param = true;
  847               }
  848   
  849               if (c == ')') {
  850                   ++index;
  851                   c = desc.charAt(++nextPos);
  852                   param = false;
  853               }
  854   
  855               while (c == '[')
  856                   c = desc.charAt(++nextPos);
  857   
  858               if (c == 'L') {
  859                   nextPos = desc.indexOf(';', nextPos) + 1;
  860                   if (nextPos <= 0)
  861                       throw new IndexOutOfBoundsException("bad descriptor");
  862               }
  863               else
  864                   ++nextPos;
  865   
  866               curPos = index;
  867               index = nextPos;
  868               return curPos;
  869           }
  870       }
  871   }

Save This Page
Home » javassist-sources » javassist » bytecode » [javadoc | source]