forked from kangjianwei/LearningJDK
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathWindowsFileSystem.java
382 lines (322 loc) · 13.2 KB
/
WindowsFileSystem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.WatchService;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// "file"文件系统在windows上的实现
class WindowsFileSystem extends FileSystem {
private static final String GLOB_SYNTAX = "glob";
private static final String REGEX_SYNTAX = "regex";
// windows上支持的文件属性视图
private static Set<String> set = new HashSet<>(Arrays.asList("user", "basic", "dos", "owner", "acl"));
private static final Set<String> supportedFileAttributeViews = Collections.unmodifiableSet(set);
private final WindowsFileSystemProvider provider; // windows文件系统提供器
// default directory (is absolute), and default root
private final String defaultDirectory; // 当前文件系统默认的工作目录(默认为用户工作目录,跟[user.dir]参数相关)
private final String defaultRoot; // 从默认工作目录中提取的盘符信息
// 基于指定的工作目录创建平台平台相关的文件系统
WindowsFileSystem(WindowsFileSystemProvider provider, String dir) {
this.provider = provider;
/* parse default directory and check it is absolute */
// 对指定的路径dir进行解析,需要对解析后的路径本地化
WindowsPathParser.Result result = WindowsPathParser.parse(dir);
// 这里要求路径类型必须为绝对路径或为UNC路径
if((result.type() != WindowsPathType.ABSOLUTE) && (result.type() != WindowsPathType.UNC)) {
throw new AssertionError("Default directory is not an absolute path");
}
this.defaultDirectory = result.path();
this.defaultRoot = result.root();
}
// 构造windows平台下的路径对象,返回的路径已经本地化
@Override
public final Path getPath(String first, String... more) {
String path;
if(more.length == 0) {
path = first;
} else {
StringBuilder sb = new StringBuilder();
sb.append(first);
for(String segment : more) {
if(segment.length()>0) {
if(sb.length()>0) {
sb.append('\\');
}
sb.append(segment);
}
}
path = sb.toString();
}
// 使用当前文件系统对指定的路径进行解析,返回的路径已经本地化
return WindowsPath.parse(this, path);
}
// 返回创建了当前文件系统的windows文件系统提供器
@Override
public FileSystemProvider provider() {
return provider;
}
// 返回当前文件系统使用的file分隔符;例如windows上是'\',linux/mac上是'/'
@Override
public String getSeparator() {
return "\\";
}
// 判断当前文件系统是否已经开启
@Override
public boolean isOpen() {
return true;
}
// 判断当前文件系统是否只读
@Override
public boolean isReadOnly() {
return false;
}
// 关闭当前文件系统
@Override
public void close() throws IOException {
throw new UnsupportedOperationException();
}
// 返回当前文件系统中的根路径列表
@Override
public Iterable<Path> getRootDirectories() {
int drives = 0;
try {
// 获取驱动器的盘符列表
drives = WindowsNativeDispatcher.GetLogicalDrives();
} catch(WindowsException x) {
// shouldn't happen
throw new AssertionError(x.getMessage());
}
// iterate over roots, ignoring those that the security manager denies
ArrayList<Path> result = new ArrayList<>();
SecurityManager sm = System.getSecurityManager();
// 遍历26个字母,查看当前文件系统中到底有哪些盘符
for(int i = 0; i<=25; i++) { // 0->A, 1->B, 2->C...
if((drives & (1 << i)) != 0) {
String root = (char) ('A' + i) + ":\\";
if(sm != null) {
try {
sm.checkRead(root);
} catch(SecurityException x) {
continue;
}
}
// 路径工厂,创建windows平台的路径对象(不会做本地化操作)
WindowsPath windowsPath = WindowsPath.createFromNormalizedPath(this, root);
// 记录找到的盘符(根路径)
result.add(windowsPath);
}
}
return Collections.unmodifiableList(result);
}
// 返回当前文件系统中的文件存储列表
@Override
public Iterable<FileStore> getFileStores() {
SecurityManager sm = System.getSecurityManager();
if(sm != null) {
try {
sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
} catch(SecurityException se) {
return Collections.emptyList();
}
}
return new Iterable<FileStore>() {
public Iterator<FileStore> iterator() {
return new FileStoreIterator();
}
};
}
/*
* 返回当前文件系统支持的文件属性视图
*
* 不同平台的支持情况:
* windows linux mac
* "user" √ √
* "basic" √ √ √
* "dos" √ √
* "owner" √ √ √
* "acl" √
* "posix" √ √
* "unix" √ √
* "jrt" √ √ √
* "zip" √ √ √
*/
@Override
public Set<String> supportedFileAttributeViews() {
return supportedFileAttributeViews;
}
// 返回一个由指定正则构造的路径匹配器;其中,syntaxAndInput可以是"glob"正则或"regex"正则(参见Globs类)
@Override
public PathMatcher getPathMatcher(String syntaxAndInput) {
// 如果syntaxAndInput中不存在":",则抛异常
int pos = syntaxAndInput.indexOf(':');
if(pos<=0 || pos == syntaxAndInput.length()) {
throw new IllegalArgumentException();
}
// 获取正则类型:"glob"类型或"regex"类型
String syntax = syntaxAndInput.substring(0, pos);
// 获取正则表达式
String input = syntaxAndInput.substring(pos + 1);
String regex;
// 如果是"glob"类型的正则,则需要转换
if(syntax.equalsIgnoreCase(GLOB_SYNTAX)) {
// 将"glob"类型的正则表达式转换为"regex"类型的正则表达式
regex = Globs.toWindowsRegexPattern(input);
} else {
// 如果是"regex"类型的正则,直接使用
if(syntax.equalsIgnoreCase(REGEX_SYNTAX)) {
regex = input;
} else {
throw new UnsupportedOperationException("Syntax '" + syntax + "' not recognized");
}
}
/* match in unicode_case_insensitive */
// 解析正则表达式regex,解析时不区分大小写且允许匹配Unicode符号
final Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
/* return matcher */
return new PathMatcher() {
// 判断指定的路径是否符合预设的模式,如果符合,则对其访问
@Override
public boolean matches(Path path) {
// 利用当前Pattern中的正则表达式创建Matcher以进行匹配动作
Matcher matcher = pattern.matcher(path.toString());
// 判断是否匹配
return matcher.matches();
}
};
}
// 返回一个目录监视服务,目前仅在"file"文件系统上提供支持
@Override
public WatchService newWatchService() throws IOException {
return new WindowsWatchService(this);
}
// 返回一个账户服务,可用来搜索本机的用户和组信息
@Override
public UserPrincipalLookupService getUserPrincipalLookupService() {
return LookupService.instance;
}
// 返回当前文件系统默认的工作目录(默认是当前源码根目录)
String defaultDirectory() {
return defaultDirectory;
}
// 返回从默认工作目录中提取的盘符信息
String defaultRoot() {
return defaultRoot;
}
// 账户服务
private static class LookupService {
static final UserPrincipalLookupService instance = new UserPrincipalLookupService() {
// 查询指定名称的user
@Override
public UserPrincipal lookupPrincipalByName(String name) throws IOException {
return WindowsUserPrincipals.lookup(name);
}
// 查询指定名称的group
@Override
public GroupPrincipal lookupPrincipalByGroupName(String group) throws IOException {
UserPrincipal user = WindowsUserPrincipals.lookup(group);
if(!(user instanceof GroupPrincipal)) {
throw new UserPrincipalNotFoundException(group);
}
return (GroupPrincipal) user;
}
};
}
/**
* Iterator returned by getFileStores method.
*/
// 当前文件系统中的文件存储列表
private class FileStoreIterator implements Iterator<FileStore> {
private final Iterator<Path> roots; // 当前文件系统中的根路径列表
private FileStore next;
FileStoreIterator() {
this.roots = getRootDirectories().iterator();
}
@Override
public synchronized boolean hasNext() {
if(next != null) {
return true;
}
next = readNext();
return next != null;
}
@Override
public synchronized FileStore next() {
if(next == null) {
next = readNext();
}
if(next == null) {
throw new NoSuchElementException();
} else {
FileStore result = next;
next = null;
return result;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private FileStore readNext() {
assert Thread.holdsLock(this);
for(; ; ) {
if(!roots.hasNext()) {
return null;
}
WindowsPath root = (WindowsPath) roots.next();
// ignore if security manager denies access
try {
root.checkRead();
} catch(SecurityException x) {
continue;
}
try {
FileStore fs = WindowsFileStore.create(root.toString(), true);
if(fs != null) {
return fs;
}
} catch(IOException ioe) {
// skip it
}
}
}
}
}