JarFileFactory.java revision 49965c1dc9da104344f4893a05e45795a5740d20
1b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org/*
2b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
5b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * This code is free software; you can redistribute it and/or modify it
6b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * under the terms of the GNU General Public License version 2 only, as
7b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * published by the Free Software Foundation.  Oracle designates this
8b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * particular file as subject to the "Classpath" exception as provided
9b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * by Oracle in the LICENSE file that accompanied this code.
10b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
11b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * This code is distributed in the hope that it will be useful, but WITHOUT
12b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * version 2 for more details (a copy is included in the LICENSE file that
15b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * accompanied this code).
16b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
17b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * You should have received a copy of the GNU General Public License version
18b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * 2 along with this work; if not, write to the Free Software Foundation,
19b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
21b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * or visit www.oracle.com if you need additional information or have any
23b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * questions.
24b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org */
25b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
26b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgpackage sun.net.www.protocol.jar;
27b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
28b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport java.io.IOException;
29b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport java.io.FileNotFoundException;
30b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport java.net.URL;
31c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.orgimport java.net.URLConnection;
323c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgimport java.util.HashMap;
33b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport java.util.jar.JarFile;
34b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport java.security.Permission;
35b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgimport sun.net.util.URLUtil;
36b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
37df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org/* A factory for cached JAR file. This class is used to both retrieve
38a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org * and cache Jar files.
39b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
4081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström * @author Benjamin Renaud
41b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * @since JDK1.2
42b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org */
43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.orgclass JarFileFactory implements URLJarFile.URLJarFileCloseController {
44a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org
45a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org    /* the url to file cache */
46b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    private static final HashMap<String, JarFile> fileCache = new HashMap<>();
4781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
4881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    /* the file to url cache */
4950fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org    private static final HashMap<JarFile, URL> urlCache = new HashMap<>();
50776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
51ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org    private static final JarFileFactory instance = new JarFileFactory();
52b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
53b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    private JarFileFactory() { }
54b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
55d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg    public static JarFileFactory getInstance() {
56b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        return instance;
57b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    URLConnection getConnection(JarFile jarFile) throws IOException {
6081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        URL u;
6181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        synchronized (instance) {
6281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            u = urlCache.get(jarFile);
6381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        }
6481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        if (u != null)
6581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            return u.openConnection();
6681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
6781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return null;
6881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
6981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    public JarFile get(URL url) throws IOException {
7181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return get(url, true);
7281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
7381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    JarFile get(URL url, boolean useCaches) throws IOException {
7581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        JarFile result;
7781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        JarFile local_result;
7881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        if (useCaches) {
8081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            synchronized (instance) {
8181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                result = getCachedJarFile(url);
8281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            }
8381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            if (result == null) {
8481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                local_result = URLJarFile.getJarFile(url, this);
8581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                synchronized (instance) {
8681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    result = getCachedJarFile(url);
8781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    if (result == null) {
8881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        fileCache.put(URLUtil.urlNoFragString(url), local_result);
8981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        urlCache.put(local_result, url);
9081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        result = local_result;
9181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    } else {
9281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        if (local_result != null) {
9381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            local_result.close();
9481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        }
9581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    }
9681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                }
9781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            }
9881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        } else {
9981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            result = URLJarFile.getJarFile(url, this);
10081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        }
10181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        if (result == null)
10281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            throw new FileNotFoundException(url.toString());
10381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
10481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return result;
10581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
10681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
10781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    /**
108d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg     * Callback method of the URLJarFileCloseController to
10981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström     * indicate that the JarFile is close. This way we can
11081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström     * remove the JarFile from the cache
11181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström     */
11281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    public void close(JarFile jarFile) {
11381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        synchronized (instance) {
11481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            URL urlRemoved = urlCache.remove(jarFile);
11581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            if (urlRemoved != null)
11681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
11781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        }
11881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
11981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    private JarFile getCachedJarFile(URL url) {
12181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        assert Thread.holdsLock(instance);
12281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
12381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        /* if the JAR file is cached, the permission will always be there */
12581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        if (result != null) {
12681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            Permission perm = getPermission(result);
12781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            if (perm != null) {
12881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                SecurityManager sm = System.getSecurityManager();
12981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                if (sm != null) {
13081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    try {
13181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        sm.checkPermission(perm);
13281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    } catch (SecurityException se) {
13381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        // fallback to checkRead/checkConnect for pre 1.2
13481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        // security managers
13581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        if ((perm instanceof java.io.FilePermission) &&
13681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            perm.getActions().indexOf("read") != -1) {
13781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            sm.checkRead(perm.getName());
13881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        } else if ((perm instanceof
13981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            java.net.SocketPermission) &&
14081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            perm.getActions().indexOf("connect") != -1) {
14181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            sm.checkConnect(url.getHost(), url.getPort());
14281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        } else {
14381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                            throw se;
14481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                        }
14581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    }
14681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                }
14781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            }
14881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        }
14981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return result;
15081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
15181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
15281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    private Permission getPermission(JarFile jarFile) {
15381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        try {
15481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            URLConnection uc = getConnection(jarFile);
15581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            if (uc != null)
15681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                return uc.getPermission();
15781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        } catch (IOException ioe) {
15881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström            // gulp
15981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        }
16081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
16181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return null;
16281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
16381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
16481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström