1 /*------------------------------------------------------------------------------
  2 Name:      CorbaConnection.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Helper to connect to xmlBlaster using IIOP
  6 Author:    xmlBlaster@marcelruff.info
  7 ------------------------------------------------------------------------------*/
  8 package org.xmlBlaster.client.protocol.corba;
  9 
 10 import org.xmlBlaster.client.protocol.I_XmlBlasterConnection;
 11 
 12 import java.util.logging.Logger;
 13 import java.util.logging.Level;
 14 
 15 import org.xmlBlaster.util.FileLocator;
 16 import org.xmlBlaster.util.Global;
 17 import org.xmlBlaster.client.qos.ConnectReturnQos;
 18 import org.xmlBlaster.util.XmlBlasterException;
 19 import org.xmlBlaster.util.def.ErrorCode;
 20 import org.xmlBlaster.util.qos.address.Address;
 21 import org.xmlBlaster.util.xbformat.I_ProgressListener;
 22 
 23 import org.xmlBlaster.util.plugin.I_Plugin;
 24 import org.xmlBlaster.util.plugin.PluginInfo;
 25 import org.xmlBlaster.util.protocol.corba.OrbInstanceFactory;
 26 
 27 import org.xmlBlaster.util.def.Constants;
 28 import org.xmlBlaster.util.MsgUnitRaw;
 29 import org.xmlBlaster.protocol.corba.serverIdl.Server;
 30 import org.xmlBlaster.protocol.corba.serverIdl.ServerHelper;
 31 import org.xmlBlaster.protocol.corba.authenticateIdl.AuthServer;
 32 import org.xmlBlaster.protocol.corba.authenticateIdl.AuthServerHelper;
 33 
 34 import org.omg.CosNaming.NamingContext;
 35 import org.omg.CosNaming.NamingContextExt;
 36 import org.omg.CosNaming.NameComponent;
 37 import org.omg.CosNaming.BindingHolder;
 38 import org.omg.CosNaming.BindingListHolder;
 39 import org.omg.CosNaming.BindingIteratorHolder;
 40 
 41 import java.applet.Applet;
 42 
 43 
 44 /**
 45  * This is a helper class, helping a Java client to connect to xmlBlaster
 46  * using IIOP (CORBA).
 47  * <p>
 48  * Please note that you don't need to use this wrapper, you can use the raw CORBA
 49  * interface as well. You can also hack your own little wrapper, which does exactly
 50  * what you want.
 51  * <p>
 52  * This class converts the Corba based exception<br />
 53  *    org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException<br />
 54  * to<br />
 55  *    org.xmlBlaster.util.XmlBlasterException
 56  * <p>
 57  * There is a constructor for applets, and standalone Java clients.
 58  * <p />
 59  * If you need a failsafe client, you can invoke the xmlBlaster CORBA methods
 60  * through this class as well (for example use corbaConnection.publish() instead of the direct
 61  * CORBA server.publish()).
 62  * <p />
 63  * You should set jacorb.retries=0  in $HOME/.jacorb_properties if you use the failsafe mode
 64  * <p />
 65  * If you want to connect from a servlet, please use the framework in xmlBlaster/src/java/org/xmlBlaster/protocol/http
 66  * <p />
 67  * NOTE: JacORB 1.1 does not release the listener thread and the poa threads of the callback server
 68  * on orb.shutdown().<br />
 69  * Therefor we recycle the ORB and POA instance to avoid a thread leak.
 70  * The drawback is that a client for the bug being can't change the orb behavior after the
 71  * first time the ORB is created.<br />
 72  * This will be fixed as soon as possible.
 73  *
 74  * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
 75  * @author <a href="mailto:xmlBlaster@marcelruff.info">Marcel Ruff</a>.
 76  */
 77 public final class CorbaConnection implements I_XmlBlasterConnection, I_Plugin
 78 {
 79    private String ME = "CorbaConnection";
 80    private Global glob;
 81    private static Logger log = Logger.getLogger(CorbaConnection.class.getName());
 82 
 83    private org.omg.CORBA.ORB orb;
 84 
 85    private NamingContextExt nameService;
 86    private AuthServer authServer;
 87    private Server xmlBlaster;
 88    private Address clientAddress;
 89    private String sessionId;
 90    private boolean verbose = true;
 91    private PluginInfo pluginInfo;
 92 
 93 
 94    /**
 95     * Called by plugin loader which calls init(Global, PluginInfo) thereafter. 
 96     */
 97    public CorbaConnection() {
 98    }
 99 
100    /**
101     * CORBA client access to xmlBlaster for <strong>applets</strong>.
102     * <p />
103     * Use these environment settings for JacORB if you don't use this constructor!
104     * <br />
105     * Example:
106     *  <pre>
107     *     &lt;APPLET
108     *        CODEBASE = "http://localhost"
109     *        CODE     = "DemoApplet.class"
110     *        NAME     = "xmlBlaster demo"
111     *        WIDTH    = 200
112     *        HEIGHT   = 200
113     *        HSPACE   = 0
114     *        VSPACE   = 0
115     *        ALIGN    = middle
116     *     >
117     *     &lt;PARAM name=org.omg.CORBA.ORBClass value=org.jacorb.orb.ORB>
118     *     &lt;PARAM name=org.omg.CORBA.ORBSingletonClass value=org.jacorb.orb.ORBSingleton>
119     *     &lt;PARAM name=SVCnameroot value=xmlBlaster-Authenticate>
120     *     &lt;/APPLET>
121     *  </pre>
122     * @param ap  Applet handle
123     */
124    public CorbaConnection(Global glob, Applet ap) {
125        // try to force to use JacORB instead of builtin CORBA:
126       String orbClassName = "org.jacorb.orb.ORB";
127       String orbSingleton = "org.jacorb.orb.ORBSingleton";
128       java.util.Properties props = new java.util.Properties();
129       props.put("org.omg.CORBA.ORBClass", orbClassName);
130       props.put("org.omg.CORBA.ORBSingletonClass", orbSingleton);
131 
132       orb = org.omg.CORBA.ORB.init(ap, props); // for applets only
133 
134       init(glob, null);
135 
136       log.info("Using ORB=" + orbClassName + " and ORBSingleton=" + orbSingleton);
137    }
138 
139    /** 
140     * Enforced by I_Plugin
141     * @return "IOR"
142     */
143    public String getType() {
144       return getProtocol();
145    }
146 
147    /** Enforced by I_Plugin */
148    public String getVersion() {
149       return "1.0";
150    }
151 
152    /**
153     * This method is called by the PluginManager (enforced by I_Plugin). 
154     * @see org.xmlBlaster.util.plugin.I_Plugin#init(org.xmlBlaster.util.Global,org.xmlBlaster.util.plugin.PluginInfo)
155     */
156    public void init(org.xmlBlaster.util.Global glob, PluginInfo pluginInfo) {
157       this.glob = (glob == null) ? Global.instance() : glob;
158 
159       this.pluginInfo = pluginInfo;
160       resetConnection();
161       log.info("Created '" + getProtocol() + "' protocol plugin to connect to xmlBlaster server");
162    }
163 
164    /**
165     * Reset
166     */
167    public void resetConnection() {
168       if (log.isLoggable(Level.FINE)) log.fine("resetConnection():");
169       this.authServer   = null;
170       this.xmlBlaster = null;
171    }
172 
173    /**
174     * @return The connection protocol name "IOR"
175     */
176    public final String getProtocol() {
177       return "IOR";
178    }
179 
180    /**
181     * Accessing the orb handle.
182     * @return org.omg.CORBA.ORB
183     */
184    public org.omg.CORBA.ORB getOrb() {
185       return this.orb;
186    }
187 
188    /**
189     * Accessing the xmlBlaster handle.
190     * For internal use, throws a COMMUNICATION XmlBlasterException if xmlBlaster==null
191     * We use this for similar handling as org.omg exceptions.
192     * @return Server
193     */
194    private Server getXmlBlaster() throws XmlBlasterException {
195       if (this.xmlBlaster == null) {
196          if (log.isLoggable(Level.FINE)) log.fine("No CORBA connection available.");
197          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME,
198                                        "The CORBA xmlBlaster handle is null, no connection available");
199       }
200       return this.xmlBlaster;
201    }
202 
203 
204    /**
205     * Locate the CORBA Name Service.
206     * <p />
207     * The found name service is cached, for better performance in subsequent calls
208     * @return NamingContextExt, reference on name service
209     * @exception XmlBlasterException id="NoNameService"
210     *                    CORBA error handling if no naming service is found
211     */
212    NamingContextExt getNamingService() throws XmlBlasterException
213    {
214       if (log.isLoggable(Level.FINER)) log.finer("getNamingService() ...");
215       if (nameService != null)
216          return nameService;
217 
218       if (orb == null) {
219          log.severe("orb==null, internal problem");
220          Thread.dumpStack();
221          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "orb==null, internal problem");
222       }
223 
224       // Get a reference to the Name Service, CORBA compliant:
225       org.omg.CORBA.Object nameServiceObj = null;
226       try {
227          nameServiceObj = orb.resolve_initial_references("NameService");
228       }
229       catch (Throwable e) {
230          String text = "Can't access naming service, is there any running?\n" +
231                        " - try to specify '-dispatch/connection/plugin/ior/iorFile <fileName>' if server is running on same host (not using any naming service)\n" +
232                        " - try to specify '-bootstrapHostname <hostName> -bootstrapPort " + Constants.XMLBLASTER_PORT + "' to locate xmlBlaster (not using any naming service)\n" +
233                        " - or contact the server administrator to start a naming service";
234          if (this.verbose)
235             log.warning(text);
236          throw new XmlBlasterException(glob, ErrorCode.RESOURCE_UNAVAILABLE, "NoNameService", text);
237       }
238       if (nameServiceObj == null) {
239          throw new XmlBlasterException(glob, ErrorCode.RESOURCE_UNAVAILABLE, "NoNameService", "Can't access naming service (null), is there any running?");
240       }
241       // if (log.isLoggable(Level.FINE)) log.trace(ME, "Successfully accessed initial orb references for naming service (IOR)");
242 
243       try {
244          nameService = org.omg.CosNaming.NamingContextExtHelper.narrow(nameServiceObj);
245          if (nameService == null) {
246             log.severe("Can't access naming service (narrow problem)");
247             throw new XmlBlasterException(glob, ErrorCode.RESOURCE_UNAVAILABLE, "NoNameService", "Can't access naming service (narrow problem)");
248          }
249          if (log.isLoggable(Level.FINE)) log.fine("Successfully narrowed handle for naming service");
250          return nameService; // Note: the naming service IOR is successfully evaluated (from a IOR),
251                              // but it is not sure that the naming service is really running
252       }
253       catch (Throwable e) {
254          if (this.verbose) log.warning("Can't access naming service");
255          throw new XmlBlasterException(glob, ErrorCode.RESOURCE_UNAVAILABLE, "NoNameService", e.toString());
256       }
257    }
258 
259 
260    /**
261     * Access the authentication service.
262     * <p />
263     * There are several ways to bootstrap the authentication service:
264     * <br />
265     * <ul>
266     *    <li>Give the authentication service string-IOR at command line, e.g.<br />
267     *        <code>   -dispatch/callback/plugin/ior/iorString "IOR:0000..."</code><br />
268     *        or giving a file name<br />
269     *        <code>   -dispatch/connection/plugin/ior/iorFile yourIorFile</code></li>
270     *    <li>Give the xmlBlaster host and bootstrap port where xmlBlaster-Authenticate serves the IOR via http, give at command line e.g.
271     *        <code>   -bootstrapHostname server.xmlBlaster.org  -bootstrapPort 3412</code></li>
272     *    <li>Try to find a naming service which knows about 'xmlBlaster-Authenticate'</li>
273     * </ul>
274     * <p />
275     * @return a handle on the AuthServer IDL interface
276     * @exception XmlBlasterException id="NoAuthService"
277     *
278     */
279    public AuthServer getAuthenticationService(Address address) throws XmlBlasterException {
280       if (log.isLoggable(Level.FINER)) log.finer("getAuthenticationService() ...");
281       if (this.authServer != null) {
282          return this.authServer;
283       }
284 
285       address = (address == null) ? new Address(glob) : address;
286       if (this.pluginInfo != null)
287          address.setPluginInfoParameters(this.pluginInfo.getParameters());
288 
289       try {
290          // 0) Check if programmer has given the IOR hardcoded
291          if (address.getRawAddress() != null && address.getRawAddress().length() > 2) {
292             String authServerIOR = address.getRawAddress();
293             this.authServer = AuthServerHelper.narrow(orb.string_to_object(authServerIOR));
294             if (this.verbose) log.info("Accessing xmlBlaster using your given IOR string in Address.getRawAddress()");
295             return this.authServer;
296          }
297 
298          // 1) check if argument -IOR at program startup is given "-dispatch/connection/plugin/ior/iorString"
299          String authServerIOR = address.getEnv("iorString", (String)null).getValue();
300          if (authServerIOR != null) {
301             this.authServer = AuthServerHelper.narrow(orb.string_to_object(authServerIOR));
302             if (this.verbose) log.info("Accessing xmlBlaster using your given IOR string");
303             return this.authServer;
304          }
305          if (log.isLoggable(Level.FINE)) log.fine("No -dispatch/connection/plugin/ior/iorString ...");
306 
307          String authServerIORFile = glob.getProperty().get("dispatch/connection/plugin/ior/iorFile", (String)null);  // -dispatch/connection/plugin/ior/iorFile IOR string is given through a file
308          if (authServerIORFile != null) {
309             try {
310                authServerIOR = FileLocator.readAsciiFile(authServerIORFile);
311             } catch (XmlBlasterException e) {
312                log.warning("Accessing xmlBlaster given IOR file '" + authServerIORFile + "' failed, please check 'dispatch/connection/plugin/ior/iorFile'");
313             }
314             this.authServer = AuthServerHelper.narrow(orb.string_to_object(authServerIOR));
315             log.info("Accessing xmlBlaster using your given IOR file " + authServerIORFile);
316             return this.authServer;
317          }
318          if (log.isLoggable(Level.FINE)) log.fine("No -dispatch/connection/plugin/ior/iorFile ...");
319 
320 
321          // 2) check if argument -bootstrapHostname <hostName or IP> -bootstrapPort <number> at program startup is given
322          // To avoid the name service, one can access the AuthServer IOR directly
323          // using a http connection.
324          try {
325             authServerIOR = glob.accessFromInternalHttpServer(address, "AuthenticationService.ior", this.verbose);
326             if (System.getProperty("java.version").startsWith("1") &&  !authServerIOR.startsWith("IOR:")) {
327                authServerIOR = "IOR:000" + authServerIOR; // hack for JDK 1.1.x, where the IOR: is cut away from ByteReader ??? !!!
328                log.warning("Manipulated IOR because of missing 'IOR:'");
329             }
330             this.authServer = AuthServerHelper.narrow(orb.string_to_object(authServerIOR));
331             log.info("Accessing xmlBlaster AuthServer IOR using builtin http connection to " +
332                          address.getBootstrapUrl());
333             return this.authServer;
334          }
335          catch(XmlBlasterException e) {
336             ;
337          }
338          catch(Throwable e) {
339             if (this.verbose)  {
340                log.severe("XmlBlaster not found with internal HTTP download");
341                e.printStackTrace();
342             }
343          }
344          if (log.isLoggable(Level.FINE)) log.fine("No -bootstrapHostname / -bootstrapPort for " + address.getBootstrapUrl() + " ...");
345 
346          String contextId = glob.getProperty().get("NameService.context.id", "xmlBlaster");
347          if (contextId == null) contextId = "";
348          String contextKind = glob.getProperty().get("NameService.context.kind", "MOM");
349          if (contextKind == null) contextKind = "";
350          String clusterId = glob.getProperty().get("NameService.node.id", glob.getStrippedId());
351          if (clusterId == null) clusterId = "";
352          String clusterKind = glob.getProperty().get("NameService.node.kind", "MOM");
353          if (clusterKind == null) clusterKind = "";
354 
355          String text = "Can't access xmlBlaster Authentication Service, is the server running and ready?\n" +
356                      " - try to specify '-dispatch/connection/plugin/ior/iorFile <fileName>' if server is running on same host\n" +
357                      " - try to specify '-bootstrapHostname <hostName> -bootstrapPort " + Constants.XMLBLASTER_PORT + "' to locate xmlBlaster\n" +
358                      " - or start a naming service '" + contextId + "." + contextKind + "/" +
359                               clusterId + "." + clusterKind + "'";
360 
361          // 3) asking Name Service CORBA compliant
362          boolean useNameService = address.getEnv("useNameService", true).getValue();  // -plugin/ior/ns default is to ask the naming service
363          if (useNameService) {
364 
365             if (this.verbose) log.info("Trying to find a CORBA naming service ...");
366             try {
367                
368                // NameService entry is e.g. "xmlBlaster.MOM/heron.MOM"
369                // where "xmlBlaster.MOM" is a context node and
370                // "heron.MOM" is a subnode for each running server (containing the AuthServer POA reference)
371 
372                NamingContextExt namingContextExt = getNamingService();
373                NameComponent [] nameXmlBlaster = new NameComponent[] { new NameComponent(contextId, contextKind) };
374                if (log.isLoggable(Level.FINE)) log.fine("Query NameServer -ORBInitRef NameService=" + glob.getProperty().get("ORBInitRef","") +
375                              ((System.getProperty("ORBInitRef.NameService") != null) ? System.getProperty("ORBInitRef.NameService") : "") +
376                              " to find the xmlBlaster root context " + OrbInstanceFactory.getString(nameXmlBlaster));
377                org.omg.CORBA.Object obj = namingContextExt.resolve(nameXmlBlaster);
378                NamingContext relativeContext = org.omg.CosNaming.NamingContextExtHelper.narrow(obj);
379 
380                if (relativeContext == null) {
381                   throw new Exception("Can't resolve CORBA NameService");
382                }
383 
384                NameComponent [] nameNode = new NameComponent[] { new NameComponent(clusterId, clusterKind) };
385 
386                AuthServer authServerFirst = null;
387                String tmpId = "";           // for logging only
388                String tmpServerName = "";   // for logging only
389                String firstServerName = ""; // for logging only
390                int countServerFound = 0;    // for logging only
391                String serverNameList = "";  // for logging only
392                try {
393                   this.authServer = AuthServerHelper.narrow(relativeContext.resolve(nameNode));
394                }
395                catch (Exception ex) {
396                   if (log.isLoggable(Level.FINE)) log.fine("Query NameServer to find a suitable xmlBlaster server for " + OrbInstanceFactory.getString(nameXmlBlaster) + "/" + OrbInstanceFactory.getString(nameNode));
397                   BindingListHolder bl = new BindingListHolder();
398                   BindingIteratorHolder bi = new BindingIteratorHolder();
399                   relativeContext.list(0, bl, bi);
400                   //for (int i=0; i<bl.value.length; i++) { // bl.value.length should be 0
401                   //   String id = bl.value[i].binding_name[0].id;
402                   //   String kind = bl.value[i].binding_name[0].kind;
403 
404                   // process the remaining bindings if an iterator exists:
405                   if (this.authServer == null && bi.value != null) {
406                      BindingHolder bh = new BindingHolder();
407                      int i = 0;
408                      while ( bi.value.next_one(bh) ) {
409                         String id = bh.value.binding_name[0].id;
410                         String kind = bh.value.binding_name[0].kind;
411                         NameComponent [] nameNodeTmp = new NameComponent[] { new NameComponent(id, kind) };
412 
413                         tmpId = id;
414                         countServerFound++;
415                         tmpServerName = OrbInstanceFactory.getString(nameXmlBlaster)+"/"+OrbInstanceFactory.getString(nameNodeTmp);
416                         if (i>0) serverNameList += ", ";
417                         i++;
418                         serverNameList += tmpServerName;
419 
420                         if (clusterId.equals(id) && clusterKind.equals(kind)) {
421                            try {
422                               if (log.isLoggable(Level.FINE)) log.fine("Trying to resolve NameService entry '"+OrbInstanceFactory.getString(nameNodeTmp)+"'");
423                               this.authServer = AuthServerHelper.narrow(relativeContext.resolve(nameNodeTmp));
424                               break; // found a matching server
425                            }
426                            catch (Exception exc) {
427                               log.warning("Connecting to NameService entry '"+tmpServerName+"' failed: " + exc.toString());
428                            }
429                         }
430 
431                         if (authServerFirst == null) {
432                            if (log.isLoggable(Level.FINE)) log.fine("Remember the first server");
433                            try {
434                               firstServerName = tmpServerName;
435                               if (log.isLoggable(Level.FINE)) log.fine("Remember the first reachable xmlBlaster server from NameService entry '"+firstServerName+"'");
436                               authServerFirst = AuthServerHelper.narrow(relativeContext.resolve(nameNodeTmp));
437                            }
438                            catch (Exception exc) {
439                               log.warning("Connecting to NameService entry '"+tmpServerName+"' failed: " + exc.toString());
440                            }
441                         }
442                      }
443                   }
444                }
445 
446                if (this.authServer == null) {
447                   if (authServerFirst != null) {
448                      if (countServerFound > 1) {
449                         String str = "Can't choose one of " + countServerFound +
450                                      " avalailable server in CORBA NameService: " + serverNameList +
451                                      ". Please choose one with e.g. -NameService.node.id " + tmpId;
452                         log.severe(str);
453                         throw new Exception(str);
454                      }
455                      log.info("Choosing only available server '" + firstServerName + "' in CORBA NameService -ORBInitRef NameService=" +
456                                   System.getProperty("ORBInitRef"));
457                      this.authServer = authServerFirst;
458                      return authServerFirst;
459                   }
460                   else {
461                      throw new Exception("No xmlBlaster server found in NameService");
462                   }
463                }
464 
465                log.info("Accessing xmlBlaster using a naming service '" + nameXmlBlaster[0].id + "." + nameXmlBlaster[0].kind + "/" +
466                               nameNode[0].id + "." + nameNode[0].kind + "' on " + System.getProperty("ORBInitRef"));
467                return this.authServer;
468             }
469             catch(Throwable e) {
470                throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, text, e);
471             }
472          }
473          if (log.isLoggable(Level.FINE)) log.fine("No -plugin/ior/useNameService ...");
474          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, text);
475       }
476       finally {
477          this.verbose = false;
478       }
479    }
480 
481    /**
482     * Login to the server. 
483     * <p />
484     * @param connectQos The encrypted connect QoS 
485     * @exception XmlBlasterException if login fails
486     */
487    public String connect(String connectQos) throws XmlBlasterException {
488       if (connectQos == null)
489          throw new XmlBlasterException(glob, ErrorCode.INTERNAL_ILLEGALARGUMENT, ME, "Please pass a valid QoS for connect()");
490 
491       this.ME = "CorbaConnection";
492       if (log.isLoggable(Level.FINER)) log.finer("connect(xmlBlaster="+this.xmlBlaster+") ...");
493       try {
494          AuthServer remoteAuthServer = getAuthenticationService(this.clientAddress);
495          if (log.isLoggable(Level.FINE)) log.fine("Got authServer handle, trying connect ...");
496          return remoteAuthServer.connect(connectQos);
497       }
498       catch(XmlBlasterException e) {
499          throw e;
500       }
501       catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
502          XmlBlasterException xmlBlasterException = OrbInstanceFactory.convert(glob, e);
503          //xmlBlasterException.changeErrorCode(ErrorCode.COMMUNICATION_NOCONNECTION);
504          throw xmlBlasterException; // Wrong credentials 
505       }
506       catch(Throwable e) {
507          XmlBlasterException xmlBlasterException = XmlBlasterException.convert(glob, ME, "Login failed", e);
508          xmlBlasterException.changeErrorCode(ErrorCode.COMMUNICATION_NOCONNECTION);
509          throw xmlBlasterException;
510       }
511    }
512 
513    /**
514     * @see I_XmlBlasterConnection#connectLowlevel(Address)
515     */
516    public void connectLowlevel(Address address) throws XmlBlasterException {
517       if (log.isLoggable(Level.FINER)) log.finer("connectLowlevel() ...");
518       this.clientAddress = address;
519       if (this.orb == null) {
520          this.orb = OrbInstanceFactory.createOrbInstance(this.glob,(String[])null,
521                                               glob.getProperty().getProperties(), this.clientAddress);
522       }
523       getAuthenticationService(this.clientAddress);
524       if (log.isLoggable(Level.FINE)) log.fine("Success, connectLowlevel()");
525    }
526 
527     /**
528     * @see I_XmlBlasterConnection#setConnectReturnQos(ConnectReturnQos)
529     */
530    public void setConnectReturnQos(ConnectReturnQos connectReturnQos) throws XmlBlasterException {
531       try {
532          this.sessionId = connectReturnQos.getSecretSessionId();
533          String xmlBlasterIOR = connectReturnQos.getServerRef().getAddress();
534          this.xmlBlaster = ServerHelper.narrow(orb.string_to_object(xmlBlasterIOR));
535          this.ME = "CorbaConnection-"+connectReturnQos.getSessionName().toString();
536          if (log.isLoggable(Level.FINE)) log.fine("setConnectReturnQos(): xmlBlaster=" + this.xmlBlaster);
537       }
538       catch(Throwable e) {
539          this.xmlBlaster = null;
540          XmlBlasterException xmlBlasterException = XmlBlasterException.convert(glob, ME, "Login failed", e);
541          xmlBlasterException.changeErrorCode(ErrorCode.COMMUNICATION_NOCONNECTION);
542          throw xmlBlasterException;
543       }
544    }
545 
546    /**
547     * Logout from the server.
548     * Note that this kills the server ping thread as well (if in failsafe mode)
549     * @return true successfully logged out
550     *         false failure on logout
551     */
552    public boolean disconnect(String qos) {
553       if (log.isLoggable(Level.FINER)) log.finer("disconnect() ...");
554 
555       if (this.xmlBlaster == null) {
556          try {
557             shutdown();
558          }
559          catch (XmlBlasterException ex) {
560             log.severe("disconnect. Could not shutdown properly. " + ex.getMessage());
561          }
562          return false;
563       }
564 
565       try {
566          if (this.authServer != null) {
567             if(this.sessionId==null) {
568                this.authServer.logout(xmlBlaster);
569             }
570             else {
571                this.authServer.disconnect(this.sessionId, (qos==null)?"":qos); // secPlgn.exportMessage(""));
572             }
573          }
574          shutdown();
575          this.xmlBlaster = null;
576          return true;
577       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
578          log.warning("Remote exception: " + OrbInstanceFactory.convert(glob, e).getMessage());
579       } catch(org.omg.CORBA.OBJ_ADAPTER e) {
580          log.warning("No disconnect possible, no CORBA connection available: " + e.toString());
581       } catch(org.omg.CORBA.TRANSIENT e) {
582          log.warning("No disconnect possible, CORBA connection lost: " + e.toString());
583       } catch(org.omg.CORBA.COMM_FAILURE e) {
584          log.warning("No disconnect possible, CORBA connection lost: " + e.toString());
585       } catch(org.omg.CORBA.OBJECT_NOT_EXIST e) {
586          log.warning("No disconnect possible, CORBA connection lost: " + e.toString());
587       } catch(Throwable e) {
588          XmlBlasterException xmlBlasterException = XmlBlasterException.convert(glob, ME, null, e);
589          log.warning(xmlBlasterException.getMessage());
590          e.printStackTrace();
591       }
592 
593       try {
594          shutdown();
595       }
596       catch (XmlBlasterException ex) {
597          log.severe("disconnect. Could not shutdown properly. " + ex.getMessage());
598       }
599       this.xmlBlaster = null;
600       return false;
601    }
602 
603    /**
604     * Shut down the callback server.
605     * Is called by logout()
606     */
607    public void shutdown() throws XmlBlasterException {
608       if (log.isLoggable(Level.FINER)) log.finer("shutdown()");
609       if (this.authServer != null) {
610          this.authServer._release();
611          this.authServer = null;
612       }
613       if (this.xmlBlaster != null) {
614          this.xmlBlaster._release();
615          this.xmlBlaster = null;
616       }
617       if (this.orb != null) {
618          boolean wait_for_completion = false;
619          try {
620             this.orb.shutdown(wait_for_completion);
621             this.orb = null;
622          }
623          catch (Throwable ex) {
624             log.warning("shutdown: Exception occured during orb.shutdown("+wait_for_completion+"): " + ex.toString());
625          }
626       }
627    }
628 
629    /**
630     * @return true if you are logged in
631     */
632    public boolean isLoggedIn() {
633       return this.xmlBlaster != null;
634    }
635 
636    /**
637     * Enforced by I_XmlBlasterConnection interface (failsafe mode).
638     * see explanations of subscribe() method.
639     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
640     */
641    public final String subscribe(String xmlKey, String qos) throws XmlBlasterException {
642       if (log.isLoggable(Level.FINER)) log.finer("subscribe() ...");
643       try {
644          return getXmlBlaster().subscribe(xmlKey, qos);
645       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
646          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
647       } catch(Throwable e) {
648          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "subscribe", e);
649       }
650    }
651 
652    /**
653     * Enforced by I_XmlBlasterConnection interface (failsafe mode)
654     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
655     */
656    public final String[] unSubscribe(String xmlKey, String qos) throws XmlBlasterException {
657       if (log.isLoggable(Level.FINER)) log.finer("unSubscribe() ...");
658       try {
659          return getXmlBlaster().unSubscribe(xmlKey, qos);
660       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
661          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
662       } catch(Throwable e) {
663          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "unSubscribe", e);
664       }
665    }
666 
667 
668    /**
669     * Publish fault-tolerant the given message.
670     * <p />
671     * This is a wrapper around the raw CORBA publish() method
672     * If the server disappears you get an exception.
673     * This call will not block.
674     * <p />
675     * Enforced by I_XmlBlasterConnection interface (failsafe mode)
676     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
677     */
678    public final String publish(MsgUnitRaw msgUnit) throws XmlBlasterException {
679       if (log.isLoggable(Level.FINER)) log.finer("Publishing ...");
680       try {
681          return getXmlBlaster().publish(OrbInstanceFactory.convert(msgUnit));
682       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
683          if (log.isLoggable(Level.FINE)) log.fine("XmlBlasterException: " + e.getMessage());
684          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
685       } catch(Throwable e) {
686          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "publish() failed", e);
687       }
688    }
689 
690 
691    /**
692     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
693     */
694    public String[] publishArr(MsgUnitRaw [] msgUnitArr) throws XmlBlasterException
695    {
696       if (log.isLoggable(Level.FINER)) log.finer("publishArr() num of Entries: " + msgUnitArr.length);
697       try {
698          return getXmlBlaster().publishArr(OrbInstanceFactory.convert(msgUnitArr));
699       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
700          if (log.isLoggable(Level.FINE)) log.fine("XmlBlasterException: " + e.getMessage());
701          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
702       } catch(Throwable e) {
703          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "publishArr", e);
704       }
705    }
706 
707    /**
708     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
709     */
710    public void publishOneway(MsgUnitRaw[] msgUnitArr) throws XmlBlasterException {
711       if (log.isLoggable(Level.FINER)) log.finer("publishOneway() ...");
712       try {
713          getXmlBlaster().publishOneway(OrbInstanceFactory.convert(msgUnitArr));
714       } catch(Throwable e) {
715          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "publishOneway", e);
716       }
717    }
718 
719    /**
720     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
721     */
722    public final String[] erase(String xmlKey, String qos) throws XmlBlasterException {
723       if (log.isLoggable(Level.FINER)) log.finer("erase() ...");
724       if (xmlKey==null) xmlKey = "";
725       if (qos==null) qos = "";
726       try {
727          return getXmlBlaster().erase(xmlKey, qos);
728       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
729          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
730       } catch(Throwable e) {
731          log.severe("IO exception: " + e.toString() + " sessionId=" + this.sessionId);
732          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "erase", e);
733       }
734    }
735 
736 
737    /**
738     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
739     */
740    public final MsgUnitRaw[] get(String xmlKey, String qos) throws XmlBlasterException {
741       if (log.isLoggable(Level.FINER)) log.finer("get() ...");
742       try {
743          return OrbInstanceFactory.convert(glob, getXmlBlaster().get(xmlKey, qos));
744       } catch(org.xmlBlaster.protocol.corba.serverIdl.XmlBlasterException e) {
745          throw OrbInstanceFactory.convert(glob, e); // transform Corba exception to native exception
746       } catch(Throwable e) {
747          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "get", e);
748       }
749    }
750 
751    /**
752     * Register a listener for to receive information about the progress of incoming data. 
753     * Only one listener is supported, the last call overwrites older calls. This implementation
754     * does nothing here, it just returns null.
755     * 
756     * @param listener Your listener, pass 0 to unregister.
757     * @return The previously registered listener or 0
758     */
759    public I_ProgressListener registerProgressListener(I_ProgressListener listener) {
760       log.fine("This method is currently not implemeented.");
761       return null;
762    }
763 
764    /**
765     * @see <a href="http://www.xmlBlaster.org/xmlBlaster/src/java/org/xmlBlaster/protocol/corba/xmlBlaster.idl" target="others">CORBA xmlBlaster.idl</a>
766     * @see org.xmlBlaster.client.protocol.I_XmlBlasterConnection#ping(String)
767     */
768    public String ping(String qos) throws XmlBlasterException {
769       if (this.xmlBlaster == null && this.authServer != null) {
770          return this.authServer.ping(qos); // low level ping without having connect() to xmlBlaster
771       }
772 
773       try {
774          return getXmlBlaster().ping(qos);
775       } catch(Throwable e) {
776          throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, "ping", e);
777       }
778    }
779 
780    /**
781     * Command line usage.
782     * <p />
783     * These variables may be set in xmlBlaster.properties as well.
784     * Don't use the "-" prefix there.
785     */
786    public static String usage()
787    {
788       String text = "\n";
789       text += "CorbaConnection 'IOR' options:\n";
790       text += "   -bootstrapHostname <hostname or IP>\n";
791       text += "                       The host where to find xmlBlaster internal HTTP IOR download [localhost]\n";
792       text += "   -bootstrapPort <port>\n";
793       text += "                       The bootstrap port where xmlBlaster publishes its IOR [" + Constants.XMLBLASTER_PORT + "]\n";
794       text += "   -dispatch/connection/plugin/ior/iorString <IOR:00459...>\n";
795       text += "                       The IOR string from the running xmlBlaster server.\n";
796       text += "   -dispatch/connection/plugin/ior/iorFile <fileName>\n";
797       text += "                       A file with the xmlBlaster IOR.\n";
798       text += "   -dispatch/connection/plugin/ior/useNameService <true/false>\n";
799       text += "                       Try to access xmlBlaster through a naming service [true]\n";
800       text += "   -dispatch/callback/plugin/ior/hostname <ip>\n";
801       text += "                       Allows to set the callback-server's IP address for multi-homed hosts.\n";
802       text += "   -dispatch/callback/plugin/ior/port <port>\n";
803       text += "                       Allows to set the callback-server's port number.\n";
804       text += " For JacORB only:\n";
805       text += "   java -DOAIAddr=<ip> Use '-dispatch/callback/plugin/ior/hostname'\n";
806       text += "   java -DOAPort=<nr>  Use '-dispatch/callback/plugin/ior/port'\n";
807       text += "   java -Djacorb.log.default.verbosity=3  Switch CORBA debugging on\n";
808       text += "   java ... -ORBInitRef NameService=corbaloc:iiop:localhost:7608/StandardNS/NameServer-POA/_root\n";
809       text += "   java -DORBInitRef.NameService=corbaloc:iiop:localhost:7608/StandardNS/NameServer-POA/_root\n";
810       text += "\n";
811       return text;
812    }
813 } // class CorbaConnection


syntax highlighted by Code2HTML, v. 0.9.1