41 * @since JDK1.2 |
41 * @since JDK1.2 |
42 */ |
42 */ |
43 class JarFileFactory implements URLJarFile.URLJarFileCloseController { |
43 class JarFileFactory implements URLJarFile.URLJarFileCloseController { |
44 |
44 |
45 /* the url to file cache */ |
45 /* the url to file cache */ |
46 private static HashMap<String, JarFile> fileCache = new HashMap<String, JarFile>(); |
46 private static final HashMap<String, JarFile> fileCache = new HashMap<>(); |
47 |
47 |
48 /* the file to url cache */ |
48 /* the file to url cache */ |
49 private static HashMap<JarFile, URL> urlCache = new HashMap<JarFile, URL>(); |
49 private static final HashMap<JarFile, URL> urlCache = new HashMap<>(); |
|
50 |
|
51 private static final JarFileFactory instance = new JarFileFactory(); |
|
52 |
|
53 private JarFileFactory() { } |
|
54 |
|
55 public static JarFileFactory getInstance() { |
|
56 return instance; |
|
57 } |
50 |
58 |
51 URLConnection getConnection(JarFile jarFile) throws IOException { |
59 URLConnection getConnection(JarFile jarFile) throws IOException { |
52 URL u = urlCache.get(jarFile); |
60 URL u; |
|
61 synchronized (instance) { |
|
62 u = urlCache.get(jarFile); |
|
63 } |
53 if (u != null) |
64 if (u != null) |
54 return u.openConnection(); |
65 return u.openConnection(); |
55 |
66 |
56 return null; |
67 return null; |
57 } |
68 } |
60 return get(url, true); |
71 return get(url, true); |
61 } |
72 } |
62 |
73 |
63 JarFile get(URL url, boolean useCaches) throws IOException { |
74 JarFile get(URL url, boolean useCaches) throws IOException { |
64 |
75 |
65 JarFile result = null; |
76 JarFile result; |
66 JarFile local_result = null; |
77 JarFile local_result; |
67 |
78 |
68 if (useCaches) { |
79 if (useCaches) { |
69 synchronized (this) { |
80 synchronized (instance) { |
70 result = getCachedJarFile(url); |
81 result = getCachedJarFile(url); |
71 } |
82 } |
72 if (result == null) { |
83 if (result == null) { |
73 local_result = URLJarFile.getJarFile(url, this); |
84 local_result = URLJarFile.getJarFile(url, this); |
74 synchronized (this) { |
85 synchronized (instance) { |
75 result = getCachedJarFile(url); |
86 result = getCachedJarFile(url); |
76 if (result == null) { |
87 if (result == null) { |
77 fileCache.put(URLUtil.urlNoFragString(url), local_result); |
88 fileCache.put(URLUtil.urlNoFragString(url), local_result); |
78 urlCache.put(local_result, url); |
89 urlCache.put(local_result, url); |
79 result = local_result; |
90 result = local_result; |
97 * Callback method of the URLJarFileCloseController to |
108 * Callback method of the URLJarFileCloseController to |
98 * indicate that the JarFile is close. This way we can |
109 * indicate that the JarFile is close. This way we can |
99 * remove the JarFile from the cache |
110 * remove the JarFile from the cache |
100 */ |
111 */ |
101 public void close(JarFile jarFile) { |
112 public void close(JarFile jarFile) { |
102 URL urlRemoved = urlCache.remove(jarFile); |
113 synchronized (instance) { |
103 if( urlRemoved != null) { |
114 URL urlRemoved = urlCache.remove(jarFile); |
|
115 if (urlRemoved != null) |
104 fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); |
116 fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); |
105 } |
117 } |
106 } |
118 } |
107 |
119 |
108 |
|
109 private JarFile getCachedJarFile(URL url) { |
120 private JarFile getCachedJarFile(URL url) { |
|
121 assert Thread.holdsLock(instance); |
110 JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); |
122 JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); |
111 |
123 |
112 /* if the JAR file is cached, the permission will always be there */ |
124 /* if the JAR file is cached, the permission will always be there */ |
113 if (result != null) { |
125 if (result != null) { |
114 Permission perm = getPermission(result); |
126 Permission perm = getPermission(result); |