/* * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 David Berkman * * This file is part of the SmallMind Code Project. * * The SmallMind Code Project is free software, you can redistribute * it and/or modify it under either, at your discretion... * * 1) The terms of GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * ...or... * * 2) The terms of the Apache License, Version 2.0. * * The SmallMind Code Project 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 * General Public License or Apache License for more details. * * You should have received a copy of the GNU Affero General Public License * and the Apache License along with the SmallMind Code Project. If not, see * <http://www.gnu.org/licenses/> or <http://www.apache.org/licenses/LICENSE-2.0>. * * Additional permission under the GNU Affero GPL version 3 section 7 * ------------------------------------------------------------------ * If you modify this Program, or any covered work, by linking or * combining it with other code, such other code is not for that reason * alone subject to any of the requirements of the GNU Affero GPL * version 3. */ package org.smallmind.nutsnbolts.lang; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ClasspathClassGate implements ClassGate { private final HashMap<String, String> filePathMap; private String[] pathComponents; public ClasspathClassGate () { this(System.getProperty("java.class.path")); } public ClasspathClassGate (String classPath) { this(classPath.split(System.getProperty("path.separator"), -1)); } public ClasspathClassGate (String... pathComponents) { this.pathComponents = pathComponents; filePathMap = new HashMap<>(); } public long getLastModDate (String name) { File classFile; String filePath; synchronized (filePathMap) { if ((filePath = filePathMap.get(name)) != null) { classFile = new File(filePath); return classFile.lastModified(); } } return ClassGate.STATIC_CLASS; } public ClassStreamTicket getClassAsTicket (String name) throws Exception { String classFileName; classFileName = name.replace('.', '/') + ".class"; for (String pathComponent : pathComponents) { InputStream classStream; if (pathComponent.endsWith(".jar")) { if ((classStream = findJarStream(pathComponent, classFileName)) != null) { return new ClassStreamTicket(classStream, ClassGate.STATIC_CLASS); } } else { File classFile; long timeStamp; if ((classFile = findFile(pathComponent, classFileName)) != null) { synchronized (filePathMap) { filePathMap.put(name, classFile.getAbsolutePath()); timeStamp = classFile.lastModified(); return new ClassStreamTicket(new BufferedInputStream(new FileInputStream(classFile)), timeStamp); } } } } return null; } public URL getResource (String path) throws Exception { for (String pathComponent : pathComponents) { JarLocator jarLocator; if (pathComponent.endsWith(".jar")) { if ((jarLocator = findJarLocator(pathComponent, path)) != null) { return new URL("jar:file://" + rectifyPath(pathComponent) + "!/" + jarLocator.getJarEntry().getName()); } } else { File resourceFile; if ((resourceFile = findFile(pathComponent, path)) != null) { return new URL("file://" + rectifyPath(resourceFile.getAbsolutePath())); } } } return null; } private String rectifyPath (String path) { String rectifiedPath = path.replace('\\', '/'); return (rectifiedPath.charAt(0) == '/') ? rectifiedPath : '/' + rectifiedPath; } public InputStream getResourceAsStream (String path) throws Exception { for (String pathComponent : pathComponents) { InputStream resourceStream; if (pathComponent.endsWith(".jar")) { if ((resourceStream = findJarStream(pathComponent, path)) != null) { return resourceStream; } } else { File resourceFile; if ((resourceFile = findFile(pathComponent, path)) != null) { return new BufferedInputStream(new FileInputStream(resourceFile)); } } } return null; } private InputStream findJarStream (String jarComponentPath, String path) throws IOException { JarLocator jarLocator; if ((jarLocator = findJarLocator(jarComponentPath, path)) != null) { return new BufferedInputStream(jarLocator.getInputStream()); } return null; } private JarLocator findJarLocator (String jarComponentPath, String path) throws IOException { JarFile jarFile; JarEntry jarEntry; Enumeration<JarEntry> entryEnumeration; jarFile = new JarFile(jarComponentPath); entryEnumeration = jarFile.entries(); while (entryEnumeration.hasMoreElements()) { if ((jarEntry = entryEnumeration.nextElement()).getName().equals((path.charAt(0) == '/') ? path.substring(1) : path)) { return new JarLocator(jarFile, jarEntry); } } return null; } private File findFile (String fileComponentPath, String path) { File pathFile; pathFile = new File((path.charAt(0) == '/') ? fileComponentPath + path : fileComponentPath + '/' + path); if (pathFile.isFile()) { return pathFile; } return null; } private class JarLocator { private JarFile jarFile; private JarEntry jarEntry; private JarLocator (JarFile jarFile, JarEntry jarEntry) { this.jarFile = jarFile; this.jarEntry = jarEntry; } public JarEntry getJarEntry () { return jarEntry; } public InputStream getInputStream () throws IOException { return jarFile.getInputStream(jarFile.getEntry(jarEntry.getName())); } } }