| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 | |
| 6 class _Directory implements Directory { | |
| 7 static const CREATE_REQUEST = 0; | |
| 8 static const DELETE_REQUEST = 1; | |
| 9 static const EXISTS_REQUEST = 2; | |
| 10 static const CREATE_TEMP_REQUEST = 3; | |
| 11 static const LIST_REQUEST = 4; | |
| 12 static const RENAME_REQUEST = 5; | |
| 13 | |
| 14 static const SUCCESS_RESPONSE = 0; | |
| 15 static const ILLEGAL_ARGUMENT_RESPONSE = 1; | |
| 16 static const OSERROR_RESPONSE = 2; | |
| 17 | |
| 18 _Directory(String this._path); | |
| 19 _Directory.fromPath(Path path) : this(path.toNativePath()); | |
| 20 _Directory.current() : this(_current()); | |
| 21 | |
| 22 static String _current() native "Directory_Current"; | |
| 23 static _createTemp(String template) native "Directory_CreateTemp"; | |
| 24 static int _exists(String path) native "Directory_Exists"; | |
| 25 static _create(String path) native "Directory_Create"; | |
| 26 static _delete(String path, bool recursive) native "Directory_Delete"; | |
| 27 static _rename(String path, String newPath) native "Directory_Rename"; | |
| 28 static SendPort _newServicePort() native "Directory_NewServicePort"; | |
| 29 | |
| 30 Future<bool> exists() { | |
| 31 _ensureDirectoryService(); | |
| 32 List request = new List(2); | |
| 33 request[0] = EXISTS_REQUEST; | |
| 34 request[1] = _path; | |
| 35 return _directoryService.call(request).transform((response) { | |
| 36 if (_isErrorResponse(response)) { | |
| 37 throw _exceptionFromResponse(response, "Exists failed"); | |
| 38 } | |
| 39 return response == 1; | |
| 40 }); | |
| 41 } | |
| 42 | |
| 43 bool existsSync() { | |
| 44 if (_path is !String) { | |
| 45 throw new ArgumentError(); | |
| 46 } | |
| 47 var result = _exists(_path); | |
| 48 if (result is OSError) { | |
| 49 throw new DirectoryIOException("Exists failed", _path, result); | |
| 50 } | |
| 51 return (result == 1); | |
| 52 } | |
| 53 | |
| 54 Future<Directory> create() { | |
| 55 _ensureDirectoryService(); | |
| 56 List request = new List(2); | |
| 57 request[0] = CREATE_REQUEST; | |
| 58 request[1] = _path; | |
| 59 return _directoryService.call(request).transform((response) { | |
| 60 if (_isErrorResponse(response)) { | |
| 61 throw _exceptionFromResponse(response, "Creation failed"); | |
| 62 } | |
| 63 return this; | |
| 64 }); | |
| 65 } | |
| 66 | |
| 67 void createSync() { | |
| 68 if (_path is !String) { | |
| 69 throw new ArgumentError(); | |
| 70 } | |
| 71 var result = _create(_path); | |
| 72 if (result is OSError) { | |
| 73 throw new DirectoryIOException("Creation failed", _path, result); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 Future<Directory> createTemp() { | |
| 78 _ensureDirectoryService(); | |
| 79 List request = new List(2); | |
| 80 request[0] = CREATE_TEMP_REQUEST; | |
| 81 request[1] = _path; | |
| 82 return _directoryService.call(request).transform((response) { | |
| 83 if (_isErrorResponse(response)) { | |
| 84 throw _exceptionFromResponse(response, | |
| 85 "Creation of temporary directory failed"); | |
| 86 } | |
| 87 return new Directory(response); | |
| 88 }); | |
| 89 } | |
| 90 | |
| 91 Directory createTempSync() { | |
| 92 if (_path is !String) { | |
| 93 throw new ArgumentError(); | |
| 94 } | |
| 95 var result = _createTemp(path); | |
| 96 if (result is OSError) { | |
| 97 throw new DirectoryIOException("Creation of temporary directory failed", | |
| 98 _path, | |
| 99 result); | |
| 100 } | |
| 101 return new Directory(result); | |
| 102 } | |
| 103 | |
| 104 Future<Directory> _deleteHelper(bool recursive, String errorMsg) { | |
| 105 _ensureDirectoryService(); | |
| 106 List request = new List(3); | |
| 107 request[0] = DELETE_REQUEST; | |
| 108 request[1] = _path; | |
| 109 request[2] = recursive; | |
| 110 return _directoryService.call(request).transform((response) { | |
| 111 if (_isErrorResponse(response)) { | |
| 112 throw _exceptionFromResponse(response, errorMsg); | |
| 113 } | |
| 114 return this; | |
| 115 }); | |
| 116 return completer.future; | |
| 117 } | |
| 118 | |
| 119 Future<Directory> delete() { | |
| 120 return _deleteHelper(false, "Deletion failed"); | |
| 121 } | |
| 122 | |
| 123 void deleteSync() { | |
| 124 if (_path is !String) { | |
| 125 throw new ArgumentError(); | |
| 126 } | |
| 127 var result = _delete(_path, false); | |
| 128 if (result is OSError) { | |
| 129 throw new DirectoryIOException("Deletion failed", _path, result); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 Future<Directory> deleteRecursively() { | |
| 134 return _deleteHelper(true, "Deletion failed"); | |
| 135 } | |
| 136 | |
| 137 void deleteRecursivelySync() { | |
| 138 if (_path is !String) { | |
| 139 throw new ArgumentError(); | |
| 140 } | |
| 141 var result = _delete(_path, true); | |
| 142 if (result is OSError) { | |
| 143 throw new DirectoryIOException("Deletion failed", _path, result); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 Future<Directory> rename(String newPath) { | |
| 148 _ensureDirectoryService(); | |
| 149 List request = new List(3); | |
| 150 request[0] = RENAME_REQUEST; | |
| 151 request[1] = _path; | |
| 152 request[2] = newPath; | |
| 153 return _directoryService.call(request).transform((response) { | |
| 154 if (_isErrorResponse(response)) { | |
| 155 throw _exceptionFromResponse(response, "Rename failed"); | |
| 156 } | |
| 157 return new Directory(newPath); | |
| 158 }); | |
| 159 } | |
| 160 | |
| 161 Directory renameSync(String newPath) { | |
| 162 if (_path is !String || newPath is !String) { | |
| 163 throw new ArgumentError(); | |
| 164 } | |
| 165 var result = _rename(_path, newPath); | |
| 166 if (result is OSError) { | |
| 167 throw new DirectoryIOException("Rename failed", _path, result); | |
| 168 } | |
| 169 return new Directory(newPath); | |
| 170 } | |
| 171 | |
| 172 DirectoryLister list({bool recursive: false}) { | |
| 173 return new _DirectoryLister(_path, recursive); | |
| 174 } | |
| 175 | |
| 176 String get path { return _path; } | |
| 177 | |
| 178 bool _isErrorResponse(response) { | |
| 179 return response is List && response[0] != _SUCCESS_RESPONSE; | |
| 180 } | |
| 181 | |
| 182 Exception _exceptionFromResponse(response, String message) { | |
| 183 assert(_isErrorResponse(response)); | |
| 184 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { | |
| 185 case _ILLEGAL_ARGUMENT_RESPONSE: | |
| 186 return new ArgumentError(); | |
| 187 case _OSERROR_RESPONSE: | |
| 188 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], | |
| 189 response[_OSERROR_RESPONSE_ERROR_CODE]); | |
| 190 return new DirectoryIOException(message, _path, err); | |
| 191 default: | |
| 192 return new Exception("Unknown error"); | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 void _ensureDirectoryService() { | |
| 197 if (_directoryService == null) { | |
| 198 _directoryService = _newServicePort(); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 final String _path; | |
| 203 SendPort _directoryService; | |
| 204 } | |
| 205 | |
| 206 class _DirectoryLister implements DirectoryLister { | |
| 207 _DirectoryLister(String path, bool recursive) { | |
| 208 const int LIST_DIRECTORY = 0; | |
| 209 const int LIST_FILE = 1; | |
| 210 const int LIST_ERROR = 2; | |
| 211 const int LIST_DONE = 3; | |
| 212 | |
| 213 final int RESPONSE_TYPE = 0; | |
| 214 final int RESPONSE_PATH = 1; | |
| 215 final int RESPONSE_COMPLETE = 1; | |
| 216 final int RESPONSE_ERROR = 2; | |
| 217 | |
| 218 List request = new List(3); | |
| 219 request[0] = _Directory.LIST_REQUEST; | |
| 220 request[1] = path; | |
| 221 request[2] = recursive; | |
| 222 ReceivePort responsePort = new ReceivePort(); | |
| 223 // Use a separate directory service port for each listing as | |
| 224 // listing operations on the same directory can run in parallel. | |
| 225 _Directory._newServicePort().send(request, responsePort.toSendPort()); | |
| 226 responsePort.receive((message, replyTo) { | |
| 227 if (message is !List || message[RESPONSE_TYPE] is !int) { | |
| 228 responsePort.close(); | |
| 229 _reportError(new DirectoryIOException("Internal error")); | |
| 230 return; | |
| 231 } | |
| 232 switch (message[RESPONSE_TYPE]) { | |
| 233 case LIST_DIRECTORY: | |
| 234 if (_onDir != null) _onDir(message[RESPONSE_PATH]); | |
| 235 break; | |
| 236 case LIST_FILE: | |
| 237 if (_onFile != null) _onFile(message[RESPONSE_PATH]); | |
| 238 break; | |
| 239 case LIST_ERROR: | |
| 240 var errorType = | |
| 241 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; | |
| 242 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { | |
| 243 _reportError(new ArgumentError()); | |
| 244 } else if (errorType == _OSERROR_RESPONSE) { | |
| 245 var responseError = message[RESPONSE_ERROR]; | |
| 246 var err = new OSError( | |
| 247 responseError[_OSERROR_RESPONSE_MESSAGE], | |
| 248 responseError[_OSERROR_RESPONSE_ERROR_CODE]); | |
| 249 var errorPath = message[RESPONSE_PATH]; | |
| 250 if (errorPath == null) errorPath = path; | |
| 251 _reportError(new DirectoryIOException("Directory listing failed", | |
| 252 errorPath, | |
| 253 err)); | |
| 254 } else { | |
| 255 _reportError(new DirectoryIOException("Internal error")); | |
| 256 } | |
| 257 break; | |
| 258 case LIST_DONE: | |
| 259 responsePort.close(); | |
| 260 if (_onDone != null) _onDone(message[RESPONSE_COMPLETE]); | |
| 261 break; | |
| 262 } | |
| 263 }); | |
| 264 } | |
| 265 | |
| 266 void set onDir(void onDir(String dir)) { | |
| 267 _onDir = onDir; | |
| 268 } | |
| 269 | |
| 270 void set onFile(void onFile(String file)) { | |
| 271 _onFile = onFile; | |
| 272 } | |
| 273 | |
| 274 void set onDone(void onDone(bool completed)) { | |
| 275 _onDone = onDone; | |
| 276 } | |
| 277 | |
| 278 void set onError(void onError(e)) { | |
| 279 _onError = onError; | |
| 280 } | |
| 281 | |
| 282 void _reportError(e) { | |
| 283 if (_onError != null) { | |
| 284 _onError(e); | |
| 285 } else { | |
| 286 throw e; | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 Function _onDir; | |
| 291 Function _onFile; | |
| 292 Function _onDone; | |
| 293 Function _onError; | |
| 294 } | |
| OLD | NEW |