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

imagej.patcher.EssentialLegacyHooks 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 imagej.patcher;

import ij.IJ;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * The base {@link LegacyHooks} to be used in the patched ImageJ 1.x.
 * 

* This is the minimal implementation of {@link LegacyHooks} and will be * installed by default after patching in the extension points into ImageJ 1.x. * On its own, it does not allow to override the extension points (such as the * editor) with different implementations; one needs to install different hooks using * the {@link imagej.patcher.LegacyInjector#installHooks(ClassLoader, LegacyHooks)} method. *

*

* This class is also the perfect base class for all implementations of the * {@link LegacyHooks} interface, e.g. to offer "real" extension mechanisms such * as the SciJava-common plugin framework. *

* * @author Johannes Schindelin */ @Deprecated public class EssentialLegacyHooks extends LegacyHooks { @Override public void error(Throwable t) { IJ.handleException(t); } @Override public boolean handleNoSuchMethodError(NoSuchMethodError error) { String message = error.getMessage(); int paren = message.indexOf("("); if (paren < 0) return false; int dot = message.lastIndexOf(".", paren); if (dot < 0) return false; String path = message.substring(0, dot).replace('.', '/') + ".class"; Set urls = new LinkedHashSet(); try { Enumeration e = IJ.getClassLoader().getResources(path); while (e.hasMoreElements()) { urls.add(e.nextElement().toString()); } e = IJ.getClassLoader().getResources("/" + path); while (e.hasMoreElements()) { urls.add(e.nextElement().toString()); } } catch (Throwable t) { t.printStackTrace(); return false; } if (urls.size() == 0) return false; StringBuilder buffer = new StringBuilder(); buffer.append("There was a problem with the class "); buffer.append(message.substring(0, dot)); buffer.append(" which can be found here:\n"); for (String url : urls) { if (url.startsWith("jar:")) url = url.substring(4); if (url.startsWith("file:")) url = url.substring(5); int bang = url.indexOf("!"); if (bang < 0) buffer.append(url); else buffer.append(url.substring(0, bang)); buffer.append("\n"); } if (urls.size() > 1) { buffer.append("\nWARNING: multiple locations found!\n"); } StringWriter writer = new StringWriter(); error.printStackTrace(new PrintWriter(writer)); buffer.append(writer.toString()); IJ.log(buffer.toString()); IJ.error("Could not find method " + message + "\n(See Log for details)\n"); return true; } @Override public void initialized() { final String property = System.getProperty("ij1.patcher.initializer"); try { final ClassLoader loader = IJ.getClassLoader(); Thread.currentThread().setContextClassLoader(loader); Class runClass; if (property != null) { runClass = loader.loadClass(property); } else { try { runClass = loader.loadClass("net.imagej.legacy.plugin.LegacyInitializer"); } catch (ClassNotFoundException e) { runClass = loader.loadClass("imagej.legacy.plugin.LegacyInitializer"); } } final Runnable run = (Runnable)runClass.newInstance(); run.run(); } catch (ClassNotFoundException e) { // ignore } catch (Throwable t) { t.printStackTrace(); } } /** * Intercepts LegacyInitializer's Context creation. *

* One of the most critical code paths in Fiji * is how its runtime patches get installed. It calls the * {@link LegacyEnvironment}, of course, but the idea is for said environment * to install the essential {@link LegacyHooks} which then give ImageJ's * DefaultLegacyService a chance to spin up all of the legacy patches, * including Fiji's (which are add-ons on top of {@code imagej-legacy}). *

*

* If this critical code path fails, Fiji fails to start up properly. Ideally, * this should never happen, but this is not an ideal world: corrupt * {@code .jar} files and version skews caused by forgotten updates, * locally-modified files or simply by forward-incompatible downstream updates * can break any number of things in that path. So let's bend over another * inch (the existence of the {@code ij1-patcher} speaks volumes about our * learned ability to do so) and try extra hard to keep things working even * under very unfavorable circumstances. *

* * @param className the class name * @param arg the argument passed to the {@code runPlugIn} method * @return the object to return, or null to let ImageJ 1.x handle the call */ @Override public Object interceptRunPlugIn(final String className, final String arg) { if ("org.scijava.Context".equals(className)) { try { final Class contextClass = IJ.getClassLoader().loadClass(className); try { return contextClass.newInstance(); } catch (Throwable t) { // "Something" failed... Darn. t.printStackTrace(); // Try again, with the bare minimum of services: DefaultLegacyService // and friends Class legacyServiceClass; try { legacyServiceClass = IJ.getClassLoader().loadClass( "net.imagej.legacy.DefaultLegacyService"); } catch (Throwable t2) { legacyServiceClass = IJ.getClassLoader().loadClass( "imagej.legacy.DefaultLegacyService"); } Constructor ctor = contextClass.getConstructor((Class) Class[].class); return ctor .newInstance((Object) new Class[] { legacyServiceClass }); } } catch (Throwable t) { t.printStackTrace(); System.err.println("Giving up to create a SciJava Context!"); } } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy