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); }
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); }
/** * 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; }
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); }
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); }
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() + "]"); } }
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; }
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()])); }
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(); }