@Override protected synchronized Class findClass(String name) throws ClassNotFoundException { Class<?> clazz = classes.get(name); if (clazz == null) { if (classes.containsKey(name)) throw new ClassNotFoundException(name); byte[] classBytes = classCache.getClassBytesFor(name); try { if (classBytes != null) { clazz = defineClass(name, classBytes, 0, classBytes.length); } else { clazz = super.findClass(name); } classes.put(name, clazz); } catch (ClassNotFoundException e) { classes.put(name, null); throw e; } } return clazz; }
/** * Make glue object implementing interface cl that will call the supplied JS function when called. * Only interfaces were all methods have the same signature is supported. * * @return The glue object or null if <tt>cl</tt> is not interface or has methods with different * signatures. */ static Object create(Context cx, Class cl, Callable function) { if (!cl.isInterface()) throw new IllegalArgumentException(); Scriptable topScope = ScriptRuntime.getTopCallScope(cx); ClassCache cache = ClassCache.get(topScope); InterfaceAdapter adapter; adapter = (InterfaceAdapter) cache.getInterfaceAdapter(cl); ContextFactory cf = cx.getFactory(); if (adapter == null) { Method[] methods = cl.getMethods(); if (methods.length == 0) { throw Context.reportRuntimeError2( "msg.no.empty.interface.conversion", String.valueOf(function), cl.getClass().getName()); } boolean canCallFunction = false; canCallFunctionChecks: { Class[] argTypes = methods[0].getParameterTypes(); // check that the rest of methods has the same signature for (int i = 1; i != methods.length; ++i) { Class[] types2 = methods[i].getParameterTypes(); if (types2.length != argTypes.length) { break canCallFunctionChecks; } for (int j = 0; j != argTypes.length; ++j) { if (types2[j] != argTypes[j]) { break canCallFunctionChecks; } } } canCallFunction = true; } if (!canCallFunction) { throw Context.reportRuntimeError2( "msg.no.function.interface.conversion", String.valueOf(function), cl.getClass().getName()); } adapter = new InterfaceAdapter(cf, cl); cache.cacheInterfaceAdapter(cl, adapter); } return VMBridge.instance.newInterfaceProxy( adapter.proxyHelper, cf, adapter, function, topScope); }
private static Class<?> getAdapterClass( Scriptable scope, Class<?> superClass, Class<?>[] interfaces, Scriptable obj) { ClassCache cache = ClassCache.get(scope); Map<JavaAdapterSignature, Class<?>> generated = cache.getInterfaceAdapterCacheMap(); ObjToIntMap names = getObjectFunctionNames(obj); JavaAdapterSignature sig; sig = new JavaAdapterSignature(superClass, interfaces, names); Class<?> adapterClass = generated.get(sig); if (adapterClass == null) { String adapterName = "adapter" + cache.newClassSerialNumber(); byte[] code = createAdapterCode(names, adapterName, superClass, interfaces, null); adapterClass = loadAdapterClass(adapterName, code); if (cache.isCachingEnabled()) { generated.put(sig, adapterClass); } } return adapterClass; }
private static ClassCache cache(String className, ClassNode cn) { ClassCache classCache = new ClassCache(); classCache.className = className; classCacheMap.put(className, classCache); LOOP: for (Object m : cn.methods) { MethodNode mn = (MethodNode) m; for (Object exception : mn.exceptions) { if ("kilim/Pausable".equals(exception)) { classCache.pausableMethods.add(mn.name + mn.desc); continue LOOP; } } classCache.otherMethods.add(mn.name + mn.desc); } classCache.addSuper(cn.superName); for (Object interfaceName : cn.interfaces) { classCache.addSuper((String) interfaceName); } // System.out.println(classCache); return classCache; }
public static int getPausableStatus( String className, String methodName, String desc, Detector detector) { try { ClassCache classCache = classCacheMap.get(className); if (classCache == null) { ClassReader cr = new ClassReader(className); ClassNode cn = new ClassNode(); cr.accept(cn, /*flags*/ 0); classCache = cache(className, cn); } int status = classCache.getPausableStatus(methodName, desc); if (status == Detector.METHOD_NOT_FOUND_OR_PAUSABLE) { // check super classes for (String superName : classCache.superClasses) { status = detector.getPausableStatus(superName, methodName, desc); if (status != Detector.METHOD_NOT_FOUND_OR_PAUSABLE) break; } } return status; } catch (IOException ioe) { System.err.println("***Error reading " + className + ": " + ioe.getMessage()); return Detector.METHOD_NOT_FOUND_OR_PAUSABLE; } }
@SuppressWarnings({"unchecked", "rawtypes"}) public Object jsonToObject(final JSonNode json, Type type) throws MapperException { final ClassCache cc; try { Class<?> clazz = null; if (type instanceof ParameterizedType) { Type typ = ((ParameterizedType) type).getRawType(); if (typ instanceof Class) { clazz = (Class<?>) typ; } } else if (type instanceof Class) { clazz = (Class) type; } else if (type instanceof GenericArrayType) { // this is for 1.6 // for 1.7 we do not get GenericArrayTypeImpl here but the // actual array class type = clazz = Array.newInstance((Class<?>) ((GenericArrayType) type).getGenericComponentType(), 0) .getClass(); } if (clazz == null || clazz == Object.class) { if (json instanceof JSonArray) { type = clazz = LinkedList.class; } else if (json instanceof JSonObject) { type = clazz = HashMap.class; } else if (json instanceof JSonValue) { switch (((JSonValue) json).getType()) { case BOOLEAN: type = clazz = boolean.class; break; case DOUBLE: type = clazz = double.class; break; case LONG: type = clazz = long.class; break; case NULL: case STRING: type = clazz = String.class; } } } final TypeMapper<?> tm = typeMapper.get(clazz); if (tm != null) { return tm.reverseMap(json); } if (json instanceof JSonValue) { if (!Clazz.isPrimitive(type) && !Clazz.isString(type) && type != Object.class && ((JSonValue) json).getValue() != null && !Clazz.isEnum(type)) { // throw new MapperException(json + " cannot be mapped to " + type); } switch (((JSonValue) json).getType()) { case BOOLEAN: case DOUBLE: case LONG: if (type instanceof Class) { return JSonMapper.cast(((JSonValue) json).getValue(), (Class) type); } else { return ((JSonValue) json).getValue(); } case STRING: if (type instanceof Class && ((Class<?>) type).isEnum()) { try { return Enum.valueOf((Class<Enum>) type, ((JSonValue) json).getValue() + ""); } catch (final IllegalArgumentException e) { if (isIgnoreIllegalArgumentMappings() || isIgnoreIllegalEnumMappings()) { return null; } throw e; } } else { return ((JSonValue) json).getValue(); } case NULL: return null; } } if (type instanceof ParameterizedType) { final ParameterizedType pType = (ParameterizedType) type; Type raw = pType.getRawType(); if (raw instanceof Class && Collection.class.isAssignableFrom((Class) raw)) { final Collection<Object> inst = (Collection<Object>) mapClasses((Class) raw).newInstance(); final JSonArray obj = (JSonArray) json; for (final JSonNode n : obj) { inst.add(this.jsonToObject(n, pType.getActualTypeArguments()[0])); } return inst; } else if (raw instanceof Class && Map.class.isAssignableFrom((Class) raw)) { final Map<String, Object> inst = (Map<String, Object>) mapClasses((Class) raw).newInstance(); final JSonObject obj = (JSonObject) json; Entry<String, JSonNode> next; for (final Iterator<Entry<String, JSonNode>> it = obj.entrySet().iterator(); it.hasNext(); ) { next = it.next(); inst.put( next.getKey(), this.jsonToObject(next.getValue(), pType.getActualTypeArguments()[1])); } return inst; } } if (clazz != null) { if (clazz == Object.class) { // guess type if (json instanceof JSonArray) { type = LinkedList.class; } else if (json instanceof JSonObject) { type = HashMap.class; } } if (Collection.class.isAssignableFrom(clazz)) { final Collection<Object> inst = (Collection<Object>) mapClasses(clazz).newInstance(); final JSonArray obj = (JSonArray) json; final Type gs = clazz.getGenericSuperclass(); final Type gType; if (gs instanceof ParameterizedType) { gType = ((ParameterizedType) gs).getActualTypeArguments()[0]; } else { gType = void.class; } for (final JSonNode n : obj) { inst.add(this.jsonToObject(n, gType)); } return inst; } else if (Map.class.isAssignableFrom(clazz)) { final Map<String, Object> inst = (Map<String, Object>) mapClasses(clazz).newInstance(); final JSonObject obj = (JSonObject) json; final Type gs = clazz.getGenericSuperclass(); final Type gType; if (gs instanceof ParameterizedType) { gType = ((ParameterizedType) gs).getActualTypeArguments()[1]; } else { gType = void.class; } Entry<String, JSonNode> next; for (final Iterator<Entry<String, JSonNode>> it = obj.entrySet().iterator(); it.hasNext(); ) { next = it.next(); inst.put(next.getKey(), this.jsonToObject(next.getValue(), gType)); } return inst; } else if (clazz.isArray()) { final JSonArray obj = (JSonArray) json; final Object arr = Array.newInstance(mapClasses(clazz.getComponentType()), obj.size()); for (int i = 0; i < obj.size(); i++) { final Object v = this.jsonToObject(obj.get(i), clazz.getComponentType()); Array.set(arr, i, v); } return arr; } else { if (json instanceof JSonArray) { final java.util.List<Object> inst = new ArrayList<Object>(); final JSonArray obj = (JSonArray) json; final Type gs = clazz.getGenericSuperclass(); final Type gType; if (gs instanceof ParameterizedType) { gType = ((ParameterizedType) gs).getActualTypeArguments()[0]; } else { gType = Object.class; } for (final JSonNode n : obj) { inst.add(this.jsonToObject(n, gType)); } return inst; } else { final JSonObject obj = (JSonObject) json; if (Clazz.isPrimitive(clazz)) { // if (isIgnoreIllegalArgumentMappings()) { return null; } else { throw new IllegalArgumentException("Cannot Map " + obj + " to " + clazz); } } cc = ClassCache.getClassCache(clazz); final Object inst = cc.getInstance(); JSonNode value; Object v; for (final Setter s : cc.getSetter()) { value = obj.get(s.getKey()); if (value == null) { continue; } // Type fieldType = s.getType(); // special handling for generic fields if (fieldType instanceof TypeVariable) { final Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments(); final TypeVariable<?>[] genericTypes = clazz.getTypeParameters(); for (int i = 0; i < genericTypes.length; i++) { if (StringUtils.equals( ((TypeVariable) fieldType).getName(), genericTypes[i].getName())) { fieldType = actualTypes[i]; break; } } } v = this.jsonToObject(value, fieldType); try { s.setValue(inst, v); } catch (final IllegalArgumentException e) { if (isIgnoreIllegalArgumentMappings()) { continue; } else if (v == null && isIgnorePrimitiveNullMapping()) { continue; } throw e; } } return inst; } } } else { System.err.println("TYPE?!"); } } catch (final SecurityException e) { e.printStackTrace(); } catch (final NoSuchMethodException e) { e.printStackTrace(); } catch (final IllegalArgumentException e) { e.printStackTrace(); } catch (final InstantiationException e) { e.printStackTrace(); } catch (final IllegalAccessException e) { e.printStackTrace(); } catch (final InvocationTargetException e) { e.printStackTrace(); } return null; }
/** * @param obj * @return * @throws MapperException */ @SuppressWarnings("unchecked") public JSonNode create(final Object obj) throws MapperException { try { if (obj == null) { return new JSonValue(null); } final Class<? extends Object> clazz = obj.getClass(); TypeMapper<?> mapper; if (clazz.isPrimitive()) { if (clazz == boolean.class) { return new JSonValue((Boolean) obj); } else if (clazz == char.class) { return new JSonValue(0 + ((Character) obj).charValue()); } else if (clazz == byte.class) { return new JSonValue(((Byte) obj).longValue()); } else if (clazz == short.class) { return new JSonValue(((Short) obj).longValue()); } else if (clazz == int.class) { return new JSonValue(((Integer) obj).longValue()); } else if (clazz == long.class) { return new JSonValue(((Long) obj).longValue()); } else if (clazz == float.class) { return new JSonValue(((Float) obj).doubleValue()); } else if (clazz == double.class) { return new JSonValue(((Double) obj).doubleValue()); } } else if (clazz.isEnum()) { return new JSonValue(obj + ""); } else if (obj instanceof Boolean) { return new JSonValue(((Boolean) obj).booleanValue()); } else if (obj instanceof Character) { return new JSonValue(0 + ((Character) obj).charValue()); } else if (obj instanceof Byte) { return new JSonValue(((Byte) obj).longValue()); } else if (obj instanceof Short) { return new JSonValue(((Short) obj).longValue()); } else if (obj instanceof Integer) { return new JSonValue(((Integer) obj).longValue()); } else if (obj instanceof Long) { return new JSonValue(((Long) obj).longValue()); } else if (obj instanceof Float) { return new JSonValue(((Float) obj).doubleValue()); } else if (obj instanceof Double) { return new JSonValue(((Double) obj).doubleValue()); } else if (obj instanceof String) { return new JSonValue((String) obj); } else if (obj instanceof Map) { final JSonObject ret = new JSonObject(); Entry<Object, Object> next; for (final Iterator<Entry<Object, Object>> it = ((Map<Object, Object>) obj).entrySet().iterator(); it.hasNext(); ) { next = it.next(); if (!(next.getKey() instanceof String)) { throw new MapperException( "Map keys have to be Strings: " + clazz + " Keyclass:" + (next.getKey() == null ? "<null>" : next.getKey().getClass())); } ret.put(next.getKey().toString(), create(next.getValue())); } return ret; } else if (obj instanceof Collection) { final JSonArray ret = new JSonArray(); for (final Object o : (Collection<?>) obj) { ret.add(create(o)); } return ret; } else if (clazz.isArray()) { final JSonArray ret = new JSonArray(); for (int i = 0; i < Array.getLength(obj); i++) { ret.add(create(Array.get(obj, i))); } return ret; } else if (obj instanceof Class) { return new JSonValue(((Class<?>) obj).getName()); } else if ((mapper = typeMapper.get(clazz)) != null) { return mapper.map(obj); } else /* if (obj instanceof Storable) */ { final ClassCache cc = ClassCache.getClassCache(clazz); final JSonObject ret = new JSonObject(); for (final Getter g : cc.getGetter()) { ret.put(g.getKey(), create(g.getValue(obj))); } return ret; } } catch (final IllegalArgumentException e) { e.printStackTrace(); } catch (final IllegalAccessException e) { e.printStackTrace(); } catch (final InvocationTargetException e) { e.printStackTrace(); } catch (final SecurityException e) { e.printStackTrace(); } catch (final NoSuchMethodException e) { e.printStackTrace(); } return null; }