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