| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library get.handler; | 5 library get.handler; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 import 'dart:math'; | 9 import 'dart:math'; |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 /** | 21 /** |
| 22 * Instances of the class [GetHandler] handle GET requests. | 22 * Instances of the class [GetHandler] handle GET requests. |
| 23 */ | 23 */ |
| 24 class GetHandler { | 24 class GetHandler { |
| 25 /** | 25 /** |
| 26 * The path used to request the status of the analysis server as a whole. | 26 * The path used to request the status of the analysis server as a whole. |
| 27 */ | 27 */ |
| 28 static const String STATUS_PATH = '/status'; | 28 static const String STATUS_PATH = '/status'; |
| 29 | 29 |
| 30 /** | 30 /** |
| 31 * The path used to request code completion information. | 31 * The path used to request information about the cache entry corresponding |
| 32 * to a single file. |
| 32 */ | 33 */ |
| 33 static const String COMPLETION_PATH = '/completion'; | 34 static const String CACHE_ENTRY_PATH = '/cache_entry'; |
| 34 | 35 |
| 35 /** | 36 /** |
| 36 * The path used to request the list of source files in a certain cache | 37 * The path used to request the list of source files in a certain cache |
| 37 * state. | 38 * state. |
| 38 */ | 39 */ |
| 39 static const String CACHE_STATE_PATH = '/cache_state'; | 40 static const String CACHE_STATE_PATH = '/cache_state'; |
| 40 | 41 |
| 41 /** | 42 /** |
| 43 * The path used to request code completion information. |
| 44 */ |
| 45 static const String COMPLETION_PATH = '/completion'; |
| 46 |
| 47 /** |
| 42 * Query parameter used to represent the cache state to search for, when | 48 * Query parameter used to represent the cache state to search for, when |
| 43 * accessing [CACHE_STATE_PATH]. | 49 * accessing [CACHE_STATE_PATH]. |
| 44 */ | 50 */ |
| 45 static const String STATE_QUERY_PARAM = 'state'; | 51 static const String STATE_QUERY_PARAM = 'state'; |
| 46 | 52 |
| 47 /** | 53 /** |
| 48 * Query parameter used to represent the context to search for, when | 54 * Query parameter used to represent the context to search for, when |
| 49 * accessing [CACHE_STATE_PATH]. | 55 * accessing [CACHE_ENTRY_PATH] or [CACHE_STATE_PATH]. |
| 50 */ | 56 */ |
| 51 static const String CONTEXT_QUERY_PARAM = 'context'; | 57 static const String CONTEXT_QUERY_PARAM = 'context'; |
| 52 | 58 |
| 53 /** | 59 /** |
| 54 * Query parameter used to represent the descriptor to search for, when | 60 * Query parameter used to represent the descriptor to search for, when |
| 55 * accessing [CACHE_STATE_PATH]. | 61 * accessing [CACHE_STATE_PATH]. |
| 56 */ | 62 */ |
| 57 static const String DESCRIPTOR_QUERY_PARAM = 'descriptor'; | 63 static const String DESCRIPTOR_QUERY_PARAM = 'descriptor'; |
| 58 | 64 |
| 59 /** | 65 /** |
| 66 * Query parameter used to represent the source to search for, when accessing |
| 67 * [CACHE_ENTRY_PATH]. |
| 68 */ |
| 69 static const String SOURCE_QUERY_PARAM = 'entry'; |
| 70 |
| 71 /** |
| 60 * The socket server whose status is to be reported on. | 72 * The socket server whose status is to be reported on. |
| 61 */ | 73 */ |
| 62 SocketServer _server; | 74 SocketServer _server; |
| 63 | 75 |
| 64 /** | 76 /** |
| 65 * Buffer containing strings printed by the analysis server. | 77 * Buffer containing strings printed by the analysis server. |
| 66 */ | 78 */ |
| 67 List<String> _printBuffer; | 79 List<String> _printBuffer; |
| 68 | 80 |
| 69 /** | 81 /** |
| 70 * Initialize a newly created handler for GET requests. | 82 * Initialize a newly created handler for GET requests. |
| 71 */ | 83 */ |
| 72 GetHandler(this._server, this._printBuffer); | 84 GetHandler(this._server, this._printBuffer); |
| 73 | 85 |
| 74 /** | 86 /** |
| 75 * Handle a GET request received by the HTTP server. | 87 * Handle a GET request received by the HTTP server. |
| 76 */ | 88 */ |
| 77 void handleGetRequest(HttpRequest request) { | 89 void handleGetRequest(HttpRequest request) { |
| 78 String path = request.uri.path; | 90 String path = request.uri.path; |
| 79 if (path == STATUS_PATH) { | 91 if (path == STATUS_PATH) { |
| 80 _returnServerStatus(request); | 92 _returnServerStatus(request); |
| 81 } else if (path == CACHE_STATE_PATH) { | 93 } else if (path == CACHE_STATE_PATH) { |
| 82 _returnCacheState(request); | 94 _returnCacheState(request); |
| 95 } else if (path == CACHE_ENTRY_PATH) { |
| 96 _returnCacheEntry(request); |
| 83 } else if (path == COMPLETION_PATH) { | 97 } else if (path == COMPLETION_PATH) { |
| 84 _returnCompletionInfo(request); | 98 _returnCompletionInfo(request); |
| 85 } else { | 99 } else { |
| 86 _returnUnknownRequest(request); | 100 _returnUnknownRequest(request); |
| 87 } | 101 } |
| 88 } | 102 } |
| 89 | 103 |
| 90 /** | 104 /** |
| 91 * Create a link to [path] with query parameters [params], with inner HTML | 105 * Create a link to [path] with query parameters [params], with inner HTML |
| 92 * [innerHtml]. | 106 * [innerHtml]. |
| 93 */ | 107 */ |
| 94 String _makeLink(String path, Map<String, String> params, String innerHtml) { | 108 String _makeLink(String path, Map<String, String> params, String innerHtml) { |
| 95 Uri uri = new Uri(path: path, queryParameters: params); | 109 Uri uri = new Uri(path: path, queryParameters: params); |
| 96 return '<a href="${HTML_ESCAPE.convert(uri.toString())}">$innerHtml</a>'; | 110 return '<a href="${HTML_ESCAPE.convert(uri.toString())}">$innerHtml</a>'; |
| 97 } | 111 } |
| 98 | 112 |
| 99 /** | 113 /** |
| 114 * Generate a table showing the cache values corresponding to the given |
| 115 * [descriptors], using [getState] to get the cache state corresponding to |
| 116 * each descriptor, and [getValue] to get the cached value corresponding to |
| 117 * each descriptor. Append the resulting HTML to [response]. |
| 118 */ |
| 119 void _outputDescriptorTable(HttpResponse response, |
| 120 List<DataDescriptor> descriptors, CacheState getState(DataDescriptor), dyn
amic |
| 121 getValue(DataDescriptor)) { |
| 122 response.write('<dl>'); |
| 123 for (DataDescriptor descriptor in descriptors) { |
| 124 String descriptorName = HTML_ESCAPE.convert(descriptor.toString()); |
| 125 String descriptorState = |
| 126 HTML_ESCAPE.convert(getState(descriptor).toString()); |
| 127 response.write('<dt>$descriptorName ($descriptorState)</dt><dd>'); |
| 128 try { |
| 129 _outputValueAsHtml(response, getValue(descriptor)); |
| 130 } catch (exception) { |
| 131 response.write('(${HTML_ESCAPE.convert(exception.toString())})'); |
| 132 } |
| 133 response.write('</dd>'); |
| 134 } |
| 135 response.write('</dl>'); |
| 136 } |
| 137 |
| 138 /** |
| 139 * Render the given [value] as HTML and append it to [response]. |
| 140 */ |
| 141 void _outputValueAsHtml(HttpResponse response, dynamic value) { |
| 142 if (value == null) { |
| 143 response.write('<i>null</i>'); |
| 144 } else if (value is String) { |
| 145 response.write('<pre>${HTML_ESCAPE.convert(value)}</pre>'); |
| 146 } else if (value is List) { |
| 147 response.write('${value.length} entries'); |
| 148 response.write('<ul>'); |
| 149 for (var entry in value) { |
| 150 response.write('<li>'); |
| 151 _outputValueAsHtml(response, entry); |
| 152 response.write('</li>'); |
| 153 } |
| 154 response.write('</ul>'); |
| 155 } else { |
| 156 response.write(HTML_ESCAPE.convert(value.toString())); |
| 157 response.write( |
| 158 ' <i>(${HTML_ESCAPE.convert(value.runtimeType.toString())})</i>'); |
| 159 } |
| 160 } |
| 161 |
| 162 /** |
| 163 * Return a response containing information about a single source file in the |
| 164 * cache. |
| 165 */ |
| 166 void _returnCacheEntry(HttpRequest request) { |
| 167 // Figure out which context is being searched for. |
| 168 String contextFilter = request.uri.queryParameters[CONTEXT_QUERY_PARAM]; |
| 169 if (contextFilter == null) { |
| 170 return _returnFailure( |
| 171 request, |
| 172 'Query parameter $CONTEXT_QUERY_PARAM required'); |
| 173 } |
| 174 |
| 175 // Figure out which CacheEntry is being searched for. |
| 176 String sourceUri = request.uri.queryParameters[SOURCE_QUERY_PARAM]; |
| 177 if (sourceUri == null) { |
| 178 return _returnFailure( |
| 179 request, |
| 180 'Query parameter $SOURCE_QUERY_PARAM required'); |
| 181 } |
| 182 |
| 183 AnalysisServer analysisServer = _server.analysisServer; |
| 184 if (analysisServer == null) { |
| 185 return _returnFailure(request, 'Analysis server not running'); |
| 186 } |
| 187 HttpResponse response = request.response; |
| 188 response.statusCode = HttpStatus.OK; |
| 189 response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html"); |
| 190 response.write('<html>'); |
| 191 response.write('<head>'); |
| 192 response.write('<title>Dart Analysis Server - Search result</title>'); |
| 193 response.write('</head>'); |
| 194 response.write('<body>'); |
| 195 response.write('<h1>'); |
| 196 response.write('File ${HTML_ESCAPE.convert(sourceUri)}'); |
| 197 response.write(' in context ${HTML_ESCAPE.convert(contextFilter)}'); |
| 198 response.write('</h1>'); |
| 199 analysisServer.folderMap.forEach( |
| 200 (Folder folder, AnalysisContextImpl context) { |
| 201 if (folder.path != contextFilter) { |
| 202 return; |
| 203 } |
| 204 Source source = context.sourceFactory.forUri(sourceUri); |
| 205 if (source == null) { |
| 206 response.write('<p>Not found.</p>'); |
| 207 return; |
| 208 } |
| 209 SourceEntry entry = context.getReadableSourceEntryOrNull(source); |
| 210 if (entry == null) { |
| 211 response.write('<p>Not found.</p>'); |
| 212 return; |
| 213 } |
| 214 response.write('<h2>File info:</h2><dl>'); |
| 215 _outputDescriptorTable( |
| 216 response, |
| 217 entry.descriptors, |
| 218 entry.getState, |
| 219 entry.getValue); |
| 220 if (entry is DartEntry) { |
| 221 for (Source librarySource in entry.containingLibraries) { |
| 222 String libraryName = HTML_ESCAPE.convert(librarySource.fullName); |
| 223 response.write('<h2>In library $libraryName:</h2>'); |
| 224 _outputDescriptorTable( |
| 225 response, |
| 226 entry.libraryDescriptors, |
| 227 (DataDescriptor descriptor) => |
| 228 entry.getStateInLibrary(descriptor, librarySource), |
| 229 (DataDescriptor descriptor) => |
| 230 entry.getValueInLibrary(descriptor, librarySource)); |
| 231 } |
| 232 } |
| 233 }); |
| 234 response.write('</body>'); |
| 235 response.write('</html>'); |
| 236 response.close(); |
| 237 } |
| 238 |
| 239 /** |
| 100 * Return a response indicating the set of source files in a certain cache | 240 * Return a response indicating the set of source files in a certain cache |
| 101 * state. | 241 * state. |
| 102 */ | 242 */ |
| 103 void _returnCacheState(HttpRequest request) { | 243 void _returnCacheState(HttpRequest request) { |
| 104 // Figure out what CacheState is being searched for. | 244 // Figure out what CacheState is being searched for. |
| 105 String stateQueryParam = request.uri.queryParameters[STATE_QUERY_PARAM]; | 245 String stateQueryParam = request.uri.queryParameters[STATE_QUERY_PARAM]; |
| 106 if (stateQueryParam == null) { | 246 if (stateQueryParam == null) { |
| 107 return _returnFailure( | 247 return _returnFailure( |
| 108 request, | 248 request, |
| 109 'Query parameter $STATE_QUERY_PARAM required'); | 249 'Query parameter $STATE_QUERY_PARAM required'); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 (Folder folder, AnalysisContextImpl context) { | 300 (Folder folder, AnalysisContextImpl context) { |
| 161 if (folder.path != contextFilter) { | 301 if (folder.path != contextFilter) { |
| 162 return; | 302 return; |
| 163 } | 303 } |
| 164 context.visitCacheItems( | 304 context.visitCacheItems( |
| 165 (Source source, SourceEntry dartEntry, DataDescriptor rowDesc, CacheSt
ate state) | 305 (Source source, SourceEntry dartEntry, DataDescriptor rowDesc, CacheSt
ate state) |
| 166 { | 306 { |
| 167 if (state != stateFilter || rowDesc.toString() != descriptorFilter) { | 307 if (state != stateFilter || rowDesc.toString() != descriptorFilter) { |
| 168 return; | 308 return; |
| 169 } | 309 } |
| 170 response.write('<li>${HTML_ESCAPE.convert(source.fullName)}</li>'); | 310 String link = _makeLink(CACHE_ENTRY_PATH, { |
| 311 CONTEXT_QUERY_PARAM: folder.path, |
| 312 SOURCE_QUERY_PARAM: source.uri.toString() |
| 313 }, HTML_ESCAPE.convert(source.fullName)); |
| 314 response.write('<li>$link</li>'); |
| 171 count++; | 315 count++; |
| 172 }); | 316 }); |
| 173 }); | 317 }); |
| 174 response.write('</ul>'); | 318 response.write('</ul>'); |
| 175 response.write('<p>$count files found</p>'); | 319 response.write('<p>$count files found</p>'); |
| 176 response.write('</body>'); | 320 response.write('</body>'); |
| 177 response.write('</html>'); | 321 response.write('</html>'); |
| 178 response.close(); | 322 response.close(); |
| 179 } | 323 } |
| 180 | 324 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 if (header) { | 547 if (header) { |
| 404 response.write('</th>'); | 548 response.write('</th>'); |
| 405 } else { | 549 } else { |
| 406 response.write('</td>'); | 550 response.write('</td>'); |
| 407 } | 551 } |
| 408 } | 552 } |
| 409 | 553 |
| 410 response.write('</tr>'); | 554 response.write('</tr>'); |
| 411 } | 555 } |
| 412 } | 556 } |
| OLD | NEW |