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

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

Go to download

A runtime patcher to introduce extension points into the original ImageJ (1.x). This project offers extension points for use with ImageJ2 and it also offers limited support for headless operations.

There is a newer version: 1.2.7
Show newest version
/*
 * #%L
 * ImageJ software for multidimensional image processing and analysis.
 * %%
 * Copyright (C) 2009 - 2016 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 - 2024 Weber Informatics LLC | Privacy Policy