OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 class _Directory extends FileSystemEntity implements Directory { | 7 class _Directory extends FileSystemEntity implements Directory { |
8 final String path; | 8 final String path; |
9 | 9 |
10 _Directory(this.path) { | 10 _Directory(this.path) { |
11 if (path is! String) { | 11 if (path is! String) { |
12 throw new ArgumentError('${Error.safeToString(path)} ' | 12 throw new ArgumentError('${Error.safeToString(path)} ' |
13 'is not a String'); | 13 'is not a String'); |
14 } | 14 } |
15 } | 15 } |
16 | 16 |
17 external static _current(); | 17 external static _current(); |
18 external static _setCurrent(path); | 18 external static _setCurrent(path); |
19 external static _createTemp(String path); | 19 external static _createTemp(String path); |
20 external static String _systemTemp(); | 20 external static String _systemTemp(); |
21 external static _exists(String path); | 21 external static _exists(String path); |
22 external static _create(String path); | 22 external static _create(String path); |
23 external static _deleteNative(String path, bool recursive); | 23 external static _deleteNative(String path, bool recursive); |
24 external static _rename(String path, String newPath); | 24 external static _rename(String path, String newPath); |
25 external static void _fillWithDirectoryListing( | 25 external static void _fillWithDirectoryListing(List<FileSystemEntity> list, |
26 List<FileSystemEntity> list, String path, bool recursive, | 26 String path, bool recursive, bool followLinks); |
27 bool followLinks); | |
28 | 27 |
29 static Directory get current { | 28 static Directory get current { |
30 var result = _current(); | 29 var result = _current(); |
31 if (result is OSError) { | 30 if (result is OSError) { |
32 throw new FileSystemException( | 31 throw new FileSystemException( |
33 "Getting current working directory failed", "", result); | 32 "Getting current working directory failed", "", result); |
34 } | 33 } |
35 return new _Directory(result); | 34 return new _Directory(result); |
36 } | 35 } |
37 | 36 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 if (result is OSError) { | 100 if (result is OSError) { |
102 throw new FileSystemException("Creation failed", path, result); | 101 throw new FileSystemException("Creation failed", path, result); |
103 } | 102 } |
104 } | 103 } |
105 | 104 |
106 static Directory get systemTemp => new Directory(_systemTemp()); | 105 static Directory get systemTemp => new Directory(_systemTemp()); |
107 | 106 |
108 Future<Directory> createTemp([String prefix]) { | 107 Future<Directory> createTemp([String prefix]) { |
109 if (prefix == null) prefix = ''; | 108 if (prefix == null) prefix = ''; |
110 if (path == '') { | 109 if (path == '') { |
111 throw new ArgumentError( | 110 throw new ArgumentError("Directory.createTemp called with an empty path. " |
112 "Directory.createTemp called with an empty path. " | |
113 "To use the system temp directory, use Directory.systemTemp"); | 111 "To use the system temp directory, use Directory.systemTemp"); |
114 } | 112 } |
115 String fullPrefix; | 113 String fullPrefix; |
116 if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { | 114 if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { |
117 fullPrefix = "$path$prefix"; | 115 fullPrefix = "$path$prefix"; |
118 } else { | 116 } else { |
119 fullPrefix = "$path${Platform.pathSeparator}$prefix"; | 117 fullPrefix = "$path${Platform.pathSeparator}$prefix"; |
120 } | 118 } |
121 return _IOService._dispatch(_DIRECTORY_CREATE_TEMP, [fullPrefix]) | 119 return _IOService |
122 .then((response) { | 120 ._dispatch(_DIRECTORY_CREATE_TEMP, [fullPrefix]).then((response) { |
123 if (_isErrorResponse(response)) { | 121 if (_isErrorResponse(response)) { |
124 throw _exceptionOrErrorFromResponse( | 122 throw _exceptionOrErrorFromResponse( |
125 response, "Creation of temporary directory failed"); | 123 response, "Creation of temporary directory failed"); |
126 } | 124 } |
127 return new Directory(response); | 125 return new Directory(response); |
128 }); | 126 }); |
129 } | 127 } |
130 | 128 |
131 Directory createTempSync([String prefix]) { | 129 Directory createTempSync([String prefix]) { |
132 if (prefix == null) prefix = ''; | 130 if (prefix == null) prefix = ''; |
133 if (path == '') { | 131 if (path == '') { |
134 throw new ArgumentError( | 132 throw new ArgumentError("Directory.createTemp called with an empty path. " |
135 "Directory.createTemp called with an empty path. " | |
136 "To use the system temp directory, use Directory.systemTemp"); | 133 "To use the system temp directory, use Directory.systemTemp"); |
137 } | 134 } |
138 String fullPrefix; | 135 String fullPrefix; |
139 if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { | 136 if (path.endsWith('/') || (Platform.isWindows && path.endsWith('\\'))) { |
140 fullPrefix = "$path$prefix"; | 137 fullPrefix = "$path$prefix"; |
141 } else { | 138 } else { |
142 fullPrefix = "$path${Platform.pathSeparator}$prefix"; | 139 fullPrefix = "$path${Platform.pathSeparator}$prefix"; |
143 } | 140 } |
144 var result = _createTemp(fullPrefix); | 141 var result = _createTemp(fullPrefix); |
145 if (result is OSError) { | 142 if (result is OSError) { |
146 throw new FileSystemException("Creation of temporary directory failed", | 143 throw new FileSystemException( |
147 fullPrefix, | 144 "Creation of temporary directory failed", fullPrefix, result); |
148 result); | |
149 } | 145 } |
150 return new Directory(result); | 146 return new Directory(result); |
151 } | 147 } |
152 | 148 |
153 Future<Directory> _delete({bool recursive: false}) { | 149 Future<Directory> _delete({bool recursive: false}) { |
154 return _IOService._dispatch(_DIRECTORY_DELETE, [path, recursive]) | 150 return _IOService |
155 .then((response) { | 151 ._dispatch(_DIRECTORY_DELETE, [path, recursive]).then((response) { |
156 if (_isErrorResponse(response)) { | 152 if (_isErrorResponse(response)) { |
157 throw _exceptionOrErrorFromResponse(response, "Deletion failed"); | 153 throw _exceptionOrErrorFromResponse(response, "Deletion failed"); |
158 } | 154 } |
159 return this; | 155 return this; |
160 }); | 156 }); |
161 } | 157 } |
162 | 158 |
163 void _deleteSync({bool recursive: false}) { | 159 void _deleteSync({bool recursive: false}) { |
164 var result = _deleteNative(path, recursive); | 160 var result = _deleteNative(path, recursive); |
165 if (result is OSError) { | 161 if (result is OSError) { |
166 throw new FileSystemException("Deletion failed", path, result); | 162 throw new FileSystemException("Deletion failed", path, result); |
167 } | 163 } |
168 } | 164 } |
169 | 165 |
170 Future<Directory> rename(String newPath) { | 166 Future<Directory> rename(String newPath) { |
171 return _IOService._dispatch(_DIRECTORY_RENAME, [path, newPath]) | 167 return _IOService |
172 .then((response) { | 168 ._dispatch(_DIRECTORY_RENAME, [path, newPath]).then((response) { |
173 if (_isErrorResponse(response)) { | 169 if (_isErrorResponse(response)) { |
174 throw _exceptionOrErrorFromResponse(response, "Rename failed"); | 170 throw _exceptionOrErrorFromResponse(response, "Rename failed"); |
175 } | 171 } |
176 return new Directory(newPath); | 172 return new Directory(newPath); |
177 }); | 173 }); |
178 } | 174 } |
179 | 175 |
180 Directory renameSync(String newPath) { | 176 Directory renameSync(String newPath) { |
181 if (newPath is !String) { | 177 if (newPath is! String) { |
182 throw new ArgumentError(); | 178 throw new ArgumentError(); |
183 } | 179 } |
184 var result = _rename(path, newPath); | 180 var result = _rename(path, newPath); |
185 if (result is OSError) { | 181 if (result is OSError) { |
186 throw new FileSystemException("Rename failed", path, result); | 182 throw new FileSystemException("Rename failed", path, result); |
187 } | 183 } |
188 return new Directory(newPath); | 184 return new Directory(newPath); |
189 } | 185 } |
190 | 186 |
191 Stream<FileSystemEntity> list({bool recursive: false, | 187 Stream<FileSystemEntity> list( |
192 bool followLinks: true}) { | 188 {bool recursive: false, bool followLinks: true}) { |
193 return new _AsyncDirectoryLister( | 189 return new _AsyncDirectoryLister( |
194 FileSystemEntity._ensureTrailingPathSeparators(path), | 190 FileSystemEntity._ensureTrailingPathSeparators(path), |
195 recursive, | 191 recursive, |
196 followLinks).stream; | 192 followLinks) |
| 193 .stream; |
197 } | 194 } |
198 | 195 |
199 List<FileSystemEntity> listSync( | 196 List<FileSystemEntity> listSync( |
200 {bool recursive: false, bool followLinks: true}) { | 197 {bool recursive: false, bool followLinks: true}) { |
201 if (recursive is! bool || followLinks is! bool) { | 198 if (recursive is! bool || followLinks is! bool) { |
202 throw new ArgumentError(); | 199 throw new ArgumentError(); |
203 } | 200 } |
204 var result = <FileSystemEntity>[]; | 201 var result = <FileSystemEntity>[]; |
205 _fillWithDirectoryListing( | 202 _fillWithDirectoryListing( |
206 result, | 203 result, |
207 FileSystemEntity._ensureTrailingPathSeparators(path), | 204 FileSystemEntity._ensureTrailingPathSeparators(path), |
208 recursive, | 205 recursive, |
209 followLinks); | 206 followLinks); |
210 return result; | 207 return result; |
211 } | 208 } |
212 | 209 |
213 String toString() => "Directory: '$path'"; | 210 String toString() => "Directory: '$path'"; |
214 | 211 |
215 bool _isErrorResponse(response) => | 212 bool _isErrorResponse(response) => |
216 response is List && response[0] != _SUCCESS_RESPONSE; | 213 response is List && response[0] != _SUCCESS_RESPONSE; |
217 | 214 |
218 _exceptionOrErrorFromResponse(response, String message) { | 215 _exceptionOrErrorFromResponse(response, String message) { |
219 assert(_isErrorResponse(response)); | 216 assert(_isErrorResponse(response)); |
220 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { | 217 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { |
221 case _ILLEGAL_ARGUMENT_RESPONSE: | 218 case _ILLEGAL_ARGUMENT_RESPONSE: |
222 return new ArgumentError(); | 219 return new ArgumentError(); |
223 case _OSERROR_RESPONSE: | 220 case _OSERROR_RESPONSE: |
224 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], | 221 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], |
225 response[_OSERROR_RESPONSE_ERROR_CODE]); | 222 response[_OSERROR_RESPONSE_ERROR_CODE]); |
226 return new FileSystemException(message, path, err); | 223 return new FileSystemException(message, path, err); |
227 default: | 224 default: |
228 return new Exception("Unknown error"); | 225 return new Exception("Unknown error"); |
229 } | 226 } |
230 } | 227 } |
231 } | 228 } |
232 | 229 |
233 abstract class _AsyncDirectoryListerOps { | 230 abstract class _AsyncDirectoryListerOps { |
234 external factory _AsyncDirectoryListerOps(int pointer); | 231 external factory _AsyncDirectoryListerOps(int pointer); |
235 | 232 |
(...skipping 17 matching lines...) Expand all Loading... |
253 final bool followLinks; | 250 final bool followLinks; |
254 | 251 |
255 StreamController<FileSystemEntity> controller; | 252 StreamController<FileSystemEntity> controller; |
256 bool canceled = false; | 253 bool canceled = false; |
257 bool nextRunning = false; | 254 bool nextRunning = false; |
258 bool closed = false; | 255 bool closed = false; |
259 _AsyncDirectoryListerOps _ops; | 256 _AsyncDirectoryListerOps _ops; |
260 Completer closeCompleter = new Completer(); | 257 Completer closeCompleter = new Completer(); |
261 | 258 |
262 _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) { | 259 _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) { |
263 controller = new StreamController<FileSystemEntity>(onListen: onListen, | 260 controller = new StreamController<FileSystemEntity>( |
264 onResume: onResume, | 261 onListen: onListen, onResume: onResume, onCancel: onCancel, sync: true); |
265 onCancel: onCancel, | |
266 sync: true); | |
267 } | 262 } |
268 | 263 |
269 // Calling this function will increase the reference count on the native | 264 // Calling this function will increase the reference count on the native |
270 // object that implements the async directory lister operations. It should | 265 // object that implements the async directory lister operations. It should |
271 // only be called to pass the pointer to the IO Service, which will decrement | 266 // only be called to pass the pointer to the IO Service, which will decrement |
272 // the reference count when it is finished with it. | 267 // the reference count when it is finished with it. |
273 int _pointer() { | 268 int _pointer() { |
274 return (_ops == null) ? null : _ops.getPointer(); | 269 return (_ops == null) ? null : _ops.getPointer(); |
275 } | 270 } |
276 | 271 |
277 Stream<FileSystemEntity> get stream => controller.stream; | 272 Stream<FileSystemEntity> get stream => controller.stream; |
278 | 273 |
279 void onListen() { | 274 void onListen() { |
280 _IOService._dispatch(_DIRECTORY_LIST_START, [path, recursive, followLinks]) | 275 _IOService._dispatch( |
281 .then((response) { | 276 _DIRECTORY_LIST_START, [path, recursive, followLinks]).then((response) { |
282 if (response is int) { | 277 if (response is int) { |
283 _ops = new _AsyncDirectoryListerOps(response); | 278 _ops = new _AsyncDirectoryListerOps(response); |
284 next(); | 279 next(); |
285 } else if (response is Error) { | 280 } else if (response is Error) { |
286 controller.addError(response, response.stackTrace); | 281 controller.addError(response, response.stackTrace); |
287 close(); | 282 close(); |
288 } else { | 283 } else { |
289 error(response); | 284 error(response); |
290 close(); | 285 close(); |
291 } | 286 } |
292 }); | 287 }); |
293 } | 288 } |
294 | 289 |
295 void onResume() { | 290 void onResume() { |
296 if (!nextRunning) { | 291 if (!nextRunning) { |
297 next(); | 292 next(); |
298 } | 293 } |
299 } | 294 } |
300 | 295 |
301 Future onCancel() { | 296 Future onCancel() { |
302 canceled = true; | 297 canceled = true; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 359 } |
365 if (nextRunning) { | 360 if (nextRunning) { |
366 return; | 361 return; |
367 } | 362 } |
368 closed = true; | 363 closed = true; |
369 | 364 |
370 var pointer = _pointer(); | 365 var pointer = _pointer(); |
371 if (pointer == null) { | 366 if (pointer == null) { |
372 _cleanup(); | 367 _cleanup(); |
373 } else { | 368 } else { |
374 _IOService._dispatch(_DIRECTORY_LIST_STOP, [pointer]) | 369 _IOService |
375 .whenComplete(_cleanup); | 370 ._dispatch(_DIRECTORY_LIST_STOP, [pointer]).whenComplete(_cleanup); |
376 } | 371 } |
377 } | 372 } |
378 | 373 |
379 void error(message) { | 374 void error(message) { |
380 var errorType = | 375 var errorType = message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; |
381 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; | |
382 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { | 376 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { |
383 controller.addError(new ArgumentError()); | 377 controller.addError(new ArgumentError()); |
384 } else if (errorType == _OSERROR_RESPONSE) { | 378 } else if (errorType == _OSERROR_RESPONSE) { |
385 var responseError = message[RESPONSE_ERROR]; | 379 var responseError = message[RESPONSE_ERROR]; |
386 var err = new OSError( | 380 var err = new OSError(responseError[_OSERROR_RESPONSE_MESSAGE], |
387 responseError[_OSERROR_RESPONSE_MESSAGE], | |
388 responseError[_OSERROR_RESPONSE_ERROR_CODE]); | 381 responseError[_OSERROR_RESPONSE_ERROR_CODE]); |
389 var errorPath = message[RESPONSE_PATH]; | 382 var errorPath = message[RESPONSE_PATH]; |
390 if (errorPath == null) errorPath = path; | 383 if (errorPath == null) errorPath = path; |
391 controller.addError( | 384 controller.addError( |
392 new FileSystemException("Directory listing failed", | 385 new FileSystemException("Directory listing failed", errorPath, err)); |
393 errorPath, | |
394 err)); | |
395 } else { | 386 } else { |
396 controller.addError( | 387 controller.addError(new FileSystemException("Internal error")); |
397 new FileSystemException("Internal error")); | |
398 } | 388 } |
399 } | 389 } |
400 } | 390 } |
OLD | NEW |