View Javadoc

1   /*
2       Zsh -The Zeus Shell, a container for running more than one Zeus agent in a JVM, or for running
3       large numbers of Zeus agents with similar names. 
4       
5   Copyright (C) 2000 Chris Van Buskirk
6   
7   This library is free software; you can redistribute it and/or
8       modify it under the terms of the GNU Lesser General Public
9       License as published by the Free Software Foundation; either
10      version 2.1 of the License, or (at your option) any later version.
11  
12      This library is distributed in the hope that it will be useful,
13      but WITHOUT ANY WARRANTY; without even the implied warranty of
14      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15      Lesser General Public License for more details.
16  
17      You should have received a copy of the GNU Lesser General Public
18      License along with this library; if not, write to the Free Software
19      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  
21  The full license for this module can be found in the file lgpl.txt
22  
23  This module was originally developed by Chris Van Buskirk.
24  Some additions by Simon Thompson.
25  
26  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
27  */
28  
29  package zsh;
30  import java.io.*;
31  import java.util.*;
32  /***
33   Change Log
34   ----------
35   Simon 24/08/00 - removed the nameserver start from the main loop. 
36   Simon 24/08/00 - added comments to provide Javadoc for users
37   Simon 24/08/00 - changed agent invoker to provide following functionality. 
38                    if an agent is invoked without options invoke a default option string, 
39                    set in the bat file. 
40                    if an agent is invoked with a number after it (agentName <args> <int bottom_range> 
41                    <int top_range>)
42                    then start top_range - bottom_range instances of the agent, and name them using 
43                    the following convention agentNameXX where XX is a number
44                    if an agent is invoked with a number after it (agentName <int bottom_range> 
45                    <int top_range>)
46                    then start top_range - bottom_range instances of the agent, and name them using 
47                    the following convention agentNameXX where XX is a number
48   
49   
50   Issues
51   ------
52   I have a strong feeling that this utiltiy will prove to be a stop-gap before we
53   implement a console that allows the deployment and control of many agents from 
54   one machine over a number of machines. At the moment you have to be on the console of the 
55   machines that you have in your net in order to invoke agents on them. 
56   
57   But, having said that, it is a nice solution to a pressing problem : it sure ain't 
58   broke yet!
59   */
60  
61  /*** {@version 1.0}
62      {@author Christopher P. van Buskirk}
63      {@author Simon Thompson}
64      {@param ontology file}
65      <p>
66      zsh (zeus shell) is a utility for deploying agents within one virtual machine. 
67      Agents in a single virtual machine will run with a far smaller system overhead, 
68      but are obviously more vunerable to system failure - one can bring the others down
69      However, there has been substantial user pressure for this sort of facility in Zeus 
70      and so Chris Van Buskirk wrote the zsh utility to support it. </p>
71      <p> 
72      To run Zsh from a DOS window type <i> zsh your_ontology.ont </i> 
73      in the $zeus_install (where you installed Zeus)
74      directory, or make sure  that $zeus_install is in your path. This will invoke zsh.bat, 
75      which will invoke zsh.</p>
76      <p> {@param ontology} is the name of the ontology file that you want to use for the 
77      agency </p> 
78      <p> 
79      Your prompt should change to <b> 
80      <code> Zeus 0> </code> 
81      <p> 
82      The commands are: <br> 
83      <li> quit : exit Zsh and stop all the agents running in this shell
84      <li> yp : start a Facilitator Agent (provides a yellow pages service for the Utility Agents)
85      <li> help : provides a short help message 
86      <li> viz  : run a Visualiser
87      <li> vis : run a Visualiser
88      <li> <i> AgentName <args> </i> :run a Utility Agent of type AgentName
89      <li> <i> AgentName </i> :run a Utility Agent with the default arguement string set in the Zsh.bat file
90      <li> <i> AgentName <args> - <bottom_range> <top_range> :run top_range-bottom_range copies of the 
91      agent type <i> AgentName </i> each named according to the convention <i> AgentName_XX </i> where 
92      XX is the number of this copy. 
93      <li> <i> AgentName <bottom_range> -range <top_range> :run top_range copies of the 
94      agent type <i> AgentName </i> each named according to the convention <i> AgentName_XX </i> where 
95      XX is the number of this copy. Run the agents with the default parameters read from the Zsh.bat file
96      <li> script : run a script containing commands according to the format given above.
97      <p> After an agent is invoked you should see the number in the command prompt increase as 
98      the shell counts the number of agents that it is running at the moment. 
99  */  
100 
101 
102 public class zsh
103 {
104   static int     numAgents = 0;
105   static String  TIMESLICE = "0.5";
106   static boolean manyAgents = false; 
107   static String visualiser_ont = null; 
108   static String facilitator_ont = null; 
109   static String facilitator_time = null; 
110 
111 /*** 
112     standard main function 
113     */
114   static public void main(String[] arg)
115   {
116     String           buffer;
117     StringTokenizer  parser;
118     String           keyword;
119     String[]         params;
120     BufferedReader   keyboard 
121         = new BufferedReader (new InputStreamReader(System.in));
122     
123     // removed the nameserver auto start - zsh may run 
124     // on many machines and starting the nameserver on each of them 
125     // would be a mistake. 
126    // ns();   // automatically start the name server
127     zsh shell = new zsh(); 
128     if (arg.length>0) {
129         visualiser_ont = arg[0]; 
130         facilitator_ont = arg[0];}
131     if (arg.length>1) {
132         facilitator_time = arg[1]; }
133     while (true)
134     {
135         buffer  = shell.getCommand (keyboard);
136         parser = new StringTokenizer(buffer); 
137         keyword = shell.getKeyword (parser);
138         params  = shell.getParams  (parser);
139         if (!manyAgents) { 
140             shell.doCommand(keyword,params);
141             }
142             else {
143                 shell.runManyAgents(buffer); 
144             }
145        manyAgents = false; 
146     }
147   } //method:  zsh::main()
148 
149 
150    /***
151     method called to run a clutch of agents
152     */
153   public void runManyAgents(String buffer) { 
154      manyAgents = false; 
155      StringTokenizer parser = new StringTokenizer (buffer);
156      String keyword = this.getKeyword(parser); 
157      String [] params = this.getParams(parser);
158      System.out.println (params.length); 
159      parser = new StringTokenizer (buffer); 
160      String bottomRange = this.getBottomRange(parser); 
161      String topRange = this.getTopRange(parser); 
162      if (topRange == null) { 
163         this.runAgents(keyword,params,bottomRange); }
164         else {
165            this.runAgents (keyword,params,bottomRange,topRange); 
166         } 
167    }
168 
169 
170 /***
171     method called to run a number of agents named 0-> {@param numberAgents}
172     */
173     public void runAgents (String agentType, String[] params, String bottomRange, 
174                                 String topRange) { 
175         int numberRequired = Integer.parseInt(topRange)-Integer.parseInt(bottomRange);
176         int startCount = Integer.parseInt(bottomRange);
177         for (int count = 0; count < numberRequired; count++) {                             
178             String agentName = String.valueOf(count+startCount); 
179             doCommand (agentType, agentName, params); }
180     }
181 
182 
183     /***
184         method called to run a number of agents named 0-> {@param numberAgents}
185     */
186     public void runAgents (String agentType, String[] params, String numberAgents) { 
187        int numberRequired = Integer.parseInt(numberAgents);
188        System.out.println (params.length); 
189        for (int count = 0; count < numberRequired; count++) {                             
190             String agentName = String.valueOf(count); 
191             doCommand (agentType, agentName, params); }
192     }
193     
194     
195     protected String getBottomRange (StringTokenizer parser) { 
196         boolean counting = false; 
197         manyAgents = false;
198         int numberParams = parser.countTokens(); 
199         while (parser.hasMoreTokens())
200         {
201             String temp = parser.nextToken(); 
202         if (manyAgents == true) 
203             return temp; 
204         if (temp.equals ("-range")) {
205             manyAgents = true; 
206              }
207         
208         }
209         return (null) ;
210     }
211     
212     
213     /***
214         this method assumes that getBottom range has been called first and so 
215         it will just return the next token on the stream
216         */ 
217     protected String getTopRange (StringTokenizer parser) {
218         if (!parser.hasMoreTokens()) {
219             return null; 
220         }
221         else {
222             return (parser.nextToken()); 
223         }}
224     
225     
226   /*** 
227     get command reads a command from the specified input stream 
228     */
229   protected String getCommand(BufferedReader in)
230   {
231     String           buffer;
232 
233     System.out.print("ZEUS " +numAgents+ "> ");
234     try
235     {
236       buffer = in.readLine(); 
237       if (buffer == null)  {System.out.println();  return null;}
238             return buffer;
239     }
240     catch (IOException e) {return null;}
241 
242   } //method: getComman()
243 
244 
245 
246    /***
247     getKeyword parses out the command from the users input and 
248     returns it as a String 
249     */
250   protected String getKeyword(StringTokenizer parser)
251   {
252     String output;
253 
254     if ((parser==null) || !parser.hasMoreTokens())  
255     {
256       return null;
257     }  
258     else
259     {
260       output = parser.nextToken();
261       //System.out.println(output);
262       return output;
263     }
264   } //method: getKeyword()
265   
266 
267   /***
268     getParams works out what the Zeus parameters are, and separates 
269     them from any zsh specific parameters (ranges). 
270     */ 
271   protected String[] getParams(StringTokenizer parser)
272   {
273     
274     String[] writeArray = new String [parser.countTokens()]; 
275     int count = 0;  
276     boolean counting = false; 
277     int numberParams = writeArray.length; 
278     for (int i=0;  i < numberParams;  i++)
279     {
280         String temp = parser.nextToken(); 
281      
282         if (temp.equals ("-range")) {
283             manyAgents = true; 
284              }
285         if (manyAgents == true) 
286             count ++; 
287             writeArray[i] = temp;
288     }
289     if (count == 0) {
290         return writeArray;
291          }
292         else { 
293             String [] output = new String [numberParams - count];
294             for (int copyCount = 0; copyCount<output.length; copyCount++) { 
295                 output[copyCount] = writeArray[copyCount]; 
296             }
297         return (output); 
298         }
299   }
300 
301 
302 
303  /***
304     doCommand is the business part of the deal. 
305     It's job is to run the command that the user has given. 
306     */
307  protected void doCommand(String command, String[] parameters)
308   {
309     if (command == null)           {System.out.println();   return;}
310     if (command.equals("quit"))    {System.exit(0);                }
311     if (command.equals("help"))    {help();                 return;}
312     if (command.equals("yp"))      {yp();                   return;}
313     if (command.equals("viz"))     {viz();                  return;}
314     if (command.equals("vis"))     {viz();                  return;}
315     if (command.equals("script"))  {script(parameters[0]);  return;}
316     try
317     {
318 
319       //////////////////////////////////////////////
320       // ELSE: fire off the specified agent
321       //////////////////////////////////////////////
322       Class nextClass = Class.forName(command);
323       java.lang.reflect.Method boot = nextClass.getMethod(
324           "main", 
325           new java.lang.Class[]  { java.lang.String[].class }
326       );
327       boot.invoke(
328         nextClass.newInstance(), 
329         new java.lang.Object[] {parameters}
330       );
331        try { 
332           Thread.sleep(100); 
333       }
334       catch (Exception e) {;}
335       numAgents++;
336     }
337 
338 
339 
340 
341     //////////////////////////////////////////////////
342     // Exception Processing
343     //////////////////////////////////////////////////
344     catch (ClassNotFoundException e1) 
345     {
346       System.out.println("ERROR: could not load " +command+ " class");
347     }
348     catch (NoSuchMethodException  e2) 
349     {
350       System.out.println("ERROR: could not find " +command+ "::main()");
351     }
352     catch (java.lang.reflect.InvocationTargetException  e3) 
353     {
354       System.out.println("ERROR: invoking " +command+ "::main()");
355       System.out.println(e3.toString());
356     }
357     catch (java.lang.InstantiationException  e4) 
358     {
359       System.out.println("ERROR: invoking " +command+ "::main()");
360       System.out.println(e4.toString());
361     }
362     catch (java.lang.IllegalAccessException  e5) 
363     {
364       System.out.println("ERROR: invoking " +command+ "::main()");
365       System.out.println(e5.toString());
366     }
367 
368 
369     System.out.println();
370   } //method: doCommand()
371 
372 
373  /***
374     doCommand is the business part of the deal. 
375     It's job is to run the command that the user has given. 
376     */
377  protected void doCommand(String command, String agentName, String[] parameters)
378   {
379     if (command == null)           {System.out.println();   return;}
380     if (command.equals("quit"))    {System.exit(0);                }
381     if (command.equals("help"))    {help();                 return;}
382     if (command.equals("yp"))      {yp();                   return;}
383     if (command.equals("viz"))     {viz();                  return;}
384     if (command.equals("vis"))     {viz();                  return;}
385     if (command.equals("script"))  {script(parameters[0]);  return;}
386     
387     try
388     {
389         System.out.println("in right doCommand"); 
390         String newParams [] = new String [parameters.length +2]; 
391         for (int count = 0; count < parameters.length; count ++) {
392             System.out.println ("copying : " + parameters[count]); 
393             newParams[count] = parameters[count]; 
394         }
395         newParams[parameters.length]= "-name";
396         newParams[parameters.length +1] = agentName; 
397       //////////////////////////////////////////////
398       // ELSE: fire off the specified agent
399       //////////////////////////////////////////////
400       Class nextClass = Class.forName(command);
401       java.lang.reflect.Method boot = nextClass.getMethod(
402           "main", 
403           new java.lang.Class[]  { java.lang.String[].class }
404       );
405       boot.invoke(
406         nextClass.newInstance(),
407         new java.lang.Object[] {newParams}
408       );
409       try { 
410           Thread.sleep(100); 
411       }
412       catch (Exception e) {;}
413       
414 
415       numAgents++;
416     }
417 
418 
419 
420     //////////////////////////////////////////////////
421     // Exception Processing
422     //////////////////////////////////////////////////
423     catch (ClassNotFoundException e1) 
424     {
425       System.out.println("ERROR: could not load " +command+ " class");
426     }
427     catch (NoSuchMethodException  e2) 
428     {
429       System.out.println("ERROR: could not find " +command+ "::main()");
430     }
431     catch (java.lang.reflect.InvocationTargetException  e3) 
432     {
433       System.out.println("ERROR: invoking " +command+ "::main()");
434       System.out.println(e3.toString());
435     }
436     catch (java.lang.InstantiationException  e4) 
437     {
438       System.out.println("ERROR: invoking " +command+ "::main()");
439       System.out.println(e4.toString());
440     }
441     catch (java.lang.IllegalAccessException  e5) 
442     {
443       System.out.println("ERROR: invoking " +command+ "::main()");
444       System.out.println(e5.toString());
445     }
446 
447 
448     System.out.println();
449   } //method: doCommand()
450 
451 
452     /*** 
453     script is used to step through a file and execute the commands 
454     found there in. Modified to support the initialisation of 
455     multiple agents of a particular type. 
456     */
457   protected void script(String fname)
458   {
459     try
460     {
461       BufferedReader scriptFile = new BufferedReader(new FileReader(fname));
462       StringTokenizer  parser;
463       String           keyword;
464       String[]         params;
465       String           buffer;
466       while ((buffer = getCommand (scriptFile)) != null)
467       {
468         parser = new StringTokenizer (buffer); 
469         keyword = getKeyword (parser);
470         params  = getParams  (parser);
471         if (!manyAgents) { 
472             this.doCommand(keyword,params);
473             }
474             else {
475                 this.runManyAgents(buffer); 
476             }
477        manyAgents = false; 
478       }
479     }
480     catch (FileNotFoundException e)
481     {
482       System.out.println("ERROR: opening " +fname+ " script");
483     }
484 
485   }
486 
487 
488 
489   /////////////////////////////////////////////////////////////////////////
490   // Bootstrap the nameserver
491   /////////////////////////////////////////////////////////////////////////
492   static protected void ns()
493   {
494     String[] nsArgs = {
495       "Nameserver1",
496       "-t",  TIMESLICE,
497       "-f",  "dns.db"
498     };
499     zeus.agents.ANServer.main(nsArgs);
500   }
501 
502 
503 
504   /////////////////////////////////////////////////////////////////////////
505   // Bootstrap the facilitator
506   /////////////////////////////////////////////////////////////////////////
507   static protected void yp()
508   {
509     String[] ypArgs = {
510       "Facilitator1",
511       "-o",  facilitator_ont,
512       "-s",  "dns.db",
513       "-t",  facilitator_time
514     };
515     zeus.agents.Facilitator.main(ypArgs);
516     System.out.println();
517   }
518 
519 
520 
521   /////////////////////////////////////////////////////////////////////////
522   // Bootstrap the visualizer
523   /////////////////////////////////////////////////////////////////////////
524   static protected void viz()
525   {
526     String[] vizArgs = {
527       "Visualiser1",
528       "-o",  visualiser_ont,
529       "-s",  "dns.db",
530       "-quick"
531     };
532     zeus.visualiser.Visualiser.main(vizArgs);
533     System.out.println();
534   }
535 
536 
537 
538   /////////////////////////////////////////////////////////////////////////
539   // Help message for the console operator
540   /////////////////////////////////////////////////////////////////////////
541   static protected void help()
542   {
543     System.out.println("USAGE:");
544     System.out.println("======");
545     System.out.println("  help");
546     System.out.println("  yp");
547     System.out.println("  viz");
548     System.out.println("  agent  args");
549     System.out.println("  script filename");
550     System.out.println();
551   } 
552 
553 
554 
555 } //class: ZEUS shell
556 
557 
558