/******************************************************************************* * Copyright (c) 2010 Eric Bodden. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eric Bodden - initial API and implementation ******************************************************************************/ package de.bodden.tamiflex.playin; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.net.URISyntaxException; import java.util.Properties; import de.bodden.tamiflex.normalizer.Hasher; /** * This agent registers a {@link ClassReplacer} as a class-file transformer. */ public class Agent { public final static String PKGNAME = Agent.class.getPackage().getName().replace('.', '/'); private static String inPath = "out"; private static boolean verbose = false; public static void premain(String agentArgs, Instrumentation inst) throws IOException, ClassNotFoundException, UnmodifiableClassException, URISyntaxException, IllegalClassFormatException { System.out.println("======================================================="); System.out.println("TamiFlex Play-In Agent Version "+Agent.class.getPackage().getImplementationVersion()); loadProperties(); final ClassReplacer replacer = new ClassReplacer(inPath,verbose); inst.addTransformer(replacer,true); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.out.println("\n======================================================="); System.out.println("TamiFlex Play-In Agent Version "+Agent.class.getPackage().getImplementationVersion()); System.out.println("Replaced "+replacer.numSuccess+" out of "+replacer.numInvoked+" classes."); System.out.println("======================================================="); } }); System.out.println("======================================================="); for (Class<?> c : inst.getAllLoadedClasses()) { if(inst.isModifiableClass(c)) { inst.retransformClasses(c); } else if(verbose) { //warn if there is a class that we cannot re-transform, except for classes that resemble primitive types, //arrays or are in java.lang if(!c.isPrimitive() && !c.isArray() && (c.getPackage()==null || !c.getPackage().getName().startsWith("java.lang"))){ System.out.println("WARNING: Cannot replace class "+c.getName()); } } } } private static void loadProperties() { String propFileName = "pia.properties"; String userPropFilePath = System.getProperty("user.home")+File.separator+".tamiflex"+File.separator+propFileName; copyPropFileIfMissing(userPropFilePath); String[] paths = { propFileName, userPropFilePath }; InputStream is = null; File foundFile= null; for (String path : paths) { File file = new File(path); if(file.exists() && file.canRead()) { try { is = new FileInputStream(file); foundFile = file; break; } catch (FileNotFoundException e) { e.printStackTrace(); } } } if(is==null) throw new InternalError("No properties files found!"); Properties props = new Properties(); try { props.load(is); if(!props.containsKey("quiet") || !props.get("quiet").equals("true")) { String path = (foundFile!=null) ? foundFile.getAbsolutePath() : "<JAR FILE>!/"+propFileName; System.out.println("Loaded properties from "+path); } if(props.get("dontNormalize").equals("true")) Hasher.dontNormalize(); if(props.get("verbose").equals("true")) verbose = true; if(props.containsKey("inDir")) inPath = (String) props.get("inDir"); } catch (IOException e) { throw new InternalError("Error loading default properties file: "+e.getMessage()); } } //COPIED from POA private static void copyPropFileIfMissing(String userPropFilePath) { File f = new File(userPropFilePath); if(!f.exists()) { File dir = f.getParentFile(); if(!dir.exists()) dir.mkdirs(); try { FileOutputStream fos = new FileOutputStream(f); InputStream is = Agent.class.getClassLoader().getResourceAsStream(f.getName()); if(is==null) { throw new InternalError("No default properties file found in agent JAR file!"); } int i; while((i=is.read())!=-1) { fos.write(i); } fos.close(); is.close(); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { usage(); } private static void usage() { System.out.println("============================================================"); System.out.println("TamiFlex Play-In Agent Version "+Agent.class.getPackage().getImplementationVersion()); System.out.println(DISCLAIMER); System.out.println("============================================================"); System.exit(1); } private final static String DISCLAIMER= "Copyright (c) 2010 Eric Bodden.\n" + "\n" + "DISCLAIMER: USE OF THIS SOFTWARE IS AT OWN RISK.\n" + "\n" + "All rights reserved. This program and the accompanying materials\n" + "are made available under the terms of the Eclipse Public License v1.0\n" + "which accompanies this distribution, and is available at\n" + "http://www.eclipse.org/legal/epl-v10.html"; }