All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.imagej.patcher.JavaAgent Maven / Gradle / Ivy

/*
 * #%L
 * ImageJ software for multidimensional image processing and analysis.
 * %%
 * Copyright (C) 2009 - 2015 Board of Regents of the University of
 * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
 * Institute of Molecular Cell Biology and Genetics.
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * #L%
 */

package net.imagej.patcher;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtNewConstructor;
import javassist.Modifier;

/**
 * A Java agent to help with legacy issues.
 * 
 * @author Johannes Schindelin
 */
public class JavaAgent implements ClassFileTransformer {

	private static Instrumentation instrumentation;
	private static JavaAgent agent;
	private static Transformer transformer;

	public static void stop() {
		if (instrumentation != null && agent != null) {
			instrumentation.removeTransformer(agent);
			agent = null;
		}
		transformer = null;
	}

	/**
	 * The premain method started at JVM startup.
	 * 
	 * When this class is specified as Premain-Class in the manifest and
	 * the JVM is started with the option
	 * -javaagent:/path/to/ij1-patcher.jar then this method is called
	 * some time before the main method of the main class is called.
	 * 
	 * @param agentArgs the optional argument passed  via -javaagent:ij1-patcher.jar=ARGUMENT
	 * @param instrumentation the {@link Instrumentation} instance passed by the JVM
	 */
	public static void premain(final String agentArgs, final Instrumentation instrumentation) {
		JavaAgent.instrumentation = instrumentation;
		if ("help".equals(agentArgs)) {
			usage();
			return;
		} else if ("init".equals(agentArgs) || "preinit".equals(agentArgs) || "pre-init".equals(agentArgs)) {
			preinit();
			return;
		} else if ("noop".equals(agentArgs)) {
			return;
		} else if ("debug".equals(agentArgs)) {
			transformer = new Transformer();
		} else if (agentArgs != null && !"report".equals(agentArgs)) {
			System.err.println("Unhandled agent option: " + agentArgs);
			usage();
			return;
		}
		agent = new JavaAgent();
		instrumentation.addTransformer(agent);
		System.err.println("Legacy Java agent initialized");
	}

	@Override
	public byte[] transform(ClassLoader loader, String className,
			Class classBeingRedefined, ProtectionDomain protectionDomain,
			byte[] classfileBuffer) throws IllegalClassFormatException {
		if (className.startsWith("ij.") || className.startsWith("ij/") ||
				className.matches("net.imagej.patcher.EssentialLegacyHooks")) {
			return reportCaller("Loading " + className + " into " + loader + "!", classfileBuffer);
		}
		return null;
	}

	private static void usage() {
		System.err.println("ImageJ Legacy Agent Usage:\n" +
				"\n" +
				"The ij1-patcher agent's purpose is to help with issues arising from ImageJ 1.x\n" +
				"classes being used before the ImageJ2 legacy service's pre-initialization stage\n" +
				"had a chance to run.\n" +
				"\n" +
				"Pre-initialization of the ImageJ2 legacy service is necessary in order to add\n" +
				"the extension points to ImageJ 1.x' classes that are required for the ImageJ2\n" +
				"legacy service to synchronize between the internal states of the legacy and\n" +
				"modern mode, respectively.\n" +
				"\n" +
				"Use the agent via the JVM option -javaagent=/path/to/ij1-patcher.jar[=




© 2015 - 2025 Weber Informatics LLC | Privacy Policy