001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)JarCache.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.framework;
030:
031: import java.io.File;
032: import java.io.IOException;
033: import java.io.InputStream;
034: import java.net.JarURLConnection;
035: import java.net.MalformedURLException;
036: import java.net.URL;
037: import java.net.URLConnection;
038: import java.net.URLStreamHandler;
039: import java.util.Collections;
040: import java.util.HashMap;
041: import java.util.Iterator;
042: import java.util.LinkedList;
043: import java.util.List;
044: import java.util.logging.Level;
045: import java.util.logging.Logger;
046: import java.util.Map;
047: import java.util.Vector;
048: import java.util.jar.JarEntry;
049: import java.util.jar.JarFile;
050:
051: /** Implements a cache of JarFiles used by Classloader implementations to
052: * load classes and resources. The advantage that this class provides over
053: * traditional URLClassLoader behavior is that open JarFile references can be
054: * closed on demand when the classloader is no longer needed.
055: */
056: public class JarCache {
057: Map mOpenJarFiles = new HashMap();
058: Map mResourceIndex = Collections.synchronizedMap(new HashMap());
059: URLStreamHandler mUrlStreamHandler = new JarStreamHandlerImpl();
060:
061: /** Overrides close() method to prevent external clients from closing the
062: * JarFile. The closeImpl() method should be called instead.
063: */
064: public static class JarFileImpl extends JarFile {
065: public JarFileImpl(String name) throws IOException {
066: super (name);
067: }
068:
069: public void close() {
070: // don't close: in case somebody does this:
071: // JarURLConnection c =
072: // (JarURLConnection)getResource("jar:file:blah.jar").openConnection();
073: // c.getJarFile().close();
074: }
075:
076: public void closeImpl() throws IOException {
077: super .close();
078: }
079:
080: protected void finalize() throws IOException {
081: closeImpl();
082: }
083: }
084:
085: /** Implementation of JarURLConnection which serves content out of the cache.
086: */
087: public class JarURLConnectionImpl extends JarURLConnection {
088: JarFile mJarFile;
089:
090: public JarURLConnectionImpl(URL url)
091: throws MalformedURLException {
092: super (url);
093: }
094:
095: public JarFile getJarFile() throws IOException {
096: if (mJarFile == null) {
097: URL jarFileURL = getJarFileURL();
098: synchronized (mOpenJarFiles) {
099: mJarFile = (JarFile) mOpenJarFiles.get(jarFileURL
100: .getPath());
101: if (mJarFile == null) {
102: mJarFile = new JarFileImpl(jarFileURL.getPath());
103: mOpenJarFiles.put(jarFileURL.getPath(),
104: mJarFile);
105: }
106: }
107: }
108:
109: return mJarFile;
110: }
111:
112: public InputStream getInputStream() throws IOException {
113: return getJarFile().getInputStream(
114: getJarFile().getEntry(getEntryName()));
115: }
116:
117: public void connect() throws IOException {
118: // jarFileURLConnection = jarFileURL.openConnection();
119: }
120:
121: }
122:
123: class JarStreamHandlerImpl extends URLStreamHandler {
124: protected URLConnection openConnection(URL url)
125: throws IOException {
126: return new JarURLConnectionImpl(url);
127: }
128: }
129:
130: public URLStreamHandler getURLStreamHandler() {
131: return mUrlStreamHandler;
132: }
133:
134: public URL createURL(URL jarFileURL, String entry)
135: throws MalformedURLException {
136: URL url = new URL("jar", null, -1, jarFileURL.toString() + "!/"
137: + (entry == null ? "" : entry), getURLStreamHandler());
138: return url;
139: }
140:
141: /** Closes all JarFiles stored in the cache, which should make them
142: * eligible for filesystem-level deletion.
143: */
144: public void close() {
145: synchronized (mOpenJarFiles) {
146: Iterator iter = mOpenJarFiles.values().iterator();
147: while (iter.hasNext()) {
148: JarFileImpl jarFile = (JarFileImpl) iter.next();
149: try {
150: jarFile.closeImpl();
151: } catch (IOException exc) {
152: Logger.getLogger(
153: this .getClass().getPackage().getName())
154: .log(
155: Level.FINE,
156: "I/O error while closing "
157: + jarFile.getName(), exc);
158: }
159: }
160:
161: mResourceIndex.clear();
162: mOpenJarFiles.clear();
163: }
164: }
165:
166: public InputStream getResourceAsStream(String fileName) {
167: fileName = fileName.replace('\\', '/');
168:
169: if (fileName.startsWith("/")) {
170: fileName = fileName.substring(1);
171: } else if (fileName.startsWith("./")) {
172: fileName = fileName.substring(2);
173: }
174:
175: Object key = mResourceIndex.get(fileName);
176: synchronized (mOpenJarFiles) {
177: if (key != null) {
178: JarFile jarFile = (JarFile) mOpenJarFiles.get(key);
179: if (jarFile != null) {
180: try {
181: JarEntry entry = jarFile.getJarEntry(fileName);
182: return jarFile.getInputStream(entry);
183: } catch (IOException exc) {
184: throw new RuntimeException(exc);
185: }
186: }
187: }
188:
189: Iterator iter = mOpenJarFiles.entrySet().iterator();
190: while (iter.hasNext()) {
191: Map.Entry e = (Map.Entry) iter.next();
192: JarFile jarFile = (JarFile) e.getValue();
193: JarEntry entry = jarFile.getJarEntry(fileName);
194: if (entry != null) {
195: try {
196: mResourceIndex.put(fileName, e.getKey());
197: return jarFile.getInputStream(entry);
198: } catch (IOException exc) {
199: throw new RuntimeException(exc);
200: }
201: }
202: }
203: }
204: return null;
205: }
206:
207: public URL findResource(String fileName) {
208: fileName = fileName.replace('\\', '/');
209: if (fileName.startsWith("/")) {
210: fileName = fileName.substring(1);
211: } else if (fileName.startsWith("./")) {
212: fileName = fileName.substring(2);
213: }
214:
215: Object key = mResourceIndex.get(fileName);
216: synchronized (mOpenJarFiles) {
217: if (key != null) {
218: JarFile jarFile = (JarFile) mOpenJarFiles.get(key);
219: if (jarFile != null) {
220: try {
221: return createURL(new File(jarFile.getName())
222: .toURL(), fileName);
223: } catch (MalformedURLException exc) {
224: throw new RuntimeException(exc);
225: }
226: }
227: }
228: Iterator iter = mOpenJarFiles.entrySet().iterator();
229: while (iter.hasNext()) {
230: Map.Entry e = (Map.Entry) iter.next();
231: JarFile jarFile = (JarFile) e.getValue();
232: JarEntry entry = jarFile.getJarEntry(fileName);
233: if (entry != null) {
234: try {
235: mResourceIndex.put(fileName, e.getKey());
236: return createURL(new File(jarFile.getName())
237: .toURL(), fileName);
238: } catch (MalformedURLException exc) {
239: throw new RuntimeException(exc);
240: }
241: }
242: }
243: }
244: return null;
245: }
246:
247: public Vector findResources(String fileName) {
248: fileName = fileName.replace('\\', '/');
249: if (fileName.startsWith("/")) {
250: fileName = fileName.substring(1);
251: } else if (fileName.startsWith("./")) {
252: fileName = fileName.substring(2);
253: }
254:
255: Vector result = new Vector();
256: synchronized (mOpenJarFiles) {
257: Iterator iter = mOpenJarFiles.values().iterator();
258: while (iter.hasNext()) {
259: JarFile jarFile = (JarFile) iter.next();
260: JarEntry entry = jarFile.getJarEntry(fileName);
261: if (entry != null) {
262: try {
263: result.add(createURL(
264: new File(jarFile.getName()).toURL(),
265: fileName));
266: } catch (MalformedURLException exc) {
267: throw new RuntimeException(exc);
268: }
269: }
270: }
271: }
272: return result;
273: }
274:
275: public void addJar(String fileName) throws IOException {
276: try {
277: addJar(new JarFileImpl(fileName));
278: } catch (IOException e) {
279: throw new RuntimeException("jar file: " + fileName, e);
280: }
281: }
282:
283: public void addJar(JarFile file) throws IOException {
284: if (null == file) {
285: StringTranslator translator = (StringTranslator) EnvironmentContext
286: .getInstance().getStringTranslatorFor(this );
287: throw new java.lang.IllegalArgumentException(translator
288: .getString(LocalStringKeys.NULL_ARGUMENT, "file"));
289: }
290:
291: String name = file.getName();
292: File f = new File(name);
293: URL url = f.toURL();
294: synchronized (mOpenJarFiles) {
295: JarFileImpl prev = (JarFileImpl) mOpenJarFiles.get(url
296: .getPath());
297: if (prev != null) {
298: prev.closeImpl();
299: }
300: mOpenJarFiles.put(url.getPath(), (JarFileImpl) file);
301: }
302: }
303:
304: public URL[] getURLs() {
305: List list = new LinkedList();
306: synchronized (mOpenJarFiles) {
307: Iterator iter = mOpenJarFiles.values().iterator();
308: while (iter.hasNext()) {
309: String fileName = ((JarFile) iter.next()).getName();
310: try {
311: list
312: .add(createURL(new File(fileName).toURL(),
313: null));
314: } catch (MalformedURLException exc) {
315: throw new RuntimeException(exc);
316: }
317: }
318: }
319:
320: URL[] urls = new URL[list.size()];
321: list.toArray(urls);
322: return urls;
323: }
324: }
|