/* * Copyright, Aspect Security, Inc. * * This file is part of JavaSnoop. * * JavaSnoop is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JavaSnoop is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JavaSnoop. If not, see <http://www.gnu.org/licenses/>. */ package com.aspect.snoop.agent; import com.aspect.snoop.agent.manager.InstrumentationManager; import com.aspect.snoop.ui.JavaSnoopView; import java.io.File; import java.io.IOException; import java.lang.instrument.Instrumentation; import java.util.Properties; import java.util.jar.JarFile; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; public class SnoopAgent { private static Instrumentation inst; private static InstrumentationManager manager; private static JavaSnoopView mainView; private static final int defaultGuiDelay = 5; public static JavaSnoopView getMainView() { return mainView; } public static void premain(String args, Instrumentation instrumentation) { install(args,instrumentation); } public static void agentmain(String args, Instrumentation instrumentation) { turnOffSecurity(); install(args,instrumentation); } public static void install(String args, Instrumentation instrumentation) { inst = instrumentation; AgentLogger.debug("Loading manager..."); manager = new InstrumentationManager(inst); AgentLogger.debug("Done with manager..."); turnOffSecurity(); AgentLogger.debug("Turned off security..."); String arguments[] = args.split("\\|"); String javaSnoopDir = arguments[0]; int guiDelay = defaultGuiDelay; try { guiDelay = Integer.parseInt(arguments[1]); } catch (Exception e) { AgentLogger.error("Gui delay wasn't supplied in agent arguments: " + "defaulting to " + defaultGuiDelay,e); } final int delay = guiDelay; final String lookAndFeelOverride; if ( arguments.length == 3 ) lookAndFeelOverride = arguments[2]; else lookAndFeelOverride = null; /* * We need to add some of the libraries to be eventually * loaded by the system class loader instead of the * boostrap class loader, which is represented as null in * Java land. This causes problems. */ AgentLogger.debug("Adding runtime jars to system classloader..."); String libDir = new File(javaSnoopDir).getAbsolutePath() + File.separator + "lib" + File.separator; try { inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "rsyntaxtextarea.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "aspect-swing-worker-1.1.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "aspect-appframework-1.0.3.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "bsh-2.0b4.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "jython.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "xom-1.1.jar")); inst.appendToSystemClassLoaderSearch(new JarFile(libDir + "xstream-1.3.1.jar")); } catch (IOException ex) { AgentLogger.fatal(ex); } AgentLogger.trace("Queueing GUI to run..."); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { /* * I apologize profusely for this hack, but I can't think of a * way to avoid it. * * Lemma 1: The JavaSnoop GUI must run within the targeted * process so its reflection model and objects can * be accessed directly. * Lemma 2: You can't have 2 different Look and Feels operating * at the same time in a single JVM. * * This means that our GUIs will clash. If I set the look and * feel, it may override what the target process developers * intended. This would suck. So what we do to avoid it is * pause for a few seconds (default is 5), and give the * target process time to initialize Swing. If the process * has a long non-UI buildup, you may have to increase this * value. */ if (delay!=0) AgentLogger.trace("Delaying " + delay + " seconds..."); try { Thread.sleep(delay * 1000); } catch (InterruptedException ex) { } /* * Sometimes the application's custom LookAndFeel messes up * how JavaSnoop components are displayed because they're not * builto to the types of components we use. So we allow the * JavaSnoop user to override the target application's L&F. */ if (lookAndFeelOverride != null && !"".equals(lookAndFeelOverride)) { try { for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(laf.getName())) { UIManager.setLookAndFeel(laf.getClassName()); break; } } } catch (Exception ex) { AgentLogger.error("Problem overriding LookAndFeel",ex); } } AgentLogger.debug("Running GUI..."); JavaSnoopView view = new JavaSnoopView(manager); mainView = view; AgentLogger.debug("GUI created. Running JavaSnoop!"); view.setVisible(true); } }); return; } private static void turnOffSecurity() { /* * Test if we're inside an applet. We should be inside * an applet if the System property ("package.restrict.access.sun") * is not null and is set to true. */ boolean restricted = System.getProperty("package.restrict.access.sun") != null; /* * If we're in an applet, we need to change the System properties so * as to avoid class restrictions. We go through the current properties * and remove anything related to package restriction. */ if ( restricted ) { Properties newProps = new Properties(); Properties sysProps = System.getProperties(); for(String prop : sysProps.stringPropertyNames()) { if ( prop != null && ! prop.startsWith("package.restrict.") ) { newProps.setProperty(prop,sysProps.getProperty(prop)); } } System.setProperties(newProps); } /* * Should be the final nail in (your) coffin. */ System.setSecurityManager(null); } public static Instrumentation getInstrumentation() { return inst; } public static InstrumentationManager getAgentManager() { return manager; } }