1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package zeus.actors.intrays;
23
24 import zeus.actors.outtrays.*;
25 import java.net.*;
26 import java.io.*;
27 import java.util.*;
28 import zeus.util.*;
29 import zeus.concepts.*;
30 import zeus.actors.*;
31 import zeus.agents.*;
32 import javax.naming.*;
33 import java.net.*;
34 import java.io.*;
35 import java.util.*;
36 import zeus.util.*;
37 import zeus.concepts.*;
38
39 import javax.rmi.*;
40 import java.rmi.*;
41
42
43 /***
44 * Zeus_ACC_Server uses the FIPA_97_Server and FIPA_2000_Server classes to provide
45 * a unified message reception and handleing service.On init this class will create
46 * a FIPA_97_Server and a FIPA_2000_Server, using itself as a parameter.
47 * When either of these intrays receives a message it will call back the appropiate
48 * handle method in this class. The message will then be processed and placed on the
49 * message handleing q in this instance. Finally this message will be handled and processed.
50 * <p>
51 * @author Simon Thompson
52 * @since 1.1
53 */
54 public class Zeus_ACC_Server extends Server implements InTray, FIPA_97_Handler, FIPA_2000_Handler {
55
56 public String hostname = zeus.util.SystemProps.getProperty("HAP_Address");
57
58 /***
59 iiop2000port is used to store the number of the port that the FIPA_2000 IIOP
60 listening service (the server) will use.
61 This is package protected so that subclasses can do as they will!
62 value is set to "2000" by default
63 */
64 protected String iiop2000Port = "2000";
65
66
67 /***
68 * iiop97port is used to store the number of the port that the FIPA_97 IIOP
69 * listening service (the server) will use.
70 * This is package protected so that subclasses can do as they will!
71 * value is set to "1097" by default.
72 */
73 protected String iiop97Port = "1097";
74
75
76 /***
77 httpPort is the number of the port that the FIPA_2000 HTTP service
78 will listenon.
79 This is package protected so that you can fiddle with it in subclasses.
80 value is set to "61000" by default
81 */
82 protected String httpPort = "61000";
83
84
85 /***
86 access to the context object is provided as protected as a convienience for
87 API programmers and future extentions, it is passed to the init() of this class
88 */
89 protected AgentContext context = null;
90
91 private Queue msgQ = new Queue("Zeus_ACC_In");
92 private ZeusParser parser = new ZeusParser();
93
94
95 /***
96 name is set to "ACC" by default
97 */
98 protected String name = "ACC";
99
100 /***
101 twoThousand_Server is the reference to the FIPA_2000_IIOP_Server that
102 this class sets up and runs in it's init().
103 */
104 protected FIPA_2000_IIOP_Server twoThousand_Server = null ;
105
106
107 /***
108 ninetySeven_Server is the reference to the FIPA_97_Server that
109 this class sets up and runs in it's init()
110 */
111 protected FIPA_97_Server ninetySeven_Server = null;
112
113
114 /***
115 httpServer is the reference to the FIPA_2000_HTTP_Server that
116 this class sets up and runs in it's init()
117 */
118 protected FIPA_2000_HTTP_Server httpServer = null;
119
120
121 /***
122 host is protected to allow for interference by putative sub-classes
123 */
124 protected String host = null;
125
126
127 /***
128 class constructor that takes the AgentContext and registers this instance with it,
129 and the MailBox and grabs the reference so that it can be used later. This also sets
130 up the ServerThreads for the message transports that this Server is utilizing.
131 */
132 public Zeus_ACC_Server(AgentContext context, Zeus_ACC_MailBox mbox) {
133 this.mbox = (MailBox) mbox;
134 timeout = 10;
135 Assert.notNull(context);
136 this.context = context;
137 TransportConfig twoIIOPConf = SystemProps.getTransport("FIPA_IIOP_2000");
138 if (twoIIOPConf!=null) {
139 debug("setting iiop 2000 port to : " + twoIIOPConf.getPort());
140 iiop2000Port = twoIIOPConf.getPort(); }
141 TransportConfig twoHTTPConf = SystemProps.getTransport("FIPA_HTTP_2000");
142 if (twoHTTPConf != null) {
143 debug("setting http 2000 port to : " + twoHTTPConf.getPort());
144 httpPort = twoHTTPConf.getPort(); }
145 TransportConfig nineIIOPConf = SystemProps.getTransport("FIPA_IIOP_1997");
146 if (nineIIOPConf != null) {
147 debug("setting iiop 1997 port to : " + nineIIOPConf.getPort());
148 iiop97Port = nineIIOPConf.getPort(); }
149
150 try {
151
152
153 InetAddress ip = InetAddress.getLocalHost();
154 host = ip.getHostAddress();
155 if (hostname == null ) {
156 hostname = host; }
157 twoThousand_Server = new FIPA_2000_IIOP_Server(this,host, iiop2000Port,name,"2000Connection");
158 ninetySeven_Server = new FIPA_97_Server(this,host, iiop97Port,name,"97Connection");
159 httpServer = new FIPA_2000_HTTP_Server(this,host,httpPort,name, "HTTPConnection");
160
161 this.start();
162 this.setName("Zeus_ACC_Server");}
163 catch (Exception e ) {
164
165
166 e.printStackTrace();
167 System.out.println("ERROR - probably localhost cannot be looked up!\n WARNING: attempting to continue, but likely fatal");
168 }
169 }
170
171
172
173 /***
174 stopProcessing will cause the run loop of this class to stop
175 */
176 public void stopProcessing() {
177 processing = false;
178 }
179
180
181 /***
182 This is where the changes were needed. Instead of listening on a stupid socket ;-)
183 we simply look in our message queue to see if any goodies have been put there by nice
184 mr FIPA_97_Connection.
185 */
186 public void run() {
187 processing = true;
188 while (processing) {
189 try {
190 Object obj = this.pop();
191 debug ("popped message off queue");
192 if (obj instanceof String) {
193 String text =(String) obj;
194 debug("message popped is: " + text);
195
196 text = Misc.unescape(text);
197
198
199
200
201 forwardFIPAMessage(text);
202
203 }
204
205 yield();}
206 catch (Exception e ) {
207 e.printStackTrace();
208 System.out.println("exception in ACC server - attempting to recover");
209 }
210 catch (Error er) {
211 er.printStackTrace();
212 System.out.println("error - attempting to recover");
213 }
214 catch (Throwable tr) {
215 tr.printStackTrace();
216 System.out.println("throwable - attempting to recover");
217 }
218 }
219 }
220
221
222 /***
223 * for now the behaviour is :-
224 * get message, <br>
225 * act surprised, <br>
226 * then parse it into a FIPAPerformative, <br>
227 * map that to a Performative, <br>
228 * register self as alias in nameserver,<br>
229 * add alias to FIPAAddressBook, <br>
230 * stamp message with said alias,<br>
231 * assert a messageHandleing rule to invoke forwarding behaviour when
232 * a response is received
233 * send message to Zeus agent, <br
234 * pray.<p>
235 */
236 public void forwardFIPAMessage(String text) {
237 try {
238 debug ("forwarding");
239 FIPA_AddressBook addresses = ((FIPA_AddressBook)context.getAddressBook());
240 FIPAPerformative fmsg = parser.fipaPerformative(text);
241 FIPA_AID_Address fAddress = fmsg.getSender_As_FIPA_AID();
242 fAddress = addresses.checkAddress(fAddress);
243 if (fAddress.getAlias() == null) {
244 registerAlias(fAddress); }
245 Performative msg = fmsg.performative();
246 String alias = fAddress.getAlias();
247 msg.setSender(alias);
248 debug ("setting send address to " + alias);
249 msg.setReplyTo(alias);
250 addresses.add(fAddress);
251 setHandleMessage(fAddress, alias);
252
253 debug("Zeus content = " + msg.getContent());
254 mbox.sendMsg(msg); }
255 catch (Exception e) {
256 try {
257 java.io.File file = new java.io.File("debug.out");
258 java.io.FileOutputStream fileout = new java.io.FileOutputStream(file);
259 java.io.PrintWriter fw= new java.io.PrintWriter(fileout);
260 e.printStackTrace(fw);
261 fw.flush();
262 fw.close();} catch (Exception ne) { ne.printStackTrace(); }
263
264 }
265
266 }
267
268
269 /***
270 * set up a forwarding rule, if one is not already present.
271 */
272 private void setHandleMessage(FIPA_AID_Address faddress, String alias) {
273 if (!faddress.getForwardingRuleSet()) {
274 MsgHandler handler = context.getMsgHandler();
275 String msg_pattern[] = {"receiver",alias};
276 handler.addRule(new MessageRuleImpl(context.newId("Rule"),msg_pattern, this, "forward"));
277 faddress.setForwardingRuleSet(true);
278 }
279 }
280
281
282
283 /***
284 * provides a basic mechanism for getting aliases for agents on other platforms
285 * into the Zeus address space. If this method is called from the ACC agent
286 * stub it can be used to setup zeus names and fipa forwarding in the ANServer and
287 * in the ACC
288 */
289 public void setFIPAAlias(String name, String address) {
290 FIPA_AddressBook addresses = ((FIPA_AddressBook)context.getAddressBook());
291 FIPAPerformative fmsg = parser.fipaPerformative(address);
292 FIPA_AID_Address fAddress = fmsg.getSender_As_FIPA_AID();
293 fAddress = addresses.checkAddress(fAddress);
294 if (fAddress.getAlias() == null){
295 fAddress.setAlias(name);
296 registerAlias(fAddress,name);
297 setHandleMessage(fAddress,name);
298 addresses.add(fAddress);
299 }
300
301
302 }
303
304
305 /***
306 * provides a basic mechanism for getting aliases for agents on other platforms
307 * into the Zeus address space. If this method is called from the ACC agent
308 * stub it can be used to setup zeus names and fipa forwarding in the ANServer and
309 * in the ACC
310 */
311 public void setFIPAAlias(String name, FIPA_AID_Address fAddress) {
312 FIPA_AddressBook addresses = ((FIPA_AddressBook)context.getAddressBook());
313 fAddress = addresses.checkAddress(fAddress);
314 if (fAddress.getAlias() == null) {
315 fAddress.setAlias(name);
316 registerAlias(fAddress,name);
317 setHandleMessage(fAddress,name);
318 addresses.add(fAddress);
319 }
320 }
321
322
323 /***
324 * forward is the method called when the MsgHandler fires a MessageRule that is setup
325 * by the setHandleMessage method.
326 * It converts the Zeus Performative into a FIPA performative, does any address mapping
327 * that is needed and sends the message to the FIPA_postman.
328 */
329 public void forward(Performative perf) {
330 if (perf.getSender().startsWith("Nameserver")) return;
331 if (perf.getSender().startsWith("Facilitator")) return;
332 try {
333 FIPAPerformative fPerf = new FIPAPerformative(perf);
334 FIPA_AddressBook addresses = ((FIPA_AddressBook)context.getAddressBook());
335 String raddr = perf.getReceiver();
336 FIPA_AID_Address faddr = addresses.lookupAlias(raddr);
337 Vector recs = new Vector();
338 recs.addElement(faddr);
339 fPerf.setReceivers(recs);
340 String senderName = perf.getSender();
341
342 InetAddress ip = InetAddress.getLocalHost();
343 String localhost = hostname;
344 FIPA_AID_Address sender = new FIPA_AID_Address("(agent-identifier\n:name " + senderName + "@" + localhost + "\n:addresses (sequence " + getResponseAddress()+"))");
345
346 fPerf.setSender(sender);
347
348 FIPA_PostMan postey =((Zeus_ACC_MailBox) mbox).getFIPA_PostMan();
349 postey.push(fPerf);
350
351 }
352 catch (Exception e) {
353 e.printStackTrace();
354 }
355
356 }
357
358
359
360 /***
361 * send a registration to the nameservers that we are using. <br>
362 * @param sender is the name of the alias to use
363 */
364 protected void registerAlias(FIPA_AID_Address sender) {
365 System.out.println("In register 1");
366 String name = sender.getName()+sender.getHost();
367 AddressBook addressBook = context.getAddressBook();
368 for(int i = 0; i < context.nameservers().size(); i++ ) {
369 String key = sender.setAlias(name);
370 Address addr = (Address)context.nameservers().elementAt(i);
371 addressBook.add(addr);
372 Performative msg = new Performative("request");
373 msg.setReceiver(addr.getName());
374 msg.setReplyWith(key);
375 msg.setContent("register");
376 msg.setSender(key);
377 System.out.println("send message to nameserver");
378 mbox.sendMsg(msg);
379 System.out.println("done message");
380 }
381 }
382
383
384 /***
385 send a registration to the nameservers that we are using. <br>
386 @param sender is the name of the alias to use
387 */
388 protected void registerAlias(FIPA_AID_Address address, String name) {
389 AddressBook addressBook = context.getAddressBook();
390 for(int i = 0; i < context.nameservers().size(); i++ ) {
391 String key = address.setAlias(name);
392 Address addr = (Address)context.nameservers().elementAt(i);
393 addressBook.add(addr);
394 Performative msg = new Performative("request");
395 msg.setReceiver(addr.getName());
396 msg.setReplyWith(key);
397 msg.setContent("register");
398 msg.setSender(key);
399 mbox.sendMsg(msg);
400 }
401 }
402
403
404 /***
405 send a registration to the nameservers that we are using. <br>
406 @param sender is the name of the alias to use
407 */
408 protected void registerAlias(String name) {
409 AddressBook addressBook = context.getAddressBook();
410 for(int i = 0; i < context.nameservers().size(); i++ ) {
411 String key = name;
412 Address addr = (Address)context.nameservers().elementAt(i);
413 addressBook.add(addr);
414 Performative msg = new Performative("request");
415 msg.setReceiver(addr.getName());
416 msg.setReplyWith(key);
417 msg.setContent("register");
418 msg.setSender(key);
419 mbox.sendMsg(msg);
420 }
421 }
422
423
424 /***
425 * registerAgent is functionally identical to registerAlias, but
426 * is semantically slightly different because in the one we are using
427 * the agent name directly, while in the other we are trying to decouple
428 */
429 public void registerAgent(FIPA_AID_Address address, String name) {
430 this.registerAlias(address,name);
431 }
432
433
434 protected void finalize() {
435 try {
436 if ( listenSocket != null ) listenSocket.close();
437 timeout = -1;
438 }
439 catch(IOException e) {
440 }
441 }
442
443
444 public Address getAddress() {
445 return address;
446 }
447
448
449 /***
450 pull something off the ACC message processing queue
451 */
452 public String pop() {
453 return (String) msgQ.dequeue();
454 }
455
456
457 /***
458 * put something onto the ACC message processing queue
459 */
460 public void push(String target) {
461 debug ("enqueueing message ");
462 msgQ.enqueue(target);
463
464 }
465
466
467 /***
468 * handle(String message) is called by the FIPA_97_Server which the init method of the Zeus_ACC_Server
469 * class creates it is used as an interface to unify and collate the information
470 * reception and processing for the ACC agent. <p>
471 * implements the FIPA_97_Handler interface <p>
472 * @param message - the message picked up from the fipa_97 transport
473 */
474 public void handle(String message) {
475
476 push(message);
477 }
478
479
480
481
482 /***
483 * handle (FIPA.FipaMessage aMessage) is called by the FIPA_2000_server that the
484 * init method of this class creates.
485 * implements that FIPA_2000_Handler interface<p>
486 * ISSUES <br>
487 * ------ <br>
488 * Envelopes - what should we do???
489 *
490 * @param aMessage - the message in FIPA 2000 object (java/idl) format
491 * @see FIPA.FipaMessage
492 */
493 public synchronized void handle(FIPA.FipaMessage aMessage) {
494 byte body [] = aMessage.messageBody;
495 String messageStr = new String(body);
496
497 push(messageStr);
498 }
499
500 /***
501 return a string of addresses that this server is listening on
502 */
503 public String getResponseAddress() {
504 String httpAddress = httpServer.getResponseAddress();
505 String iiop2000Address = twoThousand_Server.getResponseAddress();
506 String iiop97Address = ninetySeven_Server.getResponseAddress();
507 String ior2000Address = twoThousand_Server.getIORAddress();
508
509 String addressStr = new String(iiop2000Address +" " + httpAddress );
510
511 return (addressStr);
512
513 }
514
515
516 public void debug(String str) {
517 System.out.println ("Zeus ACC server>> " + str);
518 }
519
520
521 }