emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Jan 2013 18:15:21 +0100
branchemul
changeset 604 3fcc279c921b
parent 555 cde0c2d7794e
child 666 8338ab1991e6
permissions -rw-r--r--
Making new clases (mostly java.io.Object*) compilable
     1 /**
     2  * Back 2 Browser Bytecode Translator
     3  * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://opensource.org/licenses/GPL-2.0.
    17  */
    18 package org.apidesign.bck2brwsr.emul.reflect;
    19 
    20 import java.lang.reflect.Method;
    21 import java.util.Enumeration;
    22 import org.apidesign.bck2brwsr.core.JavaScriptBody;
    23 
    24 /** Utilities to work on methods.
    25  *
    26  * @author Jaroslav Tulach <jtulach@netbeans.org>
    27  */
    28 public abstract class MethodImpl {
    29     public static MethodImpl INSTANCE;
    30     static {
    31         try {
    32             Class.forName(Method.class.getName());
    33         } catch (ClassNotFoundException ex) {
    34             throw new IllegalStateException(ex);
    35         }
    36     }
    37     
    38     protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
    39     
    40     
    41     //
    42     // bck2brwsr implementation
    43     //
    44 
    45     @JavaScriptBody(args = {"clazz", "prefix"},
    46         body = ""
    47         + "var c = clazz.cnstr.prototype;"
    48         + "var arr = new Array();\n"
    49         + "for (m in c) {\n"
    50         + "  if (m.indexOf(prefix) === 0) {\n"
    51         + "     arr.push(m);\n"
    52         + "     arr.push(c[m]);\n"
    53         + "  }"
    54         + "}\n"
    55         + "return arr;")
    56     private static native Object[] findMethodData(
    57         Class<?> clazz, String prefix);
    58 
    59     public static Method findMethod(
    60         Class<?> clazz, String name, Class<?>... parameterTypes) {
    61         Object[] data = findMethodData(clazz, name + "__");
    62         BIG: for (int i = 0; i < data.length; i += 2) {
    63             String sig = ((String) data[0]).substring(name.length() + 2);
    64             Method tmp = INSTANCE.create(clazz, name, data[1], sig);
    65             Class<?>[] tmpParms = tmp.getParameterTypes();
    66             if (parameterTypes.length != tmpParms.length) {
    67                 continue;
    68             }
    69             for (int j = 0; j < tmpParms.length; j++) {
    70                 if (!parameterTypes[j].equals(tmpParms[j])) {
    71                     continue BIG;
    72                 }
    73             }
    74             return tmp;
    75         }
    76         return null;
    77     }
    78 
    79     public static Method[] findMethods(Class<?> clazz, int mask) {
    80         Object[] namesAndData = findMethodData(clazz, "");
    81         int cnt = 0;
    82         for (int i = 0; i < namesAndData.length; i += 2) {
    83             String sig = (String) namesAndData[i];
    84             Object data = namesAndData[i + 1];
    85             int middle = sig.indexOf("__");
    86             if (middle == -1) {
    87                 continue;
    88             }
    89             String name = sig.substring(0, middle);
    90             sig = sig.substring(middle + 2);
    91             final Method m = INSTANCE.create(clazz, name, data, sig);
    92             if ((m.getModifiers() & mask) == 0) {
    93                 continue;
    94             }
    95             namesAndData[cnt++] = m;
    96         }
    97         Method[] arr = new Method[cnt];
    98         for (int i = 0; i < cnt; i++) {
    99             arr[i] = (Method) namesAndData[i];
   100         }
   101         return arr;
   102     }
   103 
   104     public static int signatureElements(String sig) {
   105         Enumeration<Class> en = signatureParser(sig);
   106         int cnt = 0;
   107         while (en.hasMoreElements()) {
   108             en.nextElement();
   109             cnt++;
   110         }
   111         return cnt;
   112     }
   113     
   114     public static Enumeration<Class> signatureParser(final String sig) {
   115         class E implements Enumeration<Class> {
   116             int pos;
   117             
   118             public boolean hasMoreElements() {
   119                 return pos < sig.length();
   120             }
   121 
   122             public Class nextElement() {
   123                 switch (sig.charAt(pos++)) {
   124                     case 'I':
   125                         return Integer.TYPE;
   126                     case 'J':
   127                         return Long.TYPE;
   128                     case 'D':
   129                         return Double.TYPE;
   130                     case 'F':
   131                         return Float.TYPE;
   132                     case 'B':
   133                         return Byte.TYPE;
   134                     case 'Z':
   135                         return Boolean.TYPE;
   136                     case 'S':
   137                         return Short.TYPE;
   138                     case 'V':
   139                         return Void.TYPE;
   140                     case 'C':
   141                         return Character.TYPE;
   142                     case 'L':
   143                         try {
   144                             int up = sig.indexOf("_2");
   145                             String type = sig.substring(1, up);
   146                             pos = up + 2;
   147                             return Class.forName(type);
   148                         } catch (ClassNotFoundException ex) {
   149                             // should not happen
   150                         }
   151                 }
   152                 throw new UnsupportedOperationException(sig + " at " + pos);
   153             }
   154         }
   155         return new E();
   156     }
   157 }