View Javadoc

1       /*
2        * The contents of this file are subject to the BT "ZEUS" Open Source
3        * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file
4        * except in compliance with the Licence. You may obtain a copy of the Licence
5        * from $ZEUS_INSTALL/licence.html or alternatively from
6        * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7        *
8        * Except as stated in Clause 7 of the Licence, software distributed under the
9        * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or
10       * implied. See the Licence for the specific language governing rights and
11       * limitations under the Licence.
12       *
13       * The Original Code is within the package zeus.*.
14       * The Initial Developer of the Original Code is British Telecommunications
15       * public limited company, whose registered office is at 81 Newgate Street,
16       * London, EC1A 7AJ, England. Portions created by British Telecommunications
17       * public limited company are Copyright 1996-2001. All Rights Reserved.
18       *
19       * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20       */
21  
22  package zeus.actors.factories;
23  
24  //
25  import javax.agent.service.*;
26  import zeus.actors.outtrays.*;
27  import zeus.actors.intrays.*;
28  import java.util.*;
29  import javax.rmi.*;
30  import zeus.concepts.*;
31  import zeus.actors.*;
32  import java.io.*;
33  import fipa97.FIPA_Agent_97;
34  import fipa97.FIPA_Agent_97Helper;
35  import org.omg.CORBA.*;
36  import org.omg.CORBA.portable.*;
37  import org.omg.CosNaming.*;
38  import org.omg.CosNaming.NamingContextPackage.*;
39  import zeus.actors.outtrays.*;
40  import javax.naming.*;
41  import zeus.util.*;
42  import java.io.FileWriter;
43  import java.io.File;
44  
45  
46  
47  
48  /***
49   * IIOP_Z_HTTP_TransportFactory is a simple implementation of the TransportFactory
50   * that takes an address string and returns an appropriate transport for that agent.
51   * <li> if the agent is a zeus agent then a wrapped version
52   * of the standard zeus postman and server is returned. </li>
53   * <li> if the agent is using a FIPA_97 IIOP transport then a wrapped FIPA_Agent_97 is
54   * returned </li>
55   * <li> if the agent is using a FIPA_99 IIOP transport then a wrapped FIPA.MTS is returned
56   * </li>
57   * <li> if any other transport is detected then an error is raised.</li>
58   * <p> Note: we will seek  to support other transports, but it is likely that
59   * this transport factory will not: so basically ensure that you DO NOT directly instantiate this
60   * class. <p>
61   * <B> <u>TO USE THIS</u> </B> <br>
62   * Call zeus.actors.service.TransportFactoryMethod.getTransportFactory(), this will return a class of type
63   * TransportFactory. In the initial implementation it will always be this class, *but*
64   * in the future we may implement lightweightTransportFactory, IIOP_HTTP_TransportFactory
65   * or JMS_TransportFactory, and use a system property to define which one is returned by
66   * the TransportFactoryMethod in a given agent...
67   * <p>
68   * ISSUES </P>
69   * is this at all sensible? Or am I making a mountain out of a mole hill? <br>
70   * need context to make zeus transport
71   * @author Simon Thompson
72   * @since 1.1
73   */
74  
75  public class IIOP_Z_HTTP_TransportFactory implements TransportFactory {
76      
77      private ZeusAgentContext context = null;
78      private int _maxSize = 100;
79      private static ConnectionPool pool = new ConnectionPool();
80      private File file; 
81      
82      public void setContext(ZeusAgentContext context) {
83          this.context = context;
84      }
85      
86      public void setLog (File file) {
87       this.file = file;    
88      }
89      
90      /***
91       * this method returns a transport for this address. having called this
92       * all you need to do to send a message is call Transport.send(Envelope);
93       * <P> HOW IT WORKS <p>
94       * 1) check and see if the address starts with the key word(s) iiop/iiopname
95       * 2) split out the address (name.domain.type) and port (:9000) and use
96       * them to initialise an orb
97       * 3) then churn through the naming contexts that it uses - if an address is
98       * of the form iiop://name.domain.type:9000/xxx/yyy/zzz/acc then this means
99       * that there are three naming contexts (xxx,yyy,zzz) which must be found before
100      * we can get hold of acc.
101      * 4) when we have acc we will know because an ClassCastException will have been
102      * thrown.. so handle it by trying to cast to either FIPA_Agent_97 or FIPA.MTS. If
103      * you can do that then no probs, use the result to initialise a transport object of
104      * the appropriate type and return it.
105      * 5) if no cast works then throw an UnsupportedTransportException
106      * 6) Handle the http: case (throw an Exception)
107      * 7) Otherwise try a Zeus address, and if this works then return
108      * a zeus transport object
109      * <p> ISSUES <p>
110      * This is a bad, bad method: appologies (I am in a hurry and rather up against it
111      * here!). There is far too much code in one block and it is very complex - so
112      * refactor, refactor!
113      *
114      */
115     public OutTray getTransport(String address) throws TransportUnsupportedException {
116         try {
117             //  System.out.println("address at start = " + address);
118             OutTray trans = pool.getConnection(address);
119             return trans;
120         }
121         catch (NotFoundException e) {
122             ;} // rest of method could be in this block, but just irrelevant really.
123         
124         if ( address.startsWith("iiop") || address.startsWith("iiopname")) {
125             // open it, try FIPA_97, if that throws an exception then
126             // try FIPA_99, then go home....
127             StringTokenizer tokens = new StringTokenizer(address,"/");
128             tokens.nextToken();
129             String ofInterest = tokens.nextToken();
130             //  System.out.println("of interest = " + ofInterest);
131             StringTokenizer addressFinder = new StringTokenizer(ofInterest,":");
132             String addr = addressFinder.nextToken(); // should be machine.domain.type
133             //  System.out.println("addr = " + addr);
134             String port = addressFinder.nextToken(); // should be a number
135             //    System.out.println("port = " + port);
136             Properties prop = new Properties();
137             prop.setProperty("org.omg.CORBA.ORBInitialHost",addr);
138             prop.setProperty("org.omg.CORBA.ORBInitialPort",port);
139             String args [] = new String[0];
140             ORB orb = ORB.init(args, prop);
141             org.omg.CORBA.Object objb = null;
142             debug(orb.toString());
143             String list [] = orb.list_initial_services();
144             for (int i = 0; i < list.length; i++) {
145                 debug(list[i]);
146             }
147             try {
148                 org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
149                 NamingContext nc = NamingContextHelper.narrow(objRef);
150                 //testNamingContext (nc,orb);
151                 boolean done = false ;
152                 NameComponent allPath[] = new NameComponent [_maxSize];
153                 int count =0;
154                 String name = null;
155                 while (tokens.hasMoreTokens()) {
156                     name = tokens.nextToken();
157                     debug("name = " + name);
158                 }
159                 objb = resolveNaming(nc,orb,name);
160             }
161             catch (Exception e) {
162                 e.printStackTrace();
163             }
164             
165             try {
166                 debug("objb == " + objb.toString());
167                 FIPA_Agent_97 target =  FIPA_Agent_97Helper.narrow(objb);
168                 
169                 OutTray trans = new FIPA_97_IIOP_Transport(target);
170                 pool.addConnection(address,trans);
171                 return trans;
172             } catch (Exception e) {
173                 // exception is intensional and is handled by then next try
174                 //e.printStackTrace();
175             }
176             
177             try {
178                 debug("objb == " + objb.toString());
179                 FIPA.MTS target = FIPA.MTSHelper.narrow( objb );
180                 
181                 debug("target == " + target.toString());
182                 OutTray trans = new FIPA_2000_IIOP_Transport(target);
183                 pool.addConnection(address,trans);
184                 return trans;
185             } catch (Exception e) {
186                 // exception is intensional and is thrown next...
187                 //e.printStackTrace();
188             }
189             throw new TransportUnsupportedException("iiop target appears not to be returning a object with"+
190             " an interface that is understood by Zeus" +
191             "\n currently we have only FIPA_2000/99 (FIPA.MTS) & FIPA_97 (FIPA_Agent_97)" +
192             "sorry");
193         }
194         else if (address.startsWith("corbaloc")) {
195             address = address.substring(10,address.length());
196             // System.out.println("address = " + address);
197             StringTokenizer tokens = new StringTokenizer(address,"/");
198             String ofInterest = tokens.nextToken();
199             // System.out.println("of interest = " + ofInterest);
200             StringTokenizer addressFinder = new StringTokenizer(ofInterest,":");
201             String addr = addressFinder.nextToken(); // should be machine.domain.type
202             // System.out.println("addr = " + addr);
203             String port = addressFinder.nextToken(); // should be a number
204             //System.out.println("port = " + port);
205             Properties prop = new Properties();
206             prop.setProperty("org.omg.CORBA.ORBInitialHost",addr);
207             prop.setProperty("org.omg.CORBA.ORBInitialPort",port);
208             String args [] = new String[0];
209             ORB orb = ORB.init(args, prop);
210             org.omg.CORBA.Object objb = null;
211             debug(orb.toString());
212             String list [] = orb.list_initial_services();
213             for (int i = 0; i < list.length; i++) {
214                 debug(list[i]);
215             }
216             try {
217                 org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
218                 NamingContext nc = NamingContextHelper.narrow(objRef);
219                 //testNamingContext (nc,orb);
220                 boolean done = false ;
221                 NameComponent allPath[] = new NameComponent [_maxSize];
222                 int count =0;
223                 String name = null;
224                 while (tokens.hasMoreTokens()) {
225                     name = tokens.nextToken();
226                     debug("name = " + name);
227                 }
228                 objb = resolveNaming(nc,orb,name);
229             }
230             catch (Exception e) {
231                 e.printStackTrace();
232             }
233             
234             try {
235                 debug("objb == " + objb.toString());
236                 FIPA_Agent_97 target =  FIPA_Agent_97Helper.narrow(objb);
237                 OutTray trans = new FIPA_97_IIOP_Transport(target);
238                 pool.addConnection("corbaname::"+address,trans);
239                 return trans;
240             } catch (Exception e) {
241                 // exception is intensional and is handled by then next try
242                 //e.printStackTrace();
243             }
244             
245             try {
246                 debug("objb == " + objb.toString());
247                 FIPA.MTS target = FIPA.MTSHelper.narrow( objb );
248                 
249                 debug("target == " + target.toString());
250                 OutTray trans =  new FIPA_2000_IIOP_Transport(target);
251                 //  System.out.println("Setting address");
252                 pool.addConnection("corbaname::"+address,trans);
253                 return trans;
254             } catch (Exception e) {
255                 // exception is intensional and is thrown next...
256                 //e.printStackTrace();
257             }
258             throw new TransportUnsupportedException("iiop target appears not to be returning a object with"+
259             " an interface that is understood by Zeus" +
260             "\n currently we have only FIPA_2000/99 (FIPA.MTS) & FIPA_97 (FIPA_Agent_97)" +
261             "sorry");
262             
263         }
264         else if (address.startsWith("corbaname")) {
265             address = address.substring(11,address.length());
266             // System.out.println("address = " + address);
267             StringTokenizer tokens = new StringTokenizer(address,"/");
268             String ofInterest = tokens.nextToken();
269             // System.out.println("of interest = " + ofInterest);
270             StringTokenizer addressFinder = new StringTokenizer(ofInterest,":");
271             String addr = addressFinder.nextToken(); // should be machine.domain.type
272             // System.out.println("addr = " + addr);
273             String port = addressFinder.nextToken(); // should be a number
274             //System.out.println("port = " + port);
275             Properties prop = new Properties();
276             prop.setProperty("org.omg.CORBA.ORBInitialHost",addr);
277             prop.setProperty("org.omg.CORBA.ORBInitialPort",port);
278             String args [] = new String[0];
279             ORB orb = ORB.init(args, prop);
280             org.omg.CORBA.Object objb = null;
281             debug(orb.toString());
282             String list [] = orb.list_initial_services();
283             for (int i = 0; i < list.length; i++) {
284                 debug(list[i]);
285             }
286             try {
287                 org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
288                 NamingContext nc = NamingContextHelper.narrow(objRef);
289                 //testNamingContext (nc,orb);
290                 boolean done = false ;
291                 NameComponent allPath[] = new NameComponent [_maxSize];
292                 int count =0;
293                 String name = null;
294                 while (tokens.hasMoreTokens()) {
295                     name = tokens.nextToken();
296                     debug("name = " + name);
297                 }
298                 objb = resolveNaming(nc,orb,name);
299             }
300             catch (Exception e) {
301                 e.printStackTrace();
302             }
303             
304             try {
305                 debug("objb == " + objb.toString());
306                 FIPA_Agent_97 target =  FIPA_Agent_97Helper.narrow(objb);
307                 OutTray trans = new FIPA_97_IIOP_Transport(target);
308                 pool.addConnection("corbaname::"+address,trans);
309                 return trans;
310             } catch (Exception e) {
311                 // exception is intensional and is handled by then next try
312                 //e.printStackTrace();
313             }
314             
315             try {
316                 debug("objb == " + objb.toString());
317                 FIPA.MTS target = FIPA.MTSHelper.narrow( objb );
318                 
319                 debug("target == " + target.toString());
320                 OutTray trans =  new FIPA_2000_IIOP_Transport(target);
321                 //  System.out.println("Setting address");
322                 pool.addConnection("corbaname::"+address,trans);
323                 return trans;
324             } catch (Exception e) {
325                 // exception is intensional and is thrown next...
326                 //e.printStackTrace();
327             }
328             throw new TransportUnsupportedException("iiop target appears not to be returning a object with"+
329             " an interface that is understood by Zeus" +
330             "\n currently we have only FIPA_2000/99 (FIPA.MTS) & FIPA_97 (FIPA_Agent_97)" +
331             "sorry");
332             
333         }
334         
335         else if (address.startsWith("IOR")) {
336             Properties prop = new Properties();
337             // prop.setProperty("org.omg.CORBA.ORBInitialHost",addr);
338             //prop.setProperty("org.omg.CORBA.ORBInitialPort",port);
339             String args [] = new String[0];
340             ORB orb = ORB.init(args,null);
341             
342             org.omg.CORBA.Object objb = orb.string_to_object(address);
343             debug("orb = " + objb.toString());
344             FIPA.MTS target = FIPA.MTSHelper.narrow(objb);
345             debug("MTS = " + target.toString());
346             OutTray trans = new FIPA_2000_IIOP_Transport(target);
347             debug("trans = " + trans.toString());
348             pool.addConnection(address,trans);
349             return trans;
350             
351         }
352         else if (address.startsWith("http")) {
353             FIPA_2000_HTTP_Accessor conn = new FIPA_2000_HTTP_Accessor(address);
354             OutTray trans = new FIPA_2000_HTTP_Transport(conn,file);
355             pool.addConnection(address,trans);
356             return (trans);
357             
358         }
359         else {
360             try {
361                 ZeusParser.address(address); // was commented...
362                 OutTray trans = new Zeus_Native_Transport(context);
363                 pool.addConnection(address,trans);
364                 return trans; }
365             catch ( Exception e) {
366                 e.printStackTrace();
367                 throw new TransportUnsupportedException("No transport supported for this address " +
368                 "tried FIPA_97_IIOP, FIPA_2000_IIOP & zeus native");
369                 
370                 
371             }
372         }
373     }
374     
375     
376     
377     
378     private void testNamingContext(NamingContext nc,ORB orb ) {
379         try {
380             BindingListHolder bl = new BindingListHolder();
381             BindingIteratorHolder blIt= new BindingIteratorHolder();
382             nc.list(1000, bl, blIt);
383             org.omg.CosNaming.Binding bindings[] = bl.value;
384             if (bindings.length == 0) return;
385             for (int i=0; i < bindings.length; i++) {
386                 // get the object reference for each binding
387                 org.omg.CORBA.Object obj = nc.resolve(bindings[i].binding_name);
388                 
389                 int lastIx = bindings[i].binding_name.length-1;
390                 
391                 // check to see if this is a naming context
392                 if (bindings[i].binding_type == BindingType.ncontext) {
393                     testNamingContext((NamingContext) obj, orb);
394                 } else {
395                     debug("Object: " + bindings[i].binding_name[lastIx].id);
396                 }
397                 
398                 
399             }
400         } catch (Exception e) {
401             e.printStackTrace();
402         }
403     }
404     
405     
406     /***
407      * primative at the mo  - walks the whole tree
408      */
409     private org.omg.CORBA.Object resolveNaming(NamingContext nc,ORB orb, String name  ) {
410         try {
411             BindingListHolder bl = new BindingListHolder();
412             BindingIteratorHolder blIt= new BindingIteratorHolder();
413             nc.list(1000, bl, blIt);
414             org.omg.CosNaming.Binding bindings[] = bl.value;
415             debug(bindings.toString());
416             // if (bindings.length == 0) return;
417             for (int i=0; i < bindings.length; i++) {
418                 // get the object reference for each binding
419                 org.omg.CORBA.Object obj = nc.resolve(bindings[i].binding_name);
420                 if (obj == null) { debug("BAD NAMING CONTEXT"); }
421                 int lastIx = bindings[i].binding_name.length-1;
422                 
423                 // check to see if this is a naming context
424                 if (bindings[i].binding_type == BindingType.ncontext) {
425                     debug("name == "+ name);
426                     debug("orb == " + orb.toString());
427                     debug("obj == " + obj.toString());
428                     try {
429                         NamingContext ncRef = NamingContextHelper.narrow(obj);
430                         //   NamingContext namer = (NamingContext) obj;
431                         obj = resolveNaming(ncRef, orb, name);
432                         return (obj); }
433                     catch (Exception e) {
434                         debug("E");
435                         e.printStackTrace();
436                         debug(bindings[i].binding_type.toString());
437                         for (int count = 0; count<bindings[i].binding_name.length; count++) {
438                             debug(bindings[i].binding_name[count].id);
439                             debug(bindings[i].binding_name[count].kind);}
440                         
441                         return (org.omg.CORBA.Object) obj;
442                     }
443                     
444                 } else {
445                     debug("in else");
446                     if ( bindings[i].binding_name[lastIx].id.equalsIgnoreCase(name)) {
447                         debug("got a match");
448                         return (obj);
449                     }
450                     else {
451                         debug("bindings[i].binding_name[lastIx].id == " +bindings[i].binding_name[lastIx].id);
452                         debug("but name was " + name);
453                     }
454                     
455                 }
456                 debug("end of loop");
457             }
458             
459             
460         }
461         catch (Exception e) {
462             e.printStackTrace();
463         }
464         // no match, returning null.
465         return null;
466     }// end resolveName
467     
468     
469     
470     
471     void debug(String str) {
472         System.out.println(str);
473     }
474      
475     
476 }