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