// TODO: Implement byte code instrumentation to replace calls to methods that do not exist in // proxy by invoke(callee,methodHash/methodName,args) protected void instrument( CtClass toManipulate, String extRef, ClassPool externalPool, String proxyName, ProxyLoader loader) throws NotFoundException, CannotCompileException { ClassPool proxyPool = getPool(externalPool, loader); // javassist bytecode manipulation // LOG.info(" onWrite: getting proxy "+proxyName+" from pool "+loader.getClassPath()); CtClass proxyCtClass = proxyPool.get(proxyName); // LOG.info(" onWrite: getting external class "+extRef+" from pool "+extCop.getClassPath()); CtClass extRefCtClass = externalPool.get(extRef); if (proxyCtClass.getSuperclass() == extRefCtClass) { CodeConverter conv = new CodeConverter(); conv.replaceNew(extRefCtClass, proxyCtClass, TransparentProxyFactory.factoryMethod); // replace any occurence of "new $extRefClass ()" by "$proxyClass.$factoryMathod" in code of // $className toManipulate.instrument(conv); // e.g. "new TestComponentMain()" is replaced by // "Proxy4_TestComponentMain.newExternalInstance()" in bytecode of class // "ComponentUsingAnotherOne" // LOG.info(" Finished bytecode instrumentation of "+toManipulate.getName()); } }
public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException { ClassPool classPool = ClassPool.getDefault(); classPool.appendClassPath(new ClassClassPath(JavassistLengthBug.class)); CtClass dummyClass = classPool.get("net.fwbrasil.activate.entity.Dummy"); dummyClass.instrument( new ExprEditor() { public void edit(FieldAccess fa) { if (fa.isReader() && fa.getFieldName().equals("length")) try { fa.replace("$_ = ($r) this.length.substring(1);"); } catch (CannotCompileException e) { e.printStackTrace(); } } }); dummyClass.toClass(); new Dummy().print(); }
/** * Transforms the call side pointcuts. * * @param context the transformation context * @param klass the class set. */ public void transform(final Context context, final Klass klass) throws NotFoundException, CannotCompileException { List definitions = SystemDefinitionContainer.getDefinitionsContext(); m_joinPointIndex = TransformationUtil.getJoinPointIndex(klass.getCtClass()); // TODO thread safe reentrant for (Iterator it = definitions.iterator(); it.hasNext(); ) { final SystemDefinition definition = (SystemDefinition) it.next(); final CtClass ctClass = klass.getCtClass(); final ClassMetaData classMetaData = context.getMetaDataMaker().createClassMetaData(ctClass); // filter caller classes if (classFilter(definition, classMetaData, ctClass)) { continue; } ctClass.instrument( new ExprEditor() { public void edit(MethodCall methodCall) throws CannotCompileException { try { CtBehavior where = null; try { where = methodCall.where(); } catch (RuntimeException e) { // <clinit> access leads to a bug in Javassist where = ctClass.getClassInitializer(); } // filter caller methods if (methodFilterCaller(where)) { return; } // get the callee method name, signature and class name CtMethod calleeMethod = methodCall.getMethod(); String calleeClassName = methodCall.getClassName(); // filter callee classes if (!definition.inIncludePackage(calleeClassName)) { return; } // filter callee methods if (methodFilterCallee(calleeMethod)) { return; } // create the class meta-data ClassMetaData calleeSideClassMetaData; try { calleeSideClassMetaData = context .getMetaDataMaker() .createClassMetaData(context.getClassPool().get(calleeClassName)); } catch (NotFoundException e) { // TODO - AV - 20040507 small fix for test.aopc. that use on the fly generated // classes if (calleeClassName.equals(ctClass.getName())) { calleeSideClassMetaData = classMetaData; } else { throw new WrappedRuntimeException(e); } } // create the method meta-data MethodMetaData calleeSideMethodMetaData = JavassistMetaDataMaker.createMethodMetaData(methodCall.getMethod()); // is this a caller side method pointcut? if (definition.isPickedOutByCallPointcut( calleeSideClassMetaData, calleeSideMethodMetaData)) { // // TODO: should this caller data be passed to the // join point? It is possible. // String callerMethodName = callerBehaviour.getName(); // String callerMethodSignature = // callerBehaviour.getSignature(); // CtClass[] callerMethodParameterTypes = // callerBehaviour.getParameterTypes(); // int callerMethodModifiers = // callerBehaviour.getModifiers(); // check the callee class is not the same as target class, if that is the case // then we have have class loaded and set in the ___AW_clazz already String declaringClassMethodName = TransformationUtil.STATIC_CLASS_FIELD; CtMethod method = methodCall.getMethod(); CtClass declaringClass = method.getDeclaringClass(); if (!declaringClass .getName() .replace('/', '.') .equals(where.getDeclaringClass().getName().replace('/', '.'))) { declaringClassMethodName = addCalleeMethodDeclaringClassField(ctClass, method); } // call the wrapper method instead of the callee method StringBuffer body = new StringBuffer(); StringBuffer callBody = new StringBuffer(); callBody.append(TransformationUtil.JOIN_POINT_MANAGER_FIELD); callBody.append('.'); callBody.append(TransformationUtil.PROCEED_WITH_CALL_JOIN_POINT_METHOD); callBody.append('('); callBody.append(TransformationUtil.calculateHash(method)); callBody.append(','); callBody.append(m_joinPointIndex); callBody.append(", args"); callBody.append(", $0, declaringClassMethodName, "); callBody.append(TransformationUtil.JOIN_POINT_TYPE_METHOD_CALL); callBody.append(");"); body.append('{'); if (method.getParameterTypes().length > 0) { body.append("Object[] args = $args; "); } else { body.append("Object[] args = null; "); } body.append("Class declaringClassMethodName = "); body.append(declaringClassMethodName); body.append("; "); if (methodCall.getMethod().getReturnType() == CtClass.voidType) { body.append("$_ = ").append(callBody.toString()).append("}"); } else if (!methodCall.getMethod().getReturnType().isPrimitive()) { body.append("$_ = ($r)"); body.append(callBody.toString()); body.append("}"); } else { String localResult = TransformationUtil.ASPECTWERKZ_PREFIX + "res"; body.append("Object ").append(localResult).append(" = "); body.append(callBody.toString()); body.append("if (").append(localResult).append(" != null)"); body.append("$_ = ($r) ").append(localResult).append("; else "); body.append("$_ = "); body.append( JavassistHelper.getDefaultPrimitiveValue( methodCall.getMethod().getReturnType())); body.append("; }"); } methodCall.replace(body.toString()); context.markAsAdvised(); m_joinPointIndex++; } } catch (NotFoundException nfe) { nfe.printStackTrace(); // TODO: should we swallow this exception? } } }); } TransformationUtil.setJoinPointIndex(klass.getCtClass(), m_joinPointIndex); }
public void onLoad(ClassPool pool, String cname) throws NotFoundException, CannotCompileException { System.out.println("Dissecting class " + cname); CtClass clas = pool.get(cname); clas.instrument(new VerboseEditor()); }