package org.intrace.agent; import java.lang.instrument.Instrumentation; import java.net.InetSocketAddress; import java.net.Socket; import org.intrace.agent.server.AgentClientConnection; import org.intrace.agent.server.AgentServer; import org.intrace.output.AgentHelper; import org.intrace.output.trace.TraceHandler; public class AgentInit { static int serverPort = -1; /** * Common init function. * * @param agentArgs * @param inst */ public static void initialize(String agentArgs, Instrumentation inst) { System.out.println("## Loaded InTrace Agent."); if (agentArgs == null) { agentArgs = ""; } // Setup the trace instrumentation handler AgentHelper.setInstrumentationHandler(TraceHandler.INSTANCE); // Parse startup args AgentSettings args = new AgentSettings(agentArgs); AgentHelper.getResponses(null, agentArgs); // Construct Transformer ClassTransformer t = new ClassTransformer(inst, args); inst.addTransformer(t, inst.isRetransformClassesSupported()); // Ensure loaded classes are traced t.instrumentKlasses(t.getLoadedClassesForModification()); // Start Server thread new AgentServer(t, args.getServerPort()).start(); // Store server port waitForServerPort(); args.setActualServerPort(serverPort); // Wait for callback connection if (args.getCallbackPort() > -1) { System.out.println("## Establishing Callback Connection..."); doCallbackConnection(args.getCallbackPort(), t); } // Wait for startup if (args.isWaitStart()) { try { System.out.println("## Program Paused"); AgentServer.waitForStartSignal(); } catch (InterruptedException e) { e.printStackTrace(); } } // Setup shutdown hook Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { AgentHelper.gracefulShutdown(); } }); } public static synchronized void setServerPort(int xiServerPort) { serverPort = xiServerPort; AgentInit.class.notifyAll(); } static synchronized void waitForServerPort() { try { while (serverPort == -1) { AgentInit.class.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } /** * This is a mechanism which allows a client to listen on a particular port and have the * Agent server make the initial connection. This is useful when the client launches the Agent * and wants to connect as soon as the Agent starts up. This is used by the Eclipse plugin. * @param callbackPort * @param t */ static void doCallbackConnection(int callbackPort, ClassTransformer t) { try { Socket callback = new Socket(); callback.connect(new InetSocketAddress("localhost", callbackPort)); AgentClientConnection clientConnection = new AgentClientConnection( callback, t); AgentServer.addClientConnection(clientConnection); clientConnection.start(1); clientConnection.waitForTraceConn(); } catch (Exception ex) { ex.printStackTrace(); } } }