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