Source for gnu.CORBA.Poa.gnuServantObject

   1: /* gnuServantObject.java --
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.CORBA.Poa;
  40: 
  41: import gnu.CORBA.GIOP.ReplyHeader;
  42: import gnu.CORBA.IorDelegate;
  43: import gnu.CORBA.IorObject;
  44: import gnu.CORBA.Interceptor.gnuServerRequestInfo;
  45: import gnu.CORBA.typecodes.RecordTypeCode;
  46: import gnu.CORBA.IOR;
  47: import gnu.CORBA.IorProvider;
  48: import gnu.CORBA.Minor;
  49: import gnu.CORBA.ObjectCreator;
  50: import gnu.CORBA.Unexpected;
  51: import gnu.CORBA.ResponseHandlerImpl;
  52: import gnu.CORBA.StreamHolder;
  53: 
  54: import gnu.java.lang.CPStringBuilder;
  55: 
  56: import org.omg.CORBA.Any;
  57: import org.omg.CORBA.BAD_OPERATION;
  58: import org.omg.CORBA.BAD_PARAM;
  59: import org.omg.CORBA.CompletionStatus;
  60: import org.omg.CORBA.OBJECT_NOT_EXIST;
  61: import org.omg.CORBA.OBJ_ADAPTER;
  62: import org.omg.CORBA.ORB;
  63: import org.omg.CORBA.SystemException;
  64: import org.omg.CORBA.TCKind;
  65: import org.omg.CORBA.TRANSIENT;
  66: import org.omg.CORBA.UserException;
  67: import org.omg.CORBA.portable.InputStream;
  68: import org.omg.CORBA.portable.InvokeHandler;
  69: import org.omg.CORBA.portable.ObjectImpl;
  70: import org.omg.CORBA.portable.OutputStream;
  71: import org.omg.CORBA.portable.ResponseHandler;
  72: import org.omg.PortableInterceptor.ForwardRequest;
  73: import org.omg.PortableInterceptor.ServerRequestInterceptorOperations;
  74: import org.omg.PortableServer.CurrentOperations;
  75: import org.omg.PortableServer.DynamicImplementation;
  76: import org.omg.PortableServer.ImplicitActivationPolicyValue;
  77: import org.omg.PortableServer.POA;
  78: import org.omg.PortableServer.POAManager;
  79: import org.omg.PortableServer.POAManagerPackage.State;
  80: import org.omg.PortableServer.Servant;
  81: import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
  82: import org.omg.PortableServer.ServantRetentionPolicyValue;
  83: import org.omg.PortableServer.portable.Delegate;
  84: 
  85: import java.io.IOException;
  86: 
  87: import java.util.Arrays;
  88: 
  89: /**
  90:  * Represents a CORBA object, being locally served by the associated servant.
  91:  * The calls to the object are forwarded to the calls to the servant.
  92:  *
  93:  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
  94:  */
  95: public class gnuServantObject extends ObjectImpl
  96:   implements org.omg.CORBA.Object,
  97:     InvokeHandler,
  98:     CurrentOperations,
  99:     IorProvider
 100: {
 101:   /**
 102:    * The associated servant that must also implement the {@link InvokeHandler}
 103:        * interface. This value can be temporary null if the object was created using
 104:    * POA.create_reference or POA.create_reference_with_id, private to force
 105:    * always to use {@link setServant}.
 106:    */
 107:   private Servant servant;
 108: 
 109:   /**
 110:    * The Id of this object.
 111:    */
 112:   public final byte[] Id;
 113: 
 114:   /**
 115:    * The poa that takes care about this object.
 116:    */
 117:   public final gnuPOA poa;
 118: 
 119:   /**
 120:    * The POA manager, used to control the work of this object.
 121:    */
 122:   public final POAManager manager;
 123: 
 124:   /**
 125:    * The orb.
 126:    */
 127:   public final ORB_1_4 orb;
 128: 
 129:   /**
 130:    * The object repository ids, if they were specified separately. Normally, the
 131:    * ids are requested from the servant.
 132:    */
 133:   public final String[] repository_ids;
 134: 
 135:   /**
 136:    * True indicates that the NO_RETAIN policy applies for the servant.
 137:    * The servant must be discarded after the each call.
 138:    */
 139:   boolean noRetain;
 140: 
 141:   /**
 142:    * Create an object with no connected servant. The servant must be set later.
 143:    *
 144:    * @param a_repository_ids an array of repository ids, can be null (then ids
 145:    * will be requested from the servant).
 146:    * @param an_id the object id.
 147:    * @param a_poa the POA.
 148:    */
 149:   public gnuServantObject(String[] a_repository_ids, byte[] an_id,
 150:     gnuPOA a_poa, ORB_1_4 an_orb
 151:   )
 152:   {
 153:     repository_ids = a_repository_ids;
 154:     Id = an_id;
 155:     manager = a_poa.the_POAManager();
 156:     poa = a_poa;
 157:     orb = an_orb;
 158: 
 159:     noRetain = poa.applies(ServantRetentionPolicyValue.NON_RETAIN);
 160:   }
 161: 
 162:   /**
 163:    * Get the IOR as it would be for this object.
 164:    */
 165:   public IOR getIor()
 166:   {
 167:     return orb.getLocalIor(this);
 168:   }
 169: 
 170:   /**
 171:    * Create a servant object, associated with the passed servant.
 172:    *
 173:    * @param a_servant a servant, serving this object.
 174:    * @param an_id an Object Id for this object.
 175:    *
 176:    * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler}.
 177:    */
 178:   public gnuServantObject(Servant a_servant, byte[] an_id, ORB_1_4 an_orb,
 179:     gnuPOA a_poa
 180:   )
 181:   {
 182:     Id = an_id;
 183:     setServant(a_servant);
 184:     poa = a_poa;
 185:     if (poa != null)
 186:       {
 187:         manager = poa.the_POAManager();
 188:       }
 189:     else
 190:       {
 191:         manager = null;
 192:       }
 193:     repository_ids = null;
 194:     orb = an_orb;
 195: 
 196:     noRetain = poa != null && poa.applies(ServantRetentionPolicyValue.NON_RETAIN);
 197:   }
 198: 
 199:   /**
 200:    * Set a servant, if it has not been previously set.
 201:    *
 202:    * @param a_servant a servant to set, can be null to indicate the necessity
 203:    * for the subsequent activation.
 204:    *
 205:    * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler} or
 206:    * {@link DynamicImplementation} and also not null.
 207:    */
 208:   public void setServant(Servant a_servant)
 209:   {
 210:     if (a_servant != null &&
 211:       !(a_servant instanceof InvokeHandler) &&
 212:       !(a_servant instanceof DynamicImplementation)
 213:     )
 214:       {
 215:         throw new BAD_PARAM("Must be either InvokeHandler or " +
 216:           "DynamicImplementation, but is " + a_servant
 217:         );
 218:       }
 219:     servant = a_servant;
 220:   }
 221: 
 222:   /**
 223:    * Returns the associated servant.
 224:    */
 225:   public Servant getServant()
 226:   {
 227:     return servant;
 228:   }
 229: 
 230:   /**
 231:    * Return the associated invocation handler.
 232:    */
 233:   public InvokeHandler getHandler(String operation, CookieHolder cookie,
 234:     boolean forwarding_allowed
 235:   ) throws gnuForwardRequest
 236:   {
 237:     if (servant != null && !noRetain)
 238:       {
 239:         return servantToHandler(servant);
 240:       }
 241:     else
 242:       {
 243:         // Use servant locator to locate the servant.
 244:         if (poa.servant_locator != null)
 245:           {
 246:             try
 247:               {
 248:                 servant =
 249:                   poa.servant_locator.preinvoke(Id, poa, operation, cookie);
 250:                 return servantToHandler(servant);
 251:               }
 252:             catch (org.omg.PortableServer.ForwardRequest forw_ex)
 253:               {
 254:                 if (forwarding_allowed)
 255:                   {
 256:                     throw new gnuForwardRequest(forw_ex.forward_reference);
 257:                   }
 258:                 else
 259:                   {
 260:                     servant =
 261:                       ForwardedServant.create(forw_ex.forward_reference);
 262:                     return servantToHandler(servant);
 263:                   }
 264:               }
 265:           }
 266:         else
 267:         // Use servant activator to locate the servant.
 268:         if (poa.applies(ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION) &&
 269:           poa.applies(ServantRetentionPolicyValue.RETAIN)
 270:         )
 271:           {
 272:             try
 273:               {
 274:                 poa.activate_object_with_id(Id, servant, forwarding_allowed);
 275:                 servant = poa.id_to_servant(Id);
 276:                 return servantToHandler(servant);
 277:               }
 278:             catch (gnuForwardRequest forwarded)
 279:               {
 280:                 throw forwarded;
 281:               }
 282:             catch (Exception ex)
 283:               {
 284:                 BAD_OPERATION bad =
 285:                   new BAD_OPERATION("Unable to activate", Minor.Activation,
 286:                     CompletionStatus.COMPLETED_NO
 287:                   );
 288:                 bad.initCause(ex);
 289:                 throw bad;
 290:               }
 291:           }
 292:         else if (poa.default_servant != null)
 293:           {
 294:             servant = poa.default_servant;
 295:             return servantToHandler(servant);
 296:           }
 297: 
 298:         // No servant and no servant manager - throw exception.
 299:         else
 300:           {
 301:             throw new BAD_OPERATION("Unable to activate", Minor.Activation,
 302:               CompletionStatus.COMPLETED_NO
 303:             );
 304:           }
 305:       }
 306:   }
 307: 
 308:   /**
 309:    * Convert the servant to invocation handler.
 310:    */
 311:   public InvokeHandler servantToHandler(Servant a_servant)
 312:   {
 313:     if (a_servant instanceof InvokeHandler)
 314:       {
 315:         return (InvokeHandler) a_servant;
 316:       }
 317:     else if (a_servant instanceof DynamicImplementation)
 318:       {
 319:         return new DynamicImpHandler((DynamicImplementation) a_servant);
 320:       }
 321:     else
 322:       {
 323:         throw new BAD_OPERATION(a_servant +
 324:           " must be either InvokeHandler or " + "POA DynamicImplementation"
 325:         );
 326:       }
 327:   }
 328: 
 329:   /**
 330:    * Create a servant object, associated with the passed servant. Requests the
 331:    * object id from the servant. Depending on the policies of the servants POA,
 332:    * the calls are eithe not synchronized or synchronized on POA or ORB.
 333:    *
 334:    * @param a_servant a servant, serving this object.
 335:    * @param an_id an Object Id for this object.
 336:    */
 337:   public gnuServantObject(Servant a_servant, gnuPOA a_poa)
 338:   {
 339:     this(a_servant, a_servant._object_id(), (ORB_1_4) a_servant._orb(), a_poa);
 340:   }
 341: 
 342:   /**
 343:    * Delegates call to servant, passing the poa and Id.
 344:    */
 345:   public String[] _ids()
 346:   {
 347:     if (repository_ids == null)
 348:       {
 349:         return getServant()._all_interfaces(poa, Id);
 350:       }
 351:     else
 352:       {
 353:         return repository_ids;
 354:       }
 355:   }
 356: 
 357:   /**
 358:    * Gets a string representation.
 359:    */
 360:   public String toString()
 361:   {
 362:     CPStringBuilder b = new CPStringBuilder("Servant object (");
 363:     for (int i = 0; i < Id.length; i++)
 364:       {
 365:         b.append(Integer.toHexString(Id [ i ] & 0xFF));
 366:         b.append(' ');
 367:       }
 368:     b.append(')');
 369:     return b.toString();
 370:   }
 371: 
 372:   /**
 373:    * Always returns true.
 374:    */
 375:   public boolean _is_local()
 376:   {
 377:     return true;
 378:   }
 379: 
 380:   /**
 381:    * Check if this object could be named by the given repository id.
 382:    *
 383:    * @param idl_id the repository id to check.
 384:    *
 385:    * @return true if it is one of the possible repository ids of this object.
 386:    */
 387:   public boolean _is_a(String idl_id)
 388:   {
 389:     String[] maybe = _ids();
 390:     for (int i = 0; i < maybe.length; i++)
 391:       {
 392:         if (maybe [ i ].equals(idl_id))
 393:           {
 394:             return true;
 395:           }
 396:       }
 397:     return false;
 398:   }
 399: 
 400:   /**
 401:    * Get an ORB, associated with the servant of this object.
 402:    *
 403:    * @return
 404:    */
 405:   public ORB _orb()
 406:   {
 407:     return getServant()._orb();
 408:   }
 409: 
 410:   /**
 411:    * Handle the invocation (delegates to servant).
 412:    *
 413:    * @throws TRANSIENT minor 0x535503e9 if the POA is in discarding mode.
 414:    * @throws OBJ_ADAPTER minor 0x535503ea if the POA is inactivated.
 415:    * @throws OBJECT_NOT_EXISTS minor 0x535503ec if this object is inactivated.
 416:    *
 417:    * @specnote see {@link POAManagerOperations} for specnotes about the minor
 418:    * codes.
 419:    */
 420:   public OutputStream _invoke(String method, InputStream input,
 421:     ResponseHandler r_handler
 422:   ) throws SystemException
 423:   {
 424:     boolean intercept = false;
 425:     ServerRequestInterceptorOperations interceptor = null;
 426:     gnuServerRequestInfo info = null;
 427:     ResponseHandlerImpl i_handler = null;
 428: 
 429:     try
 430:       {
 431:         if (orb.iServer != null &&
 432:           r_handler instanceof ResponseHandlerImpl
 433:         )
 434:           {
 435:             interceptor = orb.iServer;
 436: 
 437:             i_handler = (ResponseHandlerImpl) r_handler;
 438: 
 439:             info =
 440:               new gnuServerRequestInfo(this, i_handler.request_header,
 441:                 i_handler.reply_header
 442:               );
 443:             intercept = true;
 444: 
 445:             interceptor.receive_request_service_contexts(info);
 446:           }
 447: 
 448:         try
 449:           {
 450:             CookieHolder cookie = null;
 451:             AOM.Obj self = poa.aom.get(Id);
 452: 
 453:             if (poa.servant_locator != null)
 454:               {
 455:                 // If the servant locator is in use, it is always responsible
 456:                 // for providing the servant.
 457:                 self.servant = servant = null;
 458:                 cookie = new CookieHolder();
 459:               }
 460:             else if (self != null && self.isDeactiveted())
 461:               {
 462:                 if (poa.applies(
 463:                     ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION
 464:                   ) &&
 465:                   poa.servant_activator != null
 466:                 )
 467:                   {
 468:                     // Reset the servant, forcing the subsequent activation.
 469:                     servant = null;
 470:                   }
 471:                 else
 472:                   {
 473:                     throw new OBJECT_NOT_EXIST("Object deactivated",
 474:                       0x535503ec, CompletionStatus.COMPLETED_NO
 475:                     );
 476:                   }
 477:               }
 478: 
 479:             InvokeHandler handler = getHandler(method, cookie, true);
 480: 
 481:             Delegate d = null;
 482: 
 483:             try
 484:               {
 485:                 d = servant._get_delegate();
 486:                 orb.currents.put(Thread.currentThread(), this);
 487:               }
 488:             catch (Exception ex)
 489:               {
 490:                 // In some cases exception is thrown if the delegate is not set.
 491:               }
 492:             if (d instanceof ServantDelegateImpl)
 493:               {
 494:                 // If the delegate is already set, check maybe we can
 495:                 // reuse the existing instance.
 496:                 if (((ServantDelegateImpl) d).object != this)
 497:                   {
 498:                     servant._set_delegate(new ServantDelegateImpl(servant, poa, Id));
 499:                   }
 500:               }
 501:             else
 502:               {
 503:                 servant._set_delegate(new ServantDelegateImpl(servant, poa, Id));
 504:               }
 505: 
 506:             try
 507:               {
 508:                 switch (manager.get_state().value())
 509:                   {
 510:                     case State._ACTIVE :
 511: 
 512:                       OutputStream rt;
 513:                       try
 514:                         {
 515:                           if (intercept)
 516:                             {
 517:                               interceptor.receive_request(info);
 518:                             }
 519: 
 520:                           rt = handler._invoke(method, input, r_handler);
 521: 
 522:                           if (intercept)
 523:                             {
 524:                               // Handler is casted into i_handler.
 525:                               if (i_handler.isExceptionReply())
 526:                                 {
 527:                                   info.m_reply_header.reply_status =
 528:                                     ReplyHeader.USER_EXCEPTION;
 529: 
 530:                                   // Make Any, holding the user exception.
 531:                                   Any a = orb.create_any();
 532:                                   OutputStream buf = i_handler.getBuffer();
 533:                                   InputStream in = buf.create_input_stream();
 534:                                   String uex_idl = "unknown";
 535:                                   try
 536:                                     {
 537:                                       in.mark(Integer.MAX_VALUE);
 538:                                       uex_idl = in.read_string();
 539:                                       in.reset();
 540:                                     }
 541:                                   catch (IOException e)
 542:                                     {
 543:                                       throw new Unexpected(e);
 544:                                     }
 545: 
 546:                                   try
 547:                                     {
 548:                                       UserException exception =
 549:                                         ObjectCreator.readUserException(uex_idl,
 550:                                           in
 551:                                         );
 552: 
 553:                                       ObjectCreator.insertWithHelper(a,
 554:                                         exception
 555:                                       );
 556:                                     }
 557:                                   catch (Exception e)
 558:                                     {
 559:                                       // Failed due any reason, insert without
 560:                                       // helper.
 561:                                       a.insert_Streamable(new StreamHolder(
 562:                                           buf.create_input_stream()
 563:                                         )
 564:                                       );
 565: 
 566:                                       RecordTypeCode r =
 567:                                         new RecordTypeCode(TCKind.tk_except);
 568:                                       r.setId(uex_idl);
 569:                                       r.setName(ObjectCreator.getDefaultName(
 570:                                           uex_idl
 571:                                         )
 572:                                       );
 573:                                     }
 574: 
 575:                                   info.m_usr_exception = a;
 576:                                   interceptor.send_exception(info);
 577:                                 }
 578:                               else
 579:                                 {
 580:                                   info.m_reply_header.reply_status =
 581:                                     ReplyHeader.NO_EXCEPTION;
 582:                                   interceptor.send_reply(info);
 583:                                 }
 584:                             }
 585:                         }
 586:                       catch (SystemException sys_ex)
 587:                         {
 588:                           if (intercept)
 589:                             {
 590:                               info.m_reply_header.reply_status =
 591:                                 ReplyHeader.SYSTEM_EXCEPTION;
 592:                               info.m_sys_exception = sys_ex;
 593:                               interceptor.send_exception(info);
 594:                             }
 595:                           throw sys_ex;
 596:                         }
 597: 
 598:                       return rt;
 599: 
 600:                     case State._HOLDING :
 601: 
 602:                       // The holding mode is implemented
 603:                       // relying on the holding capabilites of the network
 604:                       // support (if any).
 605:                       // TODO FIXME in more recent CORBA applications, the
 606:                       // client
 607:                       // ORB can free the connection and wait for a server side
 608:                       // notification about the completed request. Implement
 609:                       // this
 610:                       // as soon as JDK specification would allow bidirectional
 611:                       // policy.
 612:                       int sleep = 5;
 613:                       int max = 500;
 614: 
 615:                       // Wait till the state will be switched into some other
 616:                       // mode.
 617:                       while (manager.get_state().value() == State._HOLDING)
 618:                         {
 619:                           try
 620:                             {
 621:                               Thread.sleep(sleep);
 622:                               if (sleep < max)
 623:                                 {
 624:                                   sleep = max;
 625:                                 }
 626:                             }
 627:                           catch (InterruptedException ex)
 628:                             {
 629:                             }
 630:                         }
 631: 
 632:                       // Handle another mode.
 633:                       return _invoke(method, input, r_handler);
 634: 
 635:                     case State._DISCARDING :
 636:                       throw new TRANSIENT("Discarding mode", 0x535503e9,
 637:                         CompletionStatus.COMPLETED_NO
 638:                       );
 639: 
 640:                     case State._INACTIVE :
 641:                       throw new OBJ_ADAPTER("POA deactivated", 0x535503ea,
 642:                         CompletionStatus.COMPLETED_NO
 643:                       );
 644: 
 645:                     default :
 646:                       throw new InternalError(); // No more states.
 647:                   }
 648:               }
 649:             finally
 650:               {
 651:                 if (poa.servant_locator != null)
 652:                   {
 653:                     poa.servant_locator.postinvoke(Id, poa, method,
 654:                       cookie.value, servant
 655:                     );
 656:                   }
 657:               }
 658:           }
 659:         finally
 660:           {
 661:             orb.currents.remove(Thread.currentThread());
 662:             if (noRetain)
 663:               servant = null;
 664:           }
 665:       }
 666:     catch (ForwardRequest fex)
 667:       {
 668:         // May be thrown by interceptor.
 669:         if (intercept)
 670:           {
 671:             Forwarding:
 672:             while (true)
 673:               {
 674:                 info.m_reply_header.reply_status =
 675:                   ReplyHeader.LOCATION_FORWARD;
 676:                 info.m_forward_reference = fex.forward;
 677:                 try
 678:                   {
 679:                     interceptor.send_other(info);
 680:                     break Forwarding;
 681:                   }
 682:                 catch (ForwardRequest fex2)
 683:                   {
 684:                     info.m_forward_reference = fex2.forward;
 685:                     fex.forward = info.m_forward_reference;
 686:                   }
 687:               }
 688:           }
 689:         throw new gnuForwardRequest(fex.forward);
 690:       }
 691:     catch (gnuForwardRequest fex)
 692:       {
 693:         // May be thrown during activation.
 694:         if (intercept)
 695:           {
 696:             Forwarding:
 697:             while (true)
 698:               {
 699:                 info.m_reply_header.reply_status =
 700:                   ReplyHeader.LOCATION_FORWARD;
 701:                 info.m_forward_reference = fex.forward_reference;
 702:                 try
 703:                   {
 704:                     interceptor.send_other(info);
 705:                     break Forwarding;
 706:                   }
 707:                 catch (ForwardRequest fex2)
 708:                   {
 709:                     info.m_forward_reference = fex2.forward;
 710:                     fex.forward_reference = (ObjectImpl) fex2.forward;
 711:                   }
 712:               }
 713:           }
 714:         throw fex;
 715:       }
 716:   }
 717: 
 718:   /**
 719:    * Compare with another object for equality, comparing the object keys.
 720:    */
 721:   public boolean equals(java.lang.Object other)
 722:   {
 723:     if (other instanceof gnuServantObject)
 724:       {
 725:         gnuServantObject o = (gnuServantObject) other;
 726: 
 727:         return Arrays.equals(o.Id, Id);
 728:       }
 729:     else
 730:       {
 731:         return false;
 732:       }
 733:   }
 734: 
 735:   /**
 736:    * Get the hash code, based on the object key.
 737:    */
 738:   public int hashCode()
 739:   {
 740:     long s = 0;
 741:     int v = 1;
 742:     for (int i = 0; i < Id.length; i++)
 743:       {
 744:         s += Id [ i ] * v;
 745:         if (s > Integer.MAX_VALUE)
 746:           {
 747:             s = s % Integer.MAX_VALUE;
 748:             v = 1;
 749:           }
 750:         v = v * 8;
 751:       }
 752:     return (int) (s % Integer.MAX_VALUE);
 753:   }
 754: 
 755:   /**
 756:    * Get the object id.
 757:    */
 758:   public byte[] get_object_id()
 759:   {
 760:     return Id;
 761:   }
 762: 
 763:   /**
 764:    * Get POA.
 765:    */
 766:   public POA get_POA()
 767:   {
 768:     return poa;
 769:   }
 770: 
 771:   /**
 772:    * Returns without action.
 773:    */
 774:   public void _release()
 775:   {
 776:   }
 777: 
 778:   /**
 779:    * Returns without action.
 780:    */
 781:   public void _releaseReply(InputStream stream)
 782:   {
 783:   }
 784: 
 785:   /**
 786:    * Checks if this object is equivalent to another instance. These objects are
 787:    * assumed equal if they are connected to the same orb and poa under the same
 788:    * Id, regardless of they delegates.
 789:    *
 790:    * @param other instance to check.
 791:    * @return
 792:    */
 793:   public boolean _is_equivalent(org.omg.CORBA.Object other)
 794:   {
 795:     if (other instanceof gnuServantObject)
 796:       {
 797:         gnuServantObject g = (gnuServantObject) other;
 798:         return orb == g.orb && poa == g.poa && Arrays.equals(Id, g.Id);
 799:       }
 800:     else if (other instanceof IorObject)
 801:       {
 802:         IorObject ir = ((IorObject) other);
 803:         try
 804:           {
 805:             IorDelegate ird = (IorDelegate) ir._get_delegate();
 806:             byte[] ior_id = poa.idFormIor(ird.getIor().key);
 807:             if (ior_id != null && Arrays.equals(ior_id, Id))
 808:               {
 809:                 return true;
 810:               }
 811:             else
 812:               {
 813:                 return false;
 814:               }
 815:           }
 816:         catch (Exception ex)
 817:           {
 818:             // Non - typical delegate or very specific subclass of
 819:             // IOR_constructed_object.
 820:             return super._is_equivalent(other);
 821:           }
 822:       }
 823:     return super._is_equivalent(other);
 824:   }
 825: }