Fix #362058. Check for illegal length in PPT filter.
[beagle.git] / BeagleClient / Message.cs
blob0fad3b2a789056e739595082d7d0bfafcbd1571d
1 //
2 // Message.cs
3 //
4 // Copyright (C) 2005 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.Reflection;
30 using System.Text;
31 using System.Xml.Serialization;
33 using Beagle.Util;
35 namespace Beagle {
37 public abstract class Message {
38 protected static Type[] GetTypes (Type parent_type)
40 ArrayList types = new ArrayList ();
42 foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies ())
43 types.AddRange (ReflectionFu.ScanAssemblyForClass (ass, parent_type));
45 return (Type[]) types.ToArray (typeof (Type));
49 public class RequestWrapper {
50 public RequestMessage Message;
52 // Needed by the XmlSerializer for deserialization
53 public RequestWrapper () { }
55 public RequestWrapper (RequestMessage request)
57 this.Message = request;
61 public abstract class RequestMessage : Message {
62 private static Type[] request_types = null;
63 private static object type_lock = new object ();
65 private Hashtable handlers = new Hashtable ();
66 private string client_name;
67 private Client client;
69 [XmlIgnore]
70 public bool Keepalive;
72 public delegate void AsyncResponseHandler (ResponseMessage response);
74 public delegate void Closed ();
75 public event Closed ClosedEvent;
77 // This is why names arguments (like in python) are a good idea.
79 public RequestMessage (bool keepalive, string client_name)
81 this.Keepalive = keepalive;
82 this.client_name = client_name;
85 public RequestMessage (bool keepalive) : this (keepalive, null)
90 public RequestMessage (string client_name) : this (false, client_name)
95 public RequestMessage () : this (false, null)
100 public static Type[] Types {
101 get {
102 lock (type_lock) {
103 if (request_types == null)
104 request_types = GetTypes (typeof (RequestMessage));
107 return request_types;
111 public void Close ()
113 if (this.client != null)
114 this.client.Close ();
117 public void RegisterAsyncResponseHandler (Type t, AsyncResponseHandler handler)
119 if (!t.IsSubclassOf (typeof (ResponseMessage)))
120 throw new ArgumentException ("Type must be a subclass of ResponsePayload");
122 this.handlers [t] = handler;
125 public void UnregisterAsyncResponseHandler (Type t)
127 if (!t.IsSubclassOf (typeof (ResponseMessage)))
128 throw new ArgumentException ("Type must be a subclass of ResponsePayload");
130 this.handlers.Remove (t);
133 private void OnClosedEvent ()
135 if (this.ClosedEvent != null)
136 this.ClosedEvent ();
139 private void OnAsyncResponse (ResponseMessage response)
141 AsyncResponseHandler async_response = (AsyncResponseHandler) this.handlers [response.GetType ()];
143 if (async_response != null) {
144 async_response (response);
148 public void SendAsync ()
150 if (this.client != null)
151 this.client.Close ();
152 this.client = new Client (this.client_name);
153 this.client.AsyncResponseEvent += OnAsyncResponse;
154 this.client.ClosedEvent += OnClosedEvent;
155 this.client.SendAsync (this);
158 public void SendAsyncBlocking ()
160 this.client = new Client (this.client_name);
161 this.client.AsyncResponseEvent += OnAsyncResponse;
162 this.client.ClosedEvent += OnClosedEvent;
163 this.client.SendAsyncBlocking (this);
166 public ResponseMessage Send ()
168 Client client = new Client (this.client_name);
169 ResponseMessage resp = client.Send (this);
170 client.Close ();
172 // Add some nice syntactic sugar by throwing an
173 // exception if the response is an error.
174 ErrorResponse err = resp as ErrorResponse;
176 if (err != null)
177 throw new ResponseMessageException (err);
179 return resp;
184 public abstract class RequestMessageExecutor {
185 public delegate void AsyncResponse (ResponseMessage response);
186 public event AsyncResponse AsyncResponseEvent;
188 public abstract ResponseMessage Execute (RequestMessage req);
190 protected void SendAsyncResponse (ResponseMessage response)
192 if (this.AsyncResponseEvent != null)
193 this.AsyncResponseEvent (response);
196 // Really only worth overriding if the request is a keepalive
197 public virtual void Cleanup () { }
200 [AttributeUsage (AttributeTargets.Class)]
201 public class RequestMessageAttribute : Attribute {
202 private Type message_type;
204 public RequestMessageAttribute (Type message_type)
206 this.message_type = message_type;
209 public Type MessageType {
210 get { return this.message_type; }
214 public class ResponseWrapper {
215 public ResponseMessage Message;
217 // Needed by the XmlSerializer for deserialization
218 public ResponseWrapper () { }
220 public ResponseWrapper (ResponseMessage response)
222 this.Message = response;
226 public abstract class ResponseMessage : Message {
227 private static Type[] response_types = null;
228 private static object type_lock = new object ();
230 public static Type[] Types {
231 get {
232 lock (type_lock) {
233 if (response_types == null)
234 response_types = GetTypes (typeof (ResponseMessage));
237 return response_types;
242 public class EmptyResponse : ResponseMessage { }
244 public class ErrorResponse : ResponseMessage {
245 public string Message;
246 public string Details;
248 // Needed by the XmlSerializer for deserialization
249 public ErrorResponse () { }
251 public ErrorResponse (Exception e)
253 this.Message = e.Message;
254 this.Details = e.ToString ();
257 public ErrorResponse (string message)
259 this.Message = message;
263 public class ResponseMessageException : Exception {
265 private string details;
267 internal ResponseMessageException (ErrorResponse response) : base (response.Message)
269 Log.Debug ("Creating a ResponseMessageException from an ErrorResponse");
270 details = response.Details;
273 internal ResponseMessageException (Exception e) : base (e.Message, e) { }
275 internal ResponseMessageException (Exception e, string message) : base (message, e) { }
277 internal ResponseMessageException (Exception e, string message, string details) : base (message, e)
279 this.details = details;
282 internal ResponseMessageException (string message) : base (message) { }
284 public override string ToString ()
286 StringBuilder sb = new StringBuilder ();
288 sb.AppendFormat ("{0}: {1}", this.GetType (), this.Message);
290 if (this.details != null)
291 sb.AppendFormat ("\n Details: {0}", this.details);
293 if (this.InnerException != null) {
294 sb.Append ("\n Inner exception: ");
295 sb.Append (this.InnerException.ToString ());
298 return sb.ToString ();