2
Copyright (C) 2011 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
27
import cli.System.IO.DriveInfo;
28
import cli.System.IO.ErrorEventArgs;
29
import cli.System.IO.ErrorEventHandler;
30
import cli.System.IO.FileSystemEventArgs;
31
import cli.System.IO.FileSystemEventHandler;
32
import cli.System.IO.FileSystemWatcher;
33
import cli.System.IO.WatcherChangeTypes;
34
import java.io.IOException;
35
import java.nio.file.*;
36
import java.nio.file.attribute.*;
37
import java.nio.file.spi.FileSystemProvider;
38
import java.util.ArrayList;
39
import java.util.Arrays;
40
import java.util.Collections;
41
import java.util.concurrent.LinkedBlockingQueue;
42
import java.util.concurrent.TimeUnit;
43
import java.util.HashSet;
44
import java.util.List;
46
import java.util.regex.Pattern;
47
import static ikvm.internal.Util.WINDOWS;
49
final class NetFileSystem extends FileSystem
51
private static final Set<String> attributes = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("basic")));
52
private final NetFileSystemProvider provider;
53
private final String separator = Character.toString(cli.System.IO.Path.DirectorySeparatorChar);
55
NetFileSystem(NetFileSystemProvider provider)
57
this.provider = provider;
60
public FileSystemProvider provider()
65
public void close() throws IOException
67
throw new UnsupportedOperationException();
70
public boolean isOpen()
75
public boolean isReadOnly()
80
public String getSeparator()
85
public Iterable<Path> getRootDirectories()
87
SecurityManager sm = System.getSecurityManager();
88
ArrayList<Path> list = new ArrayList<>();
89
for (DriveInfo info : DriveInfo.GetDrives())
95
sm.checkRead(info.get_Name());
98
catch (SecurityException _)
102
list.add(getPath(info.get_Name()));
107
public Iterable<FileStore> getFileStores()
109
SecurityManager sm = System.getSecurityManager();
114
sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
116
catch (SecurityException _)
118
return Collections.emptyList();
121
ArrayList<FileStore> list = new ArrayList<>();
122
for (DriveInfo info : DriveInfo.GetDrives())
128
sm.checkRead(info.get_Name());
131
catch (SecurityException _)
137
list.add(provider.getFileStore(info));
139
catch (IOException _)
146
public Set<String> supportedFileAttributeViews()
151
public Path getPath(String first, String... more)
153
if (more.length == 0)
155
return new NetPath(this, first);
159
StringBuilder sb = new StringBuilder(first);
160
String sep = sb.length() == 0 ? "" : separator;
161
for (String s : more)
170
return new NetPath(this, sb.toString());
174
public PathMatcher getPathMatcher(String syntaxAndPattern)
177
if (syntaxAndPattern.startsWith("glob:"))
179
String pattern = syntaxAndPattern.substring(5);
182
regex = Globs.toWindowsRegexPattern(pattern);
186
regex = Globs.toUnixRegexPattern(pattern);
189
else if (syntaxAndPattern.startsWith("regex:"))
191
regex = syntaxAndPattern.substring(6);
193
else if (syntaxAndPattern.indexOf(':') <= 0)
195
throw new IllegalArgumentException();
199
throw new UnsupportedOperationException();
201
final Pattern pattern = Pattern.compile(regex, WINDOWS ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : 0);
202
return new PathMatcher() {
204
public boolean matches(Path path) {
205
return pattern.matcher(path.toString()).matches();
210
public UserPrincipalLookupService getUserPrincipalLookupService()
212
throw new UnsupportedOperationException();
215
static final class NetWatchService implements WatchService
217
static final WatchEvent<?> overflowEvent = new WatchEvent<Object>() {
218
public Object context() {
224
public WatchEvent.Kind<Object> kind() {
225
return StandardWatchEventKinds.OVERFLOW;
228
private static final WatchKey CLOSED = new WatchKey() {
229
public boolean isValid() { return false; }
230
public List<WatchEvent<?>> pollEvents() { return null; }
231
public boolean reset() { return false; }
232
public void cancel() { }
233
public Watchable watchable() { return null; }
235
private boolean closed;
236
private final ArrayList<NetWatchKey> keys = new ArrayList<>();
237
private final LinkedBlockingQueue<WatchKey> queue = new LinkedBlockingQueue<>();
239
public synchronized void close()
244
for (NetWatchKey key : keys)
252
private WatchKey checkClosed(WatchKey key)
257
throw new ClosedWatchServiceException();
262
public WatchKey poll()
264
return checkClosed(queue.poll());
267
public WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException
269
return checkClosed(queue.poll(timeout, unit));
272
public WatchKey take() throws InterruptedException
274
return checkClosed(queue.take());
277
void enqueue(WatchKey key)
286
catch (InterruptedException _)
292
private final class NetWatchKey implements WatchKey
294
private final NetPath path;
295
private FileSystemWatcher fsw;
296
private ArrayList<WatchEvent<?>> list = new ArrayList<>();
297
private HashSet<String> modified = new HashSet<>();
298
private boolean signaled;
300
NetWatchKey(NetPath path)
305
synchronized void init(final boolean create, final boolean delete, final boolean modify, final boolean overflow, final boolean subtree)
309
// we could reuse the FileSystemWatcher, but for now we just recreate it
310
// (and we run the risk of missing some events while we're doing that)
314
fsw = new FileSystemWatcher(path.path);
317
fsw.add_Created(new FileSystemEventHandler(new FileSystemEventHandler.Method() {
318
public void Invoke(Object sender, FileSystemEventArgs e) {
319
addEvent(createEvent(e), null);
325
fsw.add_Deleted(new FileSystemEventHandler(new FileSystemEventHandler.Method() {
326
public void Invoke(Object sender, FileSystemEventArgs e) {
327
addEvent(createEvent(e), null);
333
fsw.add_Changed(new FileSystemEventHandler(new FileSystemEventHandler.Method() {
334
public void Invoke(Object sender, FileSystemEventArgs e) {
335
synchronized (NetWatchKey.this) {
336
if (modified.contains(e.get_Name())) {
337
// we already have an ENTRY_MODIFY event pending
341
addEvent(createEvent(e), e.get_Name());
345
fsw.add_Error(new ErrorEventHandler(new ErrorEventHandler.Method() {
346
public void Invoke(Object sender, ErrorEventArgs e) {
347
if (e.GetException() instanceof cli.System.ComponentModel.Win32Exception
348
&& ((cli.System.ComponentModel.Win32Exception)e.GetException()).get_ErrorCode() == -2147467259) {
349
// the directory we were watching was deleted
351
} else if (overflow) {
352
addEvent(overflowEvent, null);
358
fsw.set_IncludeSubdirectories(true);
360
fsw.set_EnableRaisingEvents(true);
363
WatchEvent<?> createEvent(final FileSystemEventArgs e)
365
return new WatchEvent<Path>() {
366
public Path context() {
367
return new NetPath((NetFileSystem)path.getFileSystem(), e.get_Name());
372
public WatchEvent.Kind<Path> kind() {
373
switch (e.get_ChangeType().Value) {
374
case WatcherChangeTypes.Created:
375
return StandardWatchEventKinds.ENTRY_CREATE;
376
case WatcherChangeTypes.Deleted:
377
return StandardWatchEventKinds.ENTRY_DELETE;
379
return StandardWatchEventKinds.ENTRY_MODIFY;
385
void cancelledByError()
398
synchronized void addEvent(WatchEvent<?> event, String modified)
401
if (modified != null)
403
this.modified.add(modified);
412
public synchronized boolean isValid()
417
public synchronized List<WatchEvent<?>> pollEvents()
419
ArrayList<WatchEvent<?>> r = list;
420
list = new ArrayList<>();
425
public synchronized boolean reset()
433
if (list.size() == 0)
456
synchronized (NetWatchService.this)
463
public Watchable watchable()
469
synchronized WatchKey register(NetPath path, boolean create, boolean delete, boolean modify, boolean overflow, boolean subtree)
473
throw new ClosedWatchServiceException();
475
NetWatchKey existing = null;
476
for (NetWatchKey key : keys)
478
if (key.watchable().equals(path))
484
if (existing == null)
486
existing = new NetWatchKey(path);
489
existing.init(create, delete, modify, overflow, subtree);
494
public WatchService newWatchService() throws IOException
496
return new NetWatchService();