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