* Filters/FilterPackage.cs, Filters/FilterRPM.cs,
[beagle.git] / BeagleClient / Message.cs
blob7e2fb17c151e5659df4282a5f0d9b43e45b7fae0
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 //Logger.Log.Debug ("Sending message");
170 ResponseMessage resp = client.Send (this);
171 //Logger.Log.Debug ("Got reply");
172 client.Close ();
173 //Logger.Log.Debug ("Closed client");
175 // Add some nice syntactic sugar by throwing an
176 // exception if the response is an error.
177 ErrorResponse err = resp as ErrorResponse;
179 if (err != null)
180 throw new ResponseMessageException (err);
182 return resp;
187 public abstract class RequestMessageExecutor {
188 public delegate void AsyncResponse (ResponseMessage response);
189 public event AsyncResponse AsyncResponseEvent;
191 public abstract ResponseMessage Execute (RequestMessage req);
193 protected void SendAsyncResponse (ResponseMessage response)
195 if (this.AsyncResponseEvent != null)
196 this.AsyncResponseEvent (response);
199 // Really only worth overriding if the request is a keepalive
200 public virtual void Cleanup () { }
203 [AttributeUsage (AttributeTargets.Class)]
204 public class RequestMessageAttribute : Attribute {
205 private Type message_type;
207 public RequestMessageAttribute (Type message_type)
209 this.message_type = message_type;
212 public Type MessageType {
213 get { return this.message_type; }
217 public class ResponseWrapper {
218 public ResponseMessage Message;
220 // Needed by the XmlSerializer for deserialization
221 public ResponseWrapper () { }
223 public ResponseWrapper (ResponseMessage response)
225 this.Message = response;
229 public abstract class ResponseMessage : Message {
230 private static Type[] response_types = null;
231 private static object type_lock = new object ();
233 public static Type[] Types {
234 get {
235 lock (type_lock) {
236 if (response_types == null)
237 response_types = GetTypes (typeof (ResponseMessage));
240 return response_types;
245 public class EmptyResponse : ResponseMessage { }
247 public class ErrorResponse : ResponseMessage {
248 public string Message;
249 public string Details;
251 // Needed by the XmlSerializer for deserialization
252 public ErrorResponse () { }
254 public ErrorResponse (Exception e)
256 this.Message = e.Message;
257 this.Details = e.ToString ();
260 public ErrorResponse (string message)
262 this.Message = message;
266 public class ResponseMessageException : Exception {
268 private string details;
270 internal ResponseMessageException (ErrorResponse response) : base (response.Message)
272 details = response.Details;
275 internal ResponseMessageException (Exception e) : base (e.Message, e) { }
277 public override string ToString ()
279 if (details != null) {
280 StringBuilder sb = new StringBuilder ();
282 sb.AppendFormat ("{0}: {1}\n", this.GetType (), this.Message);
283 sb.Append (this.details);
285 return sb.ToString ();
286 } else
287 return base.ToString ();