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