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 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); } }
/** * 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; }