View Javadoc

1   /**
2    *
3    * Copyright 2005 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.geronimo.kernel.classloader;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.FileNotFoundException;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.net.URLConnection;
25  import java.net.URLStreamHandler;
26  import java.util.jar.JarEntry;
27  import java.util.jar.JarFile;
28  
29  /**
30   * @version $Rev: 430581 $ $Date: 2006-08-10 16:16:47 -0700 (Thu, 10 Aug 2006) $
31   */
32  public class JarFileUrlStreamHandler extends URLStreamHandler {
33      public static URL createUrl(JarFile jarFile, JarEntry jarEntry) throws MalformedURLException {
34          return createUrl(jarFile, jarEntry, new File(jarFile.getName()).toURL());
35      }
36  
37      public static URL createUrl(JarFile jarFile, JarEntry jarEntry, URL codeSource) throws MalformedURLException {
38          JarFileUrlStreamHandler handler = new JarFileUrlStreamHandler(jarFile, jarEntry);
39          URL url = new URL("jar", "", -1, codeSource + "!/" + jarEntry.getName(), handler);
40          handler.setExpectedUrl(url);
41          return url;
42      }
43  
44      private URL expectedUrl;
45      private final JarFile jarFile;
46      private final JarEntry jarEntry;
47  
48      public JarFileUrlStreamHandler(JarFile jarFile, JarEntry jarEntry) {
49          if (jarFile == null) throw new NullPointerException("jarFile is null");
50          if (jarEntry == null) throw new NullPointerException("jarEntry is null");
51  
52          this.jarFile = jarFile;
53          this.jarEntry = jarEntry;
54      }
55  
56      public void setExpectedUrl(URL expectedUrl) {
57          if (expectedUrl == null) throw new NullPointerException("expectedUrl is null");
58          this.expectedUrl = expectedUrl;
59      }
60  
61      public URLConnection openConnection(URL url) throws IOException {
62          if (expectedUrl == null) throw new IllegalStateException("expectedUrl was not set");
63  
64          // the caller copied the URL reusing a stream handler from a previous call
65          if (!expectedUrl.equals(url)) {
66              // the new url is supposed to be within our context, so it must have a jar protocol
67              if (!url.getProtocol().equals("jar")) {
68                  throw new IllegalArgumentException("Unsupported protocol " + url.getProtocol());
69              }
70  
71              // split the path at "!/" into the file part and entry part
72              String path = url.getPath();
73              String[] chunks = path.split("!/", 2);
74  
75              // if we only got only one chunk, it didn't contain the required "!/" delimiter
76              if (chunks.length == 1) {
77                  throw new MalformedURLException("Url does not contain a '!' character: " + url);
78              }
79  
80              String file = chunks[0];
81              String entryPath = chunks[1];
82  
83              // this handler only supports jars on the local file system
84              if (!file.startsWith("file:")) {
85                  // let the system handler deal with this
86                  return new URL(url.toExternalForm()).openConnection();
87              }
88              file = file.substring("file:".length());
89  
90              // again the new url is supposed to be within our context so it must reference the same jar file
91              if (!jarFile.getName().equals(file)) {
92                  // let the system handler deal with this
93                  return new URL(url.toExternalForm()).openConnection();
94              }
95  
96              // get the entry
97              JarEntry newEntry = jarFile.getJarEntry(entryPath);
98              if (newEntry == null) {
99                  throw new FileNotFoundException("Entry not found: " + url);
100             }
101             return new JarFileUrlConnection(url, jarFile, newEntry);
102         }
103 
104         return new JarFileUrlConnection(url, jarFile, jarEntry);
105     }
106 }