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 | 5 |
6 class _Directory implements Directory { | 6 class _Directory implements Directory { |
7 static final kCreateRequest = 0; | 7 static final kCreateRequest = 0; |
8 static final kDeleteRequest = 1; | 8 static final kDeleteRequest = 1; |
9 static final kExistsRequest = 2; | 9 static final kExistsRequest = 2; |
10 static final kCreateTempRequest = 3; | 10 static final kCreateTempRequest = 3; |
11 static final kListRequest = 4; | 11 static final kListRequest = 4; |
12 | 12 |
| 13 static final kSuccessResponse = 0; |
| 14 static final kIllegalArgumentResponse = 1; |
| 15 static final kOSErrorResponse = 2; |
| 16 |
13 _Directory(String this._path); | 17 _Directory(String this._path); |
14 _Directory.current() : _path = _current(); | 18 _Directory.current() : _path = _current(); |
15 | 19 |
16 static String _current() native "Directory_Current"; | 20 static String _current() native "Directory_Current"; |
17 static _createTemp(String template) native "Directory_CreateTemp"; | 21 static _createTemp(String template) native "Directory_CreateTemp"; |
18 static int _exists(String path) native "Directory_Exists"; | 22 static int _exists(String path) native "Directory_Exists"; |
19 static bool _create(String path) native "Directory_Create"; | 23 static _create(String path) native "Directory_Create"; |
20 static bool _delete(String path, bool recursive) native "Directory_Delete"; | 24 static _delete(String path, bool recursive) native "Directory_Delete"; |
21 static SendPort _newServicePort() native "Directory_NewServicePort"; | 25 static SendPort _newServicePort() native "Directory_NewServicePort"; |
22 | 26 |
23 void exists(void callback(bool exists)) { | 27 void exists(void callback(bool exists)) { |
24 _ensureDirectoryService(); | 28 _ensureDirectoryService(); |
25 List request = new List(2); | 29 List request = new List(2); |
26 request[0] = kExistsRequest; | 30 request[0] = kExistsRequest; |
27 request[1] = _path; | 31 request[1] = _path; |
28 _directoryService.call(request).then((result) { | 32 _directoryService.call(request).then((response) { |
29 if (result < 0) { | 33 if (_isErrorResponse(response)) { |
30 if (_onError != null) { | 34 _reportError(response, "Exists failed"); |
31 _onError("Diretory exists test failed: $_path"); | |
32 } | |
33 } else { | 35 } else { |
34 callback(result == 1); | 36 callback(response == 1); |
35 } | 37 } |
36 }); | 38 }); |
37 } | 39 } |
38 | 40 |
39 bool existsSync() { | 41 bool existsSync() { |
40 int exists = _exists(_path); | 42 if (_path is !String) { |
41 if (exists < 0) { | 43 throw new IllegalArgumentException(); |
42 throw new DirectoryIOException("Diretory exists test failed: $_path"); | |
43 } | 44 } |
44 return (exists == 1); | 45 var result = _exists(_path); |
| 46 if (result is OSError) { |
| 47 throw new DirectoryIOException("Exists failed", _path, result); |
| 48 } |
| 49 return (result == 1); |
45 } | 50 } |
46 | 51 |
47 void create(void callback()) { | 52 void create(void callback()) { |
48 _ensureDirectoryService(); | 53 _ensureDirectoryService(); |
49 List request = new List(2); | 54 List request = new List(2); |
50 request[0] = kCreateRequest; | 55 request[0] = kCreateRequest; |
51 request[1] = _path; | 56 request[1] = _path; |
52 _directoryService.call(request).then((result) { | 57 _directoryService.call(request).then((response) { |
53 if (result) { | 58 if (_isErrorResponse(response)) { |
| 59 _reportError(response, "Creation failed"); |
| 60 } else { |
54 callback(); | 61 callback(); |
55 } else if (_onError != null) { | |
56 _onError("Directory creation failed: $_path"); | |
57 } | 62 } |
58 }); | 63 }); |
59 } | 64 } |
60 | 65 |
61 void createSync() { | 66 void createSync() { |
62 if (!_create(_path)) { | 67 if (_path is !String) { |
63 throw new DirectoryIOException("Directory creation failed: $_path"); | 68 throw new IllegalArgumentException(); |
| 69 } |
| 70 var result = _create(_path); |
| 71 if (result is OSError) { |
| 72 throw new DirectoryIOException("Creation failed", _path, result); |
64 } | 73 } |
65 } | 74 } |
66 | 75 |
67 void createTemp(void callback()) { | 76 void createTemp(void callback()) { |
68 _ensureDirectoryService(); | 77 _ensureDirectoryService(); |
69 List request = new List(2); | 78 List request = new List(2); |
70 request[0] = kCreateTempRequest; | 79 request[0] = kCreateTempRequest; |
71 request[1] = _path; | 80 request[1] = _path; |
72 _directoryService.call(request).then((result) { | 81 _directoryService.call(request).then((response) { |
73 if (result is !List) { | 82 if (_isErrorResponse(response)) { |
74 _path = result; | 83 _reportError(response, "Creation of temporary directory failed"); |
| 84 } else { |
| 85 _path = response; |
75 callback(); | 86 callback(); |
76 } else if (_onError != null) { | |
77 _onError("Could not create temporary directory [$_path]: ${result[1]}"); | |
78 } | 87 } |
79 }); | 88 }); |
80 } | 89 } |
81 | 90 |
82 void createTempSync() { | 91 void createTempSync() { |
83 if (_path is !String) { | 92 if (_path is !String) { |
84 throw new IllegalArgumentException(); | 93 throw new IllegalArgumentException(); |
85 } | 94 } |
86 var result = _createTemp(path); | 95 var result = _createTemp(path); |
87 if (result is OSError) { | 96 if (result is OSError) { |
88 throw new DirectoryIOException("Could not create temporary directory", | 97 throw new DirectoryIOException("Creation of temporary directory failed", |
| 98 _path, |
89 result); | 99 result); |
90 } | 100 } |
91 _path = result; | 101 _path = result; |
92 } | 102 } |
93 | 103 |
94 void _deleteHelper(bool recursive, String errorMsg, void callback()) { | 104 void _deleteHelper(bool recursive, String errorMsg, void callback()) { |
95 _ensureDirectoryService(); | 105 _ensureDirectoryService(); |
96 List request = new List(3); | 106 List request = new List(3); |
97 request[0] = kDeleteRequest; | 107 request[0] = kDeleteRequest; |
98 request[1] = _path; | 108 request[1] = _path; |
99 request[2] = recursive; | 109 request[2] = recursive; |
100 _directoryService.call(request).then((result) { | 110 _directoryService.call(request).then((response) { |
101 if (result) { | 111 if (_isErrorResponse(response)) { |
| 112 _reportError(response, errorMsg); |
| 113 } else { |
102 callback(); | 114 callback(); |
103 } else if (_onError != null) { | |
104 _onError("${errorMsg}: $_path"); | |
105 } | 115 } |
106 }); | 116 }); |
107 } | 117 } |
108 | 118 |
109 void delete(void callback()) { | 119 void delete(void callback()) { |
110 _deleteHelper(false, "Directory deletion failed", callback); | 120 _deleteHelper(false, "Deletion failed", callback); |
111 } | 121 } |
112 | 122 |
113 void deleteRecursively(void callback()) { | 123 void deleteRecursively(void callback()) { |
114 _deleteHelper(true, "Recursive directory deletion failed", callback); | 124 _deleteHelper(true, "Deletion failed", callback); |
115 } | 125 } |
116 | 126 |
117 void deleteSync() { | 127 void deleteSync() { |
118 bool recursive = false; | 128 if (_path is !String) { |
119 if (!_delete(_path, recursive)) { | 129 throw new IllegalArgumentException(); |
120 throw new DirectoryIOException("Directory deletion failed: $_path"); | 130 } |
| 131 var result = _delete(_path, false); |
| 132 if (result is OSError) { |
| 133 throw new DirectoryIOException("Deletion failed", _path, result); |
121 } | 134 } |
122 } | 135 } |
123 | 136 |
124 void deleteRecursivelySync() { | 137 void deleteRecursivelySync() { |
125 bool recursive = true; | 138 if (_path is !String) { |
126 if (!_delete(_path, recursive)) { | 139 throw new IllegalArgumentException(); |
127 throw new DirectoryIOException( | 140 } |
128 "Recursive directory deletion failed: $_path"); | 141 var result = _delete(_path, true); |
| 142 if (result is OSError) { |
| 143 throw new DirectoryIOException("Deletion failed", _path, result); |
129 } | 144 } |
130 } | 145 } |
131 | 146 |
132 void list([bool recursive = false]) { | 147 void list([bool recursive = false]) { |
133 final int kListDirectory = 0; | 148 final int kListDirectory = 0; |
134 final int kListFile = 1; | 149 final int kListFile = 1; |
135 final int kListError = 2; | 150 final int kListError = 2; |
136 final int kListDone = 3; | 151 final int kListDone = 3; |
137 | 152 |
| 153 final int kResponseType = 0; |
| 154 final int kResponsePath = 1; |
| 155 final int kResponseComplete = 1; |
| 156 final int kResponseError = 2; |
| 157 |
138 List request = new List(3); | 158 List request = new List(3); |
139 request[0] = kListRequest; | 159 request[0] = kListRequest; |
140 request[1] = _path; | 160 request[1] = _path; |
141 request[2] = recursive; | 161 request[2] = recursive; |
142 ReceivePort responsePort = new ReceivePort(); | 162 ReceivePort responsePort = new ReceivePort(); |
143 // Use a separate directory service port for each listing as | 163 // Use a separate directory service port for each listing as |
144 // listing operations on the same directory can run in parallel. | 164 // listing operations on the same directory can run in parallel. |
145 _newServicePort().send(request, responsePort.toSendPort()); | 165 _newServicePort().send(request, responsePort.toSendPort()); |
146 responsePort.receive((message, replyTo) { | 166 responsePort.receive((message, replyTo) { |
147 if (message is !List || message[0] is !int) { | 167 if (message is !List || message[kResponseType] is !int) { |
148 responsePort.close(); | 168 responsePort.close(); |
149 if (_onError != null) _onError("Internal error"); | 169 if (_onError != null) { |
| 170 _onError(new DirectoryIOException("Internal error")); |
| 171 } |
150 return; | 172 return; |
151 } | 173 } |
152 switch (message[0]) { | 174 switch (message[kResponseType]) { |
153 case kListDirectory: | 175 case kListDirectory: |
154 if (_onDir != null) _onDir(message[1]); | 176 if (_onDir != null) _onDir(message[kResponsePath]); |
155 break; | 177 break; |
156 case kListFile: | 178 case kListFile: |
157 if (_onFile != null) _onFile(message[1]); | 179 if (_onFile != null) _onFile(message[kResponsePath]); |
158 break; | 180 break; |
159 case kListError: | 181 case kListError: |
160 if (_onError != null) _onError(message[1]); | 182 if (_onError != null) { |
| 183 var errorType = |
| 184 message[kResponseError][_FileUtils.kErrorResponseErrorType]; |
| 185 if (errorType == _FileUtils.kIllegalArgumentResponse) { |
| 186 _onError(new IllegalArgumentException()); |
| 187 } else if (errorType == _FileUtils.kOSErrorResponse) { |
| 188 var err = new OSError( |
| 189 message[kResponseError][_FileUtils.kOSErrorResponseErrorCode], |
| 190 message[kResponseError][_FileUtils.kOSErrorResponseMessage]); |
| 191 _onError(new DirectoryIOException("Directory listing failed", |
| 192 message[kResponsePath], |
| 193 err)); |
| 194 } else { |
| 195 _onError(new DirectoryIOException("Internal error")); |
| 196 } |
| 197 } |
161 break; | 198 break; |
162 case kListDone: | 199 case kListDone: |
163 responsePort.close(); | 200 responsePort.close(); |
164 if (_onDone != null) _onDone(message[1]); | 201 if (_onDone != null) _onDone(message[kResponseComplete]); |
165 break; | 202 break; |
166 } | 203 } |
167 }); | 204 }); |
168 } | 205 } |
169 | 206 |
170 void set onDir(void onDir(String dir)) { | 207 void set onDir(void onDir(String dir)) { |
171 _onDir = onDir; | 208 _onDir = onDir; |
172 } | 209 } |
173 | 210 |
174 void set onFile(void onFile(String file)) { | 211 void set onFile(void onFile(String file)) { |
175 _onFile = onFile; | 212 _onFile = onFile; |
176 } | 213 } |
177 | 214 |
178 void set onDone(void onDone(bool completed)) { | 215 void set onDone(void onDone(bool completed)) { |
179 _onDone = onDone; | 216 _onDone = onDone; |
180 } | 217 } |
181 | 218 |
182 void set onError(void onError(String error)) { | 219 void set onError(void onError(Exception e)) { |
183 _onError = onError; | 220 _onError = onError; |
184 } | 221 } |
185 | 222 |
186 String get path() { return _path; } | 223 String get path() { return _path; } |
187 | 224 |
188 void _ensureDirectoryService() { | 225 void _ensureDirectoryService() { |
189 if (_directoryService == null) { | 226 if (_directoryService == null) { |
190 _directoryService = _newServicePort(); | 227 _directoryService = _newServicePort(); |
191 } | 228 } |
192 } | 229 } |
193 | 230 |
194 var _onDir; | 231 bool _isErrorResponse(response) { |
195 var _onFile; | 232 return response is List && response[0] != _FileUtils.kSuccessResponse; |
196 var _onDone; | 233 } |
197 var _onError; | 234 |
| 235 bool _reportError(response, String message) { |
| 236 assert(_isErrorResponse(response)); |
| 237 if (_onError != null) { |
| 238 switch (response[_FileUtils.kErrorResponseErrorType]) { |
| 239 case _FileUtils.kIllegalArgumentResponse: |
| 240 _onError(new IllegalArgumentException()); |
| 241 break; |
| 242 case _FileUtils.kOSErrorResponse: |
| 243 var err = new OSError(response[_FileUtils.kOSErrorResponseErrorCode], |
| 244 response[_FileUtils.kOSErrorResponseMessage]); |
| 245 _onError(new DirectoryIOException(message, _path, err)); |
| 246 break; |
| 247 default: |
| 248 _onError(new Exception("Unknown error")); |
| 249 break; |
| 250 } |
| 251 } |
| 252 } |
| 253 |
| 254 Function _onDir; |
| 255 Function _onFile; |
| 256 Function _onDone; |
| 257 Function _onError; |
198 | 258 |
199 String _path; | 259 String _path; |
200 SendPort _directoryService; | 260 SendPort _directoryService; |
201 } | 261 } |
OLD | NEW |