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

hudson.remoting.Which Maven / Gradle / Ivy

/*
 * The MIT License
 * 
 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Ullrich Hafner
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package hudson.remoting;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.InputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.net.JarURLConnection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.zip.ZipFile;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import java.util.logging.Level;

/**
 * Locates where a given class is loaded from.
 *
 * @author Kohsuke Kawaguchi
 */
public class Which {
    /**
     * Locates the jar file that contains the given class.
     *
     * @throws IllegalArgumentException
     *      if failed to determine.
     */
    public static URL jarURL(Class clazz) throws IOException {
        ClassLoader cl = clazz.getClassLoader();
        if(cl==null)
            cl = ClassLoader.getSystemClassLoader();
        URL res = cl.getResource(clazz.getName().replace('.', '/') + ".class");
        if(res==null)
            throw new IllegalArgumentException("Unable to locate class file for "+clazz);
        return res;
    }

    /**
     * Locates the jar file that contains the given class.
     *
     * 

* Note that jar files are not always loaded from {@link File}, * so for diagnostics purposes {@link #jarURL(Class)} is preferrable. * * @throws IllegalArgumentException * if failed to determine. */ public static File jarFile(Class clazz) throws IOException { URL res = jarURL(clazz); String resURL = res.toExternalForm(); String originalURL = resURL; if(resURL.startsWith("jar:file:") || resURL.startsWith("wsjar:file:")) return fromJarUrlToFile(resURL); if(resURL.startsWith("code-source:/")) { // OC4J apparently uses this. See http://www.nabble.com/Hudson-on-OC4J-tt16702113.html resURL = resURL.substring("code-source:/".length(), resURL.lastIndexOf('!')); // cut off jar: and the file name portion return new File(decode(new URL("file:/"+resURL).getPath())); } if(resURL.startsWith("zip:")){ // weblogic uses this. See http://www.nabble.com/patch-to-get-Hudson-working-on-weblogic-td23997258.html // also see http://www.nabble.com/Re%3A-Hudson-on-Weblogic-10.3-td25038378.html#a25043415 resURL = resURL.substring("zip:".length(), resURL.lastIndexOf('!')); // cut off zip: and the file name portion return new File(decode(new URL("file:"+resURL).getPath())); } if(resURL.startsWith("file:")) { // unpackaged classes int n = clazz.getName().split("\\.").length; // how many slashes do wo need to cut? for( ; n>0; n-- ) { int idx = Math.max(resURL.lastIndexOf('/'), resURL.lastIndexOf('\\')); if(idx<0) throw new IllegalArgumentException(originalURL + " - " + resURL); resURL = resURL.substring(0,idx); } // won't work if res URL contains ' ' // return new File(new URI(null,new URL(res).toExternalForm(),null)); // won't work if res URL contains '%20' // return new File(new URL(res).toURI()); return new File(decode(new URL(resURL).getPath())); } if(resURL.startsWith("vfszip:")) { // JBoss5 InputStream is = res.openStream(); try { Object delegate = is; try { while (delegate.getClass().getEnclosingClass()!=ZipFile.class) { Field f = delegate.getClass().getDeclaredField("delegate"); f.setAccessible(true); delegate = f.get(delegate); } } catch (NoSuchFieldException e) { // extra step for JDK6u24; zip internals have changed Field f = delegate.getClass().getDeclaredField("is"); f.setAccessible(true); delegate = f.get(delegate); } Field f = delegate.getClass().getDeclaredField("this$0"); f.setAccessible(true); ZipFile zipFile = (ZipFile)f.get(delegate); return new File(zipFile.getName()); } catch (Throwable e) { // something must have changed in JBoss5. fall through LOGGER.log(Level.FINE, "Failed to resolve vfszip into a jar location",e); } finally { is.close(); } } if(resURL.startsWith("vfs:") || resURL.startsWith("vfsfile:")) { // JBoss6 try { String resource = '/' + clazz.getName().replace('.', '/'); resURL = resURL.substring(0, resURL.lastIndexOf(resource)); Object content = new URL(res, resURL).getContent(); if (content instanceof File) { return (File)content; } Method m = content.getClass().getMethod( "getPhysicalFile" ); return (File)m.invoke(content); } catch ( Throwable e ) { // something must have changed in JBoss6. fall through LOGGER.log(Level.FINE, "Failed to resolve vfs/vfsfile into a jar location",e); } } if(resURL.startsWith("bundleresource:") || resURL.startsWith("bundle:")) { // Equinox/Felix/etc. try { URLConnection con = res.openConnection(); Method m = con.getClass().getDeclaredMethod( "getLocalURL" ); m.setAccessible(true); res = (URL)m.invoke(con); } catch ( Throwable e ) { // something must have changed in Equinox. fall through LOGGER.log(Level.FINE, "Failed to resolve bundleresource into a jar location",e); } } URLConnection con = res.openConnection(); if (con instanceof JarURLConnection) { JarURLConnection jcon = (JarURLConnection) con; JarFile jarFile = jcon.getJarFile(); if (jarFile!=null) { String n = jarFile.getName(); if(n.length()>0) {// JDK6u10 needs this return new File(n); } else { // JDK6u10 apparently starts hiding the real jar file name, // so this just keeps getting tricker and trickier... try { Field f = ZipFile.class.getDeclaredField("name"); f.setAccessible(true); return new File((String) f.get(jarFile)); } catch (NoSuchFieldException e) { LOGGER.log(Level.INFO, "Failed to obtain the local cache file name of "+clazz, e); } catch (IllegalAccessException e) { LOGGER.log(Level.INFO, "Failed to obtain the local cache file name of "+clazz, e); } } } } throw new IllegalArgumentException(originalURL + " - " + resURL); } public static File jarFile(URL resource) throws IOException { return fromJarUrlToFile(resource.toExternalForm()); } private static File fromJarUrlToFile(String resURL) throws MalformedURLException { resURL = resURL.substring(resURL.indexOf(':')+1, resURL.lastIndexOf('!')); // cut off "scheme:" and the file name portion return new File(decode(new URL(resURL).getPath())); } /** * Decode '%HH'. */ private static String decode(String s) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); for( int i=0; i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy