| 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 channel; | 5 library channel; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 | 9 |
| 10 import 'package:analysis_server/src/protocol.dart'; | 10 import 'package:analysis_server/src/protocol.dart'; |
| 11 import 'package:analyzer/src/util/utilities_timing.dart'; | 11 import 'package:analyzer/src/util/utilities_timing.dart'; |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * Instances of the class [ChannelChunkSink] uses a [Converter] to translate |
| 15 * chunks. |
| 16 */ |
| 17 class ChannelChunkSink<S, T> extends ChunkedConversionSink<S> { |
| 18 /** |
| 19 * The converter used to translate chunks. |
| 20 */ |
| 21 final Converter<S, T> converter; |
| 22 |
| 23 /** |
| 24 * The sink to which the converted chunks are added. |
| 25 */ |
| 26 final Sink sink; |
| 27 |
| 28 /** |
| 29 * A flag indicating whether the sink has been closed. |
| 30 */ |
| 31 bool closed = false; |
| 32 |
| 33 /** |
| 34 * Initialize a newly create sink to use the given [converter] to convert |
| 35 * chunks before adding them to the given [sink]. |
| 36 */ |
| 37 ChannelChunkSink(this.converter, this.sink); |
| 38 |
| 39 @override |
| 40 void add(S chunk) { |
| 41 if (!closed) { |
| 42 T convertedChunk = converter.convert(chunk); |
| 43 if (convertedChunk != null) { |
| 44 sink.add(convertedChunk); |
| 45 } |
| 46 } |
| 47 } |
| 48 |
| 49 @override |
| 50 void close() { |
| 51 closed = true; |
| 52 sink.close(); |
| 53 } |
| 54 } |
| 55 |
| 56 /** |
| 14 * The abstract class [ClientCommunicationChannel] defines the behavior of | 57 * The abstract class [ClientCommunicationChannel] defines the behavior of |
| 15 * objects that allow a client to send [Request]s to an [AnalysisServer] and to | 58 * objects that allow a client to send [Request]s to an [AnalysisServer] and to |
| 16 * receive both [Response]s and [Notification]s. | 59 * receive both [Response]s and [Notification]s. |
| 17 */ | 60 */ |
| 18 abstract class ClientCommunicationChannel { | 61 abstract class ClientCommunicationChannel { |
| 19 /** | 62 /** |
| 20 * The stream of notifications from the server. | 63 * The stream of notifications from the server. |
| 21 */ | 64 */ |
| 22 Stream<Notification> notificationStream; | 65 Stream<Notification> notificationStream; |
| 23 | 66 |
| 24 /** | 67 /** |
| 25 * The stream of responses from the server. | 68 * The stream of responses from the server. |
| 26 */ | 69 */ |
| 27 Stream<Response> responseStream; | 70 Stream<Response> responseStream; |
| 28 | 71 |
| 29 /** | 72 /** |
| 73 * Close the channel to the server. Once called, all future communication |
| 74 * with the server via [sendRequest] will silently be ignored. |
| 75 */ |
| 76 Future close(); |
| 77 |
| 78 /** |
| 30 * Send the given [request] to the server | 79 * Send the given [request] to the server |
| 31 * and return a future with the associated [Response]. | 80 * and return a future with the associated [Response]. |
| 32 */ | 81 */ |
| 33 Future<Response> sendRequest(Request request); | 82 Future<Response> sendRequest(Request request); |
| 34 | |
| 35 /** | |
| 36 * Close the channel to the server. Once called, all future communication | |
| 37 * with the server via [sendRequest] will silently be ignored. | |
| 38 */ | |
| 39 Future close(); | |
| 40 } | 83 } |
| 41 | 84 |
| 42 /** | 85 /** |
| 43 * The abstract class [ServerCommunicationChannel] defines the behavior of | |
| 44 * objects that allow an [AnalysisServer] to receive [Request]s and to return | |
| 45 * both [Response]s and [Notification]s. | |
| 46 */ | |
| 47 abstract class ServerCommunicationChannel { | |
| 48 /** | |
| 49 * A stopwatch used to accumulate the amount of time spent converting | |
| 50 * incomming requests from Json to objects. | |
| 51 */ | |
| 52 static final CountedStopwatch FromJson = new CountedStopwatch(); | |
| 53 | |
| 54 /** | |
| 55 * A stopwatch used to accumulate the amount of time spent converting outgoing | |
| 56 * responses and notifications from objects to Json. | |
| 57 */ | |
| 58 static final CountedStopwatch ToJson = new CountedStopwatch(); | |
| 59 | |
| 60 /** | |
| 61 * Listen to the channel for requests. If a request is received, invoke the | |
| 62 * [onRequest] function. If an error is encountered while trying to read from | |
| 63 * the socket, invoke the [onError] function. If the socket is closed by the | |
| 64 * client, invoke the [onDone] function. | |
| 65 * Only one listener is allowed per channel. | |
| 66 */ | |
| 67 void listen(void onRequest(Request request), {Function onError, void onDone()}
); | |
| 68 | |
| 69 /** | |
| 70 * Send the given [notification] to the client. | |
| 71 */ | |
| 72 void sendNotification(Notification notification); | |
| 73 | |
| 74 /** | |
| 75 * Send the given [response] to the client. | |
| 76 */ | |
| 77 void sendResponse(Response response); | |
| 78 | |
| 79 /** | |
| 80 * Close the communication channel. | |
| 81 */ | |
| 82 void close(); | |
| 83 } | |
| 84 | |
| 85 /** | |
| 86 * Instances of the class [JsonStreamDecoder] convert JSON strings to JSON | 86 * Instances of the class [JsonStreamDecoder] convert JSON strings to JSON |
| 87 * maps. | 87 * maps. |
| 88 */ | 88 */ |
| 89 class JsonStreamDecoder extends Converter<String, Map> { | 89 class JsonStreamDecoder extends Converter<String, Map> { |
| 90 @override | 90 @override |
| 91 Map convert(String text) => JSON.decode(text); | 91 Map convert(String text) => JSON.decode(text); |
| 92 | 92 |
| 93 @override | 93 @override |
| 94 ChunkedConversionSink startChunkedConversion(Sink sink) => | 94 ChunkedConversionSink startChunkedConversion(Sink sink) => |
| 95 new ChannelChunkSink<String, Map>(this, sink); | 95 new ChannelChunkSink<String, Map>(this, sink); |
| 96 } | 96 } |
| 97 | 97 |
| 98 /** | 98 /** |
| 99 * Instances of the class [ResponseConverter] convert JSON maps to [Response]s. | |
| 100 */ | |
| 101 class ResponseConverter extends Converter<Map, Response> { | |
| 102 @override | |
| 103 Response convert(Map json) => new Response.fromJson(json); | |
| 104 | |
| 105 @override | |
| 106 ChunkedConversionSink startChunkedConversion(Sink sink) => | |
| 107 new ChannelChunkSink<Map, Response>(this, sink); | |
| 108 } | |
| 109 | |
| 110 /** | |
| 111 * Instances of the class [NotificationConverter] convert JSON maps to | 99 * Instances of the class [NotificationConverter] convert JSON maps to |
| 112 * [Notification]s. | 100 * [Notification]s. |
| 113 */ | 101 */ |
| 114 class NotificationConverter extends Converter<Map, Notification> { | 102 class NotificationConverter extends Converter<Map, Notification> { |
| 115 @override | 103 @override |
| 116 Notification convert(Map json) => new Notification.fromJson(json); | 104 Notification convert(Map json) => new Notification.fromJson(json); |
| 117 | 105 |
| 118 @override | 106 @override |
| 119 ChunkedConversionSink startChunkedConversion(Sink sink) => | 107 ChunkedConversionSink startChunkedConversion(Sink sink) => |
| 120 new ChannelChunkSink<Map, Notification>(this, sink); | 108 new ChannelChunkSink<Map, Notification>(this, sink); |
| 121 } | 109 } |
| 122 | 110 |
| 123 /** | 111 /** |
| 124 * Instances of the class [ChannelChunkSink] uses a [Converter] to translate | 112 * Instances of the class [ResponseConverter] convert JSON maps to [Response]s. |
| 125 * chunks. | |
| 126 */ | 113 */ |
| 127 class ChannelChunkSink<S, T> extends ChunkedConversionSink<S> { | 114 class ResponseConverter extends Converter<Map, Response> { |
| 115 @override |
| 116 Response convert(Map json) => new Response.fromJson(json); |
| 117 |
| 118 @override |
| 119 ChunkedConversionSink startChunkedConversion(Sink sink) => |
| 120 new ChannelChunkSink<Map, Response>(this, sink); |
| 121 } |
| 122 |
| 123 /** |
| 124 * The abstract class [ServerCommunicationChannel] defines the behavior of |
| 125 * objects that allow an [AnalysisServer] to receive [Request]s and to return |
| 126 * both [Response]s and [Notification]s. |
| 127 */ |
| 128 abstract class ServerCommunicationChannel { |
| 128 /** | 129 /** |
| 129 * The converter used to translate chunks. | 130 * A stopwatch used to accumulate the amount of time spent converting |
| 131 * incomming requests from Json to objects. |
| 130 */ | 132 */ |
| 131 final Converter<S, T> converter; | 133 static final CountedStopwatch FromJson = new CountedStopwatch(); |
| 132 | 134 |
| 133 /** | 135 /** |
| 134 * The sink to which the converted chunks are added. | 136 * A stopwatch used to accumulate the amount of time spent converting outgoing |
| 137 * responses and notifications from objects to Json. |
| 135 */ | 138 */ |
| 136 final Sink sink; | 139 static final CountedStopwatch ToJson = new CountedStopwatch(); |
| 137 | 140 |
| 138 /** | 141 /** |
| 139 * A flag indicating whether the sink has been closed. | 142 * Close the communication channel. |
| 140 */ | 143 */ |
| 141 bool closed = false; | 144 void close(); |
| 142 | 145 |
| 143 /** | 146 /** |
| 144 * Initialize a newly create sink to use the given [converter] to convert | 147 * Listen to the channel for requests. If a request is received, invoke the |
| 145 * chunks before adding them to the given [sink]. | 148 * [onRequest] function. If an error is encountered while trying to read from |
| 149 * the socket, invoke the [onError] function. If the socket is closed by the |
| 150 * client, invoke the [onDone] function. |
| 151 * Only one listener is allowed per channel. |
| 146 */ | 152 */ |
| 147 ChannelChunkSink(this.converter, this.sink); | 153 void listen(void onRequest(Request request), {Function onError, void |
| 154 onDone()}); |
| 148 | 155 |
| 149 @override | 156 /** |
| 150 void add(S chunk) { | 157 * Send the given [notification] to the client. |
| 151 if (!closed) { | 158 */ |
| 152 T convertedChunk = converter.convert(chunk); | 159 void sendNotification(Notification notification); |
| 153 if (convertedChunk != null) { | |
| 154 sink.add(convertedChunk); | |
| 155 } | |
| 156 } | |
| 157 } | |
| 158 | 160 |
| 159 @override | 161 /** |
| 160 void close() { | 162 * Send the given [response] to the client. |
| 161 closed = true; | 163 */ |
| 162 sink.close(); | 164 void sendResponse(Response response); |
| 163 } | |
| 164 } | 165 } |
| OLD | NEW |