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

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 1
55540e827aef
child 158
91006f157c46
permissions
-rw-r--r--

Initial load

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

mercurial