package org.coldswap.agent;
import org.coldswap.instrumentation.ClassInstrumenter;
import org.coldswap.tracker.ClassWatcher;
import org.coldswap.transformer.*;
import org.coldswap.util.ClassUtil;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* (C) Copyright 2013 Faur Ioan-Aurel.
* <p/>
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
* <p/>
* This library 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
* Lesser General Public License for more details.
* <p/>
* Contributors:
* faur
* <p/>
* Created at:
* 2:01 PM 3/15/13
*/
public class ColdSwapAgent {
private static final Logger logger = Logger.getLogger(ColdSwapAgent.class.getName());
private static final ClassInstrumenter instrumenter = ClassInstrumenter.getInstance();
static {
logger.setLevel(ClassUtil.logLevel);
}
public static void premain(String args, Instrumentation inst) {
AgentArgsParser argsParser = new AgentArgsParser(args);
argsParser.buildArgs();
ClassUtil.logLevel = (Level) argsParser.getArgument("logLevel");
int maxMethods = (Integer) argsParser.getArgument("maxNumberOfMethods");
inst.addTransformer(new ClInitTransformer());
inst.addTransformer(new ObjectMethodTransformer(maxMethods));
inst.addTransformer(new IntMethodTransformer(maxMethods));
inst.addTransformer(new FloatMethodTransformer(maxMethods));
inst.addTransformer(new StringMethodTransformer(maxMethods));
inst.addTransformer(new LongMethodTransformer(maxMethods));
instrumenter.setInstrumenter(inst);
// set java library path for jnotify
StringBuilder sb = new StringBuilder(System.getProperty("user.home"));
String separator = System.getProperty("file.separator");
sb.append(separator).append(".coldswap").append(separator).append("native").append(separator);
String jlp = System.getProperty("java.library.path");
System.setProperty("java.library.path", jlp + ":" + sb.toString());
// here is a fine trick. Usually java.library.path must be set before
// the application is started. But here's a dirty trick that forces
// the class loader to automatically reload the library paths by setting a
// static field to null.
// Credits goes to folks at https://jdic.dev.java.net/
Field fieldSysPath;
try {
fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (NoSuchFieldException e) {
logger.severe("Please restart coldswap with this argument: -Djava.library.path=\"" + sb.toString() + "\"\n");
System.exit(0);
} catch (IllegalAccessException e) {
logger.severe("Please restart coldswap with this argument: -Djava.library.path=\"" + sb.toString() + "\"\n");
System.exit(0);
}
String[] dirs;
ClassWatcher[] monitors;
try {
dirs = (String[]) argsParser.getArgument("cp");
monitors = new ClassWatcher[dirs.length];
} catch (NullPointerException e) {
logger.severe("There is no folder to watch for reloading.\n" + e.toString());
return;
} catch (ClassCastException e) {
logger.severe("Invalid values provided to cp argument!\n" + e.toString());
return;
}
String recursive = "false";
try {
recursive = (String) argsParser.getArgument("recursive");
} catch (NullPointerException e) {
logger.severe("There is no recursive argument provided to ColdSwap.\n" + e.toString());
} catch (ClassCastException e) {
logger.severe("Invalid value provided to recursive argument!\n" + e.toString());
}
for (int i = 0; i < monitors.length; i++) {
monitors[i] = new ClassWatcher(dirs[i], "true".equals(recursive), maxMethods);
Thread t = new Thread(monitors[i]);
t.setDaemon(true);
t.start();
}
}
}