package com.yammer.telemetry.agent.handlers; import com.google.common.io.Resources; import javassist.*; import java.io.IOException; import java.nio.charset.Charset; public class HttpServletClassHandler extends SubTypeInstrumentationHandler { public HttpServletClassHandler() { super("javax.servlet.http.HttpServlet"); } protected boolean transform(CtClass cc, ClassPool pool) throws NotFoundException, CannotCompileException, IOException { // Find the service(HttpServletRequest, HttpServletResponse) method so we can wrap it. CtClass request = pool.get("javax.servlet.http.HttpServletRequest"); CtClass response = pool.get("javax.servlet.http.HttpServletResponse"); CtMethod serviceMethod; try { serviceMethod = cc.getDeclaredMethod("service", new CtClass[]{request, response}); } catch (NotFoundException e) { // Not every servlet will implement this method and that's okay. return false; } // Copy the method to a uniquely named location that won't conflict with anything. CtMethod copiedServiceMethod = CtNewMethod.copy(serviceMethod, cc.makeUniqueName("service"), cc, null); copiedServiceMethod.setModifiers(Modifier.PRIVATE); cc.addMethod(copiedServiceMethod); // Swap in a new method body for service() that invokes the copied version of service(). final String source = Resources.toString(Resources.getResource(getClass(), "HttpServlet_service.javassist"), Charset.forName("utf-8")); pool.importPackage("java.util"); pool.importPackage("java.math"); pool.importPackage("com.yammer.telemetry.agent"); pool.importPackage("com.yammer.telemetry.agent.handlers"); pool.importPackage("com.yammer.telemetry.tracing"); serviceMethod.setBody(source, "this", copiedServiceMethod.getName()); return true; } }