@Override public MetaMethod[] getMethods() { if (_methodsCache != null) return _methodsCache; MetaMethod[] methodArray = methods.toArray(new MetaMethod[methods.size()]); MetaMethod[] outputMethods; if (superClass != null) { List<MetaMethod> methodList = new ArrayList<MetaMethod>(); for (MetaMethod m : superClass.getMethods()) { if (_getMethod(methodArray, m.getName(), GenUtil.fromParameters(m.getParameters())) == null) { methodList.add(m); } } methodList.addAll(Arrays.asList(methodArray)); outputMethods = methodList.toArray(new MetaMethod[methodList.size()]); } else { outputMethods = methodArray; } return _methodsCache = outputMethods; }
public static void assertAssignableTypes( final Context context, final MetaClass from, final MetaClass to) { if (!to.asBoxed().isAssignableFrom(from.asBoxed())) { if (to.isArray() && from.isArray() && GenUtil.getArrayDimensions(to) == GenUtil.getArrayDimensions(from) && to.getOuterComponentType().isAssignableFrom(from.getOuterComponentType())) { return; } if (!context.isPermissiveMode()) { if (classAliases.contains(from.getFullyQualifiedName()) && classAliases.contains(to.getFullyQualifiedName())) { // handle convertibility between MetaClass API and java Class reference. return; } throw new InvalidTypeException( to.getFullyQualifiedName() + " is not assignable from " + from.getFullyQualifiedName()); } } }
BuildMetaClass make(final String proxyClassName, final MetaClass toProxy, final String privateAccessorType) { final ClassStructureBuilder builder; final boolean renderEqualsAndHash; if (!toProxy.isInterface()) { renderEqualsAndHash = true; if (toProxy.isFinal()) { throw new UnproxyableClassException(toProxy, toProxy.getFullyQualifiedName() + " is an unproxiable class because it is final"); } if (!toProxy.isDefaultInstantiable()) { throw new UnproxyableClassException(toProxy, toProxy.getFullyQualifiedName() + " must have a default " + "no-arg constructor"); } builder = ClassBuilder.define(proxyClassName, toProxy).publicScope().body(); } else { renderEqualsAndHash = false; builder = ClassBuilder.define(proxyClassName).publicScope().implementsInterface(toProxy).body(); } final String proxyVar = "$$_proxy_$$"; final Set<String> renderedMethods = new HashSet<String>(); final Map<String, MetaType> typeVariableMap = new HashMap<String, MetaType>(); final MetaParameterizedType metaParameterizedType = toProxy.getParameterizedType(); if (metaParameterizedType != null) { int i = 0; for (final MetaTypeVariable metaTypeVariable : toProxy.getTypeParameters()) { typeVariableMap.put(metaTypeVariable.getName(), metaParameterizedType.getTypeParameters()[i++]); } } builder.privateField(proxyVar, toProxy).finish(); final Set<Map.Entry<String, ProxyProperty>> entries = proxyProperties.entrySet(); for (final Map.Entry<String, ProxyProperty> entry : entries) { builder.privateField(entry.getValue().getEncodedProperty(), entry.getValue().getType()).finish(); builder.packageMethod(void.class, "$set_" + entry.getKey(), Parameter.of(entry.getValue().getType(), "o")) .append(Stmt.loadVariable(entry.getValue().getEncodedProperty()).assignValue(Refs.get("o"))) .finish(); } for (final MetaMethod method : toProxy.getMethods()) { final String methodString = GenUtil.getMethodString(method); if (renderedMethods.contains(methodString) || method.getName().equals("hashCode") || (method.getName().equals("equals") && method.getParameters().length == 1 && method.getParameters()[0].getType().getFullyQualifiedName().equals(Object.class.getName()))) continue; renderedMethods.add(methodString); if ((!method.isPublic() && !method.isProtected()) || method.isSynthetic() || method.isFinal() || method.isStatic() || method.getDeclaringClass().getFullyQualifiedName().equals(Object.class.getName())) continue; final List<Parameter> methodParms = new ArrayList<Parameter>(); final MetaParameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { methodParms.add(Parameter.of(parameters[i].getType().getErased(), "a" + i)); } final DefParameters defParameters = DefParameters.fromParameters(methodParms); final BlockBuilder methBody = builder.publicMethod(method.getReturnType(), method.getName()) .annotatedWith(OVERRIDE_ANNOTATION) .parameters(defParameters) .throws_(method.getCheckedExceptions()); methBody.appendAll(getAroundInvokeStatements(method)); methBody.appendAll(getBeforeStatements(method)); final List<Parameter> parms = defParameters.getParameters(); final Statement[] statementVars = new Statement[parms.size()]; for (int i = 0; i < parms.size(); i++) { statementVars[i] = loadVariable(parms.get(i).getName()); } if (!method.isPublic()) { PrivateAccessUtil.addPrivateAccessStubs(privateAccessorType, builder, method, new Modifier[0]); final Statement[] privateAccessStmts = new Statement[statementVars.length + 1]; privateAccessStmts[0] = Refs.get(proxyVar); System.arraycopy(statementVars, 0, privateAccessStmts, 1, statementVars.length); if (method.getReturnType().isVoid()) { methBody._(loadVariable("this").invoke(PrivateAccessUtil.getPrivateMethodName(method), privateAccessStmts)); } else { methBody._(loadVariable("this").invoke(PrivateAccessUtil.getPrivateMethodName(method), privateAccessStmts).returnValue()); } } else { if (method.getReturnType().isVoid()) { methBody._(loadVariable(proxyVar).invoke(method, statementVars)); } else { methBody._(loadVariable(proxyVar).invoke(method, statementVars).returnValue()); } } methBody.appendAll(getAfterStatements(method)); methBody.appendAll(getAroundInvokeStatements(method)); methBody.finish(); } if (renderEqualsAndHash) { // implement hashCode() builder.publicMethod(int.class, "hashCode") .annotatedWith(OVERRIDE_ANNOTATION) .body() ._( If.isNull(loadVariable(proxyVar)) ._(throw_(IllegalStateException.class, "call to hashCode() on an unclosed proxy.")) .finish() .else_() ._(Stmt.loadVariable(proxyVar).invoke("hashCode").returnValue()) .finish() ) .finish(); // implements equals() builder.publicMethod(boolean.class, "equals", Parameter.of(Object.class, "o")) .annotatedWith(OVERRIDE_ANNOTATION) .body() ._( If.isNull(loadVariable(proxyVar)) ._(throw_(IllegalStateException.class, "call to equals() on an unclosed proxy.")) .finish() .else_() ._(Stmt.loadVariable(proxyVar).invoke("equals", Refs.get("o")).returnValue()) .finish() ) .finish(); } builder.publicMethod(void.class, PROXY_BIND_METHOD).parameters(DefParameters.of(Parameter.of(toProxy, "proxy"))) ._(loadVariable(proxyVar).assignValue(loadVariable("proxy"))).finish(); return builder.getClassDefinition(); }
static { GenUtil.addClassAlias(GWTClass.class); PrivateAccessUtil.registerPrivateMemberAccessor("jsni", new GWTPrivateMemberAccessor()); }