Added python project; fixed spelling of folder

This commit is contained in:
2023-09-30 16:09:14 -05:00
parent 1f23cb73d1
commit 6bf66c5916
1075 changed files with 2165 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
0.97-rc11-20100715-0959

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
};
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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()));
}
}