001: /*
002: * @(#)URLJarFile.java 1.7 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.net.www.protocol.jar;
029:
030: import java.io.*;
031: import java.net.*;
032: import java.util.*;
033: import java.util.jar.*;
034: import java.util.zip.ZipFile;
035: import java.util.zip.ZipEntry;
036: import java.security.cert.Certificate;
037: import java.security.AccessController;
038: import java.security.PrivilegedAction;
039: import java.security.PrivilegedExceptionAction;
040: import java.security.PrivilegedActionException;
041: import sun.net.www.ParseUtil;
042:
043: /* URL jar file is a common JarFile subtype used for JarURLConnection */
044: class URLJarFile extends JarFile {
045:
046: private static int BUF_SIZE = 2048;
047:
048: private Manifest super Man;
049: private Attributes super Attr;
050: private Map super Entries;
051:
052: static JarFile getJarFile(URL url) throws IOException {
053: if (isFileURL(url))
054: return new URLJarFile(url);
055: else {
056: return retrieve(url);
057: }
058: }
059:
060: private URLJarFile(File file) throws IOException {
061: super (file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
062: }
063:
064: private URLJarFile(URL url) throws IOException {
065: super (ParseUtil.decode(url.getFile()));
066: }
067:
068: private static boolean isFileURL(URL url) {
069: return url.getProtocol().equalsIgnoreCase("file");
070: }
071:
072: /*
073: * close the jar file.
074: */
075: protected void finalize() throws IOException {
076: close();
077: }
078:
079: /**
080: * Returns the <code>ZipEntry</code> for the given entry name or
081: * <code>null</code> if not found.
082: *
083: * @param name the JAR file entry name
084: * @return the <code>ZipEntry</code> for the given entry name or
085: * <code>null</code> if not found
086: * @see java.util.zip.ZipEntry
087: */
088: public ZipEntry getEntry(String name) {
089: ZipEntry ze = super .getEntry(name);
090: if (ze != null) {
091: if (ze instanceof JarEntry)
092: return new URLJarFileEntry((JarEntry) ze);
093: else
094: throw new InternalError(super .getClass()
095: + " returned unexpected entry type "
096: + ze.getClass());
097: }
098: return null;
099: }
100:
101: public Manifest getManifest() throws IOException {
102:
103: if (!isSuperMan()) {
104: return null;
105: }
106:
107: Manifest man = new Manifest();
108: Attributes attr = man.getMainAttributes();
109: attr.putAll((Map) super Attr.clone());
110:
111: // now deep copy the manifest entries
112: if (super Entries != null) {
113: Map entries = man.getEntries();
114: Iterator it = super Entries.keySet().iterator();
115: while (it.hasNext()) {
116: Object key = it.next();
117: Attributes at = (Attributes) super Entries.get(key);
118: entries.put(key, at.clone());
119: }
120: }
121:
122: return man;
123: }
124:
125: // optimal side-effects
126: private synchronized boolean isSuperMan() throws IOException {
127:
128: if (super Man == null) {
129: super Man = super .getManifest();
130: }
131:
132: if (super Man != null) {
133: super Attr = super Man.getMainAttributes();
134: super Entries = super Man.getEntries();
135: return true;
136: } else
137: return false;
138: }
139:
140: /**
141: * Given a URL, retrieves a JAR file, caches it to disk, and creates a
142: * cached JAR file object.
143: */
144: private static JarFile retrieve(final URL url) throws IOException {
145: JarFile result = null;
146:
147: /* get the stream before asserting privileges */
148: final InputStream in = url.openConnection().getInputStream();
149:
150: try {
151: result = (JarFile) AccessController
152: .doPrivileged(new PrivilegedExceptionAction() {
153: public Object run() throws IOException {
154: OutputStream out = null;
155: try {
156: File tmpFile = File.createTempFile(
157: "jar_cache", null);
158: tmpFile.deleteOnExit();
159: out = new FileOutputStream(tmpFile);
160: int read = 0;
161: byte[] buf = new byte[BUF_SIZE];
162: while ((read = in.read(buf)) != -1) {
163: out.write(buf, 0, read);
164: }
165: out.close();
166: out = null;
167: return new URLJarFile(tmpFile);
168: } finally {
169: if (in != null) {
170: in.close();
171: }
172: if (out != null) {
173: out.close();
174: }
175: }
176: }
177: });
178: } catch (PrivilegedActionException pae) {
179: throw (IOException) pae.getException();
180: }
181:
182: return result;
183: }
184:
185: private class URLJarFileEntry extends JarEntry {
186: private JarEntry je;
187:
188: URLJarFileEntry(JarEntry je) {
189: super (je);
190: this .je = je;
191: }
192:
193: public Attributes getAttributes() throws IOException {
194: if (URLJarFile.this .isSuperMan()) {
195: Map e = URLJarFile.this .super Entries;
196: if (e != null) {
197: Attributes a = (Attributes) e.get(getName());
198: if (a != null)
199: return (Attributes) a.clone();
200: }
201: }
202: return null;
203: }
204:
205: public java.security.cert.Certificate[] getCertificates() {
206: Certificate[] certs = je.getCertificates();
207: return certs == null ? null : (Certificate[]) certs.clone();
208: }
209: }
210: }
|