aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java')
-rw-r--r--gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java215
1 files changed, 215 insertions, 0 deletions
diff --git a/gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java b/gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java
new file mode 100644
index 000000000..40194be79
--- /dev/null
+++ b/gcc-4.4.3/libjava/classpath/gnu/java/net/loader/JarURLLoader.java
@@ -0,0 +1,215 @@
+package gnu.java.net.loader;
+
+import gnu.java.net.IndexListParser;
+
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * A <code>JarURLLoader</code> is a type of <code>URLLoader</code>
+ * only loading from jar url.
+ */
+public final class JarURLLoader extends URLLoader
+{
+ // True if we've initialized -- i.e., tried open the jar file.
+ boolean initialized;
+ // The jar file for this url.
+ JarFile jarfile;
+ // Base jar: url for all resources loaded from jar.
+ final URL baseJarURL;
+ // The "Class-Path" attribute of this Jar's manifest.
+ ArrayList<URLLoader> classPath;
+ // If not null, a mapping from INDEX.LIST for this jar only.
+ // This is a set of all prefixes and top-level files that
+ // ought to be available in this jar.
+ Set indexSet;
+
+ // This constructor is used internally. It purposely does not open
+ // the jar file -- it defers this until later. This allows us to
+ // implement INDEX.LIST lazy-loading semantics.
+ private JarURLLoader(URLClassLoader classloader, URLStreamHandlerCache cache,
+ URLStreamHandlerFactory factory,
+ URL baseURL, URL absoluteUrl,
+ Set indexSet)
+ {
+ super(classloader, cache, factory, baseURL, absoluteUrl);
+
+ URL newBaseURL = null;
+ try
+ {
+ // Cache url prefix for all resources in this jar url.
+ String base = baseURL.toExternalForm() + "!/";
+ newBaseURL = new URL("jar", "", -1, base, cache.get(factory, "jar"));
+ }
+ catch (MalformedURLException ignore)
+ {
+ // Ignore.
+ }
+ this.baseJarURL = newBaseURL;
+ this.classPath = null;
+ this.indexSet = indexSet;
+ }
+
+ // This constructor is used by URLClassLoader. It will immediately
+ // try to read the jar file, in case we've found an index or a class-path
+ // setting. FIXME: it would be nice to defer this as well, but URLClassLoader
+ // makes this hard.
+ public JarURLLoader(URLClassLoader classloader, URLStreamHandlerCache cache,
+ URLStreamHandlerFactory factory,
+ URL baseURL, URL absoluteUrl)
+ {
+ this(classloader, cache, factory, baseURL, absoluteUrl, null);
+ initialize();
+ }
+
+ private void initialize()
+ {
+ JarFile jarfile = null;
+ try
+ {
+ jarfile =
+ ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
+
+ Manifest manifest;
+ Attributes attributes;
+ String classPathString;
+
+ IndexListParser parser = new IndexListParser(jarfile, baseJarURL,
+ baseURL);
+ LinkedHashMap<URL, Set<String>> indexMap = parser.getHeaders();
+ if (indexMap != null)
+ {
+ // Note that the index also computes
+ // the resulting Class-Path -- there are jars out there
+ // where the index lists some required jars which do
+ // not appear in the Class-Path attribute in the manifest.
+ this.classPath = new ArrayList<URLLoader>();
+ Iterator<Map.Entry<URL, Set<String>>> it = indexMap.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry<URL, Set<String>> entry = it.next();
+ URL subURL = entry.getKey();
+ Set<String> prefixes = entry.getValue();
+ if (subURL.equals(baseURL))
+ this.indexSet = prefixes;
+ else
+ {
+ JarURLLoader subLoader = new JarURLLoader(classloader,
+ cache,
+ factory, subURL,
+ subURL,
+ prefixes);
+ // Note that we don't care if the sub-loader itself has an
+ // index or a class-path -- only the top-level jar
+ // file gets this treatment; its index should cover
+ // everything.
+ this.classPath.add(subLoader);
+ }
+ }
+ }
+ else if ((manifest = jarfile.getManifest()) != null
+ && (attributes = manifest.getMainAttributes()) != null
+ && ((classPathString
+ = attributes.getValue(Attributes.Name.CLASS_PATH))
+ != null))
+ {
+ this.classPath = new ArrayList<URLLoader>();
+ StringTokenizer st = new StringTokenizer(classPathString, " ");
+ while (st.hasMoreElements ())
+ {
+ String e = st.nextToken ();
+ try
+ {
+ URL subURL = new URL(baseURL, e);
+ // We've seen at least one jar file whose Class-Path
+ // attribute includes the original jar. If we process
+ // that normally we end up with infinite recursion.
+ if (subURL.equals(baseURL))
+ continue;
+ JarURLLoader subLoader = new JarURLLoader(classloader,
+ cache, factory,
+ subURL, subURL);
+ this.classPath.add(subLoader);
+ ArrayList<URLLoader> extra = subLoader.getClassPath();
+ if (extra != null)
+ this.classPath.addAll(extra);
+ }
+ catch (java.net.MalformedURLException xx)
+ {
+ // Give up
+ }
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ /* ignored */
+ }
+
+ this.jarfile = jarfile;
+ this.initialized = true;
+ }
+
+ /** get resource with the name "name" in the jar url */
+ public Resource getResource(String name)
+ {
+ if (name.startsWith("/"))
+ name = name.substring(1);
+ if (indexSet != null)
+ {
+ // Trust the index.
+ String basename = name;
+ int offset = basename.lastIndexOf('/');
+ if (offset != -1)
+ basename = basename.substring(0, offset);
+ if (! indexSet.contains(basename))
+ return null;
+ // FIXME: if the index claim to hold the resource, and jar file
+ // doesn't have it, we're supposed to throw an exception. However,
+ // in our model this is tricky to implement, as another URLLoader from
+ // the same top-level jar may have an overlapping index entry.
+ }
+
+ if (! initialized)
+ initialize();
+ if (jarfile == null)
+ return null;
+
+ JarEntry je = jarfile.getJarEntry(name);
+ if (je != null)
+ return new JarURLResource(this, name, je);
+ else
+ return null;
+ }
+
+ public Manifest getManifest()
+ {
+ try
+ {
+ return (jarfile == null) ? null : jarfile.getManifest();
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
+ }
+
+ public ArrayList<URLLoader> getClassPath()
+ {
+ return classPath;
+ }
+}