Home | History | Annotate | Download | only in commons
      1 /***
      2  * ASM: a very small and fast Java bytecode manipulation framework
      3  * Copyright (c) 2000-2005 INRIA, France Telecom
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the copyright holders nor the names of its
     15  *    contributors may be used to endorse or promote products derived from
     16  *    this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 package org.objectweb.asm.commons;
     31 
     32 import java.util.HashMap;
     33 import java.util.Map;
     34 
     35 import org.objectweb.asm.Type;
     36 
     37 /**
     38  * A named method descriptor.
     39  *
     40  * @author Juozas Baliuka
     41  * @author Chris Nokleberg
     42  * @author Eric Bruneton
     43  */
     44 public class Method {
     45 
     46     /**
     47      * The method name.
     48      */
     49     private final String name;
     50 
     51     /**
     52      * The method descriptor.
     53      */
     54     private final String desc;
     55 
     56     /**
     57      * Maps primitive Java type names to their descriptors.
     58      */
     59     private final static Map DESCRIPTORS;
     60 
     61     static {
     62         DESCRIPTORS = new HashMap();
     63         DESCRIPTORS.put("void", "V");
     64         DESCRIPTORS.put("byte", "B");
     65         DESCRIPTORS.put("char", "C");
     66         DESCRIPTORS.put("double", "D");
     67         DESCRIPTORS.put("float", "F");
     68         DESCRIPTORS.put("int", "I");
     69         DESCRIPTORS.put("long", "J");
     70         DESCRIPTORS.put("short", "S");
     71         DESCRIPTORS.put("boolean", "Z");
     72     }
     73 
     74     /**
     75      * Creates a new {@link Method}.
     76      *
     77      * @param name the method's name.
     78      * @param desc the method's descriptor.
     79      */
     80     public Method(final String name, final String desc) {
     81         this.name = name;
     82         this.desc = desc;
     83     }
     84 
     85     /**
     86      * Creates a new {@link Method}.
     87      *
     88      * @param name the method's name.
     89      * @param returnType the method's return type.
     90      * @param argumentTypes the method's argument types.
     91      */
     92     public Method(
     93         final String name,
     94         final Type returnType,
     95         final Type[] argumentTypes)
     96     {
     97         this(name, Type.getMethodDescriptor(returnType, argumentTypes));
     98     }
     99 
    100     /**
    101      * Returns a {@link Method} corresponding to the given Java method
    102      * declaration.
    103      *
    104      * @param method a Java method declaration, without argument names, of the
    105      *        form "returnType name (argumentType1, ... argumentTypeN)", where
    106      *        the types are in plain Java (e.g. "int", "float",
    107      *        "java.util.List", ...).
    108      * @return a {@link Method} corresponding to the given Java method
    109      *         declaration.
    110      * @throws IllegalArgumentException if <code>method</code> could not get
    111      *         parsed.
    112      */
    113     public static Method getMethod(final String method)
    114             throws IllegalArgumentException
    115     {
    116         int space = method.indexOf(' ');
    117         int start = method.indexOf('(', space) + 1;
    118         int end = method.indexOf(')', start);
    119         if (space == -1 || start == -1 || end == -1) {
    120             throw new IllegalArgumentException();
    121         }
    122         // TODO: Check validity of returnType, methodName and arguments.
    123         String returnType = method.substring(0, space);
    124         String methodName = method.substring(space + 1, start - 1).trim();
    125         StringBuffer sb = new StringBuffer();
    126         sb.append('(');
    127         int p;
    128         do {
    129             p = method.indexOf(',', start);
    130             if (p == -1) {
    131                 sb.append(map(method.substring(start, end).trim()));
    132             } else {
    133                 sb.append(map(method.substring(start, p).trim()));
    134                 start = p + 1;
    135             }
    136         } while (p != -1);
    137         sb.append(')');
    138         sb.append(map(returnType));
    139         return new Method(methodName, sb.toString());
    140     }
    141 
    142     private static String map(final String type) {
    143         if (type.equals("")) {
    144             return type;
    145         }
    146 
    147         StringBuffer sb = new StringBuffer();
    148         int index = 0;
    149         while ((index = type.indexOf("[]", index) + 1) > 0) {
    150             sb.append('[');
    151         }
    152 
    153         String t = type.substring(0, type.length() - sb.length() * 2);
    154         String desc = (String) DESCRIPTORS.get(t);
    155         if (desc != null) {
    156             sb.append(desc);
    157         } else {
    158             sb.append('L');
    159             if (t.indexOf('.') < 0) {
    160                 sb.append("java/lang/" + t);
    161             } else {
    162                 sb.append(t.replace('.', '/'));
    163             }
    164             sb.append(';');
    165         }
    166         return sb.toString();
    167     }
    168 
    169     /**
    170      * Returns the name of the method described by this object.
    171      *
    172      * @return the name of the method described by this object.
    173      */
    174     public String getName() {
    175         return name;
    176     }
    177 
    178     /**
    179      * Returns the descriptor of the method described by this object.
    180      *
    181      * @return the descriptor of the method described by this object.
    182      */
    183     public String getDescriptor() {
    184         return desc;
    185     }
    186 
    187     /**
    188      * Returns the return type of the method described by this object.
    189      *
    190      * @return the return type of the method described by this object.
    191      */
    192     public Type getReturnType() {
    193         return Type.getReturnType(desc);
    194     }
    195 
    196     /**
    197      * Returns the argument types of the method described by this object.
    198      *
    199      * @return the argument types of the method described by this object.
    200      */
    201     public Type[] getArgumentTypes() {
    202         return Type.getArgumentTypes(desc);
    203     }
    204 
    205     public String toString() {
    206         return name + desc;
    207     }
    208 
    209     public boolean equals(final Object o) {
    210         if (!(o instanceof Method)) {
    211             return false;
    212         }
    213         Method other = (Method) o;
    214         return name.equals(other.name) && desc.equals(other.desc);
    215     }
    216 
    217     public int hashCode() {
    218         return name.hashCode() ^ desc.hashCode();
    219     }
    220 }