JrtFileSystemProvider.java revision 10967:e336cbd8b15e
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
26package jdk.internal.jrtfs;
27
28import java.io.*;
29import java.nio.channels.*;
30import java.nio.file.*;
31import java.nio.file.DirectoryStream.Filter;
32import java.nio.file.attribute.*;
33import java.nio.file.spi.FileSystemProvider;
34import java.net.URI;
35import java.net.URISyntaxException;
36import java.util.HashMap;
37import java.util.Map;
38import java.util.Set;
39import java.util.concurrent.ExecutorService;
40
41public 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}
273