1 /* 2 * Copyright (c) 1999, 2004, 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 /* 27 * Licensed Materials - Property of IBM 28 * RMI-IIOP v1.0 29 * Copyright IBM Corp. 1998 1999 All Rights Reserved 30 * 31 */ 32 33 package com.sun.corba.se.impl.util; 34 35 import org.omg.CORBA.SystemException; 36 import org.omg.CORBA.CompletionStatus; 37 import org.omg.CORBA.BAD_OPERATION; 38 import org.omg.CORBA.BAD_INV_ORDER; 39 import org.omg.CORBA.BAD_PARAM; 40 import org.omg.CORBA.ORB; 41 import org.omg.CORBA.Any; 42 import org.omg.CORBA.TypeCode; 43 import org.omg.CORBA.Principal; 44 import org.omg.CORBA.portable.InputStream; 45 import org.omg.CORBA.portable.OutputStream; 46 import org.omg.CORBA.portable.BoxedValueHelper; 47 import org.omg.CORBA.portable.ValueFactory; 48 import org.omg.CORBA.portable.Streamable; 49 import org.omg.CORBA.portable.Delegate; 50 51 52 import java.util.Hashtable; 53 import java.util.NoSuchElementException; 54 55 import java.rmi.Remote; 56 import java.rmi.NoSuchObjectException; 57 import java.rmi.RemoteException; 58 import java.rmi.server.RemoteStub; 59 60 import javax.rmi.PortableRemoteObject; 61 import javax.rmi.CORBA.Stub; 62 import javax.rmi.CORBA.Tie; 63 import javax.rmi.CORBA.Util; 64 65 import java.io.Serializable; 66 import java.io.File; 67 import java.io.FileInputStream; 68 69 import org.omg.PortableServer.POA; 70 71 import com.sun.org.omg.SendingContext.CodeBase; 72 73 import com.sun.corba.se.spi.logging.CORBALogDomains ; 74 import com.sun.corba.se.spi.presentation.rmi.PresentationManager; 75 import com.sun.corba.se.spi.presentation.rmi.StubAdapter ; 76 77 import com.sun.corba.se.impl.logging.UtilSystemException ; 78 import com.sun.corba.se.impl.logging.OMGSystemException ; 79 80 /** 81 * Handy class full of static functions. 82 */ 83 public final class Utility { 84 85 public static final String STUB_PREFIX = "_"; 86 public static final String RMI_STUB_SUFFIX = "_Stub"; 87 public static final String DYNAMIC_STUB_SUFFIX = "_DynamicStub" ; 88 public static final String IDL_STUB_SUFFIX = "Stub"; 89 public static final String TIE_SUFIX = "_Tie"; 90 private static IdentityHashtable tieCache = new IdentityHashtable(); 91 private static IdentityHashtable tieToStubCache = new IdentityHashtable(); 92 private static IdentityHashtable stubToTieCache = new IdentityHashtable(); 93 private static Object CACHE_MISS = new Object(); 94 private static UtilSystemException wrapper = UtilSystemException.get( 95 CORBALogDomains.UTIL ) ; 96 private static OMGSystemException omgWrapper = OMGSystemException.get( 97 CORBALogDomains.UTIL ) ; 98 99 /** 100 * Ensure that stubs, ties, and implementation objects 101 * are 'connected' to the runtime. Converts implementation 102 * objects to a type suitable for sending on the wire. 103 * @param obj the object to connect. 104 * @param orb the ORB to connect to if obj is exported to IIOP. 105 * @param convertToStub true if implementation types should be 106 * converted to Stubs rather than just org.omg.CORBA.Object. 107 * @return the connected object. 108 * @exception NoSuchObjectException if obj is an implementation 109 * which has not been exported. 110 */ 111 public static Object autoConnect(Object obj, ORB orb, boolean convertToStub) 112 { 113 if (obj == null) { 114 return obj; 115 } 116 117 if (StubAdapter.isStub(obj)) { 118 try { 119 StubAdapter.getDelegate(obj) ; 120 } catch (BAD_OPERATION okay) { 121 try { 122 StubAdapter.connect( obj, orb ) ; 123 } catch (RemoteException e) { 124 // The stub could not be connected because it 125 // has an invalid IOR... 126 throw wrapper.objectNotConnected( e, 127 obj.getClass().getName() ) ; 128 } 129 } 130 131 return obj; 132 } 133 134 if (obj instanceof Remote) { 135 Remote remoteObj = (Remote)obj; 136 Tie theTie = Util.getTie(remoteObj); 137 if (theTie != null) { 138 try { 139 theTie.orb(); 140 } catch (SystemException okay) { 141 theTie.orb(orb); 142 } 143 144 if (convertToStub) { 145 Object result = loadStub(theTie,null,null,true); 146 if (result != null) { 147 return result; 148 } else { 149 throw wrapper.couldNotLoadStub(obj.getClass().getName()); 150 } 151 } else { 152 return StubAdapter.activateTie( theTie ); 153 } 154 } else { 155 // This is an implementation object which has not been 156 // exported to IIOP OR is a JRMP stub or implementation 157 // object which cannot be marshalled into an ORB stream... 158 throw wrapper.objectNotExported( obj.getClass().getName() ) ; 159 } 160 } 161 162 // Didn't need to do anything, just return the input... 163 164 return obj; 165 } 166 167 /* 168 * Get a new instance of an RMI-IIOP Tie for the 169 * given server object. 170 */ 171 public static Tie loadTie(Remote obj) { 172 Tie result = null; 173 Class objClass = obj.getClass(); 174 175 // Have we tried to find this guy before? 176 177 synchronized (tieCache) { 178 179 Object it = tieCache.get(obj); 180 181 if (it == null) { 182 183 // No, so try it... 184 185 try { 186 187 // First try the classname... 188 189 result = loadTie(objClass); 190 191 // If we don't have a valid tie at this point, 192 // walk up the parent chain until we either 193 // load a tie or encounter PortableRemoteObject 194 // or java.lang.Object... 195 196 while (result == null && 197 (objClass = objClass.getSuperclass()) != null && 198 objClass != PortableRemoteObject.class && 199 objClass != Object.class) { 200 201 result = loadTie(objClass); 202 } 203 } catch (Exception ex) { 204 wrapper.loadTieFailed( ex, objClass.getName() ) ; 205 } 206 207 // Did we get it? 208 209 if (result == null) { 210 211 // Nope, so cache that fact... 212 213 tieCache.put(obj,CACHE_MISS); 214 215 } else { 216 217 // Yes, so cache it... 218 219 tieCache.put(obj,result); 220 } 221 } else { 222 223 // Yes, return a new instance or fail again if 224 // it was a miss last time... 225 226 if (it != CACHE_MISS) { 227 try { 228 result = (Tie) it.getClass().newInstance(); 229 } catch (Exception e) { 230 } 231 } 232 } 233 } 234 235 return result; 236 } 237 238 /* 239 * Load an RMI-IIOP Tie 240 */ 241 private static Tie loadTie(Class theClass) 242 { 243 return com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory(). 244 getTie( theClass ) ; 245 } 246 247 /* 248 * Clear the stub/tie caches. Intended for use by 249 * test code. 250 */ 251 public static void clearCaches() { 252 synchronized (tieToStubCache) { 253 tieToStubCache.clear(); 254 } 255 synchronized (tieCache) { 256 tieCache.clear(); 257 } 258 synchronized (stubToTieCache) { 259 stubToTieCache.clear(); 260 } 261 } 262 263 /* 264 * Load a class and check that it is assignable to a given type. 265 * @param className the class name. 266 * @param remoteCodebase the codebase to use. May be null. 267 * @param loader the class loader of last resort. May be null. 268 * @param expectedType the expected type. May be null. 269 * @return the loaded class. 270 */ 271 static Class loadClassOfType(String className, String remoteCodebase, 272 ClassLoader loader, Class expectedType, 273 ClassLoader expectedTypeClassLoader) throws ClassNotFoundException 274 { 275 Class loadedClass = null; 276 277 try { 278 //Sequence finding of the stubs according to spec 279 try{ 280 //If-else is put here for speed up of J2EE. 281 //According to the OMG spec, the if clause is not dead code. 282 //It can occur if some compiler has allowed generation 283 //into org.omg.stub hierarchy for non-offending 284 //classes. This will encourage people to 285 //produce non-offending class stubs in their own hierarchy. 286 if (!PackagePrefixChecker.hasOffendingPrefix( 287 PackagePrefixChecker.withoutPackagePrefix(className))){ 288 loadedClass = Util.loadClass( 289 PackagePrefixChecker.withoutPackagePrefix(className), 290 remoteCodebase, 291 loader); 292 } else { 293 loadedClass = Util.loadClass(className, remoteCodebase, 294 loader); 295 } 296 } catch (ClassNotFoundException cnfe) { 297 loadedClass = Util.loadClass(className, remoteCodebase, 298 loader); 299 } 300 if (expectedType == null) 301 return loadedClass; 302 } catch (ClassNotFoundException cnfe) { 303 if (expectedType == null) 304 throw cnfe; 305 } 306 307 // If no class was loaded, or if the loaded class is not of the 308 // correct type, make a further attempt to load the correct class 309 // using the classloader of the expected type. 310 // _REVISIT_ Is this step necessary, or should the Util,loadClass 311 // algorithm always produce a valid class if the setup is correct? 312 // Does the OMG standard algorithm need to be changed to include 313 // this step? 314 if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)){ 315 if (expectedType.getClassLoader() != expectedTypeClassLoader) 316 throw new IllegalArgumentException( 317 "expectedTypeClassLoader not class loader of " + 318 "expected Type."); 319 320 if (expectedTypeClassLoader != null) 321 loadedClass = expectedTypeClassLoader.loadClass(className); 322 else { 323 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 324 if (cl == null) 325 cl = ClassLoader.getSystemClassLoader(); 326 327 loadedClass = cl.loadClass(className); 328 } 329 } 330 331 return loadedClass; 332 } 333 334 /* 335 * Load a class and check that it is compatible with a given type. 336 * @param className the class name. 337 * @param remoteCodebase the codebase to use. May be null. 338 * @param loadingContext the loading context. May be null. 339 * @param relatedType the related type. May be null. 340 * @return the loaded class. 341 */ 342 public static Class loadClassForClass (String className, 343 String remoteCodebase, 344 ClassLoader loader, 345 Class relatedType, 346 ClassLoader relatedTypeClassLoader) 347 throws ClassNotFoundException 348 { 349 if (relatedType == null) 350 return Util.loadClass(className, remoteCodebase, loader); 351 352 Class loadedClass = null; 353 try { 354 loadedClass = Util.loadClass(className, remoteCodebase, loader); 355 } catch (ClassNotFoundException cnfe) { 356 if (relatedType.getClassLoader() == null) 357 throw cnfe; 358 } 359 360 // If no class was not loaded, or if the loaded class is not of the 361 // correct type, make a further attempt to load the correct class 362 // using the classloader of the related type. 363 // _REVISIT_ Is this step necessary, or should the Util,loadClass 364 // algorithm always produce a valid class if the setup is correct? 365 // Does the OMG standard algorithm need to be changed to include 366 // this step? 367 if (loadedClass == null || 368 (loadedClass.getClassLoader() != null && 369 loadedClass.getClassLoader().loadClass(relatedType.getName()) != 370 relatedType)) 371 { 372 if (relatedType.getClassLoader() != relatedTypeClassLoader) 373 throw new IllegalArgumentException( 374 "relatedTypeClassLoader not class loader of relatedType."); 375 376 if (relatedTypeClassLoader != null) 377 loadedClass = relatedTypeClassLoader.loadClass(className); 378 } 379 380 return loadedClass; 381 } 382 383 /** 384 * Get the helper for an IDLValue 385 * 386 * Throws MARSHAL exception if no helper found. 387 */ 388 public static BoxedValueHelper getHelper(Class clazz, String codebase, 389 String repId) 390 { 391 String className = null; 392 if (clazz != null) { 393 className = clazz.getName(); 394 if (codebase == null) 395 codebase = Util.getCodebase(clazz); 396 } else { 397 if (repId != null) 398 className = RepositoryId.cache.getId(repId).getClassName(); 399 if (className == null) // no repId or unrecognized repId 400 throw wrapper.unableLocateValueHelper( 401 CompletionStatus.COMPLETED_MAYBE); 402 } 403 404 try { 405 ClassLoader clazzLoader = 406 (clazz == null ? null : clazz.getClassLoader()); 407 Class helperClass = 408 loadClassForClass(className+"Helper", codebase, clazzLoader, 409 clazz, clazzLoader); 410 return (BoxedValueHelper)helperClass.newInstance(); 411 412 } catch (ClassNotFoundException cnfe) { 413 throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE, 414 cnfe ); 415 } catch (IllegalAccessException iae) { 416 throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE, 417 iae ); 418 } catch (InstantiationException ie) { 419 throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE, 420 ie ); 421 } catch (ClassCastException cce) { 422 throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE, 423 cce ); 424 } 425 } 426 427 /** 428 * Get the factory for an IDLValue 429 * 430 * Throws MARSHAL exception if no factory found. 431 */ 432 public static ValueFactory getFactory(Class clazz, String codebase, 433 ORB orb, String repId) 434 { 435 ValueFactory factory = null; 436 if ((orb != null) && (repId != null)) { 437 try { 438 factory = ((org.omg.CORBA_2_3.ORB)orb).lookup_value_factory( 439 repId); 440 } catch (org.omg.CORBA.BAD_PARAM ex) { 441 // Try other way 442 } 443 } 444 445 String className = null; 446 if (clazz != null) { 447 className = clazz.getName(); 448 if (codebase == null) 449 codebase = Util.getCodebase(clazz); 450 } else { 451 if (repId != null) 452 className = RepositoryId.cache.getId(repId).getClassName(); 453 if (className == null) // no repId or unrecognized repId 454 throw omgWrapper.unableLocateValueFactory( 455 CompletionStatus.COMPLETED_MAYBE); 456 } 457 458 // if earlier search found a non-default factory, or the same default 459 // factory that loadClassForClass would return, bale out now... 460 if (factory != null && 461 (!factory.getClass().getName().equals(className+"DefaultFactory") || 462 (clazz == null && codebase == null))) 463 return factory; 464 465 try { 466 ClassLoader clazzLoader = 467 (clazz == null ? null : clazz.getClassLoader()); 468 Class factoryClass = 469 loadClassForClass(className+"DefaultFactory", codebase, 470 clazzLoader, clazz, clazzLoader); 471 return (ValueFactory)factoryClass.newInstance(); 472 473 } catch (ClassNotFoundException cnfe) { 474 throw omgWrapper.unableLocateValueFactory( 475 CompletionStatus.COMPLETED_MAYBE, cnfe); 476 } catch (IllegalAccessException iae) { 477 throw omgWrapper.unableLocateValueFactory( 478 CompletionStatus.COMPLETED_MAYBE, iae); 479 } catch (InstantiationException ie) { 480 throw omgWrapper.unableLocateValueFactory( 481 CompletionStatus.COMPLETED_MAYBE, ie); 482 } catch (ClassCastException cce) { 483 throw omgWrapper.unableLocateValueFactory( 484 CompletionStatus.COMPLETED_MAYBE, cce); 485 } 486 } 487 488 /* 489 * Load an RMI-IIOP Stub given a Tie. 490 * @param tie the tie. 491 * @param stubClass the stub class. May be null. 492 * @param remoteCodebase the codebase to use. May be null. 493 * @param onlyMostDerived if true, will fail if cannot load a stub for the 494 * first repID in the tie. If false, will walk all repIDs. 495 * @return the stub or null if not found. 496 */ 497 498 public static Remote loadStub(Tie tie, 499 PresentationManager.StubFactory stubFactory, 500 String remoteCodebase, 501 boolean onlyMostDerived) 502 { 503 StubEntry entry = null; 504 505 // Do we already have it cached? 506 synchronized (tieToStubCache) { 507 Object cached = tieToStubCache.get(tie); 508 if (cached == null) { 509 // No, so go try to load it... 510 entry = loadStubAndUpdateCache( 511 tie, stubFactory, remoteCodebase, onlyMostDerived); 512 } else { 513 // Yes, is it a stub? If not, it was a miss last 514 // time, so return null again... 515 if (cached != CACHE_MISS) { 516 // It's a stub. 517 entry = (StubEntry) cached; 518 519 // Does the cached stub meet the requirements 520 // of the caller? If the caller does not require 521 // the most derived stub and does not require 522 // a specific stub type, we don't have to check 523 // any further because the cached type is good 524 // enough... 525 if (!entry.mostDerived && onlyMostDerived) { 526 // We must reload because we do not have 527 // the most derived cached already... 528 // The stubFactory arg must be null here 529 // to force onlyMostDerived=true to work 530 // correctly. 531 entry = loadStubAndUpdateCache(tie,null, 532 remoteCodebase,true); 533 } else if (stubFactory != null && 534 !StubAdapter.getTypeIds(entry.stub)[0].equals( 535 stubFactory.getTypeIds()[0]) ) 536 { 537 // We do not have exactly the right stub. First, try to 538 // upgrade the cached stub by forcing it to the most 539 // derived stub... 540 entry = loadStubAndUpdateCache(tie,null, 541 remoteCodebase,true); 542 543 // If that failed, try again with the exact type 544 // we need... 545 if (entry == null) { 546 entry = loadStubAndUpdateCache(tie,stubFactory, 547 remoteCodebase,onlyMostDerived); 548 } 549 } else { 550 // Use the cached stub. Is the delegate set? 551 try { 552 Delegate stubDel = StubAdapter.getDelegate( 553 entry.stub ) ; 554 } catch (Exception e2) { 555 // No, so set it if we can... 556 try { 557 Delegate del = StubAdapter.getDelegate( 558 tie ) ; 559 StubAdapter.setDelegate( entry.stub, 560 del ) ; 561 } catch (Exception e) {} 562 } 563 } 564 } 565 } 566 } 567 568 if (entry != null) { 569 return (Remote)entry.stub; 570 } else { 571 return null; 572 } 573 } 574 575 /* 576 * Load an RMI-IIOP Stub given a Tie, but do not look in the cache. 577 * This method must be called with the lock held for tieToStubCache. 578 * @param tie the tie. 579 * @param stubFactory the stub factory. May be null. 580 * @param remoteCodebase the codebase to use. May be null. 581 * @param onlyMostDerived if true, will fail if cannot load a stub for the 582 * first repID in the tie. If false, will walk all repIDs. 583 * @return the StubEntry or null if not found. 584 */ 585 private static StubEntry loadStubAndUpdateCache ( 586 Tie tie, PresentationManager.StubFactory stubFactory, 587 String remoteCodebase, boolean onlyMostDerived) 588 { 589 org.omg.CORBA.Object stub = null; 590 StubEntry entry = null; 591 boolean tieIsStub = StubAdapter.isStub( tie ) ; 592 593 if (stubFactory != null) { 594 try { 595 stub = stubFactory.makeStub(); 596 } catch (Throwable e) { 597 wrapper.stubFactoryCouldNotMakeStub( e ) ; 598 if (e instanceof ThreadDeath) { 599 throw (ThreadDeath) e; 600 } 601 } 602 } else { 603 String[] ids = null; 604 if (tieIsStub) { 605 ids = StubAdapter.getTypeIds( tie ) ; 606 } else { 607 // This will throw an exception if the tie 608 // is not a Servant. XXX Handle this better? 609 ids = ((org.omg.PortableServer.Servant)tie). 610 _all_interfaces( null, null ); 611 } 612 613 if (remoteCodebase == null) { 614 remoteCodebase = Util.getCodebase(tie.getClass()); 615 } 616 617 if (ids.length == 0) { 618 stub = new org.omg.stub.java.rmi._Remote_Stub(); 619 } else { 620 // Now walk all the RepIDs till we find a stub or fail... 621 for (int i = 0; i < ids.length; i++) { 622 if (ids[i].length() == 0) { 623 stub = new org.omg.stub.java.rmi._Remote_Stub(); 624 break; 625 } 626 627 try { 628 PresentationManager.StubFactoryFactory stubFactoryFactory = 629 com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory(); 630 RepositoryId rid = RepositoryId.cache.getId( ids[i] ) ; 631 String className = rid.getClassName() ; 632 boolean isIDLInterface = rid.isIDLType() ; 633 stubFactory = stubFactoryFactory.createStubFactory( 634 className, isIDLInterface, remoteCodebase, null, 635 tie.getClass().getClassLoader() ) ; 636 stub = stubFactory.makeStub(); 637 break; 638 } catch (Exception e) { 639 wrapper.errorInMakeStubFromRepositoryId( e ) ; 640 } 641 642 if (onlyMostDerived) 643 break; 644 } 645 } 646 } 647 648 if (stub == null) { 649 // Stub == null, so cache the miss... 650 tieToStubCache.put(tie,CACHE_MISS); 651 } else { 652 if (tieIsStub) { 653 try { 654 Delegate del = StubAdapter.getDelegate( tie ) ; 655 StubAdapter.setDelegate( stub, del ) ; 656 } catch( Exception e1 ) { 657 // The tie does not have a delegate set, so stash 658 // this tie away using the stub as a key so that 659 // later, when the stub is connected, we can find 660 // and connect the tie as well... 661 662 synchronized (stubToTieCache) { 663 stubToTieCache.put(stub,tie); 664 } 665 } 666 } else { 667 // Tie extends Servant 668 try { 669 Delegate delegate = StubAdapter.getDelegate( tie ) ; 670 StubAdapter.setDelegate( stub, delegate ) ; 671 } catch( org.omg.CORBA.BAD_INV_ORDER bad) { 672 synchronized (stubToTieCache) { 673 stubToTieCache.put(stub,tie); 674 } 675 } catch( Exception e ) { 676 // Exception is caught because of any of the 677 // following reasons 678 // 1) POA is not associated with the TIE 679 // 2) POA Policies for the tie-associated POA 680 // does not support _this_object() call. 681 throw wrapper.noPoa( e ) ; 682 } 683 } 684 // Update the cache... 685 entry = new StubEntry(stub,onlyMostDerived); 686 tieToStubCache.put(tie,entry); 687 } 688 689 return entry; 690 } 691 692 /* 693 * If we loadStub(Tie,...) stashed away a tie which was 694 * not connected, remove it from the cache and return 695 * it. 696 */ 697 public static Tie getAndForgetTie (org.omg.CORBA.Object stub) { 698 synchronized (stubToTieCache) { 699 return (Tie) stubToTieCache.remove(stub); 700 } 701 } 702 703 /* 704 * Remove any cached Stub for the given tie. 705 */ 706 public static void purgeStubForTie (Tie tie) { 707 StubEntry entry; 708 synchronized (tieToStubCache) { 709 entry = (StubEntry)tieToStubCache.remove(tie); 710 } 711 if (entry != null) { 712 synchronized (stubToTieCache) { 713 stubToTieCache.remove(entry.stub); 714 } 715 } 716 } 717 718 /* 719 * Remove cached tie/servant pair. 720 */ 721 public static void purgeTieAndServant (Tie tie) { 722 synchronized (tieCache) { 723 Object target = tie.getTarget(); 724 if (target != null) 725 tieCache.remove(target); 726 } 727 } 728 729 /* 730 * Convert a RepId to a stubName... 731 */ 732 public static String stubNameFromRepID (String repID) { 733 734 // Convert the typeid to a RepositoryId instance, get 735 // the className and mangle it as needed... 736 737 RepositoryId id = RepositoryId.cache.getId(repID); 738 String className = id.getClassName(); 739 740 if (id.isIDLType()) { 741 className = idlStubName(className); 742 } else { 743 className = stubName(className); 744 } 745 return className; 746 } 747 748 749 /* 750 * Load an RMI-IIOP Stub. This is used in PortableRemoteObject.narrow. 751 */ 752 public static Remote loadStub (org.omg.CORBA.Object narrowFrom, 753 Class narrowTo) 754 { 755 Remote result = null; 756 757 try { 758 // Get the codebase from the delegate to use when loading 759 // the new stub, if possible... 760 String codebase = null; 761 try { 762 // We can't assume that narrowFrom is a CORBA_2_3 stub, yet 763 // it may have a 2_3 Delegate that provides a codebase. Swallow 764 // the ClassCastException otherwise. 765 Delegate delegate = StubAdapter.getDelegate( narrowFrom ) ; 766 codebase = ((org.omg.CORBA_2_3.portable.Delegate)delegate). 767 get_codebase(narrowFrom); 768 769 } catch (ClassCastException e) { 770 wrapper.classCastExceptionInLoadStub( e ) ; 771 } 772 773 PresentationManager.StubFactoryFactory sff = 774 com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory() ; 775 PresentationManager.StubFactory sf = sff.createStubFactory( 776 narrowTo.getName(), false, codebase, narrowTo, 777 narrowTo.getClassLoader() ) ; 778 result = (Remote)sf.makeStub() ; 779 StubAdapter.setDelegate( result, 780 StubAdapter.getDelegate( narrowFrom ) ) ; 781 } catch (Exception err) { 782 wrapper.exceptionInLoadStub( err ) ; 783 } 784 785 return result; 786 } 787 788 /* 789 * Load an RMI-IIOP Stub class. This is used in the 790 * StaticStubFactoryFactory code. 791 */ 792 public static Class loadStubClass(String repID, 793 String remoteCodebase, 794 Class expectedType) 795 throws ClassNotFoundException 796 { 797 // Get the repID and check for "" special case. 798 // We should never be called with it (See CDRInputStream 799 // and the loadStub() method)... 800 801 if (repID.length() == 0) { 802 throw new ClassNotFoundException(); 803 } 804 805 // Get the stubname from the repID and load 806 // the class. If we have a valid 'sender', fall 807 // back to using its codebase if we need to... 808 String className = Utility.stubNameFromRepID(repID); 809 ClassLoader expectedTypeClassLoader = (expectedType == null ? null : 810 expectedType.getClassLoader()); 811 812 try { 813 return loadClassOfType(className, 814 remoteCodebase, 815 expectedTypeClassLoader, 816 expectedType, 817 expectedTypeClassLoader); 818 } catch (ClassNotFoundException e) { 819 return loadClassOfType(PackagePrefixChecker.packagePrefix() + className, 820 remoteCodebase, 821 expectedTypeClassLoader, 822 expectedType, 823 expectedTypeClassLoader); 824 } 825 } 826 827 /** 828 * Create an RMI stub name. 829 */ 830 public static String stubName (String className) 831 { 832 return stubName( className, false ) ; 833 } 834 835 public static String dynamicStubName( String className ) 836 { 837 return stubName( className, true ) ; 838 } 839 840 private static String stubName( String className, 841 boolean isDynamic ) 842 { 843 String name = stubNameForCompiler( className, isDynamic ) ; 844 if (PackagePrefixChecker.hasOffendingPrefix( name )) 845 name = PackagePrefixChecker.packagePrefix() + name ; 846 return name ; 847 } 848 849 public static String stubNameForCompiler (String className) 850 { 851 return stubNameForCompiler( className, false ) ; 852 } 853 854 private static String stubNameForCompiler( String className, 855 boolean isDynamic ) 856 { 857 int index = className.indexOf('$'); 858 if (index < 0) { 859 index = className.lastIndexOf('.'); 860 } 861 862 String suffix = isDynamic ? DYNAMIC_STUB_SUFFIX : 863 RMI_STUB_SUFFIX ; 864 865 if (index > 0) { 866 return className.substring(0,index+1) + STUB_PREFIX + 867 className.substring(index+1) + suffix; 868 } else { 869 return STUB_PREFIX + className + suffix; 870 } 871 } 872 873 /** 874 * Create an RMI tie name. 875 */ 876 public static String tieName (String className) 877 { 878 return 879 PackagePrefixChecker.hasOffendingPrefix(tieNameForCompiler(className)) ? 880 PackagePrefixChecker.packagePrefix() + tieNameForCompiler(className) : 881 tieNameForCompiler(className); 882 } 883 884 public static String tieNameForCompiler (String className) 885 { 886 int index = className.indexOf('$'); 887 if (index < 0) { 888 index = className.lastIndexOf('.'); 889 } 890 if (index > 0) { 891 return className.substring(0,index+1) + 892 STUB_PREFIX + 893 className.substring(index+1) + 894 TIE_SUFIX; 895 } else { 896 return STUB_PREFIX + 897 className + 898 TIE_SUFIX; 899 } 900 } 901 902 /** 903 * Throws the CORBA equivalent of a java.io.NotSerializableException 904 */ 905 public static void throwNotSerializableForCorba(String className) { 906 throw omgWrapper.notSerializable( CompletionStatus.COMPLETED_MAYBE, 907 className ) ; 908 } 909 910 /** 911 * Create an IDL stub name. 912 */ 913 public static String idlStubName(String className) 914 { 915 String result = null; 916 int index = className.lastIndexOf('.'); 917 if (index > 0) { 918 result = className.substring(0,index+1) + 919 STUB_PREFIX + 920 className.substring(index+1) + 921 IDL_STUB_SUFFIX; 922 } else { 923 result = STUB_PREFIX + 924 className + 925 IDL_STUB_SUFFIX; 926 } 927 return result; 928 } 929 930 public static void printStackTrace() 931 { 932 Throwable thr = new Throwable( "Printing stack trace:" ) ; 933 thr.fillInStackTrace() ; 934 thr.printStackTrace() ; 935 } 936 937 /** 938 * Read an object reference from the input stream and narrow 939 * it to the desired type. 940 * @param in the stream to read from. 941 * @throws ClassCastException if narrowFrom cannot be cast to narrowTo. 942 */ 943 public static Object readObjectAndNarrow(InputStream in, 944 Class narrowTo) 945 throws ClassCastException 946 { 947 Object result = in.read_Object(); 948 if (result != null) 949 return PortableRemoteObject.narrow(result, narrowTo); 950 else 951 return null; 952 } 953 954 /** 955 * Read an abstract interface type from the input stream and narrow 956 * it to the desired type. 957 * @param in the stream to read from. 958 * @throws ClassCastException if narrowFrom cannot be cast to narrowTo. 959 */ 960 public static Object readAbstractAndNarrow( 961 org.omg.CORBA_2_3.portable.InputStream in, Class narrowTo) 962 throws ClassCastException 963 { 964 Object result = in.read_abstract_interface(); 965 if (result != null) 966 return PortableRemoteObject.narrow(result, narrowTo); 967 else 968 return null; 969 } 970 971 972 /** Converts an Ascii Character into Hexadecimal digit 973 */ 974 static int hexOf( char x ) 975 { 976 int val; 977 978 val = x - '0'; 979 if (val >=0 && val <= 9) 980 return val; 981 982 val = (x - 'a') + 10; 983 if (val >= 10 && val <= 15) 984 return val; 985 986 val = (x - 'A') + 10; 987 if (val >= 10 && val <= 15) 988 return val; 989 990 throw wrapper.badHexDigit() ; 991 } 992 } 993 994 class StubEntry { 995 org.omg.CORBA.Object stub; 996 boolean mostDerived; 997 998 StubEntry(org.omg.CORBA.Object stub, boolean mostDerived) { 999 this.stub = stub; 1000 this.mostDerived = mostDerived; 1001 } 1002 }