package de.mpicbg.knime.scripting.groovy.utils; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; /** * Document me! * * @author Holger Brandl */ public class JarJarURLStreamHandler extends URLStreamHandler { protected URLConnection openConnection(URL u) throws IOException { return new JarJarURLConnection(u); } private int indexOfBangSlash(String spec) { int indexOfBang = spec.length(); while ((indexOfBang = spec.lastIndexOf(JarJarURLConnection.SEPARATOR_CHAR, indexOfBang)) != -1) { if ((indexOfBang != (spec.length() - 1)) && (spec.charAt(indexOfBang + 1) == '/')) { return indexOfBang + 1; } else { indexOfBang--; } } return -1; } @SuppressWarnings({"deprecation"}) protected void parseURL(URL url, String spec, int start, int limit) { String file = null; String ref = null; // first figure out if there is an anchor int refPos = spec.indexOf('#', limit); boolean refOnly = refPos == start; if (refPos > -1) { ref = spec.substring(refPos + 1, spec.length()); if (refOnly) { file = url.getFile(); } } // then figure out if the spec is // 1. absolute (jarjar:) // 2. relative (i.e. url + foo/bar/baz.ext) // 3. anchor-only (i.e. url + #foo), which we already did (refOnly) boolean absoluteSpec = false; if (spec.length() >= 7) { absoluteSpec = spec.substring(0, 7).equalsIgnoreCase("jarjar:"); } spec = spec.substring(start, limit); if (absoluteSpec) { file = parseAbsoluteSpec(spec); } else if (!refOnly) { file = parseContextSpec(url, spec); // Canonize the result after the bangslash int bangSlash = indexOfBangSlash(file); String toBangSlash = file.substring(0, bangSlash); String afterBangSlash = file.substring(bangSlash); file = toBangSlash + afterBangSlash; } file = file != null ? "jar:" + file.replaceFirst("\\" + JarJarURLConnection.SEPARATOR, "!/") : null; setURL(url, "jarjar", "", -1, file, ref); } @SuppressWarnings({"UnusedAssignment", "UnusedDeclaration"}) private String parseAbsoluteSpec(String spec) { @SuppressWarnings("unused") URL url = null; int index = -1; // check for !/ if ((index = indexOfBangSlash(spec)) == -1) { throw new NullPointerException("no " + JarJarURLConnection.SEPARATOR + " in spec"); } // test the inner URL try { String innerSpec = spec.substring(0, index - 1); url = new URL(innerSpec); } catch (MalformedURLException e) { throw new NullPointerException("invalid url: " + spec + " (" + e + ")"); } return spec; } private String parseContextSpec(URL url, String spec) { String ctxFile = url.getFile(); // if the spec begins with /, chop up the jar back !/ if (spec.startsWith("/")) { int bangSlash = indexOfBangSlash(ctxFile); if (bangSlash == -1) { throw new NullPointerException("malformed " + "context url:" + url + ": no " + JarJarURLConnection.SEPARATOR); } ctxFile = ctxFile.substring(0, bangSlash); } if (!ctxFile.endsWith("/") && (!spec.startsWith("/"))) { // chop up the last component int lastSlash = ctxFile.lastIndexOf('/'); if (lastSlash == -1) { throw new NullPointerException("malformed " + "context url:" + url); } ctxFile = ctxFile.substring(0, lastSlash + 1); } return (ctxFile + spec); } }