|
1 /* |
|
2 * Copyright 2007-2009 Sun Microsystems, Inc. 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. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 package java.nio.file.spi; |
|
27 |
|
28 import java.nio.file.*; |
|
29 import java.nio.file.attribute.FileAttribute; |
|
30 import java.nio.channels.*; |
|
31 import java.net.URI; |
|
32 import java.util.*; |
|
33 import java.util.concurrent.ExecutorService; |
|
34 import java.security.AccessController; |
|
35 import java.security.PrivilegedAction; |
|
36 import java.io.IOException; |
|
37 |
|
38 /** |
|
39 * Service-provider class for file systems. |
|
40 * |
|
41 * <p> A file system provider is a concrete implementation of this class that |
|
42 * implements the abstract methods defined by this class. A provider is |
|
43 * identified by a {@code URI} {@link #getScheme() scheme}. The default provider |
|
44 * is identified by the URI scheme "file". It creates the {@link FileSystem} that |
|
45 * provides access to the file systems accessible to the Java virtual machine. |
|
46 * The {@link FileSystems} class defines how file system providers are located |
|
47 * and loaded. The default provider is typically a system-default provider but |
|
48 * may be overridden if the system property {@code |
|
49 * java.nio.file.spi.DefaultFileSystemProvider} is set. In that case, the |
|
50 * provider has a one argument constructor whose formal parameter type is {@code |
|
51 * FileSystemProvider}. All other providers have a zero argument constructor |
|
52 * that initializes the provider. |
|
53 * |
|
54 * <p> A provider is a factory for one or more {@link FileSystem} instances. Each |
|
55 * file system is identified by a {@code URI} where the URI's scheme matches |
|
56 * the provider's {@link #getScheme scheme}. The default file system, for example, |
|
57 * is identified by the URI {@code "file:///"}. A memory-based file system, |
|
58 * for example, may be identified by a URI such as {@code "memory:///?name=logfs"}. |
|
59 * The {@link #newFileSystem newFileSystem} method may be used to create a file |
|
60 * system, and the {@link #getFileSystem getFileSystem} method may be used to |
|
61 * obtain a reference to an existing file system created by the provider. Where |
|
62 * a provider is the factory for a single file system then it is provider dependent |
|
63 * if the file system is created when the provider is initialized, or later when |
|
64 * the {@code newFileSystem} method is invoked. In the case of the default |
|
65 * provider, the {@code FileSystem} is created when the provider is initialized. |
|
66 * |
|
67 * <p> In addition to file systems, a provider is also a factory for {@link |
|
68 * FileChannel} and {@link AsynchronousFileChannel} channels. The {@link |
|
69 * #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel |
|
70 * AsynchronousFileChannel} methods are defined to open or create files, returning |
|
71 * a channel to access the file. These methods are invoked by static factory |
|
72 * methods defined in the {@link java.nio.channels} package. |
|
73 * |
|
74 * <p> All of the methods in this class are safe for use by multiple concurrent |
|
75 * threads. |
|
76 * |
|
77 * @since 1.7 |
|
78 */ |
|
79 |
|
80 public abstract class FileSystemProvider { |
|
81 // lock using when loading providers |
|
82 private static final Object lock = new Object(); |
|
83 |
|
84 // installed providers |
|
85 private static volatile List<FileSystemProvider> installedProviders; |
|
86 |
|
87 // used to avoid recursive loading of instaled providers |
|
88 private static boolean loadingProviders = false; |
|
89 |
|
90 private static Void checkPermission() { |
|
91 SecurityManager sm = System.getSecurityManager(); |
|
92 if (sm != null) |
|
93 sm.checkPermission(new RuntimePermission("fileSystemProvider")); |
|
94 return null; |
|
95 } |
|
96 private FileSystemProvider(Void ignore) { } |
|
97 |
|
98 /** |
|
99 * Initializes a new instance of this class. |
|
100 * |
|
101 * <p> During construction a provider may safely access files associated |
|
102 * with the default provider but care needs to be taken to avoid circular |
|
103 * loading of other installed providers. If circular loading of installed |
|
104 * providers is detected then an unspecified error is thrown. |
|
105 * |
|
106 * @throws SecurityException |
|
107 * If a security manager has been installed and it denies |
|
108 * {@link RuntimePermission}<tt>("fileSystemProvider")</tt> |
|
109 */ |
|
110 protected FileSystemProvider() { |
|
111 this(checkPermission()); |
|
112 } |
|
113 |
|
114 // loads all installed providers |
|
115 private static List<FileSystemProvider> loadInstalledProviders() { |
|
116 List<FileSystemProvider> list = new ArrayList<FileSystemProvider>(); |
|
117 |
|
118 ServiceLoader<FileSystemProvider> sl = ServiceLoader |
|
119 .load(FileSystemProvider.class, ClassLoader.getSystemClassLoader()); |
|
120 |
|
121 // ServiceConfigurationError may be throw here |
|
122 for (FileSystemProvider provider: sl) { |
|
123 String scheme = provider.getScheme(); |
|
124 |
|
125 // add to list if the provider is not "file" and isn't a duplicate |
|
126 if (!scheme.equalsIgnoreCase("file")) { |
|
127 boolean found = false; |
|
128 for (FileSystemProvider p: list) { |
|
129 if (p.getScheme().equalsIgnoreCase(scheme)) { |
|
130 found = true; |
|
131 break; |
|
132 } |
|
133 } |
|
134 if (!found) { |
|
135 list.add(provider); |
|
136 } |
|
137 } |
|
138 } |
|
139 return list; |
|
140 } |
|
141 |
|
142 /** |
|
143 * Returns a list of the installed file system providers. |
|
144 * |
|
145 * <p> The first invocation of this method causes the default provider to be |
|
146 * initialized (if not already initialized) and loads any other installed |
|
147 * providers as described by the {@link FileSystems} class. |
|
148 * |
|
149 * @return An unmodifiable list of the installed file system providers. The |
|
150 * list contains at least one element, that is the default file |
|
151 * system provider |
|
152 * |
|
153 * @throws ServiceConfigurationError |
|
154 * When an error occurs while loading a service provider |
|
155 */ |
|
156 public static List<FileSystemProvider> installedProviders() { |
|
157 if (installedProviders == null) { |
|
158 // ensure default provider is initialized |
|
159 FileSystemProvider defaultProvider = FileSystems.getDefault().provider(); |
|
160 |
|
161 synchronized (lock) { |
|
162 if (installedProviders == null) { |
|
163 if (loadingProviders) { |
|
164 throw new Error("Circular loading of installed providers detected"); |
|
165 } |
|
166 loadingProviders = true; |
|
167 |
|
168 List<FileSystemProvider> list = AccessController |
|
169 .doPrivileged(new PrivilegedAction<List<FileSystemProvider>>() { |
|
170 @Override |
|
171 public List<FileSystemProvider> run() { |
|
172 return loadInstalledProviders(); |
|
173 }}); |
|
174 |
|
175 // insert the default provider at the start of the list |
|
176 list.add(0, defaultProvider); |
|
177 |
|
178 installedProviders = Collections.unmodifiableList(list); |
|
179 } |
|
180 } |
|
181 } |
|
182 return installedProviders; |
|
183 } |
|
184 |
|
185 /** |
|
186 * Returns the URI scheme that identifies this provider. |
|
187 * |
|
188 * @return The URI scheme |
|
189 */ |
|
190 public abstract String getScheme(); |
|
191 |
|
192 /** |
|
193 * Constructs a new {@code FileSystem} object identified by a URI. This |
|
194 * method is invoked by the {@link FileSystems#newFileSystem(URI,Map)} |
|
195 * method to open a new file system identified by a URI. |
|
196 * |
|
197 * <p> The {@code uri} parameter is an absolute, hierarchical URI, with a |
|
198 * scheme equal (without regard to case) to the scheme supported by this |
|
199 * provider. The exact form of the URI is highly provider dependent. The |
|
200 * {@code env} parameter is a map of provider specific properties to configure |
|
201 * the file system. |
|
202 * |
|
203 * <p> This method throws {@link FileSystemAlreadyExistsException} if the |
|
204 * file system already exists because it was previously created by an |
|
205 * invocation of this method. Once a file system is {@link FileSystem#close |
|
206 * closed} it is provider-dependent if the provider allows a new file system |
|
207 * to be created with the same URI as a file system it previously created. |
|
208 * |
|
209 * @param uri |
|
210 * URI reference |
|
211 * @param env |
|
212 * A map of provider specific properties to configure the file system; |
|
213 * may be empty |
|
214 * |
|
215 * @return A new file system |
|
216 * |
|
217 * @throws IllegalArgumentException |
|
218 * If the pre-conditions for the {@code uri} parameter aren't met, |
|
219 * or the {@code env} parameter does not contain properties required |
|
220 * by the provider, or a property value is invalid |
|
221 * @throws IOException |
|
222 * An I/O error occurs creating the file system |
|
223 * @throws SecurityException |
|
224 * If a security manager is installed and it denies an unspecified |
|
225 * permission required by the file system provider implementation |
|
226 * @throws FileSystemAlreadyExistsException |
|
227 * If the file system has already been created |
|
228 */ |
|
229 public abstract FileSystem newFileSystem(URI uri, Map<String,?> env) |
|
230 throws IOException; |
|
231 |
|
232 /** |
|
233 * Returns an existing {@code FileSystem} created by this provider. |
|
234 * |
|
235 * <p> This method returns a reference to a {@code FileSystem} that was |
|
236 * created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} |
|
237 * method. File systems created the {@link #newFileSystem(FileRef,Map) |
|
238 * newFileSystem(FileRef,Map)} method are not returned by this method. |
|
239 * The file system is identified by its {@code URI}. Its exact form |
|
240 * is highly provider dependent. In the case of the default provider the URI's |
|
241 * path component is {@code "/"} and the authority, query and fragment components |
|
242 * are undefined (Undefined components are represented by {@code null}). |
|
243 * |
|
244 * <p> Once a file system created by this provider is {@link FileSystem#close |
|
245 * closed} it is provider-dependent if this method returns a reference to |
|
246 * the closed file system or throws {@link FileSystemNotFoundException}. |
|
247 * If the provider allows a new file system to be created with the same URI |
|
248 * as a file system it previously created then this method throws the |
|
249 * exception if invoked after the file system is closed (and before a new |
|
250 * instance is created by the {@link #newFileSystem newFileSystem} method). |
|
251 * |
|
252 * <p> If a security manager is installed then a provider implementation |
|
253 * may require to check a permission before returning a reference to an |
|
254 * existing file system. In the case of the {@link FileSystems#getDefault |
|
255 * default} file system, no permission check is required. |
|
256 * |
|
257 * @param uri |
|
258 * URI reference |
|
259 * |
|
260 * @return The file system |
|
261 * |
|
262 * @throws IllegalArgumentException |
|
263 * If the pre-conditions for the {@code uri} parameter aren't met |
|
264 * @throws FileSystemNotFoundException |
|
265 * If the file system does not exist |
|
266 * @throws SecurityException |
|
267 * If a security manager is installed and it denies an unspecified |
|
268 * permission. |
|
269 */ |
|
270 public abstract FileSystem getFileSystem(URI uri); |
|
271 |
|
272 /** |
|
273 * Return a {@code Path} object by converting the given {@link URI}. |
|
274 * |
|
275 * <p> The exact form of the URI is file system provider dependent. In the |
|
276 * case of the default provider, the URI scheme is {@code "file"} and the |
|
277 * given URI has a non-empty path component, and undefined query, and |
|
278 * fragment components. The resulting {@code Path} is associated with the |
|
279 * default {@link FileSystems#getDefault default} {@code FileSystem}. |
|
280 * |
|
281 * <p> If a security manager is installed then a provider implementation |
|
282 * may require to check a permission. In the case of the {@link |
|
283 * FileSystems#getDefault default} file system, no permission check is |
|
284 * required. |
|
285 * |
|
286 * @param uri |
|
287 * The URI to convert |
|
288 * |
|
289 * @throws IllegalArgumentException |
|
290 * If the URI scheme does not identify this provider or other |
|
291 * preconditions on the uri parameter do not hold |
|
292 * @throws FileSystemNotFoundException |
|
293 * The file system, identified by the URI, does not exist |
|
294 * @throws SecurityException |
|
295 * If a security manager is installed and it denies an unspecified |
|
296 * permission. |
|
297 */ |
|
298 public abstract Path getPath(URI uri); |
|
299 |
|
300 /** |
|
301 * Constructs a new {@code FileSystem} to access the contents of a file as a |
|
302 * file system. |
|
303 * |
|
304 * <p> This method is intended for specialized providers of pseudo file |
|
305 * systems where the contents of one or more files is treated as a file |
|
306 * system. The {@code file} parameter is a reference to an existing file |
|
307 * and the {@code env} parameter is a map of provider specific properties to |
|
308 * configure the file system. |
|
309 * |
|
310 * <p> If this provider does not support the creation of such file systems |
|
311 * or if the provider does not recognize the file type of the given file then |
|
312 * it throws {@code UnsupportedOperationException}. The default implementation |
|
313 * of this method throws {@code UnsupportedOperationException}. |
|
314 * |
|
315 * @param file |
|
316 * The file |
|
317 * @param env |
|
318 * A map of provider specific properties to configure the file system; |
|
319 * may be empty |
|
320 * |
|
321 * @return A new file system |
|
322 * |
|
323 * @throws UnsupportedOperationException |
|
324 * If this provider does not support access to the contents as a |
|
325 * file system or it does not recognize the file type of the |
|
326 * given file |
|
327 * @throws IllegalArgumentException |
|
328 * If the {@code env} parameter does not contain properties required |
|
329 * by the provider, or a property value is invalid |
|
330 * @throws IOException |
|
331 * If an I/O error occurs |
|
332 * @throws SecurityException |
|
333 * If a security manager is installed and it denies an unspecified |
|
334 * permission. |
|
335 */ |
|
336 public FileSystem newFileSystem(FileRef file, Map<String,?> env) |
|
337 throws IOException |
|
338 { |
|
339 throw new UnsupportedOperationException(); |
|
340 } |
|
341 |
|
342 /** |
|
343 * Opens or creates a file for reading and/or writing, returning a file |
|
344 * channel to access the file. |
|
345 * |
|
346 * <p> This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[]) |
|
347 * FileChannel.open} method to open a file channel. A provider that does not |
|
348 * support all the features required to construct a file channel throws |
|
349 * {@code UnsupportedOperationException}. The default provider is required |
|
350 * to support the creation of file channels. When not overridden, the |
|
351 * default implementation throws {@code UnsupportedOperationException}. |
|
352 * |
|
353 * @param path |
|
354 * The path of the file to open or create |
|
355 * @param options |
|
356 * Options specifying how the file is opened |
|
357 * @param attrs |
|
358 * An optional list of file attributes to set atomically when |
|
359 * creating the file |
|
360 * |
|
361 * @return A new file channel |
|
362 * |
|
363 * @throws IllegalArgumentException |
|
364 * If the set contains an invalid combination of options |
|
365 * @throws UnsupportedOperationException |
|
366 * If this provider that does not support creating file channels, |
|
367 * or an unsupported open option or file attribute is specified |
|
368 * @throws IOException |
|
369 * If an I/O error occurs |
|
370 * @throws SecurityException |
|
371 * In the case of the default file system, the {@link |
|
372 * SecurityManager#checkRead(String)} method is invoked to check |
|
373 * read access if the file is opened for reading. The {@link |
|
374 * SecurityManager#checkWrite(String)} method is invoked to check |
|
375 * write access if the file is opened for writing |
|
376 */ |
|
377 public FileChannel newFileChannel(Path path, |
|
378 Set<? extends OpenOption> options, |
|
379 FileAttribute<?>... attrs) |
|
380 throws IOException |
|
381 { |
|
382 throw new UnsupportedOperationException(); |
|
383 } |
|
384 |
|
385 /** |
|
386 * Opens or creates a file for reading and/or writing, returning an |
|
387 * asynchronous file channel to access the file. |
|
388 * |
|
389 * <p> This method is invoked by the {@link |
|
390 * AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[]) |
|
391 * AsynchronousFileChannel.open} method to open an asynchronous file channel. |
|
392 * A provider that does not support all the features required to construct |
|
393 * an asynchronous file channel throws {@code UnsupportedOperationException}. |
|
394 * The default provider is required to support the creation of asynchronous |
|
395 * file channels. When not overridden, the default implementation of this |
|
396 * method throws {@code UnsupportedOperationException}. |
|
397 * |
|
398 * @param path |
|
399 * The path of the file to open or create |
|
400 * @param options |
|
401 * Options specifying how the file is opened |
|
402 * @param executor |
|
403 * The thread pool or {@code null} to associate the channel with |
|
404 * the default thread pool |
|
405 * @param attrs |
|
406 * An optional list of file attributes to set atomically when |
|
407 * creating the file |
|
408 * |
|
409 * @return A new asynchronous file channel |
|
410 * |
|
411 * @throws IllegalArgumentException |
|
412 * If the set contains an invalid combination of options |
|
413 * @throws UnsupportedOperationException |
|
414 * If this provider that does not support creating asynchronous file |
|
415 * channels, or an unsupported open option or file attribute is |
|
416 * specified |
|
417 * @throws IOException |
|
418 * If an I/O error occurs |
|
419 * @throws SecurityException |
|
420 * In the case of the default file system, the {@link |
|
421 * SecurityManager#checkRead(String)} method is invoked to check |
|
422 * read access if the file is opened for reading. The {@link |
|
423 * SecurityManager#checkWrite(String)} method is invoked to check |
|
424 * write access if the file is opened for writing |
|
425 */ |
|
426 public AsynchronousFileChannel newAsynchronousFileChannel(Path path, |
|
427 Set<? extends OpenOption> options, |
|
428 ExecutorService executor, |
|
429 FileAttribute<?>... attrs) |
|
430 throws IOException |
|
431 { |
|
432 throw new UnsupportedOperationException(); |
|
433 } |
|
434 } |