Source for gnu.javax.rmi.CORBA.UtilDelegateImpl

   1: /* UtilDelegateImpl.java --
   2:    Copyright (C) 2002, 2005, 2006 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.javax.rmi.CORBA;
  40: 
  41: import gnu.classpath.VMStackWalker;
  42: 
  43: import gnu.CORBA.Minor;
  44: import gnu.CORBA.ObjectCreator;
  45: import gnu.CORBA.Poa.ORB_1_4;
  46: import gnu.CORBA.Poa.AOM;
  47: import gnu.CORBA.Poa.gnuPOA;
  48: import gnu.CORBA.typecodes.GeneralTypeCode;
  49: 
  50: import org.omg.CORBA.Any;
  51: import org.omg.CORBA.BAD_PARAM;
  52: import org.omg.CORBA.COMM_FAILURE;
  53: import org.omg.CORBA.CompletionStatus;
  54: import org.omg.CORBA.INVALID_TRANSACTION;
  55: import org.omg.CORBA.INV_OBJREF;
  56: import org.omg.CORBA.MARSHAL;
  57: import org.omg.CORBA.NO_PERMISSION;
  58: import org.omg.CORBA.OBJECT_NOT_EXIST;
  59: import org.omg.CORBA.OMGVMCID;
  60: import org.omg.CORBA.ORB;
  61: import org.omg.CORBA.SystemException;
  62: import org.omg.CORBA.TCKind;
  63: import org.omg.CORBA.TRANSACTION_REQUIRED;
  64: import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
  65: import org.omg.CORBA.TypeCode;
  66: import org.omg.CORBA.UNKNOWN;
  67: import org.omg.CORBA.portable.InputStream;
  68: import org.omg.CORBA.portable.OutputStream;
  69: 
  70: import java.io.ByteArrayInputStream;
  71: import java.io.ByteArrayOutputStream;
  72: import java.io.ObjectInputStream;
  73: import java.io.ObjectOutputStream;
  74: import java.io.Serializable;
  75: import java.net.MalformedURLException;
  76: import java.rmi.AccessException;
  77: import java.rmi.MarshalException;
  78: import java.rmi.NoSuchObjectException;
  79: import java.rmi.Remote;
  80: import java.rmi.RemoteException;
  81: import java.rmi.ServerError;
  82: import java.rmi.ServerException;
  83: import java.rmi.UnexpectedException;
  84: import java.rmi.server.RMIClassLoader;
  85: import java.util.Hashtable;
  86: 
  87: import javax.rmi.CORBA.Stub;
  88: import javax.rmi.CORBA.Tie;
  89: import javax.rmi.CORBA.Util;
  90: import javax.rmi.CORBA.UtilDelegate;
  91: import javax.rmi.CORBA.ValueHandler;
  92: import javax.transaction.InvalidTransactionException;
  93: import javax.transaction.TransactionRequiredException;
  94: import javax.transaction.TransactionRolledbackException;
  95: 
  96: /**
  97:  * The implementation of UtilDelegate.
  98:  *
  99:  * @author Wu Gansha (gansha.wu@intel.com) (stub)
 100:  * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) (implementation)
 101:  */
 102: public class UtilDelegateImpl
 103:   extends RmiUtilities
 104:   implements UtilDelegate
 105: {
 106:   /**
 107:    * The instance of the value handler, requested once.
 108:    */
 109:   static ValueHandler m_ValueHandler;
 110: 
 111:   /**
 112:    * The global map of all ties to they records.
 113:    */
 114:   static Hashtable m_Ties = new Hashtable();
 115: 
 116:   /**
 117:    * The global map of all targets to they records.
 118:    */
 119:   static Hashtable m_Targets = new Hashtable();
 120: 
 121:   /**
 122:    * The standard package for that the exception names are omitted.
 123:    */
 124:   static final String m_StandardPackage = "org.omg.CORBA.";
 125: 
 126:   /**
 127:    * Make a deep copy of the object.
 128:    */
 129:   public Object copyObject(Object obj, ORB orb)
 130:     throws RemoteException
 131:   {
 132:     // Strings are immutable, can be shared.
 133:     if (obj instanceof String)
 134:       return obj;
 135:     else if (obj == null)
 136:       return null;
 137:     else if (obj instanceof String[] || obj instanceof String[][]
 138:       || obj instanceof String[][][])
 139:       {
 140:         // String arrays can be just cloned.
 141:         return ((Object[]) obj).clone();
 142:       }
 143:     else if (obj instanceof Serializable)
 144:       {
 145:         try
 146:           {
 147:             ByteArrayOutputStream a = new ByteArrayOutputStream();
 148:             ObjectOutputStream ou = new ObjectOutputStream(a);
 149:             ou.writeObject(obj);
 150:             ou.close();
 151:             ObjectInputStream input = new ObjectInputStream(
 152:               new ByteArrayInputStream(a.toByteArray()));
 153:             return input.readObject();
 154:           }
 155:         catch (Exception ex)
 156:           {
 157:             RemoteException rex = new RemoteException("Cannot copy " + obj);
 158:             throw rex;
 159:           }
 160:       }
 161:     else
 162:       return obj;
 163:   }
 164: 
 165:   /**
 166:    * Make a deep copy of the object array.
 167:    */
 168:   public Object[] copyObjects(Object[] obj, ORB orb)
 169:     throws RemoteException
 170:   {
 171:     return (Object[]) copyObject(obj, orb);
 172:   }
 173: 
 174:   public ValueHandler createValueHandler()
 175:   {
 176:     if (m_ValueHandler == null)
 177:       m_ValueHandler = (ValueHandler) DelegateFactory.getInstance(DelegateFactory.VALUEHANDLER);
 178:     return m_ValueHandler;
 179:   }
 180: 
 181:   /**
 182:    * Returns the codebase of the given class.
 183:    */
 184:   public String getCodebase(Class clz)
 185:   {
 186:     return RMIClassLoader.getClassAnnotation(clz);
 187:   }
 188: 
 189:   /**
 190:    * Get the Tie that handles invocations on the given target. If the target/Tie
 191:    * pair has not been previously registered using {@link #registerTarget},
 192:    * this method tries to locate a tie class by the name pattern. If this
 193:    * succeeds, the tie-target pair is also registered.
 194:    *
 195:    * @return the Tie.
 196:    */
 197:   public Tie getTie(Remote target)
 198:   {
 199:     synchronized (m_Targets)
 200:       {
 201:         Tie tie;
 202:         TieTargetRecord r = ((TieTargetRecord) m_Targets.get(target));
 203:         if (r == null)
 204:           {
 205:             if (target instanceof Stub)
 206:               {
 207:                 tie = StubDelegateImpl.getTieFromStub(target);
 208:                 registerTarget(tie, target);
 209:               }
 210:             else
 211:               {
 212:                 // Treat this as implementation.
 213:                 String tieClassName = getTieClassName(target.getClass().getName());
 214:                 try
 215:                   {
 216:                     Class tieClass = Util.loadClass(tieClassName, null,
 217:                       target.getClass().getClassLoader());
 218:                     tie = (Tie) tieClass.newInstance();
 219:                   }
 220:                 catch (Exception e)
 221:                   {
 222:                     MARSHAL m = new MARSHAL("Unable to instantiate "
 223:                       + tieClassName);
 224:                     m.minor = Minor.TargetConversion;
 225:                     m.initCause(e);
 226:                     throw m;
 227:                   }
 228:                 tie.setTarget(target);
 229:                 registerTarget(tie, target);
 230:               }
 231:           }
 232:         else
 233:           tie = r.tie;
 234:         return tie;
 235:       }
 236:   }
 237: 
 238:   /**
 239:    * Get the Stub class name for the name, representing the given interface.
 240:    */
 241:   private String getTieClassName(String interf)
 242:   {
 243:     String stubClassName;
 244:     int p = interf.lastIndexOf('.');
 245: 
 246:     if (p < 0)
 247:       // The interface is defined in the default package.
 248:       stubClassName = "_" + interf + "_Tie";
 249:     else
 250:       stubClassName = interf.substring(0, p + 1) + "_"
 251:         + interf.substring(p + 1) + "_Tie";
 252:     return stubClassName;
 253:   }
 254: 
 255:   /**
 256:    * Register the Tie-target pair. As the Tie is a Servant, it can potentially
 257:    * be connected to several objects and hence may be registered with several
 258:    * targets.
 259:    */
 260:   public void registerTarget(Tie tie, Remote target)
 261:   {
 262:     synchronized (m_Ties)
 263:       {
 264:         synchronized (m_Targets)
 265:           {
 266:             TieTargetRecord r = (TieTargetRecord) m_Ties.get(tie);
 267:             if (r == null)
 268:               {
 269:                 // First registration for this Tie.
 270:                 r = new TieTargetRecord(tie);
 271:                 m_Ties.put(tie, r);
 272:               }
 273:             if (target != null)
 274:               {
 275:                 r.add(target);
 276:                 m_Targets.put(target, r);
 277:               }
 278:           }
 279:       }
 280:   }
 281: 
 282:   /**
 283:    * Deactivate the associated Tie, if it is found and is not connected to other
 284:    * registered targets. Independing from the POA policies, the transparent
 285:    * reactivation will not be possible.
 286:    */
 287:   public void unexportObject(Remote target)
 288:     throws NoSuchObjectException
 289:   {
 290:     synchronized (m_Ties)
 291:       {
 292:         synchronized (m_Targets)
 293:           {
 294:             TieTargetRecord r = ((TieTargetRecord) m_Targets.get(target));
 295:             if (r != null)
 296:               {
 297:                 if (target instanceof org.omg.CORBA.Object)
 298:                   r.tie.orb().disconnect((org.omg.CORBA.Object) target);
 299: 
 300:                 if (r.unused())
 301:                   {
 302:                     m_Targets.remove(target);
 303:                     m_Ties.remove(r.tie);
 304:                     r.tie.deactivate();
 305: 
 306:                     if (r.tie.orb() instanceof ORB_1_4)
 307:                       {
 308:                         // Standard case, when more deep cleanup is possible.
 309:                         // Independing from the POA policies, the object will
 310:                         // not be activable transparently.
 311:                         ORB_1_4 orb = (ORB_1_4) r.tie.orb();
 312: 
 313:                         if (target instanceof org.omg.CORBA.Object)
 314:                           {
 315:                             AOM.Obj record = orb.rootPOA.findObject((org.omg.CORBA.Object) target);
 316: 
 317:                             if (record != null && record.servant == r.tie
 318:                               && record.poa instanceof gnuPOA)
 319:                               {
 320:                                 ((gnuPOA) record.poa).aom.remove(record.key);
 321:                                 record.deactivated = true;
 322:                                 record.servant = null;
 323:                               }
 324:                           }
 325:                       }
 326:                   }
 327:               }
 328:           }
 329:       }
 330:   }
 331: 
 332:   /**
 333:    * Checks if the given stub is local.
 334:    *
 335:    * @param stub a stub to check.
 336:    * @return true if the stub is local, false otherwise.
 337:    */
 338:   public boolean isLocal(Stub stub)
 339:     throws RemoteException
 340:   {
 341:     try
 342:       {
 343:         return stub._is_local();
 344:       }
 345:     catch (SystemException e)
 346:       {
 347:         RemoteException rex = new RemoteException();
 348:         rex.initCause(e);
 349:         throw rex;
 350:       }
 351:   }
 352: 
 353:   /**
 354:    * Load the class. The method uses class loaders from the call stact first. If
 355:    * this fails, the further behaviour depends on the System Property
 356:    * "java.rmi.server.useCodebaseOnly" with default value "false".
 357:    *
 358:    * <ul>
 359:    * <li>Try the current thread context class loader first.</li>
 360:    * <li>If remoteCodebase is non-null and useCodebaseOnly is "false" then call
 361:    * java.rmi.server.RMIClassLoader.loadClass (remoteCodebase, className)</li>
 362:    * <li> If remoteCodebase is null or useCodebaseOnly is true then call
 363:    * java.rmi.server.RMIClassLoader.loadClass(className)</li>
 364:    * <li>If a class is still not successfully loaded and the loader != null
 365:    * then try Class.forName(className, false, loader). </li>
 366:    * </ul>
 367:    *
 368:    * @param className the name of the class.
 369:    * @param remoteCodebase the codebase.
 370:    * @param loader the class loader.
 371:    * @return the loaded class.
 372:    *
 373:    * @throws ClassNotFoundException of the class cannot be loaded.
 374:    */
 375:   public Class loadClass(String className, String remoteCodebase,
 376:     ClassLoader loader)
 377:     throws ClassNotFoundException
 378:   {
 379:     if (loader == null)
 380:       loader = VMStackWalker.firstNonNullClassLoader();
 381: 
 382:     String p_useCodebaseOnly = System.getProperty("java.rmi.server.useCodebaseOnly");
 383: 
 384:     boolean useCodebaseOnly = p_useCodebaseOnly != null
 385:       && p_useCodebaseOnly.trim().equalsIgnoreCase("true");
 386: 
 387:     if (useCodebaseOnly)
 388:       remoteCodebase = null;
 389: 
 390:     try
 391:       {
 392:         return RMIClassLoader.loadClass(remoteCodebase, className, loader);
 393:       }
 394:     catch (MalformedURLException x)
 395:       {
 396:         throw new ClassNotFoundException(className, x);
 397:       }
 398:   }
 399: 
 400:   /**
 401:    * Converts CORBA {@link SystemException} into RMI {@link RemoteException}.
 402:    * The exception is converted as defined in the following table:
 403:    * <p>
 404:    * <table border = "1">
 405:    * <tr>
 406:    * <th>CORBA Exception</th>
 407:    * <th>RMI Exception</th>
 408:    * </tr>
 409:    * <tr>
 410:    * <td>{@link COMM_FAILURE}</td>
 411:    * <td>{@link MarshalException}</td>
 412:    * </tr>
 413:    * <tr>
 414:    * <td>{@link INV_OBJREF}</td>
 415:    * <td>{@link  NoSuchObjectException}</td>
 416:    * </tr>
 417:    * <tr>
 418:    * <td>{@link NO_PERMISSION}</td>
 419:    * <td>{@link  AccessException}</td>
 420:    * </tr>
 421:    * <tr>
 422:    * <td>{@link MARSHAL}</td>
 423:    * <td>{@link  MarshalException}</td>
 424:    * </tr>
 425:    * <tr>
 426:    * <td>{@link BAD_PARAM} (all other cases)</td>
 427:    * <td>{@link  MarshalException}</td>
 428:    * </tr>
 429:    * <tr>
 430:    * <td>{@link OBJECT_NOT_EXIST}</td>
 431:    * <td>{@link  NoSuchObjectException}</td>
 432:    * </tr>
 433:    * <tr>
 434:    * <td>{@link TRANSACTION_REQUIRED}</td>
 435:    * <td>{@link  TransactionRequiredException}</td>
 436:    * </tr>
 437:    * <tr>
 438:    * <td>{@link TRANSACTION_ROLLEDBACK}</td>
 439:    * <td>{@link  TransactionRolledbackException}</td>
 440:    * </tr>
 441:    * <tr>
 442:    * <td>{@link INVALID_TRANSACTION}</td>
 443:    * <td>{@link  InvalidTransactionException}</td>
 444:    * </tr>
 445:    * <tr>
 446:    * <td bgcolor="lightgray">Any other {@link SystemException}</td>
 447:    * <td bgcolor="lightgray">{@link RemoteException}</td>
 448:    * </tr>
 449:    * </table>
 450:    * </p>
 451:    * <p>
 452:    * The exception detailed message always consists of
 453:    * <ol>
 454:    * <li>the string "CORBA "</li>
 455:    * <li>the CORBA name of the system exception</li>
 456:    * <li>single space</li>
 457:    * <li>the hexadecimal value of the system exception's minor code, preceeded
 458:    * by 0x (higher bits contain {@link OMGVMCID}).</li>
 459:    * <li>single space</li>
 460:    * <li>the {@link CompletionStatus} of the exception: "Yes", "No" or "Maybe".</li>
 461:    * </ol>
 462:    * <p>
 463:    * For instance, if the Internet connection was refused:
 464:    * </p>
 465:    * <p>
 466:    * <pre>
 467:    * <code>CORBA COMM_FAILURE 0x535500C9 No</code>
 468:    * </p>
 469:    * <p>
 470:    * The original CORBA exception is set as the cause of the RemoteException
 471:    * being created.
 472:    * </p>
 473:    */
 474:   public RemoteException mapSystemException(SystemException ex)
 475:   {
 476:     RemoteException rex;
 477: 
 478:     String status;
 479: 
 480:     switch (ex.completed.value())
 481:       {
 482:         case CompletionStatus._COMPLETED_MAYBE:
 483:           status = "Maybe";
 484:           break;
 485: 
 486:         case CompletionStatus._COMPLETED_NO:
 487:           status = "No";
 488:           break;
 489: 
 490:         case CompletionStatus._COMPLETED_YES:
 491:           status = "Yes";
 492:           break;
 493: 
 494:         default:
 495:           status = "Unexpected completion status " + ex.completed.value();
 496:       }
 497: 
 498:     String name = ex.getClass().getName();
 499: 
 500:     if (name.startsWith(m_StandardPackage))
 501:       name = name.substring(m_StandardPackage.length());
 502: 
 503:     String message = "CORBA " + name + " 0x" + Integer.toHexString(ex.minor)
 504:       + " " + status;
 505: 
 506:     if (ex instanceof COMM_FAILURE)
 507:       rex = new MarshalException(message, ex);
 508:     else if (ex instanceof INV_OBJREF)
 509:       {
 510:         rex = new NoSuchObjectException(message);
 511:         rex.detail = ex;
 512:       }
 513:     else if (ex instanceof NO_PERMISSION)
 514:       rex = new AccessException(message, ex);
 515:     else if (ex instanceof MARSHAL)
 516:       rex = new MarshalException(message, ex);
 517:     else if (ex instanceof BAD_PARAM)
 518:       rex = new MarshalException(message, ex);
 519:     else if (ex instanceof OBJECT_NOT_EXIST)
 520:       {
 521:         rex = new NoSuchObjectException(message);
 522:         rex.detail = ex;
 523:       }
 524:     else if (ex instanceof TRANSACTION_REQUIRED)
 525:       {
 526:         rex = new TransactionRequiredException(message);
 527:         rex.detail = ex;
 528:       }
 529:     else if (ex instanceof TRANSACTION_ROLLEDBACK)
 530:       {
 531:         rex = new TransactionRolledbackException(message);
 532:         rex.detail = ex;
 533:       }
 534:     else if (ex instanceof INVALID_TRANSACTION)
 535:       {
 536:         rex = new InvalidTransactionException(message);
 537:         rex.detail = ex;
 538:       }
 539:     else if (ex instanceof UNKNOWN)
 540:       rex = wrapException(ex.getCause());
 541:     else
 542:       rex = new RemoteException(message, ex);
 543: 
 544:     return rex;
 545:   }
 546: 
 547:   /**
 548:    * Converts the exception that was thrown by the implementation method on a
 549:    * server side into RemoteException that can be transferred and re-thrown on a
 550:    * client side. The method converts exceptions as defined in the following
 551:    * table: <table border = "1">
 552:    * <tr>
 553:    * <th>Exception to map (or subclass)</th>
 554:    * <th>Maps into</th>
 555:    * </tr>
 556:    * <tr>
 557:    * <td>{@link Error}</td>
 558:    * <td>{@link ServerError}</td>
 559:    * </tr>
 560:    * <tr>
 561:    * <td>{@link RemoteException}</td>
 562:    * <td>{@link ServerException}</td>
 563:    * </tr>
 564:    * <tr>
 565:    * <td>{@link SystemException}</td>
 566:    * <td>wrapException({@link #mapSystemException})</td>
 567:    * </tr>
 568:    * <tr>
 569:    * <td>{@link RuntimeException}</td>
 570:    * <td><b>rethrows</b></td>
 571:    * </tr>
 572:    * <tr>
 573:    * <td>Any other exception</td>
 574:    * <td>{@link UnexpectedException}</td>
 575:    * </tr>
 576:    * </table>
 577:    *
 578:    * @param ex an exception that was thrown on a server side implementation.
 579:    *
 580:    * @return the corresponding RemoteException unless it is a RuntimeException.
 581:    *
 582:    * @throws RuntimeException the passed exception if it is an instance of
 583:    * RuntimeException.
 584:    *
 585:    * @specnote It is the same behavior, as in Suns implementations 1.4.0-1.5.0.
 586:    */
 587:   public RemoteException wrapException(Throwable ex)
 588:     throws RuntimeException
 589:   {
 590:     if (ex instanceof RuntimeException)
 591:       throw (RuntimeException) ex;
 592:     else if (ex instanceof Error)
 593:       return new ServerError(ex.getMessage(), (Error) ex);
 594:     else if (ex instanceof RemoteException)
 595:       return new ServerException(ex.getMessage(), (Exception) ex);
 596:     else if (ex instanceof SystemException)
 597:       return wrapException(mapSystemException((SystemException) ex));
 598:     else
 599:       return new UnexpectedException("Unexpected", (Exception) ex);
 600:   }
 601: 
 602:   /**
 603:    * Write abstract interface to the CORBA output stream. The write format is
 604:    * matching CORBA abstract interface. Remotes and CORBA objects are written as
 605:    * objects, other classes are supposed to be value types and are written as
 606:    * such. {@link Remote}s are processed as defined in
 607:    * {@link #writeRemoteObject}. The written data contains discriminator,
 608:    * defining, that was written. Another method that writes the same content is
 609:    * {@link org.omg.CORBA_2_3.portable.OutputStream#write_abstract_interface(java.lang.Object)}.
 610:    *
 611:    * @param output a stream to write to, must be
 612:    * {@link org.omg.CORBA_2_3.portable.OutputStream}.
 613:    *
 614:    * @param object an object to write, must be CORBA object, Remote
 615:    */
 616:   public void writeAbstractObject(OutputStream output, Object object)
 617:   {
 618:     ((org.omg.CORBA_2_3.portable.OutputStream) output).write_abstract_interface(object);
 619:   }
 620: 
 621:   /**
 622:    * Write the passed java object to the output stream in the form of the CORBA
 623:    * {@link Any}. This includes creating an writing the object {@link TypeCode}
 624:    * first. Such Any can be later read by a non-RMI-IIOP CORBA implementation
 625:    * and manipulated, for instance, by means, provided in
 626:    * {@link org.omg.DynamicAny.DynAny}. Depending from the passed value, this
 627:    * method writes CORBA object, value type or value box. For value types Null
 628:    * is written with the abstract interface, its typecode having repository id
 629:    * "IDL:omg.org/CORBA/AbstractBase:1.0" and the empty string name.
 630:    *
 631:    * @param output the object to write.
 632:    * @param object the java object that must be written in the form of the CORBA
 633:    * {@link Any}.
 634:    */
 635:   public void writeAny(OutputStream output, Object object)
 636:   {
 637:     Any any = output.orb().create_any();
 638:     if (object == null)
 639:       {
 640:         GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_abstract_interface);
 641:         t.setId("IDL:omg.org/CORBA/AbstractBase:1.0");
 642:         t.setName("");
 643:         any.type(t);
 644:         output.write_any(any);
 645:         return;
 646:       }
 647:     else if (object instanceof org.omg.CORBA.Object
 648:       && !(object instanceof Remote))
 649:       {
 650:         // Write as value type.
 651:         boolean inserted = ObjectCreator.insertWithHelper(any, object);
 652:         if (inserted)
 653:           {
 654:             output.write_any(any);
 655:             return;
 656:           }
 657:       }
 658: 
 659:     if (object instanceof org.omg.CORBA.Object)
 660:       writeAnyAsRemote(output, object);
 661:     else if (object instanceof Serializable)
 662:       {
 663:         any.insert_Value((Serializable) object);
 664:         output.write_any(any);
 665:       }
 666:     else
 667:       {
 668:         MARSHAL m = new MARSHAL(object.getClass().getName()
 669:           + " must be CORBA Object, Remote or Serializable");
 670:         m.minor = Minor.NonSerializable;
 671:         throw m;
 672:       }
 673:   }
 674: 
 675:   /**
 676:    * Write Any as for remote object.
 677:    */
 678:   void writeAnyAsRemote(OutputStream output, Object object)
 679:   {
 680:     GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_objref);
 681:     t.setId(m_ValueHandler.getRMIRepositoryID(object.getClass()));
 682:     t.setName(object.getClass().getName());
 683: 
 684:     // Writing Any (typecode, followed by value).
 685:     output.write_TypeCode(t);
 686:     writeRemoteObject(output, object);
 687:   }
 688: 
 689:   /**
 690:    * Get the class name excluding the package name.
 691:    */
 692:   String getName(String n)
 693:   {
 694:     int p = n.lastIndexOf('.');
 695:     if (p < 0)
 696:       return n;
 697:     else
 698:       return n.substring(p + 1);
 699:   }
 700: 
 701:   /**
 702:    * Read Any from the input stream.
 703:    */
 704:   public Object readAny(InputStream input)
 705:   {
 706:     return input.read_any();
 707:   }
 708: 
 709:   /**
 710:    * Write the passed parameter to the output stream as CORBA object. If the
 711:    * parameter is an instance of Remote and not an instance of Stub, the method
 712:    * instantiates a suitable Tie, connects the parameter to this Tie and then
 713:    * connects that Tie to the ORB that is requested from the output stream. Then
 714:    * the object reference is written to the stream, making remote invocations
 715:    * possible. This method is used in write_value(..) method group in
 716:    * {@link org.omg.CORBA_2_3.portable.OutputStream} and also may be called
 717:    * directly from generated Stubs and Ties.
 718:    *
 719:    * @param output a stream to write to, must be
 720:    * org.omg.CORBA_2_3.portable.OutputStream
 721:    * @param object an object to write.
 722:    */
 723:   public void writeRemoteObject(OutputStream an_output, Object object)
 724:   {
 725:     org.omg.CORBA_2_3.portable.OutputStream output = (org.omg.CORBA_2_3.portable.OutputStream) an_output;
 726:     if (object == null)
 727:       an_output.write_Object(null);
 728:     else if (isTieRequired(object))
 729:       {
 730:         // Find the interface that is implemented by the object and extends
 731:         // Remote.
 732:         Class fc = getExportedInterface(object);
 733:         exportTie(output, object, fc);
 734:       }
 735:     else if (object instanceof org.omg.CORBA.Object)
 736:       {
 737:         ensureOrbRunning(output);
 738:         an_output.write_Object((org.omg.CORBA.Object) object);
 739:       }
 740:     else if (object != null && object instanceof Serializable)
 741:       writeFields(an_output, (Serializable) object);
 742:   }
 743: 
 744: }