KickJava   Java API By Example, From Geeks To Geeks.

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


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  * Initial developer(s): Dyade
22  * Contributor(s): ScalAgent Distributed Technologies
23  */

24 package fr.dyade.aaa.agent;
25
26 import java.io.*;
27 import fr.dyade.aaa.util.*;
28
29 /**
30  * <code>AgentIdStamp</code> class defines static members, variable and
31  * functions, to manage the allocation of new identifiers. It locally
32  * maintains a pair of counters, one for local agent server, one for remote
33  * agent server, keeping track of the last allocated stamp for the given
34  * target domain. Stamps are allocated in growing order and are never reused
35  * once allocated, even after agents are deleted.<p><hr>
36  * Some initial stamps are reserved for statically identifying system and
37  * well known services as factory. They are defined in <code>AgentId</code>
38  * class.
39  */

40 final class AgentIdStamp implements Serializable {
41   /** Static reference to local <code>AgentIdStamp</code> object. */
42   static AgentIdStamp stamp = null;
43
44   /** Stamp counter for local agent server. */
45   private int local;
46   /** Stamp counter for remote agent server. */
47   private int remote;
48
49   /**
50    * Initializes <code>AgentIdStamp</code> classe.
51    *
52    * @exception IOException IO problem during loading.
53    * @exception ClassNotFoundException should never happened
54    */

55   static void init()
56     throws IOException, ClassNotFoundException JavaDoc {
57     stamp = load();
58     if (stamp == null) {
59       stamp = new AgentIdStamp();
60       stamp.save();
61     }
62   }
63
64   AgentIdStamp() {
65     local = AgentId.MaxIdStamp;
66     remote = AgentId.MaxIdStamp;
67   }
68
69   /**
70    * Saves the object state on persistent storage.
71    */

72   void save() throws IOException {
73     AgentServer.getTransaction().save(this, "AgentIdStamp");
74   }
75
76   /**
77    * Restores the object state from the persistent storage.
78    */

79   static AgentIdStamp
80   load() throws IOException, ClassNotFoundException JavaDoc {
81     return (AgentIdStamp) AgentServer.getTransaction().load("AgentIdStamp");
82   }
83
84   /**
85    * The <code>writeObject</code> method is responsible for writing the
86    * state of the object for its particular class so that the corresponding
87    * <code>readObject</code> method can restore it.
88    *
89    * @param out the underlying output stream.
90    */

91   private void writeObject(java.io.ObjectOutputStream JavaDoc out)
92        throws IOException {
93     out.writeInt(local);
94     out.writeInt(remote);
95   }
96
97   /**
98    * The <code>readObject</code> is responsible for reading from the stream
99    * and restoring the classes fields.
100    *
101    * @param in the underlying input stream.
102    */

103   private void readObject(java.io.ObjectInputStream JavaDoc in)
104       throws IOException, ClassNotFoundException JavaDoc {
105     local = in.readInt();
106     remote = in.readInt();
107   }
108
109   /**
110    * Allocates a new stamp for the target agent server.
111    *
112    * @param to The target agent server
113    */

114   synchronized int newStamp(short to) throws IOException {
115     int current = (to == AgentServer.getServerId())?(++local):(++remote);
116     save();
117     return current;
118   }
119 }
120
121 /**
122  * An <code>AgentId</code> allows for uniquely identifying and localizing
123  * an agent throughout the distributed system. It defines variable members
124  * describing the identifier and all needed function members to manipulate
125  * the structure (creation, serialization, etc).
126  * <p><hr>
127  * However before describing the structure of an AgentId we must take into
128  * account a second requirement: an agent may be created onto a remote agent
129  * server, and the creating entity needs to know the new identifier created
130  * for that agent. As agents live in an asynchronous world it is not so easy
131  * to get back the identifier from the remote server. We decided instead to
132  * make the creating entity responsible for creating the identifier.<p>
133  * The two requirements are then:
134  * <ul>
135  * <li>static localization of agents to allow the system to forward
136  * notifications ;
137  * <li>local generation of identifiers for remote agents.
138  * </ul><hr>
139  * The AgentId is then built of three parts:
140  * <ul>
141  * <li>the identification of the agent server hosting the creating agent
142  * (from field),
143  * <li>the identification of the agent server hosting the created agent
144  * (to field),
145  * <li>a stamp, local to the agent server hosting the creating agent (stamp
146  * field) ; see <a HREF="AgentIdStamp.html">AgentIdStamp</a> class.
147  * </ul>
148  * The three fields form the unique global identifier of the agent, that is
149  * two agents may share a common stamp, as long as their from or to fields
150  * differ. The to field identifies the agent server hosting the agent, so it
151  * is used by the channel to forward notifications to the agent.<p>
152  *
153  * @see AgentIdStamp
154  */

155 public final class AgentId implements Serializable {
156   static final long serialVersionUID = -5096976989176739863L;
157
158   // Declares all fields transient in order to avoid useless
159
// description of each during serialization.
160

161   /** The identification of the agent server hosting the creating agent. */
162   transient short from;
163   /** The identification of the agent server hosting the created agent. */
164   transient short to;
165   /** The stamp, local to the agent server hosting the creating agent. */
166   transient int stamp;
167
168   /**
169    * A temporary string representation of object in order to improve
170    * performances.
171    */

172   transient String JavaDoc str = null;
173
174   /**
175    * The <code>writeObject</code> method is responsible for writing the
176    * state of the object for its particular class so that the corresponding
177    * <code>readObject</code> method can restore it.
178    *
179    * @param out the underlying output stream.
180    */

181   private void writeObject(java.io.ObjectOutputStream JavaDoc out)
182       throws IOException {
183     out.writeShort(from);
184     out.writeShort(to);
185     out.writeInt(stamp);
186   }
187  
188   /**
189    * The <code>readObject</code> is responsible for reading from the stream
190    * and restoring the classes fields.
191    *
192    * @param in the underlying input stream.
193    */

194   private void readObject(java.io.ObjectInputStream JavaDoc in)
195       throws IOException, ClassNotFoundException JavaDoc {
196     from = in.readShort();
197     to = in.readShort();
198     stamp = in.readInt();
199   }
200  
201   // ***** ***** ***** *****
202
// Reserved stamps for system services.
203
// ***** ***** ***** *****
204

205   /** Reserved stamp for NullId. */
206   public static final int NullIdStamp = 0;
207   /** Reserved stamp for factory <code>AgentId</code>. */
208   public static final int FactoryIdStamp = 1;
209   /** Reserved stamp for admin <code>AgentId</code>. */
210   public static final int AdminIdStamp = 2;
211   /** Maximum reserved stamp for system services. */
212   public static final int MaxSystemIdStamp = 2;
213
214   // ***** ***** ***** *****
215
// Reserved stamps for well known services.
216
// ***** ***** ***** *****
217

218   /** Minimum reserved stamp for well known services. */
219   public static int MinWKSIdStamp = MaxSystemIdStamp + 1;
220   /** Reserved stamp for name service <code>AgentId</code>. */
221   public static int NameServiceStamp = 4;
222   /** Reserved stamp for scheduler service <code>AgentId</code>. */
223   public static int SchedulerServiceStamp = 5;
224   /** Reserved stamp for fileTransfert service <code>AgentId</code>. */
225   public static int FileTransfertStamp = 6;
226   /** Reserved stamp for JNDI service <code>AgentId</code>. */
227   public static int JndiServiceStamp = 7;
228   /** Reserved stamp for local JNDI service <code>AgentId</code>. */
229   public static int LocalJndiServiceStamp = 8;
230   /** Reserved stamp for SCAdmin proxy <code>AgentId</code>. */
231   public static int SCAdminProxyStamp = 9;
232   /** Reserved stamp for JORAM administration topic <code>AgentId</code>. */
233   public static int JoramAdminStamp = 10;
234   /** Reserved stamp for JORAM administration proxy <code>AgentId</code>. */
235   public static int JoramAdminPxStamp = 11;
236   /** Reserved stamp for JMS topic <code>AgentId</code> in charge ofsending control events. */
237   public static int ControlTopicStamp = 12;
238   /** Reserved stamp for the server reconfiguration agent <code>AgentId</code> . */
239   public static int ServerConfigStamp = 13;
240   /** Maximum reserved stamp for well known services. */
241   public static int MaxWKSIdStamp = 1024;
242   /** Maximum reserved stamp. */
243   public static int MaxIdStamp = MaxWKSIdStamp;
244
245   // ***** ***** ***** *****
246
// Statically reserved id.
247
// ***** ***** ***** *****
248

249   /** null <code>AgentId</code>. */
250   public final static AgentId nullId = new AgentId((short) 0,
251                            (short) 0,
252                            NullIdStamp);
253   /**
254    * Used by channel to send messages without source agent (from proxy
255    * or engine). The from field does not be nullId because the destination
256    * node use the from.to field to get the from node id.
257    *
258    * @see Engine
259    * @see Channel#sendTo(AgentId, Notification)
260    */

261   static AgentId localId;
262   /**
263    * <code>AgentId</code> for local factory agent.
264    * @see AgentFactory
265    */

266   static AgentId factoryId;
267   /**
268    * <code>AgentId</code> for local admin agent.
269    * @see AgentAdmin
270    */

271   public static AgentId adminId;
272
273   /**
274    * Returns the <code>AgentId</code> for a remote factory agent.
275    *
276    * @param sid remote server id.
277    * @return the <code>AgentId</code> for a remote factory agent.
278    */

279   public final static AgentId factoryId(short sid) {
280     return new AgentId(sid, sid, FactoryIdStamp);
281   }
282
283   public final static AgentId localId(short sid) {
284     return new AgentId(sid, sid, NullIdStamp);
285   }
286
287   /**
288    * Statically initializes <code>AgentId</code> class.
289    */

290   static void init()
291     throws IOException, ClassNotFoundException JavaDoc {
292     // Initialize well known ids
293
localId = new AgentId(AgentServer.getServerId(),
294               AgentServer.getServerId(),
295               NullIdStamp);
296     factoryId = new AgentId(AgentServer.getServerId(),
297                 AgentServer.getServerId(),
298                 FactoryIdStamp);
299     adminId = new AgentId(AgentServer.getServerId(),
300                 AgentServer.getServerId(),
301                 AdminIdStamp);
302     // Initialize stamp values
303
AgentIdStamp.init();
304   }
305
306   /**
307    * Allocates an <code>AgentId</code> object for a new agent hosted by
308    * this agent server.
309    */

310   AgentId() throws IOException {
311     this(AgentServer.getServerId());
312   }
313
314   /**
315    * Allocates an <code>AgentId</code> object for a new agent hosted by
316    * specified agent server.
317    *
318    * @param to The identification of the agent server hosting the agent.
319    */

320   AgentId(short to) throws IOException {
321     this(AgentServer.getServerId(), to, AgentIdStamp.stamp.newStamp(to));
322   }
323
324   /**
325    * Allocates a new <code>AgentId</code> object.
326    *
327    * @param from The identification of the agent server hosting the
328    * creating agent.
329    * @param to The identification of the agent server hosting the agent.
330    * @param stamp The stamp of agent.
331    */

332   public AgentId(short from, short to, int stamp) {
333     this.from = from;
334     this.to = to;
335     this.stamp = stamp;
336   }
337
338   /**
339    *
340    */

341   public final short getFrom() {
342     return from;
343   }
344
345   /**
346    *
347    */

348   public final short getTo() {
349     return to;
350   }
351
352   /**
353    *
354    */

355   public final int getStamp() {
356     return stamp;
357   }
358
359   /**
360    * Parses the string argument as a non signed integer.
361    * The characters in the substring must all be digits.
362    *
363    * @param str the <code>String</code> containing the integer
364    * representation to be parsed.
365    * @param idx the beginning index, inclusive.
366    * @param end the ending index, exclusive.
367    * @return the integer represented by the string argument.
368    * @exception NumberFormatException if the <code>String</code>
369    * does not contain a parsable <code>int</code>.
370    */

371   public static final int parseInt(String JavaDoc str,
372                                    int idx,
373                                    int end) throws NumberFormatException JavaDoc {
374     int result = 0;
375     int digit;
376     int limit = Integer.MAX_VALUE / 10;
377     int digitzero = '0';
378         
379     while (idx < end) {
380       digit = str.charAt(idx++) - digitzero;
381       if ((digit < 0) || (digit > 9))
382         throw new NumberFormatException JavaDoc("bad digit");
383
384       if (result >= limit)
385         throw new NumberFormatException JavaDoc("limit");
386
387       result *= 10;
388       result += digit;
389     }
390
391     return result;
392   }
393
394   /**
395    * Parses the string argument as an <code>AgentId</code>.
396    *
397    * @return The <code>AgentId</code> object represented by the argument.
398    */

399   public static final AgentId fromString(String JavaDoc str) {
400     if (str == null) return null;
401     if (str.charAt(0) != '#')
402       throw new IllegalArgumentException JavaDoc(str + ": bad id");
403
404     try {
405       int start = 1;
406       int end = str.indexOf('.', start);
407       short from = (short) parseInt(str, start, end);
408       start = end +1;
409       end = str.indexOf('.', start);
410       short to = (short) parseInt(str, start, end);
411       start = end +1;
412       end = str.length();
413       int stamp = parseInt(str, start, end);
414
415       return new AgentId(from, to, stamp);
416     } catch (Exception JavaDoc exc) {
417       throw new IllegalArgumentException JavaDoc(str + ": " + exc);
418     }
419   }
420
421   /**
422    * Returns a string representation of this <code>AgentId</code> object.
423    *
424    * @return A string representation of this object.
425    */

426   public final String JavaDoc toString() {
427     if (str == null)
428       str = StringId.toStringId('#', '.', from, to, stamp);
429     return str;
430   }
431
432   /**
433    * Returns a hashcode for this <code>AgentId</code> object.
434    *
435    * @return a hash code value for this object, equal to the primitive
436    * <code>int</code> value represented by the stamp field.
437    */

438   public int hashCode() {
439     return stamp;
440   }
441
442   /**
443    *
444    * @return <code>true</code> if this id is equals to NullId;
445    * <code>false</code> otherwise.
446    */

447   public final boolean isNullId() {
448     return (stamp == NullIdStamp);
449   }
450
451   /**
452    * Indicates whether some other agent id. is "equal to" this one. This method
453    * returns <code>true</code> if and only if obj is an <code>AgentId</code>
454    * and refer to the same agent (from, to and stamp fields are equals).
455    *
456    * @param obj the reference object with which to compare.
457    * @return <code>true</code> if this object is the same as the obj
458    * argument; <code>false</code> otherwise.
459    */

460    public boolean equals(Object JavaDoc obj) {
461     if ((obj instanceof AgentId) &&
462     (((AgentId) obj).from == from) &&
463     (((AgentId) obj).to == to) &&
464     (((AgentId) obj).stamp == stamp)) {
465       return true;
466     } else {
467       return false;
468     }
469   }
470 }
471
Popular Tags