2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
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.
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.
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.
18 package org.apidesign.bck2brwsr.emul.reflect;
20 import java.lang.reflect.Array;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.Method;
23 import java.util.Enumeration;
24 import org.apidesign.bck2brwsr.core.Exported;
25 import org.apidesign.bck2brwsr.core.JavaScriptBody;
27 /** Utilities to work on methods.
29 * @author Jaroslav Tulach <jtulach@netbeans.org>
31 public abstract class MethodImpl {
32 public static MethodImpl INSTANCE;
35 Class.forName(Method.class.getName());
36 } catch (ClassNotFoundException ex) {
37 throw new IllegalStateException(ex);
41 protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
42 protected abstract Constructor create(Class<?> declaringClass, Object data, String sig);
46 // bck2brwsr implementation
49 @JavaScriptBody(args = {"clazz", "prefix", "cnstr"},
51 + "var c = clazz.cnstr;\n"
52 + "if (!cnstr) c = c.prototype;\n"
53 + "var arr = new Array();\n"
54 + "function check(m, verify) {\n"
55 + " if (m.indexOf(prefix) === 0) {\n"
56 + " if (!c[m].cls) return;\n"
58 + " for (var i = 0; i < arr.length; i += 3) {\n"
59 + " if (arr[i] === m) return;\n"
63 + " arr.push(c[m]);\n"
64 + " arr.push(c[m].cls.$class);\n"
70 + "check('wait__V', true);\n"
71 + "check('wait__VJ', true);\n"
72 + "check('wait__VJI', true);\n"
73 + "check('equals__ZLjava_lang_Object_2', true);\n"
74 + "check('toString__Ljava_lang_String_2', true);\n"
75 + "check('hashCode__I', true);\n"
76 + "check('getClass__Ljava_lang_Class_2', true);\n"
77 + "check('notify__V', true);\n"
78 + "check('notifyAll__V', true);\n"
80 private static native Object[] findMethodData(
81 Class<?> clazz, String prefix, boolean cnstr);
83 public static Constructor findConstructor(
84 Class<?> clazz, Class<?>... parameterTypes) {
85 Object[] data = findMethodData(clazz, "cons__", true);
86 BIG: for (int i = 0; i < data.length; i += 3) {
87 String sig = ((String) data[i]).substring(6);
88 Class<?> cls = (Class<?>) data[i + 2];
89 Constructor tmp = INSTANCE.create(cls, data[i + 1], sig);
90 Class<?>[] tmpParms = tmp.getParameterTypes();
91 if (parameterTypes.length != tmpParms.length) {
94 for (int j = 0; j < tmpParms.length; j++) {
95 if (!parameterTypes[j].equals(tmpParms[j])) {
104 public static Constructor[] findConstructors(Class<?> clazz, int mask) {
105 Object[] namesAndData = findMethodData(clazz, "", true);
107 for (int i = 0; i < namesAndData.length; i += 3) {
108 String sig = (String) namesAndData[i];
109 Object data = namesAndData[i + 1];
110 if (!sig.startsWith("cons__")) {
113 sig = sig.substring(6);
114 Class<?> cls = (Class<?>) namesAndData[i + 2];
115 final Constructor m = INSTANCE.create(cls, data, sig);
116 if ((m.getModifiers() & mask) == 0) {
119 namesAndData[cnt++] = m;
121 Constructor[] arr = new Constructor[cnt];
122 for (int i = 0; i < cnt; i++) {
123 arr[i] = (Constructor) namesAndData[i];
127 public static Method findMethod(
128 Class<?> clazz, String name, Class<?>... parameterTypes) {
129 Object[] data = findMethodData(clazz, name + "__", false);
130 BIG: for (int i = 0; i < data.length; i += 3) {
131 String sig = ((String) data[i]).substring(name.length() + 2);
132 Class<?> cls = (Class<?>) data[i + 2];
133 Method tmp = INSTANCE.create(cls, name, data[i + 1], sig);
134 Class<?>[] tmpParms = tmp.getParameterTypes();
135 if (parameterTypes.length != tmpParms.length) {
138 for (int j = 0; j < tmpParms.length; j++) {
139 if (!parameterTypes[j].equals(tmpParms[j])) {
148 public static Method[] findMethods(Class<?> clazz, int mask) {
149 Object[] namesAndData = findMethodData(clazz, "", false);
151 for (int i = 0; i < namesAndData.length; i += 3) {
152 String sig = (String) namesAndData[i];
153 Object data = namesAndData[i + 1];
154 int middle = sig.indexOf("__");
158 if (sig.startsWith("$") && sig.endsWith("$")) {
159 // produced by Closure compiler in debug mode
160 // needs to be ignored
163 String name = sig.substring(0, middle);
164 sig = sig.substring(middle + 2);
165 Class<?> cls = (Class<?>) namesAndData[i + 2];
166 final Method m = INSTANCE.create(cls, name, data, sig);
167 if ((m.getModifiers() & mask) == 0) {
170 namesAndData[cnt++] = m;
172 Method[] arr = new Method[cnt];
173 for (int i = 0; i < cnt; i++) {
174 arr[i] = (Method) namesAndData[i];
179 @Exported static String toSignature(Method m) {
180 StringBuilder sb = new StringBuilder();
181 sb.append(m.getName()).append("__");
182 appendType(sb, m.getReturnType());
183 Class<?>[] arr = m.getParameterTypes();
184 for (int i = 0; i < arr.length; i++) {
185 appendType(sb, arr[i]);
187 return sb.toString();
190 private static void appendType(StringBuilder sb, Class<?> type) {
191 if (type == Integer.TYPE) {
195 if (type == Long.TYPE) {
199 if (type == Double.TYPE) {
203 if (type == Float.TYPE) {
207 if (type == Byte.TYPE) {
211 if (type == Boolean.TYPE) {
215 if (type == Short.TYPE) {
219 if (type == Void.TYPE) {
223 if (type == Character.TYPE) {
227 if (type.isArray()) {
229 appendType(sb, type.getComponentType());
232 sb.append('L').append(type.getName().replace('.', '_'));
236 public static int signatureElements(String sig) {
237 Enumeration<Class> en = signatureParser(sig);
239 while (en.hasMoreElements()) {
246 public static Enumeration<Class> signatureParser(final String sig) {
247 class E implements Enumeration<Class> {
253 while (sig.charAt(len - 1) == '$') {
258 public boolean hasMoreElements() {
262 public Class nextElement() {
263 switch (sig.charAt(pos++)) {
281 return Character.TYPE;
284 int up = sig.indexOf("_2", pos);
285 String type = sig.substring(pos, up);
287 return Class.forName(type.replace('_', '.'));
288 } catch (ClassNotFoundException ex) {
289 throw new IllegalStateException(ex);
292 char nch = sig.charAt(pos++);
293 assert nch == '3' : "Can't find '3' at " + sig.substring(pos - 1);
294 final Class compType = nextElement();
295 return Array.newInstance(compType, 0).getClass();
298 throw new UnsupportedOperationException(sig + " at " + pos);