|
1 /* |
|
2 * Copyright (c) 2014, 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 jdk.internal.jrtfs; |
|
27 |
|
28 import java.io.*; |
|
29 import java.nio.channels.*; |
|
30 import java.nio.file.*; |
|
31 import java.nio.file.DirectoryStream.Filter; |
|
32 import java.nio.file.attribute.*; |
|
33 import java.nio.file.spi.FileSystemProvider; |
|
34 import java.net.URI; |
|
35 import java.net.URISyntaxException; |
|
36 import java.util.HashMap; |
|
37 import java.util.Map; |
|
38 import java.util.Set; |
|
39 import java.util.concurrent.ExecutorService; |
|
40 |
|
41 public final class JrtFileSystemProvider extends FileSystemProvider { |
|
42 private volatile FileSystem theFileSystem; |
|
43 |
|
44 public JrtFileSystemProvider() { } |
|
45 |
|
46 @Override |
|
47 public String getScheme() { |
|
48 return "jrt"; |
|
49 } |
|
50 |
|
51 /** |
|
52 * Need FilePermission ${java.home}/-", "read" to create or get jrt:/ |
|
53 */ |
|
54 private void checkPermission() { |
|
55 SecurityManager sm = System.getSecurityManager(); |
|
56 if (sm != null) { |
|
57 String home = SystemImages.RUNTIME_HOME; |
|
58 FilePermission perm = |
|
59 new FilePermission(home + File.separator + "-", "read"); |
|
60 sm.checkPermission(perm); |
|
61 } |
|
62 } |
|
63 |
|
64 private void checkUri(URI uri) { |
|
65 if (!uri.getScheme().equalsIgnoreCase(getScheme())) |
|
66 throw new IllegalArgumentException("URI does not match this provider"); |
|
67 if (uri.getAuthority() != null) |
|
68 throw new IllegalArgumentException("Authority component present"); |
|
69 if (uri.getPath() == null) |
|
70 throw new IllegalArgumentException("Path component is undefined"); |
|
71 if (!uri.getPath().equals("/")) |
|
72 throw new IllegalArgumentException("Path component should be '/'"); |
|
73 if (uri.getQuery() != null) |
|
74 throw new IllegalArgumentException("Query component present"); |
|
75 if (uri.getFragment() != null) |
|
76 throw new IllegalArgumentException("Fragment component present"); |
|
77 } |
|
78 |
|
79 @Override |
|
80 public FileSystem newFileSystem(URI uri, Map<String, ?> env) |
|
81 throws IOException |
|
82 { |
|
83 checkPermission(); |
|
84 checkUri(uri); |
|
85 return new JrtFileSystem(this, env); |
|
86 } |
|
87 |
|
88 @Override |
|
89 public Path getPath(URI uri) { |
|
90 checkPermission(); |
|
91 if (!uri.getScheme().equalsIgnoreCase(getScheme())) |
|
92 throw new IllegalArgumentException("URI does not match this provider"); |
|
93 if (uri.getAuthority() != null) |
|
94 throw new IllegalArgumentException("Authority component present"); |
|
95 if (uri.getQuery() != null) |
|
96 throw new IllegalArgumentException("Query component present"); |
|
97 if (uri.getFragment() != null) |
|
98 throw new IllegalArgumentException("Fragment component present"); |
|
99 String path = uri.getPath(); |
|
100 if (path == null || path.charAt(0) != '/') |
|
101 throw new IllegalArgumentException("Invalid path component"); |
|
102 return getTheFileSystem().getPath(path); |
|
103 } |
|
104 |
|
105 private FileSystem getTheFileSystem() { |
|
106 checkPermission(); |
|
107 FileSystem fs = this.theFileSystem; |
|
108 if (fs == null) { |
|
109 synchronized (this) { |
|
110 fs = this.theFileSystem; |
|
111 if (fs == null) { |
|
112 try { |
|
113 this.theFileSystem = fs = new JrtFileSystem(this, null) { |
|
114 @Override public void close() { |
|
115 throw new UnsupportedOperationException(); |
|
116 } |
|
117 }; |
|
118 } catch (IOException ioe) { |
|
119 throw new InternalError(ioe); |
|
120 } |
|
121 } |
|
122 } |
|
123 } |
|
124 return fs; |
|
125 } |
|
126 |
|
127 @Override |
|
128 public FileSystem getFileSystem(URI uri) { |
|
129 checkPermission(); |
|
130 checkUri(uri); |
|
131 return getTheFileSystem(); |
|
132 } |
|
133 |
|
134 // Checks that the given file is a JrtPath |
|
135 static final JrtPath toJrtPath(Path path) { |
|
136 if (path == null) |
|
137 throw new NullPointerException(); |
|
138 if (!(path instanceof JrtPath)) |
|
139 throw new ProviderMismatchException(); |
|
140 return (JrtPath)path; |
|
141 } |
|
142 |
|
143 @Override |
|
144 public void checkAccess(Path path, AccessMode... modes) throws IOException { |
|
145 toJrtPath(path).checkAccess(modes); |
|
146 } |
|
147 |
|
148 @Override |
|
149 public void copy(Path src, Path target, CopyOption... options) |
|
150 throws IOException |
|
151 { |
|
152 toJrtPath(src).copy(toJrtPath(target), options); |
|
153 } |
|
154 |
|
155 @Override |
|
156 public void createDirectory(Path path, FileAttribute<?>... attrs) |
|
157 throws IOException |
|
158 { |
|
159 toJrtPath(path).createDirectory(attrs); |
|
160 } |
|
161 |
|
162 @Override |
|
163 public final void delete(Path path) throws IOException { |
|
164 toJrtPath(path).delete(); |
|
165 } |
|
166 |
|
167 @Override |
|
168 @SuppressWarnings("unchecked") |
|
169 public <V extends FileAttributeView> V |
|
170 getFileAttributeView(Path path, Class<V> type, LinkOption... options) |
|
171 { |
|
172 return JrtFileAttributeView.get(toJrtPath(path), type); |
|
173 } |
|
174 |
|
175 @Override |
|
176 public FileStore getFileStore(Path path) throws IOException { |
|
177 return toJrtPath(path).getFileStore(); |
|
178 } |
|
179 |
|
180 @Override |
|
181 public boolean isHidden(Path path) { |
|
182 return toJrtPath(path).isHidden(); |
|
183 } |
|
184 |
|
185 @Override |
|
186 public boolean isSameFile(Path path, Path other) throws IOException { |
|
187 return toJrtPath(path).isSameFile(other); |
|
188 } |
|
189 |
|
190 @Override |
|
191 public void move(Path src, Path target, CopyOption... options) |
|
192 throws IOException |
|
193 { |
|
194 toJrtPath(src).move(toJrtPath(target), options); |
|
195 } |
|
196 |
|
197 @Override |
|
198 public AsynchronousFileChannel newAsynchronousFileChannel(Path path, |
|
199 Set<? extends OpenOption> options, |
|
200 ExecutorService exec, |
|
201 FileAttribute<?>... attrs) |
|
202 throws IOException |
|
203 { |
|
204 throw new UnsupportedOperationException(); |
|
205 } |
|
206 |
|
207 @Override |
|
208 public SeekableByteChannel newByteChannel(Path path, |
|
209 Set<? extends OpenOption> options, |
|
210 FileAttribute<?>... attrs) |
|
211 throws IOException |
|
212 { |
|
213 return toJrtPath(path).newByteChannel(options, attrs); |
|
214 } |
|
215 |
|
216 @Override |
|
217 public DirectoryStream<Path> newDirectoryStream( |
|
218 Path path, Filter<? super Path> filter) throws IOException |
|
219 { |
|
220 return toJrtPath(path).newDirectoryStream(filter); |
|
221 } |
|
222 |
|
223 @Override |
|
224 public FileChannel newFileChannel(Path path, |
|
225 Set<? extends OpenOption> options, |
|
226 FileAttribute<?>... attrs) |
|
227 throws IOException |
|
228 { |
|
229 return toJrtPath(path).newFileChannel(options, attrs); |
|
230 } |
|
231 |
|
232 @Override |
|
233 public InputStream newInputStream(Path path, OpenOption... options) |
|
234 throws IOException |
|
235 { |
|
236 return toJrtPath(path).newInputStream(options); |
|
237 } |
|
238 |
|
239 @Override |
|
240 public OutputStream newOutputStream(Path path, OpenOption... options) |
|
241 throws IOException |
|
242 { |
|
243 return toJrtPath(path).newOutputStream(options); |
|
244 } |
|
245 |
|
246 @Override |
|
247 @SuppressWarnings("unchecked") // Cast to A |
|
248 public <A extends BasicFileAttributes> A |
|
249 readAttributes(Path path, Class<A> type, LinkOption... options) |
|
250 throws IOException |
|
251 { |
|
252 if (type == BasicFileAttributes.class || type == JrtFileAttributes.class) |
|
253 return (A)toJrtPath(path).getAttributes(); |
|
254 return null; |
|
255 } |
|
256 |
|
257 @Override |
|
258 public Map<String, Object> |
|
259 readAttributes(Path path, String attribute, LinkOption... options) |
|
260 throws IOException |
|
261 { |
|
262 return toJrtPath(path).readAttributes(attribute, options); |
|
263 } |
|
264 |
|
265 @Override |
|
266 public void setAttribute(Path path, String attribute, |
|
267 Object value, LinkOption... options) |
|
268 throws IOException |
|
269 { |
|
270 toJrtPath(path).setAttribute(attribute, value, options); |
|
271 } |
|
272 } |