1 /*
   2  * Copyright (c) 2000, 2013, 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 package com.sun.corba.se.impl.orbutil;
  27 
  28 import java.lang.Character;
  29 import java.lang.reflect.Field;
  30 import java.lang.reflect.Method;
  31 import java.rmi.NoSuchObjectException;
  32 import java.security.AccessController;
  33 import java.security.PermissionCollection;
  34 import java.security.Policy;
  35 import java.security.PrivilegedAction;
  36 import java.security.ProtectionDomain;
  37 import java.security.PrivilegedActionException;
  38 import java.security.PrivilegedExceptionAction;
  39 import java.util.HashMap;
  40 import java.util.HashSet;
  41 import java.util.Hashtable;
  42 import java.util.Iterator;
  43 import java.util.Enumeration;
  44 import java.util.StringTokenizer;
  45 import java.util.NoSuchElementException;
  46 
  47 import javax.rmi.CORBA.ValueHandler;
  48 import javax.rmi.CORBA.ValueHandlerMultiFormat;
  49 import javax.rmi.CORBA.Util;
  50 
  51 import org.omg.CORBA.StructMember ;
  52 import org.omg.CORBA.TypeCode ;
  53 import org.omg.CORBA.Any ;
  54 import org.omg.CORBA.TCKind ;
  55 import org.omg.CORBA.SystemException ;
  56 import org.omg.CORBA.CompletionStatus ;
  57 import org.omg.CORBA.DATA_CONVERSION ;
  58 import org.omg.CORBA.BAD_PARAM ;
  59 import org.omg.CORBA.BAD_OPERATION ;
  60 import org.omg.CORBA.INTERNAL ;
  61 import org.omg.CORBA.TypeCodePackage.BadKind ;
  62 import org.omg.CORBA.portable.OutputStream ;
  63 import org.omg.CORBA.portable.InputStream ;
  64 
  65 import com.sun.corba.se.pept.transport.ContactInfoList ;
  66 
  67 import com.sun.corba.se.spi.ior.IOR ;
  68 import com.sun.corba.se.spi.presentation.rmi.StubAdapter ;
  69 import com.sun.corba.se.spi.orb.ORB ;
  70 import com.sun.corba.se.spi.orb.ORBVersion ;
  71 import com.sun.corba.se.spi.orb.ORBVersionFactory ;
  72 import com.sun.corba.se.spi.protocol.CorbaClientDelegate ;
  73 import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
  74 import com.sun.corba.se.spi.transport.CorbaContactInfoList ;
  75 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  76 import com.sun.corba.se.spi.ior.iiop.IIOPProfile;
  77 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate;
  78 
  79 import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
  80 import com.sun.corba.se.impl.corba.CORBAObjectImpl ;
  81 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  82 import com.sun.corba.se.impl.logging.OMGSystemException ;
  83 import com.sun.corba.se.impl.ior.iiop.JavaSerializationComponent;
  84 
  85 import sun.corba.SharedSecrets;
  86 
  87 /**
  88  *  Handy class full of static functions that don't belong in util.Utility for pure ORB reasons.
  89  */
  90 public final class ORBUtility {
  91     private ORBUtility() {}
  92 
  93     private static ORBUtilSystemException wrapper = ORBUtilSystemException.get(
  94         CORBALogDomains.UTIL ) ;
  95     private static OMGSystemException omgWrapper = OMGSystemException.get(
  96         CORBALogDomains.UTIL ) ;
  97 
  98     private static StructMember[] members = null;
  99 
 100     private static StructMember[] systemExceptionMembers (ORB orb) {
 101         if (members == null) {
 102             members = new StructMember[3];
 103             members[0] = new StructMember("id", orb.create_string_tc(0), null);
 104             members[1] = new StructMember("minor", orb.get_primitive_tc(TCKind.tk_long), null);
 105             members[2] = new StructMember("completed", orb.get_primitive_tc(TCKind.tk_long), null);
 106         }
 107         return members;
 108     }
 109 
 110     private static TypeCode getSystemExceptionTypeCode(ORB orb, String repID, String name) {
 111         synchronized (TypeCode.class) {
 112             return orb.create_exception_tc(repID, name, systemExceptionMembers(orb));
 113         }
 114     }
 115 
 116     private static boolean isSystemExceptionTypeCode(TypeCode type, ORB orb) {
 117         StructMember[] systemExceptionMembers = systemExceptionMembers(orb);
 118         try {
 119             return (type.kind().value() == TCKind._tk_except &&
 120                     type.member_count() == 3 &&
 121                     type.member_type(0).equal(systemExceptionMembers[0].type) &&
 122                     type.member_type(1).equal(systemExceptionMembers[1].type) &&
 123                     type.member_type(2).equal(systemExceptionMembers[2].type));
 124         } catch (BadKind ex) {
 125             return false;
 126         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
 127             return false;
 128         }
 129     }
 130 
 131     /**
 132      * Static method for writing a CORBA standard exception to an Any.
 133      * @param any The Any to write the SystemException into.
 134      */
 135     public static void insertSystemException(SystemException ex, Any any) {
 136         OutputStream out = any.create_output_stream();
 137         ORB orb = (ORB)(out.orb());
 138         String name = ex.getClass().getName();
 139         String repID = ORBUtility.repositoryIdOf(name);
 140         out.write_string(repID);
 141         out.write_long(ex.minor);
 142         out.write_long(ex.completed.value());
 143         any.read_value(out.create_input_stream(),
 144             getSystemExceptionTypeCode(orb, repID, name));
 145     }
 146 
 147     public static SystemException extractSystemException(Any any) {
 148         InputStream in = any.create_input_stream();
 149         ORB orb = (ORB)(in.orb());
 150         if ( ! isSystemExceptionTypeCode(any.type(), orb)) {
 151             throw wrapper.unknownDsiSysex(CompletionStatus.COMPLETED_MAYBE);
 152         }
 153         return ORBUtility.readSystemException(in);
 154     }
 155 
 156     /**
 157      * Return default ValueHandler
 158      */
 159     public static ValueHandler createValueHandler() {
 160         ValueHandler vh;
 161         try {
 162             vh = AccessController.doPrivileged(new PrivilegedExceptionAction<ValueHandler>() {
 163                 public ValueHandler run() throws Exception {
 164         return Util.createValueHandler();
 165     }
 166             });
 167         } catch (PrivilegedActionException e) {
 168             throw new InternalError(e.getCause());
 169         }
 170         return vh;
 171     }
 172 
 173     /**
 174      * Returns true if it was accurately determined that the remote ORB is
 175      * a foreign (non-JavaSoft) ORB.  Note:  If passed the ORBSingleton, this
 176      * will return false.
 177      */
 178     public static boolean isForeignORB(ORB orb)
 179     {
 180         if (orb == null)
 181             return false;
 182 
 183         try {
 184             return orb.getORBVersion().equals(ORBVersionFactory.getFOREIGN());
 185         } catch (SecurityException se) {
 186             return false;
 187         }
 188     }
 189 
 190     /** Unmarshal a byte array to an integer.
 191         Assume the bytes are in BIGENDIAN order.
 192         i.e. array[offset] is the most-significant-byte
 193         and  array[offset+3] is the least-significant-byte.
 194         @param array The array of bytes.
 195         @param offset The offset from which to start unmarshalling.
 196     */
 197     public static int bytesToInt(byte[] array, int offset)
 198     {
 199         int b1, b2, b3, b4;
 200 
 201         b1 = (array[offset++] << 24) & 0xFF000000;
 202         b2 = (array[offset++] << 16) & 0x00FF0000;
 203         b3 = (array[offset++] << 8)  & 0x0000FF00;
 204         b4 = (array[offset++] << 0)  & 0x000000FF;
 205 
 206         return (b1 | b2 | b3 | b4);
 207     }
 208 
 209     /** Marshal an integer to a byte array.
 210         The bytes are in BIGENDIAN order.
 211         i.e. array[offset] is the most-significant-byte
 212         and  array[offset+3] is the least-significant-byte.
 213         @param array The array of bytes.
 214         @param offset The offset from which to start marshalling.
 215     */
 216     public static void intToBytes(int value, byte[] array, int offset)
 217     {
 218         array[offset++] = (byte)((value >>> 24) & 0xFF);
 219         array[offset++] = (byte)((value >>> 16) & 0xFF);
 220         array[offset++] = (byte)((value >>> 8) & 0xFF);
 221         array[offset++] = (byte)((value >>> 0) & 0xFF);
 222     }
 223 
 224     /** Converts an Ascii Character into Hexadecimal digit
 225      */
 226     public static int hexOf( char x )
 227     {
 228         int val;
 229 
 230         val = x - '0';
 231         if (val >=0 && val <= 9)
 232             return val;
 233 
 234         val = (x - 'a') + 10;
 235         if (val >= 10 && val <= 15)
 236             return val;
 237 
 238         val = (x - 'A') + 10;
 239         if (val >= 10 && val <= 15)
 240             return val;
 241 
 242         throw wrapper.badHexDigit() ;
 243     }
 244 
 245     // method moved from util.Utility
 246 
 247     /**
 248      * Static method for writing a CORBA standard exception to a stream.
 249      * @param strm The OutputStream to use for marshaling.
 250      */
 251     public static void writeSystemException(SystemException ex, OutputStream strm)
 252     {
 253         String s;
 254 
 255         s = repositoryIdOf(ex.getClass().getName());
 256         strm.write_string(s);
 257         strm.write_long(ex.minor);
 258         strm.write_long(ex.completed.value());
 259     }
 260 
 261     /**
 262      * Static method for reading a CORBA standard exception from a stream.
 263      * @param strm The InputStream to use for unmarshaling.
 264      */
 265     public static SystemException readSystemException(InputStream strm)
 266     {
 267         try {
 268             String name = classNameOf(strm.read_string());
 269             SystemException ex = (SystemException)SharedSecrets.
 270                 getJavaCorbaAccess().loadClass(name).newInstance();
 271             ex.minor = strm.read_long();
 272             ex.completed = CompletionStatus.from_int(strm.read_long());
 273             return ex;
 274         } catch ( Exception ex ) {
 275             throw wrapper.unknownSysex( CompletionStatus.COMPLETED_MAYBE, ex );
 276         }
 277     }
 278 
 279     /**
 280      * Get the class name corresponding to a particular repository Id.
 281      * This is used by the system to unmarshal (instantiate) the
 282      * appropriate exception class for an marshaled as the value of
 283      * its repository Id.
 284      * @param repositoryId The repository Id for which we want a class name.
 285      */
 286     public static String classNameOf(String repositoryId)
 287     {
 288         String className=null;
 289 
 290         className = (String) exceptionClassNames.get(repositoryId);
 291         if (className == null)
 292             className = "org.omg.CORBA.UNKNOWN";
 293 
 294         return className;
 295     }
 296 
 297     /**
 298      * Return true if this repositoryId is a SystemException.
 299      * @param repositoryId The repository Id to check.
 300      */
 301     public static boolean isSystemException(String repositoryId)
 302     {
 303         String className=null;
 304 
 305         className = (String) exceptionClassNames.get(repositoryId);
 306         if (className == null)
 307             return false;
 308         else
 309             return true;
 310     }
 311 
 312     /**
 313      * @return the Java serialization encoding version.
 314      */
 315     public static byte getEncodingVersion(ORB orb, IOR ior) {
 316 
 317         // Is Java serialization enabled?
 318         // Check the JavaSerializationComponent (tagged component)
 319         // in the IIOPProfile. If present, the peer ORB's GIOP is capable
 320         // of using Java serialization instead of CDR serialization.
 321         // In such a case, use Java serialization, iff the java serialization
 322         // versions match.
 323 
 324         if (orb.getORBData().isJavaSerializationEnabled()) {
 325             IIOPProfile prof = ior.getProfile();
 326             IIOPProfileTemplate profTemp =
 327                 (IIOPProfileTemplate) prof.getTaggedProfileTemplate();
 328             java.util.Iterator iter = profTemp.iteratorById(
 329                                   ORBConstants.TAG_JAVA_SERIALIZATION_ID);
 330             if (iter.hasNext()) {
 331                 JavaSerializationComponent jc =
 332                     (JavaSerializationComponent) iter.next();
 333                 byte jcVersion = jc.javaSerializationVersion();
 334                 if (jcVersion >= Message.JAVA_ENC_VERSION) {
 335                     return Message.JAVA_ENC_VERSION;
 336                 } else if (jcVersion > Message.CDR_ENC_VERSION) {
 337                     return jc.javaSerializationVersion();
 338                 } else {
 339                     // throw error?
 340                     // Since encodingVersion is <= 0 (CDR_ENC_VERSION).
 341                 }
 342             }
 343         }
 344         return Message.CDR_ENC_VERSION; // default
 345     }
 346 
 347     /**
 348      * Get the repository id corresponding to a particular class.
 349      * This is used by the system to write the
 350      * appropriate repository id for a system exception.
 351      * @param name The class name of the system exception.
 352      */
 353     public static String repositoryIdOf(String name)
 354     {
 355         String id;
 356 
 357         id = (String) exceptionRepositoryIds.get(name);
 358         if (id == null)
 359             id = "IDL:omg.org/CORBA/UNKNOWN:1.0";
 360 
 361         return id;
 362     }
 363 
 364     private static final Hashtable exceptionClassNames = new Hashtable();
 365     private static final Hashtable exceptionRepositoryIds = new Hashtable();
 366 
 367     static {
 368 
 369         //
 370         // construct repositoryId -> className hashtable
 371         //
 372         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_CONTEXT:1.0",
 373                                 "org.omg.CORBA.BAD_CONTEXT");
 374         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_INV_ORDER:1.0",
 375                                 "org.omg.CORBA.BAD_INV_ORDER");
 376         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_OPERATION:1.0",
 377                                 "org.omg.CORBA.BAD_OPERATION");
 378         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_PARAM:1.0",
 379                                 "org.omg.CORBA.BAD_PARAM");
 380         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_TYPECODE:1.0",
 381                                 "org.omg.CORBA.BAD_TYPECODE");
 382         exceptionClassNames.put("IDL:omg.org/CORBA/COMM_FAILURE:1.0",
 383                                 "org.omg.CORBA.COMM_FAILURE");
 384         exceptionClassNames.put("IDL:omg.org/CORBA/DATA_CONVERSION:1.0",
 385                                 "org.omg.CORBA.DATA_CONVERSION");
 386         exceptionClassNames.put("IDL:omg.org/CORBA/IMP_LIMIT:1.0",
 387                                 "org.omg.CORBA.IMP_LIMIT");
 388         exceptionClassNames.put("IDL:omg.org/CORBA/INTF_REPOS:1.0",
 389                                 "org.omg.CORBA.INTF_REPOS");
 390         exceptionClassNames.put("IDL:omg.org/CORBA/INTERNAL:1.0",
 391                                 "org.omg.CORBA.INTERNAL");
 392         exceptionClassNames.put("IDL:omg.org/CORBA/INV_FLAG:1.0",
 393                                 "org.omg.CORBA.INV_FLAG");
 394         exceptionClassNames.put("IDL:omg.org/CORBA/INV_IDENT:1.0",
 395                                 "org.omg.CORBA.INV_IDENT");
 396         exceptionClassNames.put("IDL:omg.org/CORBA/INV_OBJREF:1.0",
 397                                 "org.omg.CORBA.INV_OBJREF");
 398         exceptionClassNames.put("IDL:omg.org/CORBA/MARSHAL:1.0",
 399                                 "org.omg.CORBA.MARSHAL");
 400         exceptionClassNames.put("IDL:omg.org/CORBA/NO_MEMORY:1.0",
 401                                 "org.omg.CORBA.NO_MEMORY");
 402         exceptionClassNames.put("IDL:omg.org/CORBA/FREE_MEM:1.0",
 403                                 "org.omg.CORBA.FREE_MEM");
 404         exceptionClassNames.put("IDL:omg.org/CORBA/NO_IMPLEMENT:1.0",
 405                                 "org.omg.CORBA.NO_IMPLEMENT");
 406         exceptionClassNames.put("IDL:omg.org/CORBA/NO_PERMISSION:1.0",
 407                                 "org.omg.CORBA.NO_PERMISSION");
 408         exceptionClassNames.put("IDL:omg.org/CORBA/NO_RESOURCES:1.0",
 409                                 "org.omg.CORBA.NO_RESOURCES");
 410         exceptionClassNames.put("IDL:omg.org/CORBA/NO_RESPONSE:1.0",
 411                                 "org.omg.CORBA.NO_RESPONSE");
 412         exceptionClassNames.put("IDL:omg.org/CORBA/OBJ_ADAPTER:1.0",
 413                                 "org.omg.CORBA.OBJ_ADAPTER");
 414         exceptionClassNames.put("IDL:omg.org/CORBA/INITIALIZE:1.0",
 415                                 "org.omg.CORBA.INITIALIZE");
 416         exceptionClassNames.put("IDL:omg.org/CORBA/PERSIST_STORE:1.0",
 417                                 "org.omg.CORBA.PERSIST_STORE");
 418         exceptionClassNames.put("IDL:omg.org/CORBA/TRANSIENT:1.0",
 419                                 "org.omg.CORBA.TRANSIENT");
 420         exceptionClassNames.put("IDL:omg.org/CORBA/UNKNOWN:1.0",
 421                                 "org.omg.CORBA.UNKNOWN");
 422         exceptionClassNames.put("IDL:omg.org/CORBA/OBJECT_NOT_EXIST:1.0",
 423                                 "org.omg.CORBA.OBJECT_NOT_EXIST");
 424 
 425         // SystemExceptions from OMG Transactions Service Spec
 426         exceptionClassNames.put("IDL:omg.org/CORBA/INVALID_TRANSACTION:1.0",
 427                                 "org.omg.CORBA.INVALID_TRANSACTION");
 428         exceptionClassNames.put("IDL:omg.org/CORBA/TRANSACTION_REQUIRED:1.0",
 429                                 "org.omg.CORBA.TRANSACTION_REQUIRED");
 430         exceptionClassNames.put("IDL:omg.org/CORBA/TRANSACTION_ROLLEDBACK:1.0",
 431                                 "org.omg.CORBA.TRANSACTION_ROLLEDBACK");
 432 
 433         // from portability RTF 98-07-01.txt
 434         exceptionClassNames.put("IDL:omg.org/CORBA/INV_POLICY:1.0",
 435                                 "org.omg.CORBA.INV_POLICY");
 436 
 437         // from orbrev/00-09-01 (CORBA 2.4 Draft Specification)
 438         exceptionClassNames.
 439             put("IDL:omg.org/CORBA/TRANSACTION_UNAVAILABLE:1.0",
 440                                 "org.omg.CORBA.TRANSACTION_UNAVAILABLE");
 441         exceptionClassNames.put("IDL:omg.org/CORBA/TRANSACTION_MODE:1.0",
 442                                 "org.omg.CORBA.TRANSACTION_MODE");
 443 
 444         // Exception types introduced between CORBA 2.4 and 3.0
 445         exceptionClassNames.put("IDL:omg.org/CORBA/CODESET_INCOMPATIBLE:1.0",
 446                                 "org.omg.CORBA.CODESET_INCOMPATIBLE");
 447         exceptionClassNames.put("IDL:omg.org/CORBA/REBIND:1.0",
 448                                 "org.omg.CORBA.REBIND");
 449         exceptionClassNames.put("IDL:omg.org/CORBA/TIMEOUT:1.0",
 450                                 "org.omg.CORBA.TIMEOUT");
 451         exceptionClassNames.put("IDL:omg.org/CORBA/BAD_QOS:1.0",
 452                                 "org.omg.CORBA.BAD_QOS");
 453 
 454         // Exception types introduced in CORBA 3.0
 455         exceptionClassNames.put("IDL:omg.org/CORBA/INVALID_ACTIVITY:1.0",
 456                                 "org.omg.CORBA.INVALID_ACTIVITY");
 457         exceptionClassNames.put("IDL:omg.org/CORBA/ACTIVITY_COMPLETED:1.0",
 458                                 "org.omg.CORBA.ACTIVITY_COMPLETED");
 459         exceptionClassNames.put("IDL:omg.org/CORBA/ACTIVITY_REQUIRED:1.0",
 460                                 "org.omg.CORBA.ACTIVITY_REQUIRED");
 461 
 462         //
 463         // construct className -> repositoryId hashtable
 464         //
 465         Enumeration keys = exceptionClassNames.keys();
 466         java.lang.Object s;
 467         String rId;
 468         String cName;
 469 
 470         try{
 471             while (keys.hasMoreElements()) {
 472                 s = keys.nextElement();
 473                 rId = (String) s;
 474                 cName = (String) exceptionClassNames.get(rId);
 475                 exceptionRepositoryIds.put (cName, rId);
 476             }
 477         } catch (NoSuchElementException e) { }
 478     }
 479 
 480     /** Parse a version string such as "1.1.6" or "jdk1.2fcs" into
 481         a version array of integers {1, 1, 6} or {1, 2}.
 482         A string of "n." or "n..m" is equivalent to "n.0" or "n.0.m" respectively.
 483     */
 484     public static int[] parseVersion(String version) {
 485         if (version == null)
 486             return new int[0];
 487         char[] s = version.toCharArray();
 488         //find the maximum span of the string "n.n.n..." where n is an integer
 489         int start = 0;
 490         for (; start < s.length  && (s[start] < '0' || s[start] > '9'); ++start)
 491             if (start == s.length)      //no digit found
 492                 return new int[0];
 493         int end = start + 1;
 494         int size = 1;
 495         for (; end < s.length; ++end)
 496             if (s[end] == '.')
 497                 ++size;
 498             else if (s[end] < '0' || s[end] > '9')
 499                 break;
 500         int[] val = new int[size];
 501         for (int i = 0; i < size; ++i) {
 502             int dot = version.indexOf('.', start);
 503             if (dot == -1 || dot > end)
 504                 dot = end;
 505             if (start >= dot)   //cases like "n." or "n..m"
 506                 val[i] = 0;     //convert equivalent to "n.0" or "n.0.m"
 507             else
 508                 val[i] = Integer.parseInt(version.substring(start, dot));
 509             start = dot + 1;
 510         }
 511         return val;
 512     }
 513 
 514     /** Compare two version arrays.
 515         Return 1, 0 or -1 if v1 is greater than, equal to, or less than v2.
 516     */
 517     public static int compareVersion(int[] v1, int[] v2) {
 518         if (v1 == null)
 519             v1 = new int[0];
 520         if (v2 == null)
 521             v2 = new int[0];
 522         for (int i = 0; i < v1.length; ++i) {
 523             if (i >= v2.length || v1[i] > v2[i])        //v1 is longer or greater than v2
 524                 return 1;
 525             if (v1[i] < v2[i])
 526                 return -1;
 527         }
 528         return v1.length == v2.length ? 0 : -1;
 529     }
 530 
 531     /** Compare two version strings.
 532         Return 1, 0 or -1 if v1 is greater than, equal to, or less than v2.
 533     */
 534     public static synchronized int compareVersion(String v1, String v2) {
 535         return compareVersion(parseVersion(v1), parseVersion(v2));
 536     }
 537 
 538     private static String compressClassName( String name )
 539     {
 540         // Note that this must end in . in order to be renamed correctly.
 541         String prefix = "com.sun.corba.se." ;
 542         if (name.startsWith( prefix ) ) {
 543             return "(ORB)." + name.substring( prefix.length() ) ;
 544         } else
 545             return name ;
 546     }
 547 
 548     // Return a compressed representation of the thread name.  This is particularly
 549     // useful on the server side, where there are many SelectReaderThreads, and
 550     // we need a short unambiguous name for such threads.
 551     public static String getThreadName( Thread thr )
 552     {
 553         if (thr == null)
 554             return "null" ;
 555 
 556         // This depends on the formatting in SelectReaderThread and CorbaConnectionImpl.
 557         // Pattern for SelectReaderThreads:
 558         // SelectReaderThread CorbaConnectionImpl[ <host> <post> <state>]
 559         // Any other pattern in the Thread's name is just returned.
 560         String name = thr.getName() ;
 561         StringTokenizer st = new StringTokenizer( name ) ;
 562         int numTokens = st.countTokens() ;
 563         if (numTokens != 5)
 564             return name ;
 565 
 566         String[] tokens = new String[numTokens] ;
 567         for (int ctr=0; ctr<numTokens; ctr++ )
 568             tokens[ctr] = st.nextToken() ;
 569 
 570         if( !tokens[0].equals("SelectReaderThread"))
 571             return name ;
 572 
 573         return "SelectReaderThread[" + tokens[2] + ":" + tokens[3] + "]" ;
 574     }
 575 
 576     private static String formatStackTraceElement( StackTraceElement ste )
 577     {
 578         return compressClassName( ste.getClassName() ) + "." + ste.getMethodName() +
 579             (ste.isNativeMethod() ? "(Native Method)" :
 580              (ste.getFileName() != null && ste.getLineNumber() >= 0 ?
 581               "(" + ste.getFileName() + ":" + ste.getLineNumber() + ")" :
 582               (ste.getFileName() != null ?  "("+ste.getFileName()+")" : "(Unknown Source)")));
 583     }
 584 
 585     private static void printStackTrace( StackTraceElement[] trace )
 586     {
 587         System.out.println( "    Stack Trace:" ) ;
 588         // print the stack trace, ommitting the zeroth element, which is
 589         // always this method.
 590         for ( int ctr = 1; ctr < trace.length; ctr++ ) {
 591             System.out.print( "        >" ) ;
 592             System.out.println( formatStackTraceElement( trace[ctr] ) ) ;
 593         }
 594     }
 595 
 596     //
 597     // Implements all dprint calls in this package.
 598     //
 599     public static synchronized void dprint(java.lang.Object obj, String msg) {
 600         System.out.println(
 601             compressClassName( obj.getClass().getName() ) + "("  +
 602             getThreadName( Thread.currentThread() ) + "): " + msg);
 603     }
 604 
 605     public static synchronized void dprint(String className, String msg) {
 606         System.out.println(
 607             compressClassName( className ) + "("  +
 608             getThreadName( Thread.currentThread() ) + "): " + msg);
 609     }
 610 
 611     public synchronized void dprint(String msg) {
 612         ORBUtility.dprint(this, msg);
 613     }
 614 
 615     public static synchronized void dprintTrace(Object obj, String msg) {
 616         ORBUtility.dprint(obj, msg);
 617 
 618         Throwable thr = new Throwable() ;
 619         printStackTrace( thr.getStackTrace() ) ;
 620     }
 621 
 622     public static synchronized void dprint(java.lang.Object caller,
 623         String msg, Throwable t)
 624     {
 625         System.out.println(
 626             compressClassName( caller.getClass().getName() ) +
 627             '(' + Thread.currentThread() + "): " + msg);
 628 
 629         if (t != null)
 630             printStackTrace( t.getStackTrace() ) ;
 631     }
 632 
 633     public static String[] concatenateStringArrays( String[] arr1, String[] arr2 )
 634     {
 635         String[] result = new String[
 636             arr1.length + arr2.length ] ;
 637 
 638         for (int ctr = 0; ctr<arr1.length; ctr++)
 639             result[ctr] = arr1[ctr] ;
 640 
 641         for (int ctr = 0; ctr<arr2.length; ctr++)
 642             result[ctr + arr1.length] = arr2[ctr] ;
 643 
 644         return result ;
 645     }
 646 
 647     /**
 648      * Throws the CORBA equivalent of a java.io.NotSerializableException
 649      *
 650      * Duplicated from util/Utility for Pure ORB reasons.  There are two
 651      * reasons for this:
 652      *
 653      * 1) We can't introduce dependencies on the util version from outside
 654      * of the io/util packages since it will not exist in the pure ORB
 655      * build running on JDK 1.3.x.
 656      *
 657      * 2) We need to pick up the correct minor code from OMGSystemException.
 658      */
 659     public static void throwNotSerializableForCorba(String className) {
 660         throw omgWrapper.notSerializable( CompletionStatus.COMPLETED_MAYBE,
 661             className ) ;
 662     }
 663 
 664     /**
 665      * Returns the maximum stream format version supported by our
 666      * ValueHandler.
 667      */
 668     public static byte getMaxStreamFormatVersion() {
 669         ValueHandler vh;
 670         try {
 671             vh = AccessController.doPrivileged(new PrivilegedExceptionAction<ValueHandler>() {
 672                 public ValueHandler run() throws Exception {
 673                     return Util.createValueHandler();
 674                 }
 675             });
 676         } catch (PrivilegedActionException e) {
 677             throw new InternalError(e.getCause());
 678         }
 679 
 680         if (!(vh instanceof javax.rmi.CORBA.ValueHandlerMultiFormat))
 681             return ORBConstants.STREAM_FORMAT_VERSION_1;
 682         else
 683             return ((ValueHandlerMultiFormat)vh).getMaximumStreamFormatVersion();
 684     }
 685 
 686     public static CorbaClientDelegate makeClientDelegate( IOR ior )
 687     {
 688         ORB orb = ior.getORB() ;
 689         CorbaContactInfoList ccil = orb.getCorbaContactInfoListFactory().create( ior ) ;
 690         CorbaClientDelegate del = orb.getClientDelegateFactory().create(ccil);
 691         return del ;
 692     }
 693 
 694     /** This method is used to create untyped object references.
 695     */
 696     public static org.omg.CORBA.Object makeObjectReference( IOR ior )
 697     {
 698         CorbaClientDelegate del = makeClientDelegate( ior ) ;
 699         org.omg.CORBA.Object objectImpl = new CORBAObjectImpl() ;
 700         StubAdapter.setDelegate( objectImpl, del ) ;
 701         return objectImpl ;
 702     }
 703 
 704     /** This method obtains an IOR from a CORBA object reference.
 705     * It will return null if obj is a local object, a null object,
 706     * or an object implemented by a different ORB.  It will
 707     * throw BAD_OPERATION if obj is an unconnected RMI-IIOP object.
 708     * @return IOR the IOR that represents this objref.  This will
 709     * never be null.
 710     * @exception BAD_OPERATION (from oi._get_delegate) if obj is a
 711     * normal objref, but does not have a delegate set.
 712     * @exception BAD_PARAM if obj is a local object, or else was
 713     * created by a foreign ORB.
 714     */
 715     public static IOR getIOR( org.omg.CORBA.Object obj )
 716     {
 717         if (obj == null)
 718             throw wrapper.nullObjectReference() ;
 719 
 720         IOR ior = null ;
 721         if (StubAdapter.isStub(obj)) {
 722             org.omg.CORBA.portable.Delegate del = StubAdapter.getDelegate(
 723                 obj ) ;
 724 
 725             if (del instanceof CorbaClientDelegate) {
 726                 CorbaClientDelegate cdel = (CorbaClientDelegate)del ;
 727                 ContactInfoList cil = cdel.getContactInfoList() ;
 728 
 729                 if (cil instanceof CorbaContactInfoList) {
 730                     CorbaContactInfoList ccil = (CorbaContactInfoList)cil ;
 731                     ior = ccil.getTargetIOR() ;
 732                     if (ior == null)
 733                         throw wrapper.nullIor() ;
 734 
 735                     return ior ;
 736                 } else {
 737                     // This is our code, but the ContactInfoList is not a
 738                     // CorbaContactInfoList.  This should not happen, because
 739                     // we are in the CORBA application of the DCSA framework.
 740                     // This is a coding error, and thus an INTERNAL exception
 741                     // should be thrown.
 742                     // XXX needs minor code
 743                     throw new INTERNAL() ;
 744                 }
 745             }
 746 
 747             // obj is implemented by a foreign ORB, because the Delegate is not a
 748             // ClientDelegate.
 749             // XXX this case could be handled by marshalling and
 750             // unmarshalling.  However, object_to_string cannot be used
 751             // here, as it is implemented with getIOR.  Note that this
 752             // will require access to an ORB, so that we can create streams
 753             // as needed.  The ORB is available simply as io._orb().
 754             throw wrapper.objrefFromForeignOrb() ;
 755         } else
 756             throw wrapper.localObjectNotAllowed() ;
 757     }
 758 
 759     /** Obtains an IOR for the object reference obj, first connecting it to
 760     * the ORB if necessary.
 761     * @return IOR the IOR that represents this objref.  This will
 762     * never be null.
 763     * @exception BAD_OPERATION if the object could not be connected,
 764     * if a connection attempt was needed.
 765     * @exception BAD_PARAM if obj is a local object, or else was
 766     * created by a foreign ORB.
 767     */
 768     public static IOR connectAndGetIOR( ORB orb, org.omg.CORBA.Object obj )
 769     {
 770         IOR result ;
 771         try {
 772             result = getIOR( obj ) ;
 773         } catch (BAD_OPERATION bop) {
 774             if (StubAdapter.isStub(obj)) {
 775                 try {
 776                     StubAdapter.connect( obj, orb ) ;
 777                 } catch (java.rmi.RemoteException exc) {
 778                     throw wrapper.connectingServant( exc ) ;
 779                 }
 780             } else {
 781                 orb.connect( obj ) ;
 782             }
 783 
 784             result = getIOR( obj ) ;
 785         }
 786 
 787         return result ;
 788     }
 789 
 790     public static String operationNameAndRequestId(CorbaMessageMediator m)
 791     {
 792         return "op/" + m.getOperationName() + " id/" + m.getRequestId();
 793     }
 794 
 795     public static boolean isPrintable(char c)
 796     {
 797         if (Character.isJavaIdentifierStart(c)) {
 798             // Letters and $ _
 799             return true;
 800         }
 801         if (Character.isDigit(c)) {
 802             return true;
 803         }
 804         switch (Character.getType(c)) {
 805         case Character.MODIFIER_SYMBOL : return true; // ` ^
 806         case Character.DASH_PUNCTUATION : return true; // -
 807         case Character.MATH_SYMBOL : return true; // = ~ + | < >
 808         case Character.OTHER_PUNCTUATION : return true; // !@#%&*;':",./?
 809         case Character.START_PUNCTUATION : return true; // ( [ {
 810         case Character.END_PUNCTUATION : return true; // ) ] }
 811         }
 812         return false;
 813     }
 814 
 815     public static String getClassSecurityInfo(final Class cl)
 816     {
 817         // Returns a String which looks similar to:
 818         // PermissionCollection java.security.Permissions@1053693 ...
 819         // (java.io.FilePermission <<ALL FILES>> ....)
 820         // (java.io.FilePermission /export0/sunwappserv/lib/- ...)
 821         // ... other permissions ...
 822         // Domain ProtectionDomain  (file:/export0/sunwappserv/lib-)
 823         // java.security.Permissions@141fedb (
 824         // (java.io.FilePermission <<ALL FILES>> ...)
 825         // (java.io.FilePermission /var/tmp//- ...)
 826 
 827         String result =
 828             (String)AccessController.doPrivileged(new PrivilegedAction() {
 829                 public java.lang.Object run() {
 830                     StringBuffer sb = new StringBuffer(500);
 831                     ProtectionDomain pd = cl.getProtectionDomain();
 832                     Policy policy = Policy.getPolicy();
 833                     PermissionCollection pc = policy.getPermissions(pd);
 834                     sb.append("\nPermissionCollection ");
 835                     sb.append(pc.toString());
 836                     // Don't need to add 'Protection Domain' string, it's
 837                     // in ProtectionDomain.toString() already.
 838                     sb.append(pd.toString());
 839                     return sb.toString();
 840                 }
 841             });
 842         return result;
 843     }
 844 }
 845 
 846 // End of file.