1 /* 2 * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net.www.protocol.jar; 27 28 import java.io.*; 29 import java.net.*; 30 import java.util.*; 31 import java.util.jar.*; 32 import java.util.zip.ZipFile; 33 import java.security.Permission; 34 35 /* A factory for cached JAR file. This class is used to both retrieve 36 * and cache Jar files. 37 * 38 * @author Benjamin Renaud 39 * @since JDK1.2 40 */ 41 class JarFileFactory implements URLJarFile.URLJarFileCloseController { 42 43 /* the url to file cache */ 44 private static HashMap fileCache = new HashMap(); 45 46 /* the file to url cache */ 47 private static HashMap urlCache = new HashMap(); 48 49 URLConnection getConnection(JarFile jarFile) throws IOException { 50 URL u = (URL)urlCache.get(jarFile); 51 if (u != null) 52 return u.openConnection(); 53 54 return null; 55 } 56 57 public JarFile get(URL url) throws IOException { 58 return get(url, true); 59 } 60 61 JarFile get(URL url, boolean useCaches) throws IOException { 62 if (url.getProtocol().equalsIgnoreCase("file")) { 63 // Deal with UNC pathnames specially. See 4180841 64 65 String host = url.getHost(); 66 if (host != null && !host.equals("") && 67 !host.equalsIgnoreCase("localhost")) { 68 69 url = new URL("file", "", "//" + host + url.getPath()); 70 } 71 } 72 73 JarFile result = null; 74 JarFile local_result = null; 75 76 if (useCaches) { 77 synchronized (this) { 78 result = getCachedJarFile(url); 79 } 80 if (result == null) { 81 local_result = URLJarFile.getJarFile(url, this); 82 synchronized (this) { 83 result = getCachedJarFile(url); 84 if (result == null) { 85 fileCache.put(url, local_result); 86 urlCache.put(local_result, url); 87 result = local_result; 88 } else { 89 if (local_result != null) { 90 local_result.close(); 91 } 92 } 93 } 94 } 95 } else { 96 result = URLJarFile.getJarFile(url, this); 97 } 98 if (result == null) 99 throw new FileNotFoundException(url.toString()); 100 101 return result; 102 } 103 104 /** 105 * Callback method of the URLJarFileCloseController to 106 * indicate that the JarFile is close. This way we can 107 * remove the JarFile from the cache 108 */ 109 public void close(JarFile jarFile) { 110 URL urlRemoved = (URL) urlCache.remove(jarFile); 111 if( urlRemoved != null) { 112 fileCache.remove(urlRemoved); 113 } 114 } 115 116 private JarFile getCachedJarFile(URL url) { 117 JarFile result = (JarFile)fileCache.get(url); 118 119 /* if the JAR file is cached, the permission will always be there */ 120 if (result != null) { 121 Permission perm = getPermission(result); 122 if (perm != null) { 123 SecurityManager sm = System.getSecurityManager(); 124 if (sm != null) { 125 try { 126 sm.checkPermission(perm); 127 } catch (SecurityException se) { 128 // fallback to checkRead/checkConnect for pre 1.2 129 // security managers 130 if ((perm instanceof java.io.FilePermission) && 131 perm.getActions().indexOf("read") != -1) { 132 sm.checkRead(perm.getName()); 133 } else if ((perm instanceof 134 java.net.SocketPermission) && 135 perm.getActions().indexOf("connect") != -1) { 136 sm.checkConnect(url.getHost(), url.getPort()); 137 } else { 138 throw se; 139 } 140 } 141 } 142 } 143 } 144 return result; 145 } 146 147 private Permission getPermission(JarFile jarFile) { 148 try { 149 URLConnection uc = (URLConnection)getConnection(jarFile); 150 if (uc != null) 151 return uc.getPermission(); 152 } catch (IOException ioe) { 153 // gulp 154 } 155 156 return null; 157 } 158 }