Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java
32288 views
1
/*
2
* Copyright (c) 2008, 2013, 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 sun.nio.fs;
27
28
import java.nio.file.*;
29
import java.nio.file.attribute.*;
30
import java.io.*;
31
import java.net.URI;
32
import java.util.*;
33
import java.lang.ref.WeakReference;
34
35
import com.sun.nio.file.ExtendedWatchEventModifier;
36
37
import static sun.nio.fs.WindowsNativeDispatcher.*;
38
import static sun.nio.fs.WindowsConstants.*;
39
40
/**
41
* Windows implementation of Path
42
*/
43
44
class WindowsPath extends AbstractPath {
45
46
// The maximum path that does not require long path prefix. On Windows
47
// the maximum path is 260 minus 1 (NUL) but for directories it is 260
48
// minus 12 minus 1 (to allow for the creation of a 8.3 file in the
49
// directory).
50
private static final int MAX_PATH = 247;
51
52
// Maximum extended-length path
53
private static final int MAX_LONG_PATH = 32000;
54
55
// FIXME - eliminate this reference to reduce space
56
private final WindowsFileSystem fs;
57
58
// path type
59
private final WindowsPathType type;
60
// root component (may be empty)
61
private final String root;
62
// normalized path
63
private final String path;
64
65
// the path to use in Win32 calls. This differs from path for relative
66
// paths and has a long path prefix for all paths longer than MAX_PATH.
67
private volatile WeakReference<String> pathForWin32Calls;
68
69
// offsets into name components (computed lazily)
70
private volatile Integer[] offsets;
71
72
// computed hash code (computed lazily, no need to be volatile)
73
private int hash;
74
75
76
/**
77
* Initializes a new instance of this class.
78
*/
79
private WindowsPath(WindowsFileSystem fs,
80
WindowsPathType type,
81
String root,
82
String path)
83
{
84
this.fs = fs;
85
this.type = type;
86
this.root = root;
87
this.path = path;
88
}
89
90
/**
91
* Creates a Path by parsing the given path.
92
*/
93
static WindowsPath parse(WindowsFileSystem fs, String path) {
94
WindowsPathParser.Result result = WindowsPathParser.parse(path);
95
return new WindowsPath(fs, result.type(), result.root(), result.path());
96
}
97
98
/**
99
* Creates a Path from a given path that is known to be normalized.
100
*/
101
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
102
String path,
103
BasicFileAttributes attrs)
104
{
105
try {
106
WindowsPathParser.Result result =
107
WindowsPathParser.parseNormalizedPath(path);
108
if (attrs == null) {
109
return new WindowsPath(fs,
110
result.type(),
111
result.root(),
112
result.path());
113
} else {
114
return new WindowsPathWithAttributes(fs,
115
result.type(),
116
result.root(),
117
result.path(),
118
attrs);
119
}
120
} catch (InvalidPathException x) {
121
throw new AssertionError(x.getMessage());
122
}
123
}
124
125
/**
126
* Creates a WindowsPath from a given path that is known to be normalized.
127
*/
128
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
129
String path)
130
{
131
return createFromNormalizedPath(fs, path, null);
132
}
133
134
/**
135
* Special implementation with attached/cached attributes (used to quicken
136
* file tree traveral)
137
*/
138
private static class WindowsPathWithAttributes
139
extends WindowsPath implements BasicFileAttributesHolder
140
{
141
final WeakReference<BasicFileAttributes> ref;
142
143
WindowsPathWithAttributes(WindowsFileSystem fs,
144
WindowsPathType type,
145
String root,
146
String path,
147
BasicFileAttributes attrs)
148
{
149
super(fs, type, root, path);
150
ref = new WeakReference<BasicFileAttributes>(attrs);
151
}
152
153
@Override
154
public BasicFileAttributes get() {
155
return ref.get();
156
}
157
158
@Override
159
public void invalidate() {
160
ref.clear();
161
}
162
163
// no need to override equals/hashCode.
164
}
165
166
// use this message when throwing exceptions
167
String getPathForExceptionMessage() {
168
return path;
169
}
170
171
// use this path for permission checks
172
String getPathForPermissionCheck() {
173
return path;
174
}
175
176
// use this path for Win32 calls
177
// This method will prefix long paths with \\?\ or \\?\UNC as required.
178
String getPathForWin32Calls() throws WindowsException {
179
// short absolute paths can be used directly
180
if (isAbsolute() && path.length() <= MAX_PATH)
181
return path;
182
183
// return cached values if available
184
WeakReference<String> ref = pathForWin32Calls;
185
String resolved = (ref != null) ? ref.get() : null;
186
if (resolved != null) {
187
// Win32 path already available
188
return resolved;
189
}
190
191
// resolve against default directory
192
resolved = getAbsolutePath();
193
194
// Long paths need to have "." and ".." removed and be prefixed with
195
// "\\?\". Note that it is okay to remove ".." even when it follows
196
// a link - for example, it is okay for foo/link/../bar to be changed
197
// to foo/bar. The reason is that Win32 APIs to access foo/link/../bar
198
// will access foo/bar anyway (which differs to Unix systems)
199
if (resolved.length() > MAX_PATH) {
200
if (resolved.length() > MAX_LONG_PATH) {
201
throw new WindowsException("Cannot access file with path exceeding "
202
+ MAX_LONG_PATH + " characters");
203
}
204
resolved = addPrefixIfNeeded(GetFullPathName(resolved));
205
}
206
207
// cache the resolved path (except drive relative paths as the working
208
// directory on removal media devices can change during the lifetime
209
// of the VM)
210
if (type != WindowsPathType.DRIVE_RELATIVE) {
211
synchronized (path) {
212
pathForWin32Calls = new WeakReference<String>(resolved);
213
}
214
}
215
return resolved;
216
}
217
218
// return this path resolved against the file system's default directory
219
private String getAbsolutePath() throws WindowsException {
220
if (isAbsolute())
221
return path;
222
223
// Relative path ("foo" for example)
224
if (type == WindowsPathType.RELATIVE) {
225
String defaultDirectory = getFileSystem().defaultDirectory();
226
if (isEmpty())
227
return defaultDirectory;
228
if (defaultDirectory.endsWith("\\")) {
229
return defaultDirectory + path;
230
} else {
231
StringBuilder sb =
232
new StringBuilder(defaultDirectory.length() + path.length() + 1);
233
return sb.append(defaultDirectory).append('\\').append(path).toString();
234
}
235
}
236
237
// Directory relative path ("\foo" for example)
238
if (type == WindowsPathType.DIRECTORY_RELATIVE) {
239
String defaultRoot = getFileSystem().defaultRoot();
240
return defaultRoot + path.substring(1);
241
}
242
243
// Drive relative path ("C:foo" for example).
244
if (isSameDrive(root, getFileSystem().defaultRoot())) {
245
// relative to default directory
246
String remaining = path.substring(root.length());
247
String defaultDirectory = getFileSystem().defaultDirectory();
248
String result;
249
if (defaultDirectory.endsWith("\\")) {
250
result = defaultDirectory + remaining;
251
} else {
252
result = defaultDirectory + "\\" + remaining;
253
}
254
return result;
255
} else {
256
// relative to some other drive
257
String wd;
258
try {
259
int dt = GetDriveType(root + "\\");
260
if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR)
261
throw new WindowsException("");
262
wd = GetFullPathName(root + ".");
263
} catch (WindowsException x) {
264
throw new WindowsException("Unable to get working directory of drive '" +
265
Character.toUpperCase(root.charAt(0)) + "'");
266
}
267
String result = wd;
268
if (wd.endsWith("\\")) {
269
result += path.substring(root.length());
270
} else {
271
if (path.length() > root.length())
272
result += "\\" + path.substring(root.length());
273
}
274
return result;
275
}
276
}
277
278
// returns true if same drive letter
279
private static boolean isSameDrive(String root1, String root2) {
280
return Character.toUpperCase(root1.charAt(0)) ==
281
Character.toUpperCase(root2.charAt(0));
282
}
283
284
// Add long path prefix to path if required
285
static String addPrefixIfNeeded(String path) {
286
if (path.length() > MAX_PATH) {
287
if (path.startsWith("\\\\")) {
288
path = "\\\\?\\UNC" + path.substring(1, path.length());
289
} else {
290
path = "\\\\?\\" + path;
291
}
292
}
293
return path;
294
}
295
296
@Override
297
public WindowsFileSystem getFileSystem() {
298
return fs;
299
}
300
301
// -- Path operations --
302
303
private boolean isEmpty() {
304
return path.length() == 0;
305
}
306
307
private WindowsPath emptyPath() {
308
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", "");
309
}
310
311
@Override
312
public Path getFileName() {
313
int len = path.length();
314
// represents empty path
315
if (len == 0)
316
return this;
317
// represents root component only
318
if (root.length() == len)
319
return null;
320
int off = path.lastIndexOf('\\');
321
if (off < root.length())
322
off = root.length();
323
else
324
off++;
325
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", path.substring(off));
326
}
327
328
@Override
329
public WindowsPath getParent() {
330
// represents root component only
331
if (root.length() == path.length())
332
return null;
333
int off = path.lastIndexOf('\\');
334
if (off < root.length())
335
return getRoot();
336
else
337
return new WindowsPath(getFileSystem(),
338
type,
339
root,
340
path.substring(0, off));
341
}
342
343
@Override
344
public WindowsPath getRoot() {
345
if (root.length() == 0)
346
return null;
347
return new WindowsPath(getFileSystem(), type, root, root);
348
}
349
350
// package-private
351
WindowsPathType type() {
352
return type;
353
}
354
355
// package-private
356
boolean isUnc() {
357
return type == WindowsPathType.UNC;
358
}
359
360
boolean needsSlashWhenResolving() {
361
if (path.endsWith("\\"))
362
return false;
363
return path.length() > root.length();
364
}
365
366
@Override
367
public boolean isAbsolute() {
368
return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC;
369
}
370
371
static WindowsPath toWindowsPath(Path path) {
372
if (path == null)
373
throw new NullPointerException();
374
if (!(path instanceof WindowsPath)) {
375
throw new ProviderMismatchException();
376
}
377
return (WindowsPath)path;
378
}
379
380
@Override
381
public WindowsPath relativize(Path obj) {
382
WindowsPath other = toWindowsPath(obj);
383
if (this.equals(other))
384
return emptyPath();
385
386
// can only relativize paths of the same type
387
if (this.type != other.type)
388
throw new IllegalArgumentException("'other' is different type of Path");
389
390
// can only relativize paths if root component matches
391
if (!this.root.equalsIgnoreCase(other.root))
392
throw new IllegalArgumentException("'other' has different root");
393
394
int bn = this.getNameCount();
395
int cn = other.getNameCount();
396
397
// skip matching names
398
int n = (bn > cn) ? cn : bn;
399
int i = 0;
400
while (i < n) {
401
if (!this.getName(i).equals(other.getName(i)))
402
break;
403
i++;
404
}
405
406
// append ..\ for remaining names in the base
407
StringBuilder result = new StringBuilder();
408
for (int j=i; j<bn; j++) {
409
result.append("..\\");
410
}
411
412
// append remaining names in child
413
for (int j=i; j<cn; j++) {
414
result.append(other.getName(j).toString());
415
result.append("\\");
416
}
417
418
// drop trailing slash in result
419
result.setLength(result.length()-1);
420
return createFromNormalizedPath(getFileSystem(), result.toString());
421
}
422
423
@Override
424
public Path normalize() {
425
final int count = getNameCount();
426
if (count == 0 || isEmpty())
427
return this;
428
429
boolean[] ignore = new boolean[count]; // true => ignore name
430
int remaining = count; // number of names remaining
431
432
// multiple passes to eliminate all occurrences of "." and "name/.."
433
int prevRemaining;
434
do {
435
prevRemaining = remaining;
436
int prevName = -1;
437
for (int i=0; i<count; i++) {
438
if (ignore[i])
439
continue;
440
441
String name = elementAsString(i);
442
443
// not "." or ".."
444
if (name.length() > 2) {
445
prevName = i;
446
continue;
447
}
448
449
// "." or something else
450
if (name.length() == 1) {
451
// ignore "."
452
if (name.charAt(0) == '.') {
453
ignore[i] = true;
454
remaining--;
455
} else {
456
prevName = i;
457
}
458
continue;
459
}
460
461
// not ".."
462
if (name.charAt(0) != '.' || name.charAt(1) != '.') {
463
prevName = i;
464
continue;
465
}
466
467
// ".." found
468
if (prevName >= 0) {
469
// name/<ignored>/.. found so mark name and ".." to be
470
// ignored
471
ignore[prevName] = true;
472
ignore[i] = true;
473
remaining = remaining - 2;
474
prevName = -1;
475
} else {
476
// Cases:
477
// C:\<ignored>\..
478
// \\server\\share\<ignored>\..
479
// \<ignored>..
480
if (isAbsolute() || type == WindowsPathType.DIRECTORY_RELATIVE) {
481
boolean hasPrevious = false;
482
for (int j=0; j<i; j++) {
483
if (!ignore[j]) {
484
hasPrevious = true;
485
break;
486
}
487
}
488
if (!hasPrevious) {
489
// all proceeding names are ignored
490
ignore[i] = true;
491
remaining--;
492
}
493
}
494
}
495
}
496
} while (prevRemaining > remaining);
497
498
// no redundant names
499
if (remaining == count)
500
return this;
501
502
// corner case - all names removed
503
if (remaining == 0) {
504
return (root.length() == 0) ? emptyPath() : getRoot();
505
}
506
507
// re-constitute the path from the remaining names.
508
StringBuilder result = new StringBuilder();
509
if (root != null)
510
result.append(root);
511
for (int i=0; i<count; i++) {
512
if (!ignore[i]) {
513
result.append(getName(i));
514
result.append("\\");
515
}
516
}
517
518
// drop trailing slash in result
519
result.setLength(result.length()-1);
520
return createFromNormalizedPath(getFileSystem(), result.toString());
521
}
522
523
@Override
524
public WindowsPath resolve(Path obj) {
525
WindowsPath other = toWindowsPath(obj);
526
if (other.isEmpty())
527
return this;
528
if (other.isAbsolute())
529
return other;
530
531
switch (other.type) {
532
case RELATIVE: {
533
String result;
534
if (path.endsWith("\\") || (root.length() == path.length())) {
535
result = path + other.path;
536
} else {
537
result = path + "\\" + other.path;
538
}
539
return new WindowsPath(getFileSystem(), type, root, result);
540
}
541
542
case DIRECTORY_RELATIVE: {
543
String result;
544
if (root.endsWith("\\")) {
545
result = root + other.path.substring(1);
546
} else {
547
result = root + other.path;
548
}
549
return createFromNormalizedPath(getFileSystem(), result);
550
}
551
552
case DRIVE_RELATIVE: {
553
if (!root.endsWith("\\"))
554
return other;
555
// if different roots then return other
556
String thisRoot = root.substring(0, root.length()-1);
557
if (!thisRoot.equalsIgnoreCase(other.root))
558
return other;
559
// same roots
560
String remaining = other.path.substring(other.root.length());
561
String result;
562
if (path.endsWith("\\")) {
563
result = path + remaining;
564
} else {
565
result = path + "\\" + remaining;
566
}
567
return createFromNormalizedPath(getFileSystem(), result);
568
}
569
570
default:
571
throw new AssertionError();
572
}
573
}
574
575
// generate offset array
576
private void initOffsets() {
577
if (offsets == null) {
578
ArrayList<Integer> list = new ArrayList<>();
579
if (isEmpty()) {
580
// empty path considered to have one name element
581
list.add(0);
582
} else {
583
int start = root.length();
584
int off = root.length();
585
while (off < path.length()) {
586
if (path.charAt(off) != '\\') {
587
off++;
588
} else {
589
list.add(start);
590
start = ++off;
591
}
592
}
593
if (start != off)
594
list.add(start);
595
}
596
synchronized (this) {
597
if (offsets == null)
598
offsets = list.toArray(new Integer[list.size()]);
599
}
600
}
601
}
602
603
@Override
604
public int getNameCount() {
605
initOffsets();
606
return offsets.length;
607
}
608
609
private String elementAsString(int i) {
610
initOffsets();
611
if (i == (offsets.length-1))
612
return path.substring(offsets[i]);
613
return path.substring(offsets[i], offsets[i+1]-1);
614
}
615
616
@Override
617
public WindowsPath getName(int index) {
618
initOffsets();
619
if (index < 0 || index >= offsets.length)
620
throw new IllegalArgumentException();
621
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", elementAsString(index));
622
}
623
624
@Override
625
public WindowsPath subpath(int beginIndex, int endIndex) {
626
initOffsets();
627
if (beginIndex < 0)
628
throw new IllegalArgumentException();
629
if (beginIndex >= offsets.length)
630
throw new IllegalArgumentException();
631
if (endIndex > offsets.length)
632
throw new IllegalArgumentException();
633
if (beginIndex >= endIndex)
634
throw new IllegalArgumentException();
635
636
StringBuilder sb = new StringBuilder();
637
Integer[] nelems = new Integer[endIndex - beginIndex];
638
for (int i = beginIndex; i < endIndex; i++) {
639
nelems[i-beginIndex] = sb.length();
640
sb.append(elementAsString(i));
641
if (i != (endIndex-1))
642
sb.append("\\");
643
}
644
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", sb.toString());
645
}
646
647
@Override
648
public boolean startsWith(Path obj) {
649
if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
650
return false;
651
WindowsPath other = (WindowsPath)obj;
652
653
// if this path has a root component the given path's root must match
654
if (!this.root.equalsIgnoreCase(other.root)) {
655
return false;
656
}
657
658
// empty path starts with itself
659
if (other.isEmpty())
660
return this.isEmpty();
661
662
// roots match so compare elements
663
int thisCount = getNameCount();
664
int otherCount = other.getNameCount();
665
if (otherCount <= thisCount) {
666
while (--otherCount >= 0) {
667
String thisElement = this.elementAsString(otherCount);
668
String otherElement = other.elementAsString(otherCount);
669
// FIXME: should compare in uppercase
670
if (!thisElement.equalsIgnoreCase(otherElement))
671
return false;
672
}
673
return true;
674
}
675
return false;
676
}
677
678
@Override
679
public boolean endsWith(Path obj) {
680
if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
681
return false;
682
WindowsPath other = (WindowsPath)obj;
683
684
// other path is longer
685
if (other.path.length() > this.path.length()) {
686
return false;
687
}
688
689
// empty path ends in itself
690
if (other.isEmpty()) {
691
return this.isEmpty();
692
}
693
694
int thisCount = this.getNameCount();
695
int otherCount = other.getNameCount();
696
697
// given path has more elements that this path
698
if (otherCount > thisCount) {
699
return false;
700
}
701
702
// compare roots
703
if (other.root.length() > 0) {
704
if (otherCount < thisCount)
705
return false;
706
// FIXME: should compare in uppercase
707
if (!this.root.equalsIgnoreCase(other.root))
708
return false;
709
}
710
711
// match last 'otherCount' elements
712
int off = thisCount - otherCount;
713
while (--otherCount >= 0) {
714
String thisElement = this.elementAsString(off + otherCount);
715
String otherElement = other.elementAsString(otherCount);
716
// FIXME: should compare in uppercase
717
if (!thisElement.equalsIgnoreCase(otherElement))
718
return false;
719
}
720
return true;
721
}
722
723
@Override
724
public int compareTo(Path obj) {
725
if (obj == null)
726
throw new NullPointerException();
727
String s1 = path;
728
String s2 = ((WindowsPath)obj).path;
729
int n1 = s1.length();
730
int n2 = s2.length();
731
int min = Math.min(n1, n2);
732
for (int i = 0; i < min; i++) {
733
char c1 = s1.charAt(i);
734
char c2 = s2.charAt(i);
735
if (c1 != c2) {
736
c1 = Character.toUpperCase(c1);
737
c2 = Character.toUpperCase(c2);
738
if (c1 != c2) {
739
return c1 - c2;
740
}
741
}
742
}
743
return n1 - n2;
744
}
745
746
@Override
747
public boolean equals(Object obj) {
748
if ((obj != null) && (obj instanceof WindowsPath)) {
749
return compareTo((Path)obj) == 0;
750
}
751
return false;
752
}
753
754
@Override
755
public int hashCode() {
756
// OK if two or more threads compute hash
757
int h = hash;
758
if (h == 0) {
759
for (int i = 0; i< path.length(); i++) {
760
h = 31*h + Character.toUpperCase(path.charAt(i));
761
}
762
hash = h;
763
}
764
return h;
765
}
766
767
@Override
768
public String toString() {
769
return path;
770
}
771
772
// -- file operations --
773
774
// package-private
775
long openForReadAttributeAccess(boolean followLinks)
776
throws WindowsException
777
{
778
int flags = FILE_FLAG_BACKUP_SEMANTICS;
779
if (!followLinks && getFileSystem().supportsLinks())
780
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
781
return CreateFile(getPathForWin32Calls(),
782
FILE_READ_ATTRIBUTES,
783
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
784
0L,
785
OPEN_EXISTING,
786
flags);
787
}
788
789
void checkRead() {
790
SecurityManager sm = System.getSecurityManager();
791
if (sm != null) {
792
sm.checkRead(getPathForPermissionCheck());
793
}
794
}
795
796
void checkWrite() {
797
SecurityManager sm = System.getSecurityManager();
798
if (sm != null) {
799
sm.checkWrite(getPathForPermissionCheck());
800
}
801
}
802
803
void checkDelete() {
804
SecurityManager sm = System.getSecurityManager();
805
if (sm != null) {
806
sm.checkDelete(getPathForPermissionCheck());
807
}
808
}
809
810
@Override
811
public URI toUri() {
812
return WindowsUriSupport.toUri(this);
813
}
814
815
@Override
816
public WindowsPath toAbsolutePath() {
817
if (isAbsolute())
818
return this;
819
820
// permission check as per spec
821
SecurityManager sm = System.getSecurityManager();
822
if (sm != null) {
823
sm.checkPropertyAccess("user.dir");
824
}
825
826
try {
827
return createFromNormalizedPath(getFileSystem(), getAbsolutePath());
828
} catch (WindowsException x) {
829
throw new IOError(new IOException(x.getMessage()));
830
}
831
}
832
833
@Override
834
public WindowsPath toRealPath(LinkOption... options) throws IOException {
835
checkRead();
836
String rp = WindowsLinkSupport.getRealPath(this, Util.followLinks(options));
837
return createFromNormalizedPath(getFileSystem(), rp);
838
}
839
840
@Override
841
public WatchKey register(WatchService watcher,
842
WatchEvent.Kind<?>[] events,
843
WatchEvent.Modifier... modifiers)
844
throws IOException
845
{
846
if (watcher == null)
847
throw new NullPointerException();
848
if (!(watcher instanceof WindowsWatchService))
849
throw new ProviderMismatchException();
850
851
// When a security manager is set then we need to make a defensive
852
// copy of the modifiers and check for the Windows specific FILE_TREE
853
// modifier. When the modifier is present then check that permission
854
// has been granted recursively.
855
SecurityManager sm = System.getSecurityManager();
856
if (sm != null) {
857
boolean watchSubtree = false;
858
final int ml = modifiers.length;
859
if (ml > 0) {
860
modifiers = Arrays.copyOf(modifiers, ml);
861
int i=0;
862
while (i < ml) {
863
if (modifiers[i++] == ExtendedWatchEventModifier.FILE_TREE) {
864
watchSubtree = true;
865
break;
866
}
867
}
868
}
869
String s = getPathForPermissionCheck();
870
sm.checkRead(s);
871
if (watchSubtree)
872
sm.checkRead(s + "\\-");
873
}
874
875
return ((WindowsWatchService)watcher).register(this, events, modifiers);
876
}
877
}
878
879