src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java

Wed, 28 Mar 2012 02:50:50 -0700

author
mbankal
date
Wed, 28 Mar 2012 02:50:50 -0700
changeset 371
e324dfb90c9e
parent 158
91006f157c46
child 443
3c73273667ae
permissions
-rw-r--r--

7079902: Refine CORBA data models
Reviewed-by: coffeys

     1 /*
     2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 /*
    26  * Licensed Materials - Property of IBM
    27  * RMI-IIOP v1.0
    28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
    29  *
    30  */
    32 package com.sun.corba.se.impl.javax.rmi.CORBA; // Util (sed marker, don't remove!)
    34 import java.rmi.RemoteException;
    35 import java.rmi.UnexpectedException;
    36 import java.rmi.MarshalException;
    38 import java.rmi.server.RMIClassLoader;
    40 import java.util.Hashtable;
    41 import java.util.Enumeration;
    42 import java.util.Properties;
    43 import java.util.Map;
    44 import java.util.WeakHashMap;
    46 import java.io.Serializable;
    47 import java.io.NotSerializableException;
    49 import java.lang.reflect.Constructor;
    51 import javax.rmi.CORBA.ValueHandler;
    52 import javax.rmi.CORBA.Tie;
    54 import java.security.AccessController;
    55 import java.security.PrivilegedAction;
    57 import java.rmi.MarshalException;
    58 import java.rmi.NoSuchObjectException;
    59 import java.rmi.AccessException;
    60 import java.rmi.Remote;
    61 import java.rmi.ServerError;
    62 import java.rmi.ServerException;
    63 import java.rmi.ServerRuntimeException;
    65 import javax.transaction.TransactionRequiredException;
    66 import javax.transaction.TransactionRolledbackException;
    67 import javax.transaction.InvalidTransactionException;
    69 import org.omg.CORBA.SystemException;
    70 import org.omg.CORBA.Any;
    71 import org.omg.CORBA.TypeCode;
    72 import org.omg.CORBA.COMM_FAILURE;
    73 import org.omg.CORBA.BAD_PARAM;
    74 import org.omg.CORBA.INV_OBJREF;
    75 import org.omg.CORBA.NO_PERMISSION;
    76 import org.omg.CORBA.MARSHAL;
    77 import org.omg.CORBA.OBJECT_NOT_EXIST;
    78 import org.omg.CORBA.TRANSACTION_REQUIRED;
    79 import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
    80 import org.omg.CORBA.INVALID_TRANSACTION;
    81 import org.omg.CORBA.BAD_OPERATION;
    82 import org.omg.CORBA.ACTIVITY_REQUIRED;
    83 import org.omg.CORBA.ACTIVITY_COMPLETED;
    84 import org.omg.CORBA.INVALID_ACTIVITY;
    85 import org.omg.CORBA.CompletionStatus;
    86 import org.omg.CORBA.TCKind;
    87 import org.omg.CORBA.portable.UnknownException;
    88 import org.omg.CORBA.portable.InputStream;
    89 import org.omg.CORBA.portable.OutputStream;
    91 // This class must be able to function with non-Sun ORBs.
    92 // This means that any of the following com.sun.corba classes
    93 // must only occur in contexts that also handle the non-Sun case.
    95 import com.sun.corba.se.pept.transport.ContactInfoList ;
    96 import com.sun.corba.se.spi.orb.ORB;
    97 import com.sun.corba.se.spi.orb.ORBVersionFactory;
    98 import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
    99 import com.sun.corba.se.spi.transport.CorbaContactInfoList ;
   100 import com.sun.corba.se.spi.protocol.LocalClientRequestDispatcher ;
   101 import com.sun.corba.se.spi.copyobject.ReflectiveCopyException ;
   102 import com.sun.corba.se.spi.copyobject.CopierManager ;
   103 import com.sun.corba.se.spi.copyobject.ObjectCopierFactory ;
   104 import com.sun.corba.se.spi.copyobject.ObjectCopier ;
   105 import com.sun.corba.se.impl.io.ValueHandlerImpl;
   106 import com.sun.corba.se.impl.orbutil.ORBConstants;
   107 import com.sun.corba.se.impl.orbutil.ORBUtility;
   108 import com.sun.corba.se.impl.logging.OMGSystemException;
   109 import com.sun.corba.se.impl.util.Utility;
   110 import com.sun.corba.se.impl.util.IdentityHashtable;
   111 import com.sun.corba.se.impl.util.JDKBridge;
   112 import com.sun.corba.se.impl.orbutil.ORBClassLoader;
   113 import com.sun.corba.se.impl.logging.UtilSystemException;
   114 import com.sun.corba.se.spi.logging.CORBALogDomains;
   116 /**
   117  * Provides utility methods that can be used by stubs and ties to
   118  * perform common operations.
   119  */
   120 public class Util implements javax.rmi.CORBA.UtilDelegate
   121 {
   122     // Runs as long as there are exportedServants
   123     private static KeepAlive keepAlive = null;
   125     // Maps targets to ties.
   126     private static IdentityHashtable exportedServants = new IdentityHashtable();
   128     private static ValueHandlerImpl valueHandlerSingleton = new ValueHandlerImpl();
   130     private UtilSystemException utilWrapper = UtilSystemException.get(
   131                                                   CORBALogDomains.RPC_ENCODING);
   133     private static Util instance = null;
   135     public Util() {
   136         setInstance(this);
   137     }
   139     private static void setInstance( Util util ) {
   140         assert instance == null : "Instance already defined";
   141         instance = util;
   142     }
   144     public static Util getInstance() {
   145         return instance;
   146     }
   148     public static boolean isInstanceDefined() {
   149         return instance != null;
   150     }
   152     // Used by TOAFactory.shutdown to unexport all targets for this
   153     // particular ORB.  This happens during ORB shutdown.
   154     public void unregisterTargetsForORB(org.omg.CORBA.ORB orb)
   155     {
   156         for (Enumeration e = exportedServants.keys(); e.hasMoreElements(); )
   157         {
   158             java.lang.Object key = e.nextElement();
   159             Remote target = (Remote)(key instanceof Tie ? ((Tie)key).getTarget() : key);
   161             // Bug 4476347: BAD_OPERATION is thrown if the ties delegate isn't set.
   162             // We can ignore this because it means the tie is not connected to an ORB.
   163             try {
   164                 if (orb == getTie(target).orb()) {
   165                     try {
   166                         unexportObject(target);
   167                     } catch( java.rmi.NoSuchObjectException ex ) {
   168                         // We neglect this exception if at all if it is
   169                         // raised. It is not harmful.
   170                     }
   171                 }
   172             } catch (BAD_OPERATION bad) {
   173                 /* Ignore */
   174             }
   175         }
   176     }
   178    /**
   179      * Maps a SystemException to a RemoteException.
   180      * @param ex the SystemException to map.
   181      * @return the mapped exception.
   182      */
   183     public RemoteException mapSystemException(SystemException ex)
   184     {
   185         if (ex instanceof UnknownException) {
   186             Throwable orig = ((UnknownException)ex).originalEx;
   187             if (orig instanceof Error) {
   188                 return new ServerError("Error occurred in server thread",(Error)orig);
   189             } else if (orig instanceof RemoteException) {
   190                 return new ServerException("RemoteException occurred in server thread",
   191                     (Exception)orig);
   192             } else if (orig instanceof RuntimeException) {
   193                 throw (RuntimeException) orig;
   194             }
   195         }
   197         // Build the message string...
   198         String name = ex.getClass().getName();
   199         String corbaName = name.substring(name.lastIndexOf('.')+1);
   200         String status;
   201         switch (ex.completed.value()) {
   202             case CompletionStatus._COMPLETED_YES:
   203                 status = "Yes";
   204                 break;
   205             case CompletionStatus._COMPLETED_NO:
   206                 status = "No";
   207                 break;
   208             case CompletionStatus._COMPLETED_MAYBE:
   209             default:
   210                 status = "Maybe";
   211                 break;
   212         }
   214         String message = "CORBA " + corbaName + " " + ex.minor + " " + status;
   216         // Now map to the correct RemoteException type...
   217         if (ex instanceof COMM_FAILURE) {
   218             return new MarshalException(message, ex);
   219         } else if (ex instanceof INV_OBJREF) {
   220             RemoteException newEx = new NoSuchObjectException(message);
   221             newEx.detail = ex;
   222             return newEx;
   223         } else if (ex instanceof NO_PERMISSION) {
   224             return new AccessException(message, ex);
   225         } else if (ex instanceof MARSHAL) {
   226             return new MarshalException(message, ex);
   227         } else if (ex instanceof OBJECT_NOT_EXIST) {
   228             RemoteException newEx = new NoSuchObjectException(message);
   229             newEx.detail = ex;
   230             return newEx;
   231         } else if (ex instanceof TRANSACTION_REQUIRED) {
   232             RemoteException newEx = new TransactionRequiredException(message);
   233             newEx.detail = ex;
   234             return newEx;
   235         } else if (ex instanceof TRANSACTION_ROLLEDBACK) {
   236             RemoteException newEx = new TransactionRolledbackException(message);
   237             newEx.detail = ex;
   238             return newEx;
   239         } else if (ex instanceof INVALID_TRANSACTION) {
   240             RemoteException newEx = new InvalidTransactionException(message);
   241             newEx.detail = ex;
   242             return newEx;
   243         } else if (ex instanceof BAD_PARAM) {
   244             Exception inner = ex;
   246             // Pre-Merlin Sun ORBs used the incorrect minor code for
   247             // this case.  See Java to IDL ptc-00-01-08 1.4.8.
   248             if (ex.minor == ORBConstants.LEGACY_SUN_NOT_SERIALIZABLE ||
   249                 ex.minor == OMGSystemException.NOT_SERIALIZABLE) {
   251                 if (ex.getMessage() != null)
   252                     inner = new NotSerializableException(ex.getMessage());
   253                 else
   254                     inner = new NotSerializableException();
   256                 inner.initCause( ex ) ;
   257             }
   259             return new MarshalException(message,inner);
   260         } else if (ex instanceof ACTIVITY_REQUIRED) {
   261             try {
   262                 Class cl = ORBClassLoader.loadClass(
   263                                "javax.activity.ActivityRequiredException");
   264                 Class[] params = new Class[2];
   265                 params[0] = java.lang.String.class;
   266                 params[1] = java.lang.Throwable.class;
   267                 Constructor cr = cl.getConstructor(params);
   268                 Object[] args = new Object[2];
   269                 args[0] = message;
   270                 args[1] = ex;
   271                 return (RemoteException) cr.newInstance(args);
   272             } catch (Throwable e) {
   273                 utilWrapper.classNotFound(
   274                               e, "javax.activity.ActivityRequiredException");
   275             }
   276         } else if (ex instanceof ACTIVITY_COMPLETED) {
   277             try {
   278                 Class cl = ORBClassLoader.loadClass(
   279                                "javax.activity.ActivityCompletedException");
   280                 Class[] params = new Class[2];
   281                 params[0] = java.lang.String.class;
   282                 params[1] = java.lang.Throwable.class;
   283                 Constructor cr = cl.getConstructor(params);
   284                 Object[] args = new Object[2];
   285                 args[0] = message;
   286                 args[1] = ex;
   287                 return (RemoteException) cr.newInstance(args);
   288               } catch (Throwable e) {
   289                   utilWrapper.classNotFound(
   290                                 e, "javax.activity.ActivityCompletedException");
   291               }
   292         } else if (ex instanceof INVALID_ACTIVITY) {
   293             try {
   294                 Class cl = ORBClassLoader.loadClass(
   295                                "javax.activity.InvalidActivityException");
   296                 Class[] params = new Class[2];
   297                 params[0] = java.lang.String.class;
   298                 params[1] = java.lang.Throwable.class;
   299                 Constructor cr = cl.getConstructor(params);
   300                 Object[] args = new Object[2];
   301                 args[0] = message;
   302                 args[1] = ex;
   303                 return (RemoteException) cr.newInstance(args);
   304               } catch (Throwable e) {
   305                   utilWrapper.classNotFound(
   306                                 e, "javax.activity.InvalidActivityException");
   307               }
   308         }
   310         // Just map to a generic RemoteException...
   311         return new RemoteException(message, ex);
   312     }
   314     /**
   315      * Writes any java.lang.Object as a CORBA any.
   316      * @param out the stream in which to write the any.
   317      * @param obj the object to write as an any.
   318      */
   319     public void writeAny( org.omg.CORBA.portable.OutputStream out,
   320                          java.lang.Object obj)
   321     {
   322         org.omg.CORBA.ORB orb = out.orb();
   324         // Create Any
   325         Any any = orb.create_any();
   327         // Make sure we have a connected object...
   328         java.lang.Object newObj = Utility.autoConnect(obj,orb,false);
   330         if (newObj instanceof org.omg.CORBA.Object) {
   331             any.insert_Object((org.omg.CORBA.Object)newObj);
   332         } else {
   333             if (newObj == null) {
   334                 // Handle the null case, including backwards
   335                 // compatibility issues
   336                 any.insert_Value(null, createTypeCodeForNull(orb));
   337             } else {
   338                 if (newObj instanceof Serializable) {
   339                     // If they're our Any and ORB implementations,
   340                     // we may want to do type code related versioning.
   341                     TypeCode tc = createTypeCode((Serializable)newObj, any, orb);
   342                     if (tc == null)
   343                         any.insert_Value((Serializable)newObj);
   344                     else
   345                         any.insert_Value((Serializable)newObj, tc);
   346                 } else if (newObj instanceof Remote) {
   347                     ORBUtility.throwNotSerializableForCorba(newObj.getClass().getName());
   348                 } else {
   349                     ORBUtility.throwNotSerializableForCorba(newObj.getClass().getName());
   350                 }
   351             }
   352         }
   354         out.write_any(any);
   355     }
   357     /**
   358      * When using our own ORB and Any implementations, we need to get
   359      * the ORB version and create the type code appropriately.  This is
   360      * to overcome a bug in which the JDK 1.3.x ORBs used a tk_char
   361      * rather than a tk_wchar to describe a Java char field.
   362      *
   363      * This only works in RMI-IIOP with Util.writeAny since we actually
   364      * know what ORB and stream we're writing with when we insert
   365      * the value.
   366      *
   367      * Returns null if it wasn't possible to create the TypeCode (means
   368      * it wasn't our ORB or Any implementation).
   369      *
   370      * This does not handle null objs.
   371      */
   372     private TypeCode createTypeCode(Serializable obj,
   373                                     org.omg.CORBA.Any any,
   374                                     org.omg.CORBA.ORB orb) {
   376         if (any instanceof com.sun.corba.se.impl.corba.AnyImpl &&
   377             orb instanceof ORB) {
   379             com.sun.corba.se.impl.corba.AnyImpl anyImpl
   380                 = (com.sun.corba.se.impl.corba.AnyImpl)any;
   382             ORB ourORB = (ORB)orb;
   384             return anyImpl.createTypeCodeForClass(obj.getClass(), ourORB);
   386         } else
   387             return null;
   388     }
   391     /**
   392      * This is used to create the TypeCode for a null reference.
   393      * It also handles backwards compatibility with JDK 1.3.x.
   394      *
   395      * This method will not return null.
   396      */
   397     private TypeCode createTypeCodeForNull(org.omg.CORBA.ORB orb)
   398     {
   399         if (orb instanceof ORB) {
   401             ORB ourORB = (ORB)orb;
   403             // Preserve backwards compatibility with Kestrel and Ladybird
   404             // by not fully implementing interop issue resolution 3857,
   405             // and returning a null TypeCode with a tk_value TCKind.
   406             // If we're not talking to Kestrel or Ladybird, fall through
   407             // to the abstract interface case (also used for foreign ORBs).
   408             if (!ORBVersionFactory.getFOREIGN().equals(ourORB.getORBVersion()) &&
   409                 ORBVersionFactory.getNEWER().compareTo(ourORB.getORBVersion()) > 0) {
   411                 return orb.get_primitive_tc(TCKind.tk_value);
   412             }
   413         }
   415         // Use tk_abstract_interface as detailed in the resolution
   417         // REVISIT: Define this in IDL and get the ID in generated code
   418         String abstractBaseID = "IDL:omg.org/CORBA/AbstractBase:1.0";
   420         return orb.create_abstract_interface_tc(abstractBaseID, "");
   421     }
   423     /**
   424      * Reads a java.lang.Object as a CORBA any.
   425      * @param in the stream from which to read the any.
   426      * @return the object read from the stream.
   427      */
   428     public Object readAny(InputStream in)
   429     {
   430         Any any = in.read_any();
   431         if ( any.type().kind().value() == TCKind._tk_objref )
   432             return any.extract_Object ();
   433         else
   434             return any.extract_Value();
   435     }
   437     /**
   438      * Writes a java.lang.Object as a CORBA Object. If <code>obj</code> is
   439      * an exported RMI-IIOP server object, the tie is found
   440      * and wired to <code>obj</code>, then written to <code>out.write_Object(org.omg.CORBA.Object)</code>.
   441      * If <code>obj</code> is a CORBA Object, it is written to
   442      * <code>out.write_Object(org.omg.CORBA.Object)</code>.
   443      * @param out the stream in which to write the object.
   444      * @param obj the object to write.
   445      */
   446     public void writeRemoteObject(OutputStream out, java.lang.Object obj)
   447     {
   448         // Make sure we have a connected object, then
   449         // write it out...
   451         Object newObj = Utility.autoConnect(obj,out.orb(),false);
   452         out.write_Object((org.omg.CORBA.Object)newObj);
   453     }
   455     /**
   456      * Writes a java.lang.Object as either a value or a CORBA Object.
   457      * If <code>obj</code> is a value object or a stub object, it is written to
   458      * <code>out.write_abstract_interface(java.lang.Object)</code>. If <code>obj</code> is an exported
   459      * RMI-IIOP server object, the tie is found and wired to <code>obj</code>,
   460      * then written to <code>out.write_abstract_interface(java.lang.Object)</code>.
   461      * @param out the stream in which to write the object.
   462      * @param obj the object to write.
   463      */
   464     public void writeAbstractObject( OutputStream out, java.lang.Object obj )
   465     {
   466         // Make sure we have a connected object, then
   467         // write it out...
   469         Object newObj = Utility.autoConnect(obj,out.orb(),false);
   470         ((org.omg.CORBA_2_3.portable.OutputStream)out).write_abstract_interface(newObj);
   471     }
   473     /**
   474      * Registers a target for a tie. Adds the tie to an internal table and calls
   475      * {@link Tie#setTarget} on the tie object.
   476      * @param tie the tie to register.
   477      * @param target the target for the tie.
   478      */
   479     public void registerTarget(javax.rmi.CORBA.Tie tie, java.rmi.Remote target)
   480     {
   481         synchronized (exportedServants) {
   482             // Do we already have this target registered?
   483             if (lookupTie(target) == null) {
   484                 // No, so register it and set the target...
   485                 exportedServants.put(target,tie);
   486                 tie.setTarget(target);
   488                 // Do we need to instantiate our keep-alive thread?
   489                 if (keepAlive == null) {
   490                     // Yes. Instantiate our keep-alive thread and start
   491                     // it up...
   492                     keepAlive = (KeepAlive)AccessController.doPrivileged(new PrivilegedAction() {
   493                         public java.lang.Object run() {
   494                             return new KeepAlive();
   495                         }
   496                     });
   497                     keepAlive.start();
   498                 }
   499             }
   500         }
   501     }
   503     /**
   504      * Removes the associated tie from an internal table and calls {@link Tie#deactivate}
   505      * to deactivate the object.
   506      * @param target the object to unexport.
   507      */
   508     public void unexportObject(java.rmi.Remote target)
   509         throws java.rmi.NoSuchObjectException
   510     {
   511         synchronized (exportedServants) {
   512             Tie cachedTie = lookupTie(target);
   513             if (cachedTie != null) {
   514                 exportedServants.remove(target);
   515                 Utility.purgeStubForTie(cachedTie);
   516                 Utility.purgeTieAndServant(cachedTie);
   517                 try {
   518                     cleanUpTie(cachedTie);
   519                 } catch (BAD_OPERATION e) {
   520                     // ignore
   521                 } catch (org.omg.CORBA.OBJ_ADAPTER e) {
   522                     // This can happen when the target was never associated with a POA.
   523                     // We can safely ignore this case.
   524                 }
   526                 // Is it time to shut down our keep alive thread?
   527                 if (exportedServants.isEmpty()) {
   528                     keepAlive.quit();
   529                     keepAlive = null;
   530                 }
   531             } else {
   532                 throw new java.rmi.NoSuchObjectException("Tie not found" );
   533             }
   534         }
   535     }
   537     protected void cleanUpTie(Tie cachedTie)
   538         throws java.rmi.NoSuchObjectException
   539     {
   540         cachedTie.setTarget(null);
   541         cachedTie.deactivate();
   542     }
   544     /**
   545      * Returns the tie (if any) for a given target object.
   546      * @return the tie or null if no tie is registered for the given target.
   547      */
   548     public Tie getTie (Remote target)
   549     {
   550         synchronized (exportedServants) {
   551             return lookupTie(target);
   552         }
   553     }
   555     /**
   556      * An unsynchronized version of getTie() for internal use.
   557      */
   558     private static Tie lookupTie (Remote target)
   559     {
   560         Tie result = (Tie)exportedServants.get(target);
   561         if (result == null && target instanceof Tie) {
   562             if (exportedServants.contains(target)) {
   563                 result = (Tie)target;
   564             }
   565         }
   566         return result;
   567     }
   569     /**
   570      * Returns a singleton instance of a class that implements the
   571      * {@link ValueHandler} interface.
   572      * @return a class which implements the ValueHandler interface.
   573      */
   574     public ValueHandler createValueHandler()
   575     {
   576         return valueHandlerSingleton;
   577     }
   579     /**
   580      * Returns the codebase, if any, for the given class.
   581      * @param clz the class to get a codebase for.
   582      * @return a space-separated list of URLs, or null.
   583      */
   584     public String getCodebase(java.lang.Class clz) {
   585         return RMIClassLoader.getClassAnnotation(clz);
   586     }
   588     /**
   589      * Returns a class instance for the specified class.
   590      * @param className the name of the class.
   591      * @param remoteCodebase a space-separated list of URLs at which
   592      * the class might be found. May be null.
   593      * @param loadingContext a class whose ClassLoader may be used to
   594      * load the class if all other methods fail.
   595      * @return the <code>Class</code> object representing the loaded class.
   596      * @exception ClassNotFoundException if class cannot be loaded.
   597      */
   598     public Class loadClass( String className, String remoteCodebase,
   599         ClassLoader loader) throws ClassNotFoundException
   600     {
   601         return JDKBridge.loadClass(className,remoteCodebase,loader);
   602     }
   604     /**
   605      * The <tt>isLocal</tt> method has the same semantics as the
   606      * ObjectImpl._is_local method, except that it can throw a RemoteException.
   607      * (no it doesn't but the spec says it should.)
   608      *
   609      * The <tt>_is_local()</tt> method is provided so that stubs may determine
   610      * if a particular object is implemented by a local servant and hence local
   611      * invocation APIs may be used.
   612      *
   613      * @param stub the stub to test.
   614      *
   615      * @return The <tt>_is_local()</tt> method returns true if
   616      * the servant incarnating the object is located in the same process as
   617      * the stub and they both share the same ORB instance.  The <tt>_is_local()</tt>
   618      * method returns false otherwise. The default behavior of <tt>_is_local()</tt> is
   619      * to return false.
   620      *
   621      * @throws RemoteException The Java to IDL specification does to
   622      * specify the conditions that cause a RemoteException to be thrown.
   623      */
   624     public boolean isLocal(javax.rmi.CORBA.Stub stub) throws RemoteException
   625     {
   626         boolean result = false ;
   628         try {
   629             org.omg.CORBA.portable.Delegate delegate = stub._get_delegate() ;
   630             if (delegate instanceof CorbaClientDelegate) {
   631                 // For the Sun ORB
   632                 CorbaClientDelegate cdel = (CorbaClientDelegate)delegate ;
   633                 ContactInfoList cil = cdel.getContactInfoList() ;
   634                 if (cil instanceof CorbaContactInfoList) {
   635                     CorbaContactInfoList ccil = (CorbaContactInfoList)cil ;
   636                     LocalClientRequestDispatcher lcs = ccil.getLocalClientRequestDispatcher() ;
   637                     result = lcs.useLocalInvocation( null ) ;
   638                 }
   639             } else {
   640                 // For a non-Sun ORB
   641                 result = delegate.is_local( stub ) ;
   642             }
   643         } catch (SystemException e) {
   644             throw javax.rmi.CORBA.Util.mapSystemException(e);
   645         }
   647         return result ;
   648     }
   650     /**
   651      * Wraps an exception thrown by an implementation
   652      * method.  It returns the corresponding client-side exception.
   653      * @param orig the exception to wrap.
   654      * @return the wrapped exception.
   655      */
   656     public RemoteException wrapException(Throwable orig)
   657     {
   658         if (orig instanceof SystemException) {
   659             return mapSystemException((SystemException)orig);
   660         }
   662         if (orig instanceof Error) {
   663             return new ServerError("Error occurred in server thread",(Error)orig);
   664         } else if (orig instanceof RemoteException) {
   665             return new ServerException("RemoteException occurred in server thread",
   666                                        (Exception)orig);
   667         } else if (orig instanceof RuntimeException) {
   668             throw (RuntimeException) orig;
   669         }
   671         if (orig instanceof Exception)
   672             return new UnexpectedException( orig.toString(), (Exception)orig );
   673         else
   674             return new UnexpectedException( orig.toString());
   675     }
   677     /**
   678      * Copies or connects an array of objects. Used by local stubs
   679      * to copy any number of actual parameters, preserving sharing
   680      * across parameters as necessary to support RMI semantics.
   681      * @param obj the objects to copy or connect.
   682      * @param orb the ORB.
   683      * @return the copied or connected objects.
   684      * @exception RemoteException if any object could not be copied or connected.
   685      */
   686     public Object[] copyObjects (Object[] obj, org.omg.CORBA.ORB orb)
   687         throws RemoteException
   688     {
   689         if (obj == null)
   690             // Bug fix for 5018613: JCK test expects copyObjects to throw
   691             // NPE when obj==null.  This is actually not in the spec, since
   692             // obj is not really an RMI-IDL data type, but we follow our
   693             // test here, and force this error to be thrown.
   694             throw new NullPointerException() ;
   696         Class compType = obj.getClass().getComponentType() ;
   697         if (Remote.class.isAssignableFrom( compType ) && !compType.isInterface()) {
   698             // obj is an array of remote impl types.  This
   699             // causes problems with stream copier, so we copy
   700             // it over to an array of Remotes instead.
   701             Remote[] result = new Remote[obj.length] ;
   702             System.arraycopy( (Object)obj, 0, (Object)result, 0, obj.length ) ;
   703             return (Object[])copyObject( result, orb ) ;
   704         } else
   705             return (Object[])copyObject( obj, orb ) ;
   706     }
   708     /**
   709      * Copies or connects an object. Used by local stubs to copy
   710      * an actual parameter, result object, or exception.
   711      * @param obj the object to copy.
   712      * @param orb the ORB.
   713      * @return the copy or connected object.
   714      * @exception RemoteException if the object could not be copied or connected.
   715      */
   716     public Object copyObject (Object obj, org.omg.CORBA.ORB orb)
   717         throws RemoteException
   718     {
   719         if (orb instanceof ORB) {
   720             ORB lorb = (ORB)orb ;
   722             try {
   723                 try {
   724                     // This gets the copier for the current invocation, which was
   725                     // previously set by preinvoke.
   726                     return lorb.peekInvocationInfo().getCopierFactory().make().copy( obj ) ;
   727                 } catch (java.util.EmptyStackException exc) {
   728                     // copyObject was invoked outside of an invocation, probably by
   729                     // a test.  Get the default copier from the ORB.
   730                     // XXX should we just make the default copier available directly
   731                     // and avoid constructing one on each call?
   732                     CopierManager cm = lorb.getCopierManager() ;
   733                     ObjectCopier copier = cm.getDefaultObjectCopierFactory().make() ;
   734                     return copier.copy( obj ) ;
   735                 }
   736             } catch (ReflectiveCopyException exc) {
   737                 RemoteException rexc = new RemoteException() ;
   738                 rexc.initCause( exc ) ;
   739                 throw rexc ;
   740             }
   741         } else {
   742             org.omg.CORBA_2_3.portable.OutputStream out =
   743                 (org.omg.CORBA_2_3.portable.OutputStream)orb.create_output_stream();
   744             out.write_value((Serializable)obj);
   745             org.omg.CORBA_2_3.portable.InputStream in =
   746                 (org.omg.CORBA_2_3.portable.InputStream)out.create_input_stream();
   747             return in.read_value();
   748         }
   749     }
   750 }
   752 class KeepAlive extends Thread
   753 {
   754     boolean quit = false;
   756     public KeepAlive ()
   757     {
   758         setDaemon(false);
   759     }
   761     public synchronized void run ()
   762     {
   763         while (!quit) {
   764             try {
   765                 wait();
   766             } catch (InterruptedException e) {}
   767         }
   768     }
   770     public synchronized void quit ()
   771     {
   772         quit = true;
   773         notifyAll();
   774     }
   775 }

mercurial