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 |