| /* |
| * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.net.www.protocol.jar; |
| |
| import java.io.InputStream; |
| import java.io.IOException; |
| import java.io.FileNotFoundException; |
| import java.io.BufferedInputStream; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.net.MalformedURLException; |
| import java.net.UnknownServiceException; |
| import java.util.Enumeration; |
| import java.util.Map; |
| import java.util.List; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarFile; |
| import java.util.jar.Manifest; |
| import java.security.Permission; |
| |
| /** |
| * @author Benjamin Renaud |
| * @since 1.2 |
| */ |
| public class JarURLConnection extends java.net.JarURLConnection { |
| |
| private static final boolean debug = false; |
| |
| /* the Jar file factory. It handles both retrieval and caching. |
| */ |
| private static final JarFileFactory factory = JarFileFactory.getInstance(); |
| |
| /* the url for the Jar file */ |
| private URL jarFileURL; |
| |
| /* the permission to get this JAR file. This is the actual, ultimate, |
| * permission, returned by the jar file factory. |
| */ |
| private Permission permission; |
| |
| /* the url connection for the JAR file */ |
| private URLConnection jarFileURLConnection; |
| |
| /* the entry name, if any */ |
| private String entryName; |
| |
| /* the JarEntry */ |
| private JarEntry jarEntry; |
| |
| /* the jar file corresponding to this connection */ |
| private JarFile jarFile; |
| |
| /* the content type for this connection */ |
| private String contentType; |
| |
| public JarURLConnection(URL url, Handler handler) |
| throws MalformedURLException, IOException { |
| super(url); |
| |
| jarFileURL = getJarFileURL(); |
| jarFileURLConnection = jarFileURL.openConnection(); |
| entryName = getEntryName(); |
| } |
| |
| public JarFile getJarFile() throws IOException { |
| connect(); |
| return jarFile; |
| } |
| |
| public JarEntry getJarEntry() throws IOException { |
| connect(); |
| return jarEntry; |
| } |
| |
| public Permission getPermission() throws IOException { |
| return jarFileURLConnection.getPermission(); |
| } |
| |
| class JarURLInputStream extends java.io.FilterInputStream { |
| JarURLInputStream (InputStream src) { |
| super (src); |
| } |
| public void close () throws IOException { |
| try { |
| super.close(); |
| } finally { |
| if (!getUseCaches()) { |
| jarFile.close(); |
| } |
| } |
| } |
| } |
| |
| |
| |
| public void connect() throws IOException { |
| if (!connected) { |
| /* the factory call will do the security checks */ |
| jarFile = factory.get(getJarFileURL(), getUseCaches()); |
| |
| /* we also ask the factory the permission that was required |
| * to get the jarFile, and set it as our permission. |
| */ |
| if (getUseCaches()) { |
| jarFileURLConnection = factory.getConnection(jarFile); |
| } |
| |
| if ((entryName != null)) { |
| jarEntry = (JarEntry)jarFile.getEntry(entryName); |
| if (jarEntry == null) { |
| try { |
| if (!getUseCaches()) { |
| jarFile.close(); |
| } |
| } catch (Exception e) { |
| } |
| throw new FileNotFoundException("JAR entry " + entryName + |
| " not found in " + |
| jarFile.getName()); |
| } |
| } |
| connected = true; |
| } |
| } |
| |
| public InputStream getInputStream() throws IOException { |
| connect(); |
| |
| InputStream result = null; |
| |
| if (entryName == null) { |
| throw new IOException("no entry name specified"); |
| } else { |
| if (jarEntry == null) { |
| throw new FileNotFoundException("JAR entry " + entryName + |
| " not found in " + |
| jarFile.getName()); |
| } |
| result = new JarURLInputStream (jarFile.getInputStream(jarEntry)); |
| } |
| return result; |
| } |
| |
| public int getContentLength() { |
| long result = getContentLengthLong(); |
| if (result > Integer.MAX_VALUE) |
| return -1; |
| return (int) result; |
| } |
| |
| public long getContentLengthLong() { |
| long result = -1; |
| try { |
| connect(); |
| if (jarEntry == null) { |
| /* if the URL referes to an archive */ |
| result = jarFileURLConnection.getContentLengthLong(); |
| } else { |
| /* if the URL referes to an archive entry */ |
| result = getJarEntry().getSize(); |
| } |
| } catch (IOException e) { |
| } |
| return result; |
| } |
| |
| public Object getContent() throws IOException { |
| Object result = null; |
| |
| connect(); |
| if (entryName == null) { |
| result = jarFile; |
| } else { |
| result = super.getContent(); |
| } |
| return result; |
| } |
| |
| public String getContentType() { |
| if (contentType == null) { |
| if (entryName == null) { |
| contentType = "x-java/jar"; |
| } else { |
| try { |
| connect(); |
| InputStream in = jarFile.getInputStream(jarEntry); |
| contentType = guessContentTypeFromStream( |
| new BufferedInputStream(in)); |
| in.close(); |
| } catch (IOException e) { |
| // don't do anything |
| } |
| } |
| if (contentType == null) { |
| contentType = guessContentTypeFromName(entryName); |
| } |
| if (contentType == null) { |
| contentType = "content/unknown"; |
| } |
| } |
| return contentType; |
| } |
| |
| public String getHeaderField(String name) { |
| return jarFileURLConnection.getHeaderField(name); |
| } |
| |
| /** |
| * Sets the general request property. |
| * |
| * @param key the keyword by which the request is known |
| * (e.g., "<code>accept</code>"). |
| * @param value the value associated with it. |
| */ |
| public void setRequestProperty(String key, String value) { |
| jarFileURLConnection.setRequestProperty(key, value); |
| } |
| |
| /** |
| * Returns the value of the named general request property for this |
| * connection. |
| * |
| * @return the value of the named general request property for this |
| * connection. |
| */ |
| public String getRequestProperty(String key) { |
| return jarFileURLConnection.getRequestProperty(key); |
| } |
| |
| /** |
| * Adds a general request property specified by a |
| * key-value pair. This method will not overwrite |
| * existing values associated with the same key. |
| * |
| * @param key the keyword by which the request is known |
| * (e.g., "<code>accept</code>"). |
| * @param value the value associated with it. |
| */ |
| public void addRequestProperty(String key, String value) { |
| jarFileURLConnection.addRequestProperty(key, value); |
| } |
| |
| /** |
| * Returns an unmodifiable Map of general request |
| * properties for this connection. The Map keys |
| * are Strings that represent the request-header |
| * field names. Each Map value is a unmodifiable List |
| * of Strings that represents the corresponding |
| * field values. |
| * |
| * @return a Map of the general request properties for this connection. |
| */ |
| public Map<String,List<String>> getRequestProperties() { |
| return jarFileURLConnection.getRequestProperties(); |
| } |
| |
| /** |
| * Set the value of the <code>allowUserInteraction</code> field of |
| * this <code>URLConnection</code>. |
| * |
| * @param allowuserinteraction the new value. |
| * @see java.net.URLConnection#allowUserInteraction |
| */ |
| public void setAllowUserInteraction(boolean allowuserinteraction) { |
| jarFileURLConnection.setAllowUserInteraction(allowuserinteraction); |
| } |
| |
| /** |
| * Returns the value of the <code>allowUserInteraction</code> field for |
| * this object. |
| * |
| * @return the value of the <code>allowUserInteraction</code> field for |
| * this object. |
| * @see java.net.URLConnection#allowUserInteraction |
| */ |
| public boolean getAllowUserInteraction() { |
| return jarFileURLConnection.getAllowUserInteraction(); |
| } |
| |
| /* |
| * cache control |
| */ |
| |
| /** |
| * Sets the value of the <code>useCaches</code> field of this |
| * <code>URLConnection</code> to the specified value. |
| * <p> |
| * Some protocols do caching of documents. Occasionally, it is important |
| * to be able to "tunnel through" and ignore the caches (e.g., the |
| * "reload" button in a browser). If the UseCaches flag on a connection |
| * is true, the connection is allowed to use whatever caches it can. |
| * If false, caches are to be ignored. |
| * The default value comes from DefaultUseCaches, which defaults to |
| * true. |
| * |
| * @see java.net.URLConnection#useCaches |
| */ |
| public void setUseCaches(boolean usecaches) { |
| jarFileURLConnection.setUseCaches(usecaches); |
| } |
| |
| /** |
| * Returns the value of this <code>URLConnection</code>'s |
| * <code>useCaches</code> field. |
| * |
| * @return the value of this <code>URLConnection</code>'s |
| * <code>useCaches</code> field. |
| * @see java.net.URLConnection#useCaches |
| */ |
| public boolean getUseCaches() { |
| return jarFileURLConnection.getUseCaches(); |
| } |
| |
| /** |
| * Sets the value of the <code>ifModifiedSince</code> field of |
| * this <code>URLConnection</code> to the specified value. |
| * |
| * @param value the new value. |
| * @see java.net.URLConnection#ifModifiedSince |
| */ |
| public void setIfModifiedSince(long ifmodifiedsince) { |
| jarFileURLConnection.setIfModifiedSince(ifmodifiedsince); |
| } |
| |
| /** |
| * Sets the default value of the <code>useCaches</code> field to the |
| * specified value. |
| * |
| * @param defaultusecaches the new value. |
| * @see java.net.URLConnection#useCaches |
| */ |
| public void setDefaultUseCaches(boolean defaultusecaches) { |
| jarFileURLConnection.setDefaultUseCaches(defaultusecaches); |
| } |
| |
| /** |
| * Returns the default value of a <code>URLConnection</code>'s |
| * <code>useCaches</code> flag. |
| * <p> |
| * Ths default is "sticky", being a part of the static state of all |
| * URLConnections. This flag applies to the next, and all following |
| * URLConnections that are created. |
| * |
| * @return the default value of a <code>URLConnection</code>'s |
| * <code>useCaches</code> flag. |
| * @see java.net.URLConnection#useCaches |
| */ |
| public boolean getDefaultUseCaches() { |
| return jarFileURLConnection.getDefaultUseCaches(); |
| } |
| } |