protected void replaceMethodCallInMethod(MethodDetail md) throws NotFoundException, CannotCompileException { String callingObject = ", null"; if (!Modifier.isStatic(md.where.getModifiers())) { callingObject = ", this"; } String invocationClassName = callerInfos.get(md.callerInfoField); String typedTargetObject = javassist.Modifier.isStatic(md.calledMethod.getModifiers()) ? "" : "invocation.typedTargetObject=$0;"; String replaced = methodByMethodInfoFromWeakReference("info", md.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + invocationClassName + " invocation = new " + invocationClassName + " (info" + callingObject + ", $0, $args, info.getInterceptors());" + OptimizedBehaviourInvocations.setArguments( md.calledMethod.getParameterTypes().length) + typedTargetObject + "invocation.setTargetObject($0);" + "$_ = ($r)invocation.invokeNext();" + "} else { " + "$_ = $proceed($$); " + "}"; md.call.replace(replaced); }
/** * Determine the name of parameter with index i in the given method. Use the locals attributes * about local variables from the classfile. Note: This is still work in progress. * * @param method * @param locals * @param i * @return the name of the parameter if available or a number if not. */ static String parameterNameFor(CtBehavior method, LocalVariableAttribute locals, int i) { if (locals == null) { return Integer.toString(i + 1); } int modifiers = method.getModifiers(); int j = i; if (Modifier.isSynchronized(modifiers)) { // skip object to synchronize upon. j++; // System.err.println("Synchronized"); } if (Modifier.isStatic(modifiers) == false) { // skip "this" j++; // System.err.println("Instance"); } String variableName = locals.variableName(j); // if (variableName.equals("this")) { // System.err.println("'this' returned as a parameter name for " // + method.getName() + " index " + j // + // ", names are probably shifted. Please submit source for class in slf4j bugreport"); // } return variableName; }
/** * Filters the caller methods. * * @param method the method to filter * @return boolean true if the method should be filtered away */ private boolean methodFilterCaller(final CtBehavior method) { if (Modifier.isNative(method.getModifiers()) || Modifier.isInterface(method.getModifiers()) || method.getName().equals(TransformationUtil.GET_META_DATA_METHOD) || method.getName().equals(TransformationUtil.SET_META_DATA_METHOD) || method.getName().equals(TransformationUtil.CLASS_LOOKUP_METHOD) || method.getName().equals(TransformationUtil.GET_UUID_METHOD)) { return true; } else { return false; } }
private static CtMethod delegator0(CtMethod delegate, CtClass declaring) throws CannotCompileException, NotFoundException { MethodInfo deleInfo = delegate.getMethodInfo2(); String methodName = deleInfo.getName(); String desc = deleInfo.getDescriptor(); ConstPool cp = declaring.getClassFile2().getConstPool(); MethodInfo minfo = new MethodInfo(cp, methodName, desc); minfo.setAccessFlags(deleInfo.getAccessFlags()); ExceptionsAttribute eattr = deleInfo.getExceptionsAttribute(); if (eattr != null) minfo.setExceptionsAttribute((ExceptionsAttribute) eattr.copy(cp, null)); Bytecode code = new Bytecode(cp, 0, 0); boolean isStatic = Modifier.isStatic(delegate.getModifiers()); CtClass deleClass = delegate.getDeclaringClass(); CtClass[] params = delegate.getParameterTypes(); int s; if (isStatic) { s = code.addLoadParameters(params, 0); code.addInvokestatic(deleClass, methodName, desc); } else { code.addLoad(0, deleClass); s = code.addLoadParameters(params, 1); code.addInvokespecial(deleClass, methodName, desc); } code.addReturn(delegate.getReturnType()); code.setMaxLocals(++s); code.setMaxStack(s < 2 ? 2 : s); // for a 2-word return value minfo.setCodeAttribute(code.toCodeAttribute()); return new CtMethod(minfo, declaring); }
protected void replaceMethodCallInCon(ConstructorDetail cd) throws CannotCompileException, NotFoundException { String invocationClassName = callerInfos.get(cd.callerInfoField); String typedTargetObject = javassist.Modifier.isStatic(cd.calledMethod.getModifiers()) ? "" : "invocation.typedTargetObject=$0;"; String replaced = methodByConInfoFromWeakReference("info", cd.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + invocationClassName + " invocation = new " + invocationClassName + " (info, this, $0, $args, info.getInterceptors());" + typedTargetObject + OptimizedBehaviourInvocations.setArguments( cd.calledMethod.getParameterTypes().length) + "invocation.setTargetObject($0);" + "$_ = ($r)invocation.invokeNext();" + "} else { " + "$_ = $proceed($$); " + "}"; cd.call.replace(replaced); }
// this GwtCreateHandler has been introduced to make possible the // instanciation of abstract classes // that gwt-test-utils doesn't patch right now public Object create(Class<?> classLiteral) throws Exception { if (classLiteral.isAnnotation() || classLiteral.isArray() || classLiteral.isEnum() || classLiteral.isInterface() || !Modifier.isAbstract(classLiteral.getModifiers())) { return null; } Class<?> newClass = cache.get(classLiteral); if (newClass != null) { return newClass.newInstance(); } CtClass ctClass = GwtClassPool.getCtClass(classLiteral); CtClass subClass = GwtClassPool.get().makeClass(classLiteral.getCanonicalName() + "SubClass"); subClass.setSuperclass(ctClass); for (CtMethod m : ctClass.getDeclaredMethods()) { if (javassist.Modifier.isAbstract(m.getModifiers())) { CtMethod copy = new CtMethod(m, subClass, null); subClass.addMethod(copy); } } GwtPatcherUtils.patch(subClass, null); newClass = subClass.toClass(GwtClassLoader.get(), null); cache.put(classLiteral, newClass); return newClass.newInstance(); }
protected void replaceConCallInMethod(ConByMethodDetail cd) throws NotFoundException, CannotCompileException { // If target constructor is advisable we do not want to create an optimized invocation class // since the interceptor chain for its execution pointcut does not get invoked. if (cd.isTgtConAdvised) { super.replaceConCallInMethod(cd); return; } String callingObject = "null"; if (!Modifier.isStatic(cd.where.getModifiers())) { callingObject = "this"; } String invocationClassName = callerInfos.get(cd.callerInfoField); String replaced = conByMethodInfoFromWeakReference("info", cd.callerInfoField) + "if (info.getInterceptors() != (org.jboss.aop.advice.Interceptor[])null) { " + "java.lang.Object callingObject = " + callingObject + "; " + invocationClassName + " invocation = new " + invocationClassName + " (info," + callingObject + ", $args, info.getInterceptors());" + OptimizedBehaviourInvocations.setArguments( cd.calledConstructor.getParameterTypes().length) + "$_ = ($r)invocation.invokeNext();" + "} else { " + "$_ = $proceed($$); " + "}"; cd.call.replace(replaced); }
private Object[] extractParams(Mapping mapping, HttpServletRequest request) { Object[] params; ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(mapping.clazz)); CtMethod cm = null; CtClass[] parameterTypes = new CtClass[0]; try { cm = pool.get(mapping.clazz.getName()).getDeclaredMethod(mapping.method.getName()); parameterTypes = cm.getParameterTypes(); } catch (NotFoundException e) { e.printStackTrace(); } if (0 == parameterTypes.length) return new Object[0]; params = new Object[parameterTypes.length]; LocalVariableAttribute attr = (LocalVariableAttribute) cm.getMethodInfo().getCodeAttribute().getAttribute(LocalVariableAttribute.tag); int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1; for (int i = 0; i < params.length; i++) { String name = attr.variableName(i + pos); String typeName = parameterTypes[i].getName(); Binder binder = Binder.valueOf(typeName); Object param = binder.get(name, request, mapping); params[i] = param; } return params; }
private FieldInjectionTarget(TargetMember targetMember, CtClass ctClass, CtField ctField) { super(targetMember, ctClass); this.ctField = ctField; if (!Modifier.isStatic(ctField.getModifiers())) { throw new InjectionException( "Field is not static [" + targetMember.getQualifiedName() + "]"); } }
@Test(groups = "unit", timeOut = 1000) public void test() throws ClassNotFoundException { final Collection<Class<?>> descriptionClasses = Lists.newArrayList(); final URL url = AnnotationTests.class.getClassLoader().getResource("META-INF/jobs/persistence.xml"); final String jpaConfigContents = InputContexts.toString(InputContexts.forUrl(url)); final List<Class<? extends ActivityDescription>> activityDescriptionsMapped = Lists.newArrayList(); for (final Class<? extends ActivityFactory<?>> factoryClass : FACTORIES) { // Make sure the class is make as a ManageBean to DI context picks it up. assert factoryClass.getAnnotation(ManagedBean.class) != null : "Factory class " + factoryClass + " is not annotated with @ManagedBean"; // assert factoryClass.getDeclaredConstructors().length == 1; boolean foundInjectedConstructor = false; for (Constructor<?> constructor : factoryClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0 || constructor.getAnnotation(Inject.class) != null) { foundInjectedConstructor = true; } } assert foundInjectedConstructor; final ActivityFactoryFor factoryAnnotation = factoryClass.getAnnotation(ActivityFactoryFor.class); // Make sure this class specifies which ActivityDescription it acts an ActivityFactory for. assert factoryAnnotation != null; final Class<? extends ActivityDescription> descriptionClass = factoryAnnotation.value(); activityDescriptionsMapped.add(descriptionClass); assert ActivityDescription.class.isAssignableFrom(descriptionClass); // Make sure there are not multiple descriptions per factory assert !descriptionClasses.contains(descriptionClass); // Make sure the description can be persisted assert descriptionClass.getAnnotation(Entity.class) != null : descriptionClass + " is not annotated with entity."; assert jpaConfigContents.contains(descriptionClass.getCanonicalName()) : "Class " + descriptionClass.getCanonicalName() + " not found in JPA configuration."; } final Pattern pattern = Pattern.compile("\\<class\\>.*\\<"); final Matcher matcher = pattern.matcher(jpaConfigContents); int start = 0; while (matcher.find(start)) { final int startIdx = matcher.start() + "<class>".length(); final int endIdx = jpaConfigContents.indexOf("<", startIdx); final String classStr = jpaConfigContents.substring(startIdx, endIdx); final Class<?> clazz = Class.forName(classStr); if (ActivityDescription.class.isAssignableFrom(clazz)) { if (!Modifier.isAbstract(clazz.getModifiers())) { assert activityDescriptionsMapped.contains(clazz) : "No activity factory found for description class " + clazz; } } start = endIdx; } }
public static void patch(CtClass c, IPatcher patcher) throws Exception { treatClassToPatch(c); if (patcher != null) { patcher.initClass(c); } for (CtMethod m : c.getDeclaredMethods()) { boolean wasAbstract = false; String newBody = null; if (Modifier.isAbstract(m.getModifiers())) { m.setModifiers(m.getModifiers() - Modifier.ABSTRACT); wasAbstract = true; } if (patcher != null) { newBody = patcher.getNewBody(m); } if (newBody != null) { if (newBody.startsWith(AutomaticPatcher.INSERT_BEFORE)) { GwtPatcherUtils.insertBefore( m, newBody.substring(AutomaticPatcher.INSERT_BEFORE.length())); } else if (newBody.startsWith(AutomaticPatcher.INSERT_AFTER)) { GwtPatcherUtils.insertAfter(m, newBody.substring(AutomaticPatcher.INSERT_AFTER.length())); } else { GwtPatcherUtils.replaceImplementation(m, newBody); } } else if (wasAbstract) { if (patcher != null) { m.setBody( "{ throw new " + UnsupportedOperationException.class.getName() + "(\"Abstract method '" + c.getSimpleName() + "." + m.getName() + "()' is not patched by " + patcher.getClass().getName() + "\"); }"); } else { m.setBody( "{ throw new " + UnsupportedOperationException.class.getName() + "(\"Abstract method '" + c.getSimpleName() + "." + m.getName() + "()' is not patched by any declared " + IPatcher.class.getSimpleName() + " instance\"); }"); } } } if (patcher != null) { patcher.finalizeClass(c); } }
/* 31: */ /* 32: */ public TransformCall(Transformer next, String oldMethodName, CtMethod substMethod) /* 33: */ { /* 34: 44 */ super(next); /* 35: 45 */ this.methodname = oldMethodName; /* 36: 46 */ this.methodDescriptor = substMethod.getMethodInfo2().getDescriptor(); /* 37: 47 */ this.classname = (this.newClassname = substMethod.getDeclaringClass().getName()); /* 38: 48 */ this.newMethodname = substMethod.getName(); /* 39: 49 */ this.constPool = null; /* 40: 50 */ this.newMethodIsPrivate = Modifier.isPrivate(substMethod.getModifiers()); /* 41: */ }
private static void treatClassToPatch(CtClass c) throws CannotCompileException { if (c == null) { throw new IllegalArgumentException("the class to patch cannot be null"); } int modifiers = c.getModifiers(); if (Modifier.isAnnotation(modifiers)) { throw new IllegalArgumentException("the class to patch cannot be an annotation"); } if (Modifier.isInterface(modifiers)) { throw new IllegalArgumentException("the class to patch cannot be an interface"); } if (Modifier.isEnum(modifiers)) { throw new IllegalArgumentException("the class to patch cannot be an enum"); } c.setModifiers(Modifier.PUBLIC); addDefaultConstructor(c); }
public ObjBase makeValue(ObjectId id, DBObject rawData, Class<? extends ObjBase> c) { if (Modifier.isAbstract(c.getModifiers()) || Modifier.isInterface(c.getModifiers())) { // extract declared schema from result, use that class Object schemaId = rawData.get(ReservedFieldNames.SCHEMA); try { c = (Class<ObjBase>) ClassUtil.findClass(schemaId.toString()); } catch (ClassNotFoundException ex) { log.warn("Could not find fallback schema {}", schemaId); return null; } } ObjBase value = makeStub(id, c, rawData); // update stub with the rest of the data, if (value != null && !(value instanceof Swappable)) try { unmarshaller.unmarshall(Bson.createDocument(rawData), value, this); } catch (MarshallingException me) { log.warn(me.getMessage(), me); } return value; }
private Map<String, CtField> collectReactiveFields(CtClass managedCtClass) { final Map<String, CtField> persistentFieldMap = new HashMap<String, CtField>(); for (CtField ctField : managedCtClass.getDeclaredFields()) { // skip static fields, skip final fields, and skip fields added by enhancement if (Modifier.isStatic(ctField.getModifiers()) || ctField.getName().startsWith(DROOLS_PREFIX)) { continue; } // skip outer reference in inner classes if ("this$0".equals(ctField.getName())) { continue; } // optimization: skip final field, unless it is a Reactive Collection/List/... in which case // we need to consider anyway: if (Modifier.isFinal(ctField.getModifiers())) { if (!isCtFieldACollection(ctField)) { continue; } } persistentFieldMap.put(ctField.getName(), ctField); } // CtClass.getFields() does not return private fields, while CtClass.getDeclaredFields() does // not return inherit for (CtField ctField : managedCtClass.getFields()) { if (ctField.getDeclaringClass().equals(managedCtClass)) { // Already processed above continue; } if (Modifier.isStatic(ctField.getModifiers()) || ctField.getName().startsWith(DROOLS_PREFIX)) { continue; } persistentFieldMap.put(ctField.getName(), ctField); } return persistentFieldMap; }
/** * Return whether or not the class has a method with the given name * * @param theClass the class to inspect * @param theName the name of the method to look for * @return true if the class contains the method, false otherwise */ private static boolean hasMethod(CtClass theClass, String theName) { try { return theClass.getDeclaredMethod(theName) != null && !Modifier.isAbstract(theClass.getDeclaredMethod(theName).getModifiers()); } catch (NotFoundException e) { try { if (theClass.getSuperclass() != null) { return hasMethod(theClass.getSuperclass(), theName); } else { return false; } } catch (NotFoundException e1) { return false; } } }
AccessType(Method method) { int modifier = method.getModifiers(); if (Modifier.isPrivate(modifier)) { throw new UnsupportedOperationException("method = private"); } if (Modifier.isFinal(modifier)) { throw new UnsupportedOperationException("method = final"); } this.method = method; accesssType = ""; staticType = ""; syncType = ""; methodName = ""; methodName = method.getName(); if (Modifier.isProtected(modifier)) { accesssType = "protected"; } if (Modifier.isPackage(modifier)) { accesssType = ""; } if (Modifier.isPublic(modifier)) { accesssType = "public"; } if (Modifier.isStatic(modifier)) { staticType = "static"; } if (Modifier.isSynchronized(modifier)) { syncType = "synchronized"; } returnType = createParameterName(method.getReturnType()); Set<String> throwSet = new HashSet<String>(); for (Class<?> ex : method.getExceptionTypes()) { throwSet.add(ex.getSimpleName()); } this.throwSet = throwSet; List<Parameter> paramList = new ArrayList<Parameter>(); for (Class<?> p : method.getParameterTypes()) { paramList.add(createParameterName(p)); } this.paramList = paramList; }
private CtField[] collectPersistentFields(CtClass managedCtClass) { final List<CtField> persistentFieldList = new LinkedList<CtField>(); for (CtField ctField : managedCtClass.getDeclaredFields()) { // skip static fields and skip fields added by enhancement if (Modifier.isStatic(ctField.getModifiers()) || ctField.getName().startsWith("$$_hibernate_")) { continue; } // skip outer reference in inner classes if ("this$0".equals(ctField.getName())) { continue; } if (enhancementContext.isPersistentField(ctField)) { persistentFieldList.add(ctField); } } return enhancementContext.order( persistentFieldList.toArray(new CtField[persistentFieldList.size()])); }
/** * Get the bean proeprties from the given class * * @param thePool the class pool to use when creating new fields * @param theClass the class the new fields will belong to * @param theInterface the original bean class * @return a Map of the bean property names with the new field for the property as the value * @throws javassist.CannotCompileException thrown if there is an error generating the methods * @throws javassist.NotFoundException thrown if there is an error generating the methods */ private static <T> Map<String, CtField> properties( final ClassPool thePool, final CtClass theClass, final Class<T> theInterface) throws NotFoundException, CannotCompileException { Map<String, CtField> aMap = new HashMap<String, CtField>(); for (Method aMethod : theInterface.getDeclaredMethods()) { // see if we've already processed this method. Normal .equals for a method will not work // because the classes have to be the same, // what we want is the semantics of isAssignableFrom, not .equals between the classes // declaring the methods. Thus, the FINDER // predicate implementation does exactly that. It's a copy of the Method.equals function, but // with the .equals for the declaring // class changed to isAssignableFrom so we get the expected behavior. FINDER.method = aMethod; if (Iterables2.find(processedMethods, FINDER)) { continue; } // we want to ignore methods with implementations, we should not override them. if (!Modifier.isAbstract(aMethod.getModifiers())) { // mark the method as one we've already handled in case we get this method again on a // superclass/interface processedMethods.add(aMethod); continue; } if (!aMethod.getName().startsWith("get") && !aMethod.getName().startsWith("is") && !aMethod.getName().startsWith("has") && !aMethod.getName().startsWith("set")) { if (EmpireOptions.STRICT_MODE) { throw new IllegalArgumentException( "Non-bean style methods found, implementations for them cannot not be generated"); } else { LOGGER.warn( "Non-bean style methods found, implementations for them cannot not be generated : " + aMethod.getName()); } } String aProp = aMethod.getName().substring(aMethod.getName().startsWith("is") ? 2 : 3); aProp = String.valueOf(aProp.charAt(0)).toLowerCase() + aProp.substring(1); Class aType = null; Type generics = null; if (aMethod.getName().startsWith("get") || aMethod.getName().startsWith("is") || aMethod.getName().startsWith("has")) { aType = aMethod.getReturnType(); generics = aMethod.getGenericReturnType(); } else if (aMethod.getName().startsWith("set") && aMethod.getParameterTypes().length > 0) { aType = aMethod.getParameterTypes()[0]; if (aMethod.getGenericParameterTypes() != null && aMethod.getGenericParameterTypes().length > 0) { generics = aMethod.getGenericParameterTypes()[0]; } } if (aType != null) { CtField aNewField = new CtField(thePool.get(aType.getName()), aProp, theClass); if (generics != null && generics instanceof ParameterizedTypeImpl) { for (Type t : ((ParameterizedTypeImpl) generics).getActualTypeArguments()) { String aFlag = ""; String aName; if (t instanceof WildcardTypeImpl) { WildcardTypeImpl aWildcard = (WildcardTypeImpl) t; // trying to suss out super v extends w/o resorting to string munging. if (aWildcard.getLowerBounds().length == 0 && aWildcard.getUpperBounds().length > 0) { // no lower bounds afaik indicates ? extends Foo aFlag = "+"; aName = ((Class) aWildcard.getUpperBounds()[0]).getName(); } else if (aWildcard.getLowerBounds().length > 0) { // lower & upper bounds I believe indicates something of the form Foo super Bar aFlag = "-"; aName = ((Class) aWildcard.getLowerBounds()[0]).getName(); } else { throw new CannotCompileException( "Unknown or unsupported type signature found: " + t); } } else { aName = ((Class) t).getName(); } aNewField .getFieldInfo() .addAttribute( new SignatureAttribute( aNewField.getFieldInfo().getConstPool(), "L" + aType.getName().replace('.', '/') + "<" + aFlag + "L" + aName.replace('.', '/') + ";>;")); } } aMap.put(aProp, aNewField); } // mark the method as one we've already handled in case we get this method again on a // superclass/interface processedMethods.add(aMethod); } return aMap; }
private static void removeNativeModifier(CtMethod m) throws Exception { if (Modifier.isNative(m.getModifiers())) { m.setModifiers(m.getModifiers() - Modifier.NATIVE); } }
private static CtClass makeExpressionClass( Source.Staged staged, String superClassName, String memberClassName) { // Here we make the language class accessible! if (!Modifier.isPublic(staged.getLanguage().getModifiers())) { staged.getLanguage().setModifiers(Modifier.setPublic(staged.getLanguage().getModifiers())); } CtClass clazz; try { ClassPool cp = ClassPool.getDefault(); CtClass superClass = cp.getCtClass(superClassName); clazz = cp.makeClass( superClass.getName() + "$Generated" + id + "$" + staged.getMember().getDeclaringClass().getName().replace(".", "_") + "$" + staged.getMember().getName().replace(".", "_"), superClass); id++; // Make accepted language static fields HashMap<CtClass, String> acceptedLanguageMap = new HashMap<>(); for (Use.Argument a : staged.getArguments()) { for (CtClass l : a.getAcceptedLanguages()) { if (!acceptedLanguageMap.containsKey(l) && !l.equals(Util.LANGUAGE_CLASS)) { String lName = "acceptedLanguage" + acceptedLanguageMap.size(); int lPersistentId = Dispatcher.addPersistent(l); CtField lField = CtField.make( "private static final " + CtClass.class.getName() + " " + lName + " = (" + CtClass.class.getName() + ") " + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + lPersistentId + ");", clazz); clazz.addField(lField); acceptedLanguageMap.put(l, lName); } } } // Make language field String languageName = "language"; int languagePersistentId = Dispatcher.addPersistent(staged.getLanguage()); CtField languageField = CtField.make( "private static final " + CtClass.class.getName() + " " + languageName + " = (" + CtClass.class.getName() + ") " + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + languagePersistentId + ");", clazz); clazz.addField(languageField); // Make member field String memberName = "member"; int memberPersistentId = Dispatcher.addPersistent(staged.getMember()); CtField memberField = CtField.make( "private static final " + memberClassName + " " + memberName + " = (" + memberClassName + ")" + Util.DISPATCHER_CLASS.getName() + ".removePersistent(" + memberPersistentId + ");", clazz); clazz.addField(memberField); // Make constructor String constructorSource = "private constructor(" + Util.EXPRESSION_CLASS.getName() + "[] arguments, " + Util.STATIC_INFO_CLASS.getName() + " staticInfo, " + Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n" + " super(arguments, staticInfo, closureHolder);\n" + "}"; CtConstructor constructor = CtNewConstructor.make(constructorSource, clazz); clazz.addConstructor(constructor); // Make factory-like invoke methods ImmutableList<Use.Argument> args = staged.getArguments(); StringBuilder invokeSource = new StringBuilder(); if (staged.isStrict() || Util.isCarrier(staged.getType())) { invokeSource.append( "public static " + staged.getType().getCtClass().getName() + " invoke("); } else if (staged.getType().isReference()) { invokeSource.append("public static " + Util.LOCAL_CARRIER_CLASS.getName() + " invoke("); } else { invokeSource.append("public static " + clazz.getName() + " invoke("); } if (staged.getArguments().size() > 253) { invokeSource.append("Object[] objectArguments, "); if (!staged.getStaticInfoElements().isEmpty()) { invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, "); } invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n"); for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource .append(" ") .append(Util.GLOBAL_CARRIER_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.GLOBAL_CARRIER_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource .append(" ") .append(Util.LOCAL_CARRIER_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.LOCAL_CARRIER_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } else if (args.get(i).getType().isReference()) { invokeSource .append(" ") .append(Type.OBJECT.getCtClass().getName()) .append(" argument") .append(i) .append(" = objectArguments[") .append(i) .append("];\n"); } else { invokeSource .append(" ") .append(Util.EXPRESSION_CLASS.getName()) .append(" argument") .append(i) .append(" = (") .append(Util.EXPRESSION_CLASS.getName()) .append(") objectArguments[") .append(i) .append("];\n"); } } } else { for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource.append(Util.GLOBAL_CARRIER_CLASS.getName()).append(" argument").append(i); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource.append(Util.LOCAL_CARRIER_CLASS.getName()).append(" argument").append(i); } else if (args.get(i).getType().isReference()) { invokeSource.append(Type.OBJECT.getCtClass().getName()).append(" argument").append(i); } else { invokeSource.append(Util.EXPRESSION_CLASS.getName()).append(" argument").append(i); } invokeSource.append(", "); } if (!staged.getStaticInfoElements().isEmpty()) { invokeSource.append(Util.STATIC_INFO_CLASS.getName() + " staticInfo, "); } invokeSource.append(Util.CLOSURE_HOLDER_CLASS.getName() + " closureHolder) {\n"); } invokeSource.append( " " + Util.EXPRESSION_CLASS.getName() + " payload;\n" + " " + Util.EXPRESSION_CLASS.getName() + "[] arguments = new " + Util.EXPRESSION_CLASS.getName() + "[" + args.size() + "];\n"); for (int i = 0; i < args.size(); i++) { if (Util.isGlobalCarrier(args.get(i).getType())) { invokeSource.append( " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrierChecked(argument" + i + ");\n" + " if (!(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + ".selfLiftGlobalCarrier(argument" + i + ");\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n"); } else if (Util.isLocalCarrier(args.get(i).getType()) || (args.get(i).getType().isReference() && !Util.couldBeGlobalCarrier(args.get(i).getType()))) { invokeSource.append( " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadLocalCarrierChecked(argument" + i + ");\n" + " if (" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = payload.getRaw();\n" + " } else {\n" + " payload.evaluate();\n" // This handles the weird case when the materialized argument could be globally // carried and might need unloading and checking // We know that it is an ObjectValue instance + " " + Util.EXPRESSION_CLASS.getName() + " value = payload.asValueIfEvaluated();\n" + " Object obj = value.materializeAsObject(); \n" + " if (obj instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") obj);\n" + " if (payload == null || !(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = value;\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = value;\n" + " }\n" + " }\n"); } else if (args.get(i).getType().isReference()) { invokeSource.append( " if (argument" + i + " instanceof " + Util.LOCAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadLocalCarrierChecked((" + Util.LOCAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " if (" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = payload.getRaw();\n" + " } else {\n" + " payload.evaluate();\n" // This handles the weird case when the materialized argument could be globally // carried and might need unloading and checking // We know that it is an ObjectValue instance + " " + Util.EXPRESSION_CLASS.getName() + " value = payload.asValueIfEvaluated();\n" + " Object obj = value.materializeAsObject(); \n" + " if (obj instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") obj);\n" + " if (payload == null || !(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = value;\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = value;\n" + " }\n" + " }\n" + " } else if (argument" + i + " instanceof " + Util.GLOBAL_CARRIER_CLASS.getName() + ") {\n" + " payload = " + Util.DISPATCHER_CLASS.getName() + ".unloadGlobalCarrierChecked((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " if (!(" + generateLanguageAcceptCheck( "payload", args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ")) {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + ".selfLiftGlobalCarrier((" + Util.GLOBAL_CARRIER_CLASS.getName() + ") argument" + i + ");\n" + " } else {\n" + " arguments[" + i + "] = payload;\n" + " }\n" + " } else {\n" + " arguments[" + i + "] = " + Util.DISPATCHER_CLASS.getName() + "." + Util.getLiftMethodName(Type.OBJECT) + "(argument" + i + ");\n" + " }\n"); } else { invokeSource.append( " if (" + generateLanguageAcceptCheck( "argument" + i, args.get(i).getAcceptedLanguages(), acceptedLanguageMap) + ") {\n" + " arguments[" + i + "] = argument" + i + generateConversionSuffix(args.get(i).getType()) + ".getRaw();\n" + " } else {\n" + " argument" + i + ".evaluate();\n" + " arguments[" + i + "] = argument" + i + ".asValueIfEvaluated();\n" + " }\n"); } } String construction; if (!staged.getStaticInfoElements().isEmpty()) { construction = "new " + clazz.getName() + "(arguments, staticInfo, closureHolder)"; } else { construction = "new " + clazz.getName() + "(arguments, null, closureHolder)"; } if (staged.isStrict()) { Type type = staged.getType(); if (type.isReference()) { invokeSource.append( " return (" + type.getCtClass().getName() + ") (" + construction + ").materializeAsObject();\n"); } else if (type.equals(Type.BOOLEAN)) { invokeSource.append(" return (" + construction + ").materializeAsBoolean();\n"); } else if (type.equals(Type.INT)) { invokeSource.append(" return (" + construction + ").materializeAsInteger();\n"); } else if (type.equals(Type.LONG)) { invokeSource.append(" return (" + construction + ").materializeAsLong();\n"); } else if (type.equals(Type.FLOAT)) { invokeSource.append(" return (" + construction + ").materializeAsFloat();\n"); } else if (type.equals(Type.DOUBLE)) { invokeSource.append(" return (" + construction + ").materializeAsDouble();\n"); } else if (type.equals(Type.BYTE)) { invokeSource.append(" return (" + construction + ").materializeAsByte();\n"); } else if (type.equals(Type.CHAR)) { invokeSource.append(" return (" + construction + ").materializeAsCharacter();\n"); } else if (type.equals(Type.SHORT)) { invokeSource.append(" return (" + construction + ").materializeAsShort();\n"); } else if (type.equals(Type.VOID)) { invokeSource.append(" return (" + construction + ").evaluate();\n"); } } else { if (Util.isGlobalCarrier(staged.getType())) { if (staged.getType().getCtClass().equals(Util.GLOBAL_CARRIER_CLASS)) { invokeSource.append( " return new " + Util.GLOBAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass()); invokeSource.append( " return new " + staged.getType().getCtClass().getName() + "((" + Util.DISAMBIGUATION_PARAMETER_CLASS.getName() + ") null, " + construction + ");\n"); } } else if (Util.isLocalCarrier(staged.getType())) { if (staged.getType().getCtClass().equals(Util.LOCAL_CARRIER_CLASS)) { invokeSource.append( " return new " + Util.LOCAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { CarrierTransformer.transformCarrierChecked(staged.getType().getCtClass()); invokeSource.append( " return new " + staged.getType().getCtClass().getName() + "((" + Util.DISAMBIGUATION_PARAMETER_CLASS.getName() + ") null, " + construction + ");\n"); } } else if (staged.getType().isReference()) { invokeSource.append( " return new " + Util.LOCAL_CARRIER_CLASS.getName() + "(" + construction + ");\n"); } else { invokeSource.append(" return " + construction + ";\n"); } } invokeSource.append("}"); CtMethod invoke = CtMethod.make(invokeSource.toString(), clazz); clazz.addMethod(invoke); // Make isomorphic hash code method String isomorphicHashCodeSource = "int isomorphicHashCode() {\n" + " if (!$0.isomorphicHashCodeHasBeenCalculated) {\n" + " super.isomorphicHashCode(" + staged.getMember().hashCode() + ");\n" + " }" + " return $0.isomorphicHashCode;" + "}"; CtMethod isomorphicHashCode = CtMethod.make(isomorphicHashCodeSource, clazz); clazz.addMethod(isomorphicHashCode); // Make isomorphism check method String isIsomorphicToSource = "boolean isIsomorphicTo(java.util.IdentityHashMap identityMap, " + Util.EXPRESSION_CLASS.getName() + " expression) {\n" + " if (!(expression instanceof " + clazz.getName() + ")) { return false; }\n" + " return super.isIsomorphicTo(identityMap, expression);\n" + "}"; CtMethod isIsomorphicTo = CtMethod.make(isIsomorphicToSource, clazz); clazz.addMethod(isIsomorphicTo); // Make cache clone (with empty leaves to save memory) creation method String cacheCloneSource = Util.EXPRESSION_CLASS.getName() + " cacheClone(java.util.IdentityHashMap identityMap) {\n" + " " + Util.EXPRESSION_CLASS.getName() + " e = (" + Util.EXPRESSION_CLASS.getName() + ") identityMap.get(this);\n" + " if (e != null) {\n" + " return e;\n" + " } else {\n" + " " + Util.EXPRESSION_CLASS.getName() + "[] clonedArguments = super.cacheCloneArguments(identityMap);\n" + " if (clonedArguments != null) {\n" + " " + clazz.getName() + " s = new " + clazz.getName() + "(clonedArguments, $0.staticInfo, null);\n" + " s.isomorphicHashCode = $0.isomorphicHashCode();\n" + " s.isomorphicHashCodeHasBeenCalculated = true;\n" + " identityMap.put(this, s);\n" + " return s;\n" + " } else {\n" + " identityMap.put(this, this);\n" + " return this;\n" + " }\n" + " }\n" + "}"; CtMethod cacheClone = CtMethod.make(cacheCloneSource, clazz); clazz.addMethod(cacheClone); // Make language acceptance check method String isAcceptedBySource = "boolean isAcceptedBy(" + CtClass.class.getName() + " language) { return $0.language.equals(language); }"; CtMethod isAcceptedBy = CtMethod.make(isAcceptedBySource, clazz); clazz.addMethod(isAcceptedBy); // Make polymorphic member retrieval method String getMemberSource = "public " + memberClassName + " getMember() { return $0." + memberName + "; }"; CtMethod getMember = CtMethod.make(getMemberSource, clazz); clazz.addMethod(getMember); // Make evaluation method Class<?> closureInterface = getClosureInterface(staged.getType()); String evaluateSource; if (Util.isGlobalCarrier(staged.getType()) && !staged.isStrict()) { evaluateSource = "public void evaluate() { throw new UnsupportedOperationException(); }"; } else { evaluateSource = "public void evaluate() {\n" + " if ($0.value != null) { return; }\n" + " " + closureInterface.getName() + " closure;\n" + " " + Util.ENVIRONMENT_CLASS.getName() + " environment;\n" + " if ($0.closureHolder == null) {\n" + " " + Util.CLOSURE_HOLDER_CLASS.getName() + " cachedClosureHolder = " + GlobalCache.class.getName() + ".getCachedClosureHolder($0);\n" + " if (cachedClosureHolder == null) {\n" + " " + Util.BINDER_CLASS.getName() + " binder = new " + Util.BINDER_CLASS.getName() + "($0);\n" + " closure = " + staged.getLanguage().getName() + ".make" + closureInterface.getSimpleName() + "($0, binder, false);\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, binder.getBoundCount());\n" + " if (!binder.inspectionOccurred()) {\n" + " " + GlobalCache.class.getName() + ".cache($0, closure, binder.getBoundCount());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") cachedClosureHolder.getClosure();\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, cachedClosureHolder.getEnvironmentSize());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") $0.closureHolder.getClosure();\n" + " if (closure == null) {\n" + " " + Util.CLOSURE_HOLDER_CLASS.getName() + " cachedClosureHolder = " + GlobalCache.class.getName() + ".getCachedClosureHolder($0);\n" + " if (cachedClosureHolder == null) {\n" + " " + Util.BINDER_CLASS.getName() + " binder = new " + Util.BINDER_CLASS.getName() + "($0);\n" + " closure = " + staged.getLanguage().getName() + ".make" + closureInterface.getSimpleName() + "($0, binder, $0.closureHolder.isPermanent());\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, binder.getBoundCount());\n" + " if (!binder.inspectionOccurred()) {\n" + " $0.closureHolder.set(closure, binder.getBoundCount());\n" + " " + GlobalCache.class.getName() + ".cache($0, closure, binder.getBoundCount());\n" + " }\n" + " } else {\n" + " closure = (" + closureInterface.getName() + ") cachedClosureHolder.getClosure();\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, cachedClosureHolder.getEnvironmentSize());\n" + " $0.closureHolder.set(closure, cachedClosureHolder.getEnvironmentSize());\n" + " }\n" + " } else {\n" + " environment = new " + Util.ENVIRONMENT_CLASS.getName() + "($0, $0.closureHolder.getEnvironmentSize());\n" + " }\n" + " }\n" + (staged.getType().equals(Type.VOID) ? " closure.evaluate(environment);\n" : " $0.value = " + Util.DISPATCHER_CLASS.getName() + "." + Util.getLiftMethodName(staged.getType()) + "(closure.evaluate(environment));\n") + "}"; } CtMethod evaluate = CtMethod.make(evaluateSource, clazz); clazz.addMethod(evaluate); clazz.toClass(); } catch (CannotCompileException | NotFoundException e) { throw new RuntimeException(e); } return clazz; }
private boolean isJAXRSEntity(Class<?> javaClass, Class<? extends Annotation> annotation) { if (!hasAnnotation(javaClass, annotation)) return false; if (javaClass.isInterface() || Modifier.isAbstract(javaClass.getModifiers())) return false; return true; }
private void enhance_(ApplicationClass applicationClass, boolean buildAuthorityRegistryOnly) throws Exception { Plugin.trace("about to enhance applicationClass: %s", applicationClass); CtClass ctClass = makeClass(applicationClass); Set<CtBehavior> s = new HashSet<CtBehavior>(); s.addAll(Arrays.asList(ctClass.getDeclaredMethods())); s.addAll(Arrays.asList(ctClass.getMethods())); s.addAll(Arrays.asList(ctClass.getConstructors())); s.addAll(Arrays.asList(ctClass.getDeclaredConstructors())); for (final CtBehavior ctBehavior : s) { if (!Modifier.isPublic(ctBehavior.getModifiers()) || javassist.Modifier.isAbstract(ctBehavior.getModifiers())) { continue; } boolean needsEnhance = false; RequireRight rr = null; RequirePrivilege rp = null; RequireAccounting ra = null; boolean allowSystem = false; Object[] aa = ctBehavior.getAnnotations(); for (Object o : aa) { if (o instanceof RequirePrivilege) { needsEnhance = true; rp = (RequirePrivilege) o; continue; } if (o instanceof RequireRight) { needsEnhance = true; rr = (RequireRight) o; continue; } if (o instanceof AllowSystemAccount) { allowSystem = true; continue; } if (o instanceof RequireAccounting) { needsEnhance = true; ra = (RequireAccounting) o; } } if (!needsEnhance) continue; String key = ctBehavior.getLongName(); String errMsg = String.format("Error enhancing class %s.%s: ", ctClass, ctBehavior); // process rr & rp if (null != rr || null != rp) { // check before/after enhancement Authority.registAuthoriable_(key, rr, rp); if (!buildAuthorityRegistryOnly) { // verify if before attribute of rr and rp is consistent if (null != rr && null != rp && (rr.before() != rp.before())) { String reason = "The before setting of RequireRight and RequirePrivilege doesn't match"; throw new RuntimeException(errMsg + reason); } boolean before = true; if (null != rr) before = rr.before(); if (null != rp) before = rp.before(); // try best to guess the target object String curObj = ""; if (null != rr) { // target object only impact dynamic access checking, hence rr shall not be null boolean isConstructor = ctBehavior instanceof CtConstructor; boolean isStatic = false; if (!isConstructor) isStatic = Modifier.isStatic(ctBehavior.getModifiers()); int paraCnt = ctBehavior.getParameterTypes().length; int id = rr.target(); // calibrate target id if (0 == id) { if (isConstructor) { id = -1; } else if (isStatic) { if (paraCnt > 0) id = 1; else id = -1; } } else if (id > paraCnt) { id = paraCnt; } // speculate cur target statement String sid = null; if (id == -1) sid = "_"; if (id > -1) sid = String.valueOf(id); if (null != sid) { curObj = "play.modules.aaa.PlayDynamicRightChecker.setObjectIfNoCurrent($" + sid + ");"; } if (-1 == id) before = false; } // check permission enhancement if (before) { ctBehavior.insertBefore( curObj + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\"" + key + "\", " + Boolean.toString(allowSystem) + ");"); } else { ctBehavior.insertAfter( curObj + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\"" + key + "\", " + Boolean.toString(allowSystem) + ");"); } } } if (buildAuthorityRegistryOnly) continue; // process ra if (null != ra) { CtClass[] paraTypes = ctBehavior.getParameterTypes(); String sParam = null; if (0 < paraTypes.length) { sParam = "new Object[0]"; } else { sParam = "{$$}"; } String msg = ra.value(); if (null == msg || "".equals(msg)) msg = key; if (ra.before()) { ctBehavior.insertBefore( "play.modules.aaa.utils.Accounting.info(\"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + ");"); } else { ctBehavior.insertAfter( "play.modules.aaa.utils.Accounting.info(\"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + ");"); } CtClass etype = ClassPool.getDefault().get("java.lang.Exception"); ctBehavior.addCatch( "{play.modules.aaa.utils.Accounting.error($e, \"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + "); throw $e;}", etype); } } if (buildAuthorityRegistryOnly) return; applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.detach(); }