KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > dyade > aaa > agent > Message


1 /*
2  * Copyright (C) 2001 - 2006 ScalAgent Distributed Technologies
3  * Copyright (C) 1996 - 2000 BULL
4  * Copyright (C) 1996 - 2000 INRIA
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA.
20  */

21 package fr.dyade.aaa.agent;
22
23 import java.io.*;
24 import java.util.Date JavaDoc;
25
26 import org.objectweb.util.monolog.api.BasicLevel;
27 import org.objectweb.util.monolog.api.Logger;
28
29 import fr.dyade.aaa.util.*;
30
31 /**
32  * The internal message structure.
33  * A message is divided in 2 parts:<ul>
34  * <li>An immutable part with source and destination agent unique id, and
35  * notification object.
36  * <li>A variable part containing information about message routing (next hop)
37  * and the current stamp of the message.
38  * </ul>
39  */

40 final class Message implements Serializable {
41   static final long serialVersionUID = -2179939607085028300L;
42
43   /** <code>AgentId</code> of sender. */
44   transient AgentId from;
45   /** <code>AgentId</code> of destination agent. */
46   transient AgentId to;
47   /** The notification. */
48   transient Notification not;
49
50   /** The unique id. of source server */
51   transient short source;
52   /** The unique id. of destination server*/
53   transient short dest;
54   /** The current stamp of the message */
55   transient int stamp;
56
57   /** Get the unique server id. of the sender of this message */
58   short getSource() {
59     return source;
60   }
61  
62   /** Get the unique server id. of the addressee of this message */
63   short getDest() {
64     return dest;
65   }
66
67   /** Get the stamp of this message */
68   int getStamp() {
69     return stamp;
70   }
71
72   /**
73    * Returns a string representation for this object.
74    *
75    * @return A string representation of this object.
76    */

77   public String JavaDoc toString() {
78     return appendToString(new StringBuffer JavaDoc()).toString();
79   }
80
81   /**
82    * Adds a string representation for this object in the
83    * StringBuffer parameter.
84    *
85    * @return A string representation of this object.
86    */

87   public StringBuffer JavaDoc appendToString(StringBuffer JavaDoc strbuf) {
88     strbuf.append('(').append(super.toString());
89     strbuf.append(",from=").append(from);
90     strbuf.append(",to=").append(to);
91     strbuf.append(",not=").append(not);
92     strbuf.append(",source=").append(source);
93     strbuf.append(",dest=").append(dest);
94     strbuf.append(",stamp=").append(stamp);
95     strbuf.append(')');
96     
97     return strbuf;
98   }
99
100   final static int LENGTH = 25;
101
102   final static int PERSISTENT = 0x01;
103   final static int DETACHABLE = 0x10;
104
105   transient private byte iobuf[] = new byte [LENGTH];
106
107   /**
108    * The writeObject method is responsible for writing the state of the
109    * object for its particular class so that the corresponding readObject
110    * method can restore it.
111    * Be careful this method should only be used for saving messages in
112    * persistent storage, sending messages will be done by another way.
113    */

114   private void writeObject(java.io.ObjectOutputStream JavaDoc out)
115        throws IOException {
116     int idx = writeToBuf(iobuf, 0);
117
118     // Writes notification attributes
119
iobuf[idx++] = (byte) ((not.persistent?PERSISTENT:0) |
120                            (not.detachable?DETACHABLE:0));
121
122     // Writes data on stream
123
out.write(iobuf, 0, LENGTH);
124     
125     if (! not.detachable) {
126       // Writes notification object
127
out.writeObject(not);
128     }
129   }
130
131   /**
132    * Write the Message internal state to the buffer.
133    */

134   int writeToBuf(byte[] buf, int idx) {
135       // Writes sender's AgentId
136
buf[idx++] = (byte) (from.from >>> 8);
137     buf[idx++] = (byte) (from.from >>> 0);
138     buf[idx++] = (byte) (from.to >>> 8);
139     buf[idx++] = (byte) (from.to >>> 0);
140     buf[idx++] = (byte) (from.stamp >>> 24);
141     buf[idx++] = (byte) (from.stamp >>> 16);
142     buf[idx++] = (byte) (from.stamp >>> 8);
143     buf[idx++] = (byte) (from.stamp >>> 0);
144     // Writes adressee's AgentId
145
buf[idx++] = (byte) (to.from >>> 8);
146     buf[idx++] = (byte) (to.from >>> 0);
147     buf[idx++] = (byte) (to.to >>> 8);
148     buf[idx++] = (byte) (to.to >>> 0);
149     buf[idx++] = (byte) (to.stamp >>> 24);
150     buf[idx++] = (byte) (to.stamp >>> 16);
151     buf[idx++] = (byte) (to.stamp >>> 8);
152     buf[idx++] = (byte) (to.stamp >>> 0);
153     // Writes source server id of message
154
buf[idx++] = (byte) (source >>> 8);
155     buf[idx++] = (byte) (source >>> 0);
156     // Writes destination server id of message
157
buf[idx++] = (byte) (dest >>> 8);
158     buf[idx++] = (byte) (dest >>> 0);
159     // Writes stamp of message
160
buf[idx++] = (byte) (stamp >>> 24);
161     buf[idx++] = (byte) (stamp >>> 16);
162     buf[idx++] = (byte) (stamp >>> 8);
163     buf[idx++] = (byte) (stamp >>> 0);
164
165     return idx;
166   }
167
168   /**
169    * The readObject method is responsible for reading from the stream and
170    * restoring the classes fields.
171    * Be careful this method should only be used for restoring messages from
172    * persistent storage, receiving messages will be done by another way.
173    */

174   private void readObject(java.io.ObjectInputStream JavaDoc in)
175        throws IOException, ClassNotFoundException JavaDoc {
176     iobuf = new byte[25];
177     in.readFully(iobuf, 0, 25);
178
179     int idx = readFromBuf(iobuf, 0);
180
181     // Reads notification attributes
182
boolean persistent = ((iobuf[idx] & PERSISTENT) == 0)?false:true;
183     boolean detachable = ((iobuf[idx] & DETACHABLE) == 0)?false:true;
184
185     if (! detachable) {
186       // Reads notification object
187
not = (Notification) in.readObject();
188       not.detachable = false;
189       not.detached = false;
190     }
191   }
192
193   int readFromBuf(byte[] buf, int idx) {
194     // Reads sender's AgentId
195
from = new AgentId(
196       (short) (((buf[idx++] & 0xFF) << 8) + (buf[idx++] & 0xFF)),
197       (short) (((buf[idx++] & 0xFF) << 8) + (buf[idx++] & 0xFF)),
198       ((buf[idx++] & 0xFF) << 24) + ((buf[idx++] & 0xFF) << 16) +
199       ((buf[idx++] & 0xFF) << 8) + ((buf[idx++] & 0xFF) << 0));
200     // Reads adressee's AgentId
201
to = new AgentId(
202       (short) (((buf[idx++] & 0xFF) << 8) + (buf[idx++] & 0xFF)),
203       (short) (((buf[idx++] & 0xFF) << 8) + (buf[idx++] & 0xFF)),
204       ((buf[idx++] & 0xFF) << 24) + ((buf[idx++] & 0xFF) << 16) +
205       ((buf[idx++] & 0xFF) << 8) + ((buf[idx++] & 0xFF) << 0));
206     // Reads source server id of message
207
source = (short) (((buf[idx++] & 0xFF) << 8) +
208                       ((buf[idx++] & 0xFF) << 0));
209     // Reads destination server id of message
210
dest = (short) (((buf[idx++] & 0xFF) << 8) +
211                     ((buf[idx++] & 0xFF) << 0));
212     // Reads stamp of message
213
stamp = ((buf[idx++] & 0xFF) << 24) + ((buf[idx++] & 0xFF) << 16) +
214       ((buf[idx++] & 0xFF) << 8) + ((buf[idx++] & 0xFF) << 0);
215
216     return idx;
217   }
218
219   transient private String JavaDoc stringId = null;
220
221   final String JavaDoc toStringId() {
222     if (stringId == null) {
223       stringId = StringId.toStringId('@', '_', dest, stamp, -1);
224     }
225     return stringId;
226   }
227
228
229   /**
230    * Tests if the associated notification is persistent or not.
231    *
232    * @return true if the associated notification is persistent.
233    */

234   boolean isPersistent() {
235     return ((not != null) && not.persistent);
236   }
237
238   /**
239    * Saves the object state on persistent storage.
240    */

241   void save() throws IOException {
242     if (isPersistent()) {
243       AgentServer.getTransaction().save(this, toStringId());
244       if (not.detachable) {
245         not.messageId = StringId.toStringId('N', '_', dest, stamp, -1);
246         AgentServer.getTransaction().save(not, not.messageId);
247       }
248     }
249   }
250
251   /**
252    * Restores the object state from the persistent storage.
253    *
254    * @exception IOException
255    * when accessing the stored image
256    * @exception ClassNotFoundException
257    * if the stored image class may not be found
258    */

259   static Message
260   load(String JavaDoc name) throws IOException, ClassNotFoundException JavaDoc {
261     Message msg = (Message) AgentServer.getTransaction().load(name);
262     if (msg.not == null) {
263       String JavaDoc messageId = StringId.toStringId('N', '_', msg.dest, msg.stamp, -1);
264       msg.not = (Notification) AgentServer.getTransaction().load(messageId);
265       msg.not.messageId = messageId;
266       msg.not.detachable = true;
267       msg.not.detached = false;
268     }
269     msg.not.persistent = true;
270
271     return msg;
272   }
273
274   /**
275    * Deletes the current object in persistent storage.
276    */

277   void delete() throws IOException {
278     if (isPersistent()) {
279       AgentServer.getTransaction().delete(toStringId());
280       if (not.detachable && ! not.detached) {
281         // The Notification is not stored with message, and it is not detached
282
// so it may be deleted individually.
283
AgentServer.getTransaction().delete(not.getMessageId());
284       }
285     }
286   }
287
288   /**
289    * Construct a new message.
290    */

291   private Message() {}
292
293   private static Pool pool = null;
294
295   static {
296     int size = Integer.getInteger("fr.dyade.aaa.agent.Message$Pool.size", 150).intValue();
297     pool = new Pool("Message", size);
298   }
299
300   /**
301    * Allocates a message from the pool.
302    */

303   static Message alloc() {
304     Message msg = null;
305     
306     try {
307       msg = (Message) pool.allocElement();
308     } catch (Exception JavaDoc exc) {
309       return new Message();
310     }
311     return msg;
312   }
313
314   /**
315    * Allocates a message from the pool.
316    *
317    * @param from id of source Agent.
318    * @param to id of destination Agent.
319    * @param not Notification to be signaled.
320    */

321   static Message alloc(AgentId from, AgentId to, Notification not) {
322     Message msg = alloc();
323     msg.set(from, to, not);
324     return msg;
325   }
326
327   /**
328    * Frees the message to the pool.
329    */

330   void free() {
331     not = null; /* to let gc do its work */
332     stringId = null;
333     pool.freeElement(this);
334   }
335   
336   private void set(AgentId from, AgentId to, Notification not) {
337     this.from = (AgentId) from;
338     this.to = (AgentId) to;
339     if (not != null) {
340       this.not = (Notification) not.clone();
341       this.not.detached = not.detached;
342       this.not.messageId = not.messageId;
343     }
344   }
345 }
346
Popular Tags