private static void inheritAnnotations(final CtClass theClass, final CtMethod theMethod) throws NotFoundException { if (hasMethod(theClass, theMethod)) { CtMethod aOtherMethod = theClass.getMethod(theMethod.getName(), theMethod.getSignature()); // method we're probably overriding or implementing in the case of an abstract method. AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) aOtherMethod.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag); if (annotationsAttribute != null) { ConstPool cp = theClass.getClassFile().getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag); for (Object obj : annotationsAttribute.getAnnotations()) { Annotation a = (Annotation) obj; Annotation theAnnotation = new Annotation(a.getTypeName(), cp); if (a.getMemberNames() != null) { for (Object aName : a.getMemberNames()) { theAnnotation.addMemberValue(aName.toString(), a.getMemberValue(aName.toString())); } } attr.setAnnotation(theAnnotation); } theMethod.getMethodInfo().addAttribute(attr); } } }
/** * For a given interface, generate basic getter and setter methods for all the properties on the * interface. * * @param theInterface the interface * @param thePool the class pool * @param theClass the concrete implementation of the interface * @param <T> the type of the interface * @throws CannotCompileException thrown if there is an error generating the methods * @throws NotFoundException thrown if there is an error generating the methods */ private static <T> void generateMethods( final Class<T> theInterface, final ClassPool thePool, final CtClass theClass) throws CannotCompileException, NotFoundException { Map<String, CtField> aProps = properties(thePool, theClass, theInterface); for (String aProp : aProps.keySet()) { // CtField aNewField = new CtField(thePool.get(aProps.get(aProp).getName()), aProp, theClass); // CtField aNewField = field(theInterface, thePool, theClass, aProp); CtField aNewField = aProps.get(aProp); if (!hasField(theClass, aNewField.getName())) { theClass.addField(aNewField); } if (!hasMethod(theClass, getterName(aProp)) && !hasMethod(theClass, booleanGetterName(aProp))) { CtMethod aMethod = CtNewMethod.getter(getterName(aProp), aNewField); if (aNewField.getType() == CtPrimitiveType.booleanType && !hasMethod(theClass, aMethod)) { aMethod = CtNewMethod.getter(booleanGetterName(aProp), aNewField); } inheritAnnotations(theClass, aMethod); SignatureAttribute attr = (SignatureAttribute) aNewField.getFieldInfo().getAttribute(SignatureAttribute.tag); if (attr != null) { aMethod .getMethodInfo() .addAttribute( new SignatureAttribute( aMethod.getMethodInfo().getConstPool(), "()" + attr.getSignature())); } theClass.addMethod(aMethod); } if (!hasMethod(theClass, setterName(aProp))) { CtMethod aMethod = CtNewMethod.setter(setterName(aProp), aNewField); inheritAnnotations(theClass, aMethod); SignatureAttribute attr = (SignatureAttribute) aNewField.getFieldInfo().getAttribute(SignatureAttribute.tag); if (attr != null) { aMethod .getMethodInfo() .addAttribute( new SignatureAttribute( aMethod.getMethodInfo().getConstPool(), "(" + attr.getSignature() + ")V")); } theClass.addMethod(aMethod); } } }
/** * Similar to main method but is not static * * @param args command line parameters * @throws Exception if something fails during the execution */ public void doIt2(String[] args) throws Exception { // Se carga la clase para la que se quiere modificar sus bytecodes ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.jzb.ja.Clase1"); // Se puede iterar imprimiendo los metodos, y su signatura, contenidos en la clase for (CtMethod mm : cc.getMethods()) { System.out.println(mm.getName() + " " + mm.getMethodInfo().getDescriptor()); } // Se puede buscar un metodo en concreto... CtMethod mr = cc.getMethod("diHola", "(Ljava/lang/String;)Ljava/lang/String;"); // ... Borrarlo... cc.removeMethod(mr); // .. Y volver a escribir su .class moficado en una carpeta raiz cc.writeFile("c:\\tmp"); // Posteriormente, tanto por este codigo de creación dinamica, o porque se usa // el fichero .class generado antes, se obtiene un error de "Metodo No Existe" Class c1 = cc.toClass(); Clase1 o1 = (Clase1) c1.newInstance(); System.out.println(o1.sumaUno(2)); System.out.println(o1.diHola("Pepe")); }
@Override public void describeTo(StringBuilder stringBuilder) { ClosureUtil.SourceInfo sourceInfo = ClosureUtil.getSourceInfo(invoker.getClosure()); if (sourceInfo == null) { ClassPool pool = ClassPool.getDefault(); try { CtClass ctClass = pool.get(invoker.getClosure().getClass().getName()); CtMethod ctMethod = ctClass.getDeclaredMethod("doCall"); int lineNumber = ctMethod.getMethodInfo().getLineNumber(0); ClassFile classFile = ctClass.getClassFile(); String sourceFile = classFile.getSourceFile(); if (lineNumber != -1 && sourceFile != null) { stringBuilder .append("closure at line ") .append(lineNumber) .append(" of ") .append(sourceFile); } else { stringBuilder.append("closure ").append(invoker.getClosure().getClass().getName()); } } catch (NotFoundException e) { stringBuilder.append(invoker.getClosure().getClass().getName()); } } else { stringBuilder .append("closure at line ") .append(sourceInfo.getLineNumber()) .append(" of ") .append(sourceInfo.getUri()); } }
private void findAndRemoveMethod(CtClass ctClass, String methodName) throws NotFoundException { try { CtMethod ctMethod = ctClass.getDeclaredMethod(methodName); ctClass.getClassFile().getMethods().remove(ctMethod.getMethodInfo()); } catch (Exception e) { } }
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 void findAndRemoveMethod(CtClass ctClass, CtField ctField, String className) { try { CtMethod ctMethod = ctClass.getDeclaredMethod( ctField.getName(), new CtClass[] {ctClass.getClassPool().get(className)}); ctClass.getClassFile().getMethods().remove(ctMethod.getMethodInfo()); } catch (Exception e) { } }
private void initExtraHarvest() { try { CtClass terraForming = HookManager.getInstance() .getClassPool() .get("com.wurmonline.server.behaviours.Terraforming"); CtClass[] paramTypes = { HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"), CtPrimitiveType.intType, CtPrimitiveType.intType, CtPrimitiveType.booleanType, CtPrimitiveType.intType, CtPrimitiveType.floatType, HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item") }; CtMethod method = terraForming.getMethod( "harvest", Descriptor.ofMethod(CtPrimitiveType.booleanType, paramTypes)); MethodInfo methodInfo = method.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); CodeIterator codeIterator = codeAttribute.iterator(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); int quantityIndex = -1; for (int i = 0; i < attr.tableLength(); i++) { if ("quantity".equals(attr.variableName(i))) { quantityIndex = attr.index(i); } } if (quantityIndex == -1) { throw new HookException("Quantity variable can not be resolved"); } while (codeIterator.hasNext()) { int pos = codeIterator.next(); int op = codeIterator.byteAt(pos); if (op == CodeIterator.ISTORE) { int fieldRefIdx = codeIterator.byteAt(pos + 1); if (quantityIndex == fieldRefIdx) { Bytecode bytecode = new Bytecode(codeIterator.get().getConstPool()); bytecode.addIconst(extraHarvest); bytecode.add(Bytecode.IADD); codeIterator.insertAt(pos, bytecode.get()); break; } } } } catch (NotFoundException | BadBytecode e) { throw new HookException(e); } }