/** * Copyright (C) 2004 Orbeon, Inc. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html */ package org.orbeon.oxf.util; import org.apache.commons.lang3.StringUtils; import org.orbeon.oxf.common.OXFException; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLDecoder; import java.util.*; public class SystemUtils { public static File getTemporaryDirectory() { return new File(System.getProperty("java.io.tmpdir")).getAbsoluteFile(); } /** * @param pth java.io.File.pathSeparator delimited path. * @return What you think. */ public static File[] pathToFiles(final String pth) { final ArrayList pthArr = new ArrayList(); final StringTokenizer st = new StringTokenizer (pth, File.pathSeparator); while (st.hasMoreTokens()) { final String fnam = st.nextToken(); final File fil = new File(fnam); pthArr.add(fil); } final File[] ret = new File[pthArr.size()]; pthArr.toArray(ret); return ret; } /** * @param trgt Receiver of path elements ( as java.io.File ) from pth. * @param pth java.io.File.pathSeparator delimited path. */ public static void gatherPaths(final Collection trgt, final String pth) { final File[] files = pathToFiles(pth); for (int i = 0; i < files.length; i++) { trgt.add(files[i]); } } /** * @param c Reciever of java.io.File's gathered from sun.boot.class.path elements * as well as the contents of the dirs named in java.ext.dirs. */ public static void gatherSystemPaths(final Collection c) { final String bootcp = System.getProperty("sun.boot.class.path"); gatherPaths(c, bootcp); final String extDirProp = System.getProperty("java.ext.dirs"); final File[] extDirs = pathToFiles(extDirProp); for (int i = 0; i < extDirs.length; i++) { final File[] jars = extDirs[i].listFiles(); if (jars != null) { // jars can be null when java.ext.dirs points to a non-existant directory for (int j = 0; j < jars.length; j++) { final File fil = jars[j]; final String fnam = fil.toString(); final int fnamLen = fnam.length(); if (fnamLen < 5) continue; if (fnam.regionMatches(true, fnamLen - 4, ".jar", 0, 4)) { c.add(fil); } else if (fnam.regionMatches(true, fnamLen - 4, ".zip", 0, 4)) { c.add(fil); } } } } } /** * Walks class loader hierarchy of clazz looking for instances of URLClassLoader. * For each found gets file urls and adds, converted, elements to the path. * Note that the more junior a class loader is the later in the path it's * contribution is. <br/> * Also, tries to deal with fact that urls may or may not be encoded. * Converts the urls to java.io.File and checks for existence. If it * exists file name is used as is. If not name is URLDecoded. If the * decoded form exists that that is used. If neither exists then the * undecoded for is used. * * @param clazz Class to try and build a classpath from. * @return java.io.File.pathSeparator delimited path. */ public static String pathFromLoaders(final Class clazz) throws java.io.UnsupportedEncodingException { final TreeSet sysPths = new TreeSet(); gatherSystemPaths(sysPths); final StringBuilder sbuf = new StringBuilder(); final LinkedList urlLst = new LinkedList(); for (ClassLoader cl = clazz.getClassLoader(); cl != null; cl = cl.getParent()) { if (!(cl instanceof java.net.URLClassLoader)) { continue; } final java.net.URLClassLoader ucl = (java.net.URLClassLoader) cl; final java.net.URL[] urls = ucl.getURLs(); if (urls == null) continue; for (int i = urls.length - 1; i > -1; i--) { final java.net.URL url = urls[i]; final String prot = url.getProtocol(); if (!"file".equalsIgnoreCase(prot)) continue; urlLst.addFirst(url); } } for (final Iterator itr = urlLst.iterator(); itr.hasNext();) { final java.net.URL url = (java.net.URL) itr.next(); final String fnam = url.getFile(); final File fil = new File(fnam); if (sysPths.contains(fil)) continue; // 11/14/2004 d : Odd test attempts to deal with fact that // a.) The URLs passed to a URLClassLoader don't have to be encoded // in general. // b.) The app class loader and the extensions class loader, the // jdk class loaders responsible for loading classes from classpath // and the extensions dir respectively, do encode their urls. // c.) java.io.File.toURL doesn't produce encoded urls. ( Perhaps // a sun bug... ) // As you can see given (a) and (c) odds are pretty good that // should anyone use something other than jdk class loaders we // will end up unencoded urls. if (!fil.exists()) { final String unEncNam = URLDecoder.decode(fnam, "utf-8"); final File unEncFil = new File(unEncNam); if (unEncFil.exists()) sbuf.append(unEncNam); } else { sbuf.append(fnam); } sbuf.append(File.pathSeparatorChar); } final String ret = sbuf.toString(); return ret; } public static String getJarPath(Class clazz) { String resourceName = StringUtils.replace(clazz.getName(), ".", "/") + ".class"; try { URL url = clazz.getClassLoader().getResource(resourceName); if (url == null) throw new IllegalArgumentException("Invalid resource name: " + resourceName); if (url.getProtocol().equals("jar")) { if (url.getProtocol().equals("jar")) { // The current class is in a JAR file String fileName = url.getFile(); int end = fileName.length() - ("!/".length() + resourceName.length()); final String fileSlash = "file:/"; final int fileSlashLen = fileSlash.length(); if (end > fileSlashLen && fileName.regionMatches(true, 0, fileSlash, 0, fileSlashLen)) { fileName = fileName.substring(fileSlashLen, end); File file = new File(fileName); if (!file.exists()) { // Try to decode only if we cannot find the file (see explanation in other method above) fileName = URLDecoder.decode(fileName, "utf-8"); } File jarDirectory = new File(fileName).getParentFile(); if (jarDirectory.isDirectory()) return jarDirectory.getCanonicalPath(); } } } return null; } catch (IOException e) { throw new OXFException(e); } } private SystemUtils() { // disallow instantiation } }