Added python project; fixed spelling of folder
This commit is contained in:
1
Java Projects/Bookshelf/bin/resources/jars/tmp/.version
Normal file
1
Java Projects/Bookshelf/bin/resources/jars/tmp/.version
Normal file
@@ -0,0 +1 @@
|
||||
0.97-rc11-20100715-0959
|
@@ -0,0 +1,5 @@
|
||||
Manifest-Version: 1.0
|
||||
ImplementationVersion: 3.1
|
||||
Main-Class: com.simontuffs.onejar.Boot
|
||||
One-Jar-Main-Class: nl.siegmann.epublib.viewer.Viewer
|
||||
|
BIN
Java Projects/Bookshelf/bin/resources/jars/tmp/OneJar.class
Normal file
BIN
Java Projects/Bookshelf/bin/resources/jars/tmp/OneJar.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* One-JAR(TM) (http://www.simontuffs.com/one-jar). Copyright (c) 2004-2010,
|
||||
* P. Simon Tuffs (simon@simontuffs.com). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Neither the name of P. Simon Tuffs, nor the names of any contributors,
|
||||
* nor the name One-JAR may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 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 OWNER 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.
|
||||
*
|
||||
* Including this file inside the built One-JAR file conforms with these terms.
|
||||
*/
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010, P. Simon Tuffs (simon@simontuffs.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the full license at http://one-jar.sourceforge.net/one-jar-license.html
|
||||
* This license is also included in the distributions of this software
|
||||
* under doc/one-jar-license.txt
|
||||
*/
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.simontuffs.onejar.Boot;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* One-JAR Jar files are intended to be executed using the following kind of command:
|
||||
* <pre>
|
||||
* java -jar <one-jar.jar> [args]
|
||||
* </pre>
|
||||
* This class allows a One-JAR jar-file to be executed using the alternative command:
|
||||
* <pre>
|
||||
* java -cp <one-jar.jar> OneJar [args]
|
||||
* </pre>
|
||||
* Its main role is in testing the behaviour of OneJar on platforms which mangle the classpath
|
||||
* when running with the first kind of command, but it can also be a useful alternative
|
||||
* execution mechanism.
|
||||
* <p>Note: the same effect can be obtained by using the Boot class, albeit with more
|
||||
* typing:
|
||||
* <pre>
|
||||
* java -cp <one-jar.jar> com.simontuffs.onejar.Boot [args]
|
||||
* @author simon
|
||||
*
|
||||
*/
|
||||
public class OneJar {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("OneJar" + Arrays.asList(args).toString().replace('[','(').replace(']',')'));
|
||||
new OneJar().run(args);
|
||||
|
||||
}
|
||||
|
||||
public void run(String[] args) throws Exception {
|
||||
Boot.run(args);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010, P. Simon Tuffs (simon@simontuffs.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the full license at http://one-jar.sourceforge.net/one-jar-license.html
|
||||
* This license is also included in the distributions of this software
|
||||
* under doc/one-jar-license.txt
|
||||
*/
|
||||
|
||||
package com.simontuffs.onejar;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* Run a java application which requires multiple support jars from inside
|
||||
* a single jar file.
|
||||
*
|
||||
* <p>
|
||||
* Developer time JVM properties:
|
||||
* <pre>
|
||||
* -Done-jar.main.class={name} Use named class as main class to run.
|
||||
* -Done-jar.record[=recording] Record loaded classes into "recording" directory.
|
||||
* Flatten jar.names into directory tree suitable
|
||||
* for use as a classpath.
|
||||
* -Done-jar.jar.names Record loaded classes, preserve jar structure
|
||||
* -Done-jar.verbose Run the JarClassLoader in verbose mode.
|
||||
* </pre>
|
||||
* @author simon@simontuffs.com (<a href="http://www.simontuffs.com">http://www.simontuffs.com</a>)
|
||||
*/
|
||||
public class Boot {
|
||||
|
||||
/**
|
||||
* The name of the manifest attribute which controls which class
|
||||
* to bootstrap from the jar file. The boot class can
|
||||
* be in any of the contained jar files.
|
||||
*/
|
||||
public final static String BOOT_CLASS = "Boot-Class";
|
||||
public final static String ONE_JAR_CLASSLOADER = "One-Jar-Class-Loader";
|
||||
public final static String ONE_JAR_MAIN_CLASS = "One-Jar-Main-Class";
|
||||
public final static String ONE_JAR_DEFAULT_MAIN_JAR = "One-Jar-Default-Main-Jar";
|
||||
public final static String ONE_JAR_MAIN_ARGS = "One-Jar-Main-Args";
|
||||
public final static String ONE_JAR_URL_FACTORY = "One-Jar-URL-Factory";
|
||||
|
||||
public final static String MANIFEST = "META-INF/MANIFEST.MF";
|
||||
public final static String MAIN_JAR = "main/main.jar";
|
||||
|
||||
public final static String WRAP_CLASS_LOADER = "Wrap-Class-Loader";
|
||||
public final static String WRAP_DIR = "wrap";
|
||||
public final static String WRAP_JAR = "/" + WRAP_DIR + "/wraploader.jar";
|
||||
|
||||
// System properties.
|
||||
public final static String PROPERTY_PREFIX = "one-jar.";
|
||||
public final static String P_MAIN_CLASS = PROPERTY_PREFIX + "main.class";
|
||||
public final static String P_MAIN_JAR = PROPERTY_PREFIX + "main.jar";
|
||||
public final static String P_MAIN_APP = PROPERTY_PREFIX + "main.app";
|
||||
public final static String P_RECORD = PROPERTY_PREFIX + "record";
|
||||
public final static String P_JARNAMES = PROPERTY_PREFIX + "jar.names";
|
||||
public final static String P_VERBOSE = PROPERTY_PREFIX + "verbose";
|
||||
public final static String P_INFO = PROPERTY_PREFIX + "info";
|
||||
public final static String P_STATISTICS = PROPERTY_PREFIX + "statistics";
|
||||
public final static String P_SHOW_PROPERTIES = PROPERTY_PREFIX + "show.properties";
|
||||
public final static String P_JARPATH = PROPERTY_PREFIX + "jar.path";
|
||||
public final static String P_ONE_JAR_CLASS_PATH = PROPERTY_PREFIX + "class.path";
|
||||
public final static String P_JAVA_CLASS_PATH = "java.class.path";
|
||||
public final static String P_PATH_SEPARATOR = "|";
|
||||
public final static String P_EXPAND_DIR = PROPERTY_PREFIX + "expand.dir";
|
||||
|
||||
// Command-line arguments
|
||||
public final static String A_HELP = "--one-jar-help";
|
||||
public final static String A_VERSION = "--one-jar-version";
|
||||
|
||||
public final static String[] HELP_PROPERTIES = {
|
||||
P_MAIN_CLASS, "Specifies the name of the class which should be executed \n(via public static void main(String[])",
|
||||
P_MAIN_APP, "Specifies the name of the main/<app>.jar to be executed",
|
||||
P_RECORD, "true: Enables recording of the classes loaded by the application",
|
||||
P_JARNAMES, "true: Recorded classes are kept in directories corresponding to their jar names.\n" +
|
||||
"false: Recorded classes are flattened into a single directory. \nDuplicates are ignored (first wins)",
|
||||
P_VERBOSE, "true: Print verbose classloading information",
|
||||
P_INFO, "true: Print informative classloading information",
|
||||
P_STATISTICS, "true: Shows statistics about the One-Jar Classloader",
|
||||
P_JARPATH, "Full path of the one-jar file being executed. \nOnly needed if java.class.path does not contain the path to the jar, e.g. on Max OS/X.",
|
||||
P_ONE_JAR_CLASS_PATH, "Extra classpaths to be added to the execution environment. \nUse platform independent path separator '" + P_PATH_SEPARATOR + "'",
|
||||
P_EXPAND_DIR, "Directory to use for expanded files.",
|
||||
P_SHOW_PROPERTIES, "true: Shows the JVM system properties.",
|
||||
};
|
||||
|
||||
public final static String[] HELP_ARGUMENTS = {
|
||||
A_HELP, "Shows this message, then exits.",
|
||||
A_VERSION, "Shows the version of One-JAR, then exits.",
|
||||
};
|
||||
|
||||
protected static String mainJar;
|
||||
|
||||
protected static boolean info, verbose, statistics;
|
||||
protected static String myJarPath;
|
||||
|
||||
protected static long startTime = System.currentTimeMillis();
|
||||
protected static long endTime = 0;
|
||||
|
||||
|
||||
// Singleton loader. This must not be changed once it is set, otherwise all
|
||||
// sorts of nasty class-cast exceptions will ensue. Hence we control
|
||||
// access to it strongly.
|
||||
private static JarClassLoader loader = null;
|
||||
|
||||
|
||||
/**
|
||||
* This method provides access to the bootstrap One-JAR classloader which
|
||||
* is needed in the URL connection Handler when opening streams relative
|
||||
* to classes.
|
||||
* @return
|
||||
*/
|
||||
public synchronized static JarClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the single point of entry for setting the "loader" member. It checks to
|
||||
* make sure programming errors don't call it more than once.
|
||||
* @param $loader
|
||||
*/
|
||||
public synchronized static void setClassLoader(JarClassLoader $loader) {
|
||||
if (loader != null) throw new RuntimeException("Attempt to set a second Boot loader");
|
||||
loader = $loader;
|
||||
}
|
||||
|
||||
protected static void VERBOSE(String message) {
|
||||
if (verbose) System.out.println("Boot: " + message);
|
||||
}
|
||||
|
||||
protected static void WARNING(String message) {
|
||||
System.err.println("Boot: Warning: " + message);
|
||||
}
|
||||
|
||||
protected static void INFO(String message) {
|
||||
if (info) System.out.println("Boot: Info: " + message);
|
||||
}
|
||||
|
||||
protected static void PRINTLN(String message) {
|
||||
System.out.println("Boot: " + message);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
run(args);
|
||||
}
|
||||
|
||||
public static void run(String args[]) throws Exception {
|
||||
|
||||
args = processArgs(args);
|
||||
|
||||
// Is the main class specified on the command line? If so, boot it.
|
||||
// Otherwise, read the main class out of the manifest.
|
||||
String mainClass = null;
|
||||
|
||||
{
|
||||
// Default properties are in resource 'one-jar.properties'.
|
||||
Properties properties = new Properties();
|
||||
String props = "one-jar.properties";
|
||||
InputStream is = Boot.class.getResourceAsStream("/" + props);
|
||||
if (is != null) {
|
||||
INFO("loading properties from " + props);
|
||||
properties.load(is);
|
||||
}
|
||||
|
||||
// Merge in anything in a local file with the same name.
|
||||
if (new File(props).exists()) {
|
||||
is = new FileInputStream(props);
|
||||
if (is != null) {
|
||||
INFO("merging properties from " + props);
|
||||
properties.load(is);
|
||||
}
|
||||
}
|
||||
|
||||
// Set system properties only if not already specified.
|
||||
Enumeration _enum = properties.propertyNames();
|
||||
while (_enum.hasMoreElements()) {
|
||||
String name = (String)_enum.nextElement();
|
||||
if (System.getProperty(name) == null) {
|
||||
System.setProperty(name, properties.getProperty(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Boolean.valueOf(System.getProperty(P_SHOW_PROPERTIES, "false")).booleanValue()) {
|
||||
// What are the system properties.
|
||||
Properties props = System.getProperties();
|
||||
String keys[] = (String[])props.keySet().toArray(new String[]{});
|
||||
Arrays.sort(keys);
|
||||
|
||||
for (int i=0; i<keys.length; i++) {
|
||||
String key = keys[i];
|
||||
System.out.println(key + "=" + props.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
// Process developer properties:
|
||||
if (mainClass == null) {
|
||||
mainClass = System.getProperty(P_MAIN_CLASS);
|
||||
}
|
||||
|
||||
if (mainJar == null) {
|
||||
String app = System.getProperty(P_MAIN_APP);
|
||||
if (app != null) {
|
||||
mainJar = "main/" + app + ".jar";
|
||||
} else {
|
||||
mainJar = System.getProperty(P_MAIN_JAR, MAIN_JAR);
|
||||
}
|
||||
}
|
||||
|
||||
// Pick some things out of the top-level JAR file.
|
||||
String jar = getMyJarPath();
|
||||
JarFile jarFile = new JarFile(jar);
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
String bootLoaderName = attributes.getValue(ONE_JAR_CLASSLOADER);
|
||||
|
||||
if (mainJar == null) {
|
||||
mainJar = attributes.getValue(ONE_JAR_DEFAULT_MAIN_JAR);
|
||||
}
|
||||
|
||||
String mainargs = attributes.getValue(ONE_JAR_MAIN_ARGS);
|
||||
if (mainargs != null && args.length == 0) {
|
||||
// Replace the args with built-in. Support escaped whitespace.
|
||||
args = mainargs.split("[^\\\\]\\s");
|
||||
for (int i=0; i<args.length; i++) {
|
||||
args[i] = args[i].replaceAll("\\\\(\\s)", "$1");
|
||||
}
|
||||
}
|
||||
|
||||
// If no main-class specified, check the manifest of the main jar for
|
||||
// a Boot-Class attribute.
|
||||
if (mainClass == null) {
|
||||
mainClass = attributes.getValue(ONE_JAR_MAIN_CLASS);
|
||||
if (mainClass == null) {
|
||||
mainClass = attributes.getValue(BOOT_CLASS);
|
||||
if (mainClass != null) {
|
||||
WARNING("The manifest attribute " + BOOT_CLASS + " is deprecated in favor of the attribute " + ONE_JAR_MAIN_CLASS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mainClass == null) {
|
||||
// Still don't have one (default). One final try: look for a jar file in a
|
||||
// main directory. There should be only one, and it's manifest
|
||||
// Main-Class attribute is the main class. The JarClassLoader will take
|
||||
// care of finding it.
|
||||
InputStream is = Boot.class.getResourceAsStream("/" + mainJar);
|
||||
if (is != null) {
|
||||
JarInputStream jis = new JarInputStream(is);
|
||||
Manifest mainmanifest = jis.getManifest();
|
||||
jis.close();
|
||||
mainClass = mainmanifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
|
||||
} else {
|
||||
// There is no main jar. Info unless mainJar is empty string.
|
||||
// The load(mainClass) will scan for main jars anyway.
|
||||
if (!"".equals(mainJar)){
|
||||
INFO("Unable to locate main jar '" + mainJar + "' in the JAR file " + getMyJarPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do we need to create a wrapping classloader? Check for the
|
||||
// presence of a "wrap" directory at the top of the jar file.
|
||||
URL url = Boot.class.getResource(WRAP_JAR);
|
||||
|
||||
if (url != null) {
|
||||
// Wrap class loaders.
|
||||
final JarClassLoader bootLoader = getBootLoader(bootLoaderName);
|
||||
bootLoader.load(null);
|
||||
|
||||
// Read the "Wrap-Class-Loader" property from the wraploader jar file.
|
||||
// This is the class to use as a wrapping class-loader.
|
||||
InputStream is = Boot.class.getResourceAsStream(WRAP_JAR);
|
||||
if (is != null) {
|
||||
JarInputStream jis = new JarInputStream(is);
|
||||
final String wrapLoader = jis.getManifest().getMainAttributes().getValue(WRAP_CLASS_LOADER);
|
||||
jis.close();
|
||||
if (wrapLoader == null) {
|
||||
WARNING(url + " did not contain a " + WRAP_CLASS_LOADER + " attribute, unable to load wrapping classloader");
|
||||
} else {
|
||||
INFO("using " + wrapLoader);
|
||||
JarClassLoader wrapped = getWrapLoader(bootLoader, wrapLoader);
|
||||
if (wrapped == null) {
|
||||
WARNING("Unable to instantiate " + wrapLoader + " from " + WRAP_DIR + ": using default JarClassLoader");
|
||||
wrapped = getBootLoader(null);
|
||||
}
|
||||
setClassLoader(wrapped);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setClassLoader(getBootLoader(bootLoaderName, Boot.class.getClassLoader()));
|
||||
INFO("using JarClassLoader: " + getClassLoader().getClass().getName());
|
||||
}
|
||||
|
||||
// Allow injection of the URL factory.
|
||||
String urlfactory = attributes.getValue(ONE_JAR_URL_FACTORY);
|
||||
if (urlfactory != null) {
|
||||
loader.setURLFactory(urlfactory);
|
||||
}
|
||||
|
||||
mainClass = loader.load(mainClass);
|
||||
|
||||
if (mainClass == null && !loader.isExpanded())
|
||||
throw new Exception(getMyJarName() + " main class was not found (fix: add main/main.jar with a Main-Class manifest attribute, or specify -D" + P_MAIN_CLASS + "=<your.class.name>), or use " + ONE_JAR_MAIN_CLASS + " in the manifest");
|
||||
|
||||
if (mainClass != null) {
|
||||
// Guard against the main.jar pointing back to this
|
||||
// class, and causing an infinite recursion.
|
||||
String bootClass = Boot.class.getName();
|
||||
if (bootClass.equals(mainClass))
|
||||
throw new Exception(getMyJarName() + " main class (" + mainClass + ") would cause infinite recursion: check main.jar/META-INF/MANIFEST.MF/Main-Class attribute: " + mainClass);
|
||||
|
||||
Class cls = loader.loadClass(mainClass);
|
||||
|
||||
endTime = System.currentTimeMillis();
|
||||
showTime();
|
||||
|
||||
Method main = cls.getMethod("main", new Class[]{String[].class});
|
||||
main.invoke(null, new Object[]{args});
|
||||
}
|
||||
}
|
||||
|
||||
public static void showTime() {
|
||||
long endtime = System.currentTimeMillis();
|
||||
if (statistics) {
|
||||
PRINTLN("Elapsed time: " + (endtime - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProperties(IProperties jarloader) {
|
||||
INFO("setProperties(" + jarloader + ")");
|
||||
if (getProperty(P_RECORD)) {
|
||||
jarloader.setRecord(true);
|
||||
jarloader.setRecording(System.getProperty(P_RECORD));
|
||||
}
|
||||
if (getProperty(P_JARNAMES)) {
|
||||
jarloader.setRecord(true);
|
||||
jarloader.setFlatten(false);
|
||||
}
|
||||
if (getProperty(P_VERBOSE)) {
|
||||
jarloader.setVerbose(true);
|
||||
jarloader.setInfo(true);
|
||||
verbose = true;
|
||||
}
|
||||
if (getProperty(P_INFO)) {
|
||||
jarloader.setInfo(true);
|
||||
info = true;
|
||||
}
|
||||
|
||||
statistics = getProperty(P_STATISTICS);
|
||||
}
|
||||
|
||||
public static boolean getProperty(String key) {
|
||||
return Boolean.valueOf(System.getProperty(key, "false")).booleanValue();
|
||||
}
|
||||
|
||||
public static String getMyJarName() {
|
||||
String name = getMyJarPath();
|
||||
int last = name.lastIndexOf("/");
|
||||
if (last >= 0) {
|
||||
name = name.substring(last+1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getMyJarPath() {
|
||||
if (myJarPath != null) {
|
||||
return myJarPath;
|
||||
}
|
||||
myJarPath = System.getProperty(P_JARPATH);
|
||||
if (myJarPath == null) {
|
||||
try {
|
||||
// Hack to obtain the name of this jar file.
|
||||
String jarname = System.getProperty(P_JAVA_CLASS_PATH);
|
||||
// Open each Jar file looking for this class name. This allows for
|
||||
// JVM's that place more than the jar file on the classpath.
|
||||
String jars[] =jarname.split(System.getProperty("path.separator"));
|
||||
for (int i=0; i<jars.length; i++) {
|
||||
jarname = jars[i];
|
||||
VERBOSE("Checking " + jarname + " as One-Jar file");
|
||||
// Allow for URL based paths, as well as file-based paths. File
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new URL(jarname).openStream();
|
||||
} catch (MalformedURLException mux) {
|
||||
// Try a local file.
|
||||
try {
|
||||
is = new FileInputStream(jarname);
|
||||
} catch (IOException iox) {
|
||||
// Ignore..., but it isn't good to have bad entries on the classpath.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ZipEntry entry = findJarEntry(new JarInputStream(is), Boot.class.getName().replace('.', '/') + ".class");
|
||||
if (entry != null) {
|
||||
myJarPath = jarname;
|
||||
break;
|
||||
} else {
|
||||
// One more try as a Zip file: supports launch4j on Windows.
|
||||
entry = findZipEntry(new ZipFile(jarname), Boot.class.getName().replace('.', '/') + ".class");
|
||||
if (entry != null) {
|
||||
myJarPath = jarname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
WARNING("jar=" + myJarPath + " loaded from " + P_JAVA_CLASS_PATH + " (" + System.getProperty(P_JAVA_CLASS_PATH) + ")");
|
||||
}
|
||||
}
|
||||
if (myJarPath == null) {
|
||||
throw new IllegalArgumentException("Unable to locate " + Boot.class.getName() + " in the java.class.path: consider using -D" + P_JARPATH + " to specify the one-jar filename.");
|
||||
}
|
||||
// Normalize those annoying DOS backslashes.
|
||||
myJarPath = myJarPath.replace('\\', '/');
|
||||
return myJarPath;
|
||||
}
|
||||
|
||||
public static JarEntry findJarEntry(JarInputStream jis, String name) throws IOException {
|
||||
JarEntry entry;
|
||||
while ((entry = jis.getNextJarEntry()) != null) {
|
||||
if (entry.getName().equals(name)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ZipEntry findZipEntry(ZipFile zip, String name) throws IOException {
|
||||
Enumeration entries = zip.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
VERBOSE(("findZipEntry(): entry=" + entry.getName()));
|
||||
if (entry.getName().equals(name))
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int firstWidth(String[] table) {
|
||||
int width = 0;
|
||||
for (int i=0; i<table.length; i+=2) {
|
||||
if (table[i].length() > width) width = table[i].length();
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
public static String pad(String indent, String string, int width) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(indent);
|
||||
buf.append(string);
|
||||
for (int i=0; i<width-string.length(); i++) {
|
||||
buf.append(" ");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String wrap(String indent, String string, int width) {
|
||||
String padding = pad(indent, "", width);
|
||||
string = string.replaceAll("\n", "\n" + padding);
|
||||
return string;
|
||||
}
|
||||
|
||||
public static String[] processArgs(String args[]) throws Exception {
|
||||
// Check for arguments which matter to us, and strip them.
|
||||
VERBOSE("processArgs(" + Arrays.asList(args) + ")");
|
||||
ArrayList list = new ArrayList();
|
||||
for (int a=0; a<args.length; a++) {
|
||||
String argument = args[a];
|
||||
if (argument.startsWith(A_HELP)) {
|
||||
int width = firstWidth(HELP_ARGUMENTS);
|
||||
// Width of first column
|
||||
|
||||
System.out.println("One-Jar uses the following command-line arguments");
|
||||
for (int i=0; i<HELP_ARGUMENTS.length; i++) {
|
||||
System.out.print(pad(" ", HELP_ARGUMENTS[i++], width+1));
|
||||
System.out.println(wrap(" ", HELP_ARGUMENTS[i], width+1));
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
width = firstWidth(HELP_PROPERTIES);
|
||||
System.out.println("One-Jar uses the following VM properties (-D<property>=<true|false|string>)");
|
||||
for (int i=0; i<HELP_PROPERTIES.length; i++) {
|
||||
System.out.print(pad(" ", HELP_PROPERTIES[i++], width+1));
|
||||
System.out.println(wrap(" ", HELP_PROPERTIES[i], width+1));
|
||||
}
|
||||
System.out.println();
|
||||
System.exit(0);
|
||||
} else if (argument.startsWith(A_VERSION)) {
|
||||
InputStream is = Boot.class.getResourceAsStream("/.version");
|
||||
if (is != null) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
String version = br.readLine();
|
||||
br.close();
|
||||
System.out.println("One-JAR version " + version);
|
||||
} else {
|
||||
System.out.println("Unable to determine One-JAR version (missing /.version resource in One-JAR archive)");
|
||||
}
|
||||
System.exit(0);
|
||||
} else {
|
||||
list.add(argument);
|
||||
}
|
||||
}
|
||||
return (String[])list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
protected static JarClassLoader getBootLoader(final String loader) {
|
||||
JarClassLoader bootLoader = (JarClassLoader)AccessController.doPrivileged(
|
||||
new PrivilegedAction() {
|
||||
public Object run() {
|
||||
if (loader != null) {
|
||||
try {
|
||||
Class cls = Class.forName(loader);
|
||||
Constructor ctor = cls.getConstructor(new Class[]{String.class});
|
||||
return ctor.newInstance(new Object[]{WRAP_DIR});
|
||||
} catch (Exception x) {
|
||||
WARNING("Unable to instantiate " + loader + ": " + x + " continuing using default " + JarClassLoader.class.getName());
|
||||
}
|
||||
}
|
||||
return new JarClassLoader(WRAP_DIR);
|
||||
}
|
||||
}
|
||||
);
|
||||
return bootLoader;
|
||||
}
|
||||
|
||||
protected static JarClassLoader getBootLoader(final String loader, ClassLoader parent) {
|
||||
return (JarClassLoader)AccessController.doPrivileged(
|
||||
new PrivilegedAction() {
|
||||
public Object run() {
|
||||
if (loader != null) {
|
||||
try {
|
||||
Class cls = Class.forName(loader);
|
||||
Constructor ctor = cls.getConstructor(new Class[]{ClassLoader.class});
|
||||
return ctor.newInstance(new Object[]{Boot.class.getClassLoader()});
|
||||
} catch (Exception x) {
|
||||
WARNING("Unable to instantiate " + loader + ": " + x + " continuing using default " + JarClassLoader.class.getName());
|
||||
}
|
||||
}
|
||||
return new JarClassLoader(Boot.class.getClassLoader());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected static JarClassLoader getWrapLoader(final ClassLoader bootLoader, final String wrapLoader) {
|
||||
return ((JarClassLoader)AccessController.doPrivileged(
|
||||
new PrivilegedAction() {
|
||||
public Object run() {
|
||||
try {
|
||||
Class jarLoaderClass = bootLoader.loadClass(wrapLoader);
|
||||
Constructor ctor = jarLoaderClass.getConstructor(new Class[]{ClassLoader.class});
|
||||
return ctor.newInstance(new Object[]{bootLoader});
|
||||
} catch (Throwable t) {
|
||||
WARNING(t.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public static long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010, P. Simon Tuffs (simon@simontuffs.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the full license at http://one-jar.sourceforge.net/one-jar-license.html
|
||||
* This license is also included in the distributions of this software
|
||||
* under doc/one-jar-license.txt
|
||||
*/
|
||||
|
||||
package com.simontuffs.onejar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.FileNameMap;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
|
||||
/**
|
||||
* @author simon@simontuffs.com
|
||||
*
|
||||
*/
|
||||
public class Handler extends URLStreamHandler {
|
||||
|
||||
/**
|
||||
* This protocol name must match the name of the package in which this class
|
||||
* lives.
|
||||
*/
|
||||
public static String PROTOCOL = "onejar";
|
||||
|
||||
/**
|
||||
* @see java.net.URLStreamHandler#openConnection(java.net.URL)
|
||||
*/
|
||||
protected URLConnection openConnection(final URL u) throws IOException {
|
||||
final String resource = u.getPath();
|
||||
return new URLConnection(u) {
|
||||
public void connect() {
|
||||
}
|
||||
public String getContentType() {
|
||||
FileNameMap fileNameMap = java.net.URLConnection.getFileNameMap();
|
||||
String contentType = fileNameMap.getContentTypeFor(resource);
|
||||
if (contentType == null)
|
||||
contentType = "text/plain";
|
||||
return contentType;
|
||||
}
|
||||
public InputStream getInputStream() throws IOException {
|
||||
// Use the Boot classloader to get the resource. There
|
||||
// is only one per one-jar.
|
||||
JarClassLoader cl = Boot.getClassLoader();
|
||||
InputStream is = cl.getByteStream(resource);
|
||||
// sun.awt image loading does not like null input streams returned here.
|
||||
// Throw IOException (probably better anyway).
|
||||
if (is == null)
|
||||
throw new IOException("cl.getByteStream() returned null for " + resource);
|
||||
return is;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.simontuffs.onejar;
|
||||
|
||||
/**
|
||||
* Interface to the controlling properties for a JarClassLoader.
|
||||
* @author simon
|
||||
*
|
||||
*/
|
||||
public interface IProperties {
|
||||
|
||||
public void setVerbose(boolean verbose);
|
||||
public void setInfo(boolean info);
|
||||
public void setRecord(boolean record);
|
||||
public void setFlatten(boolean flatten);
|
||||
public void setRecording(String recording);
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010, P. Simon Tuffs (simon@simontuffs.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the full license at http://one-jar.sourceforge.net/one-jar-license.html
|
||||
* This license is also included in the distributions of this software
|
||||
* under doc/one-jar-license.txt
|
||||
*
|
||||
* Many thanks to the following for their contributions to One-Jar:
|
||||
* Contributor: sebastian : http://code.google.com/u/@WBZRRlBYBxZHXQl9/
|
||||
* Original creator of the OneJarFile/OneJarUrlConnecion solution to resource location
|
||||
* using jar protocols.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.simontuffs.onejar;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
public class OneJarFile extends JarFile {
|
||||
|
||||
protected final String jarFilename;
|
||||
protected final String filename;
|
||||
protected final JarEntry wrappedJarFile;
|
||||
|
||||
public OneJarFile(String myJarPath, String jarFilename, String filename) throws IOException {
|
||||
super(myJarPath);
|
||||
this.jarFilename = jarFilename;
|
||||
this.filename = filename;
|
||||
wrappedJarFile = super.getJarEntry(this.jarFilename);
|
||||
}
|
||||
|
||||
public JarEntry getJarEntry(String name) {
|
||||
String filename = name.substring(name.indexOf("!/") + 2);
|
||||
if (filename.equals(MANIFEST_NAME)) {
|
||||
// Synthesize a JarEntry.
|
||||
return new JarEntry(filename) {
|
||||
};
|
||||
}
|
||||
try {
|
||||
JarInputStream is = new JarInputStream(super.getInputStream(wrappedJarFile));
|
||||
try {
|
||||
JarEntry entry;
|
||||
while ((entry = is.getNextJarEntry()) != null) {
|
||||
if (entry.getName().equals(filename)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Undefined Error", e);
|
||||
}
|
||||
return null;
|
||||
// throw new RuntimeException("Entry not found : " + name);
|
||||
}
|
||||
|
||||
public Enumeration entries() {
|
||||
try {
|
||||
final JarInputStream is = new JarInputStream(super.getInputStream(wrappedJarFile));
|
||||
return new Enumeration() {
|
||||
|
||||
protected JarEntry next;
|
||||
|
||||
public Object nextElement() {
|
||||
if (next != null) {
|
||||
JarEntry tmp = next;
|
||||
next = null;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
try {
|
||||
return is.getNextJarEntry();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Undefined Error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
if (next != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
next = is.getNextJarEntry();
|
||||
if (next == null) {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Undefined Error", e);
|
||||
}
|
||||
return next != null;
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Undefined Error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized InputStream getInputStream(ZipEntry ze) throws IOException {
|
||||
if (ze == null)
|
||||
return null;
|
||||
try {
|
||||
JarInputStream is = new JarInputStream(super.getInputStream(wrappedJarFile));
|
||||
if (filename.equals(MANIFEST_NAME)) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
is.getManifest().write(baos);
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
}
|
||||
try {
|
||||
JarEntry entry;
|
||||
while ((entry = is.getNextJarEntry()) != null) {
|
||||
if (entry.getName().equals(ze.getName())) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
copy(is, baos);
|
||||
return new ByteArrayInputStream(baos.toByteArray());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Undefined Error", e);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Entry not found : " + ze.getName());
|
||||
}
|
||||
|
||||
protected void copy(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buf = new byte[1024];
|
||||
while (true) {
|
||||
int len = in.read(buf);
|
||||
if (len < 0)
|
||||
break;
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2010, P. Simon Tuffs (simon@simontuffs.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* See the full license at http://one-jar.sourceforge.net/one-jar-license.html
|
||||
* This license is also included in the distributions of this software
|
||||
* under doc/one-jar-license.txt
|
||||
*
|
||||
* Contributor: sebastian : http://code.google.com/u/@WBZRRlBYBxZHXQl9/
|
||||
* Original creator of the OneJarFile/OneJarUrlConnecion solution to resource location
|
||||
* using jar protocols.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.simontuffs.onejar;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.jar.JarFile;
|
||||
public class OneJarURLConnection extends JarURLConnection {
|
||||
|
||||
private JarFile jarFile;
|
||||
|
||||
public OneJarURLConnection(URL url) throws MalformedURLException {
|
||||
super(url);
|
||||
}
|
||||
|
||||
public JarFile getJarFile() throws IOException {
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
public void connect() throws IOException {
|
||||
String jarWithContent = getEntryName();
|
||||
int separator = jarWithContent.indexOf("!/");
|
||||
// Handle the case where a URL points to the top-level jar file, i.e. no '!/' separator.
|
||||
if (separator >= 0) {
|
||||
String jarFilename = jarWithContent, filename = null;
|
||||
jarFilename = jarWithContent.substring(0, separator++);
|
||||
filename = jarWithContent.substring(++separator);
|
||||
jarFile = new OneJarFile(Boot.getMyJarPath(), jarFilename, filename);
|
||||
} else {
|
||||
// Entry in the top-level One-JAR.
|
||||
jarFile = new JarFile(Boot.getMyJarPath());
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return jarFile.getInputStream(jarFile.getJarEntry(getEntryName()));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user