1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 package Ice;
6 
7 /**
8  * Utility methods for the Ice run time.
9  **/
10 public final class Util
11 {
12     /**
13      * Creates a new empty property set.
14      *
15      * @return A new empty property set.
16      **/
17     public static Properties
createProperties()18     createProperties()
19     {
20         return new PropertiesI();
21     }
22 
23     /**
24      * Creates a property set initialized from an argument vector.
25      *
26      * @param args A command-line argument vector, possibly containing
27      * options to set properties. If the command-line options include
28      * a <code>--Ice.Config</code> option, the corresponding configuration
29      * files are parsed. If the same property is set in a configuration
30      * file and in the argument vector, the argument vector takes precedence.
31      * <p>
32      * This method modifies the argument vector by removing any Ice-related options.
33      *
34      * @return A property set initialized with the property settings
35      * that were removed from <code>args</code>.
36      **/
37     public static Properties
createProperties(StringSeqHolder args)38     createProperties(StringSeqHolder args)
39     {
40         return new PropertiesI(args, null);
41     }
42 
43     /**
44      * Creates a property set initialized from an argument vector.
45      *
46      * @param args A command-line argument vector, possibly containing
47      * options to set properties. If the command-line options include
48      * a <code>--Ice.Config</code> option, the corresponding configuration
49      * files are parsed. If the same property is set in a configuration
50      * file and in the argument vector, the argument vector takes precedence.
51      * <p>
52      * This method modifies the argument vector by removing any Ice-related options.
53      * @param defaults Default values for the property set. Settings in configuration
54      * files and <code>args</code> override these defaults.
55      *
56      * @return An initalized property set.
57      **/
58     public static Properties
createProperties(StringSeqHolder args, Properties defaults)59     createProperties(StringSeqHolder args, Properties defaults)
60     {
61         return new PropertiesI(args, defaults);
62     }
63 
64     /**
65      * Creates a property set initialized from an argument vector.
66      *
67      * @param args A command-line argument vector, possibly containing
68      * options to set properties. If the command-line options include
69      * a <code>--Ice.Config</code> option, the corresponding configuration
70      * files are parsed. If the same property is set in a configuration
71      * file and in the argument vector, the argument vector takes precedence.
72      *
73      * @return A property set initialized with the property settings
74      * in <code>args</code>.
75      **/
76     public static Properties
createProperties(String[] args)77     createProperties(String[] args)
78     {
79         StringSeqHolder argsH = new StringSeqHolder(args);
80         return createProperties(argsH);
81     }
82 
83     /**
84      * Creates a property set initialized from an argument vector.
85      *
86      * @param args A command-line argument vector, possibly containing
87      * options to set properties. If the command-line options include
88      * a <code>--Ice.Config</code> option, the corresponding configuration
89      * files are parsed. If the same property is set in a configuration
90      * file and in the argument vector, the argument vector takes precedence.
91      * @param defaults Default values for the property set. Settings in configuration
92      * files and <code>args</code> override these defaults.
93      *
94      * @return An initalized property set.
95      **/
96     public static Properties
createProperties(String[] args, Properties defaults)97     createProperties(String[] args, Properties defaults)
98     {
99         StringSeqHolder argsH = new StringSeqHolder(args);
100         return createProperties(argsH, defaults);
101     }
102 
103     /**
104      * Creates a communicator.
105      *
106      * @param args A command-line argument vector. Any Ice-related options
107      * in this vector are used to intialize the communicator.
108      * This method modifies the argument vector by removing any Ice-related options.
109      *
110      * @return The initialized communicator.
111      **/
112     public static Communicator
initialize(StringSeqHolder args)113     initialize(StringSeqHolder args)
114     {
115         return initialize(args, (InitializationData)null);
116     }
117 
118     /**
119      * Creates a communicator.
120      *
121      * @param args A command-line argument vector. Any Ice-related options
122      * in this vector are used to intialize the communicator.
123      *
124      * @return The initialized communicator.
125      **/
126     public static Communicator
initialize(String[] args)127     initialize(String[] args)
128     {
129         StringSeqHolder argsH = new StringSeqHolder(args);
130         return initialize(argsH);
131     }
132 
133     /**
134      * Creates a communicator.
135      *
136      * @param args A command-line argument vector. Any Ice-related options
137      * in this vector are used to intialize the communicator.
138      * This method modifies the argument vector by removing any Ice-related options.
139      *
140      * @param initData Additional intialization data. Property settings in <code>args</code>
141      * override property settings in <code>initData</code>.
142      *
143      * @return The initialized communicator.
144      *
145      * @see InitializationData
146      **/
147     public static Communicator
initialize(StringSeqHolder args, InitializationData initData)148     initialize(StringSeqHolder args, InitializationData initData)
149     {
150         if(initData == null)
151         {
152             initData = new InitializationData();
153         }
154         else
155         {
156             initData = initData.clone();
157         }
158         initData.properties = createProperties(args, initData.properties);
159 
160         CommunicatorI result = new CommunicatorI(initData);
161         result.finishSetup(args);
162         return result;
163     }
164 
165      /**
166      * Creates a communicator.
167      *
168      * @param args A command-line argument vector. Any Ice-related options
169      * in this vector are used to intialize the communicator.
170      * This method modifies the argument vector by removing any Ice-related options.
171      *
172      * @param configFile Path to a config file that sets the new communicator's default
173      * properties.
174      *
175      * @return The initialized communicator.
176      **/
177     public static Communicator
initialize(StringSeqHolder args, String configFile)178     initialize(StringSeqHolder args, String configFile)
179     {
180         InitializationData initData = null;
181         if(configFile != null)
182         {
183             initData = new InitializationData();
184             initData.properties = Util.createProperties();
185             initData.properties.load(configFile);
186         }
187 
188         return initialize(args, initData);
189     }
190 
191     /**
192      * Creates a communicator.
193      *
194      * @param args A command-line argument vector. Any Ice-related options
195      * in this vector are used to intialize the communicator.
196      *
197      * @param initData Additional intialization data. Property settings in <code>args</code>
198      * override property settings in <code>initData</code>.
199      *
200      * @return The initialized communicator.
201      *
202      * @see InitializationData
203      **/
204     public static Communicator
initialize(String[] args, InitializationData initData)205     initialize(String[] args, InitializationData initData)
206     {
207         StringSeqHolder argsH = new StringSeqHolder(args);
208         return initialize(argsH, initData);
209     }
210 
211     /**
212      * Creates a communicator.
213      *
214      * @param args A command-line argument vector. Any Ice-related options
215      * in this vector are used to intialize the communicator.
216      *
217      * @param configFile Path to a config file that sets the new communicator's default
218      * properties.
219      *
220      * @return The initialized communicator.
221      *
222      * @see InitializationData
223      **/
224     public static Communicator
initialize(String[] args, String configFile)225     initialize(String[] args, String configFile)
226     {
227         StringSeqHolder argsH = new StringSeqHolder(args);
228         return initialize(argsH, configFile);
229     }
230 
231     /**
232      * Creates a communicator.
233      *
234      * @param initData Additional intialization data.
235      *
236      * @return The initialized communicator.
237      *
238      * @see InitializationData
239      **/
240     public static Communicator
initialize(InitializationData initData)241     initialize(InitializationData initData)
242     {
243         if(initData == null)
244         {
245             initData = new InitializationData();
246         }
247         else
248         {
249             initData = initData.clone();
250         }
251 
252         CommunicatorI result = new CommunicatorI(initData);
253         result.finishSetup(new StringSeqHolder(new String[0]));
254         return result;
255     }
256 
257      /**
258      * Creates a communicator.
259      *
260      * @param configFile Path to a config file that sets the new communicator's default
261      * properties.
262      *
263      * @return The initialized communicator.
264      **/
265     public static Communicator
initialize(String configFile)266     initialize(String configFile)
267     {
268         InitializationData initData = null;
269         if(configFile != null)
270         {
271             initData = new InitializationData();
272             initData.properties = Util.createProperties();
273             initData.properties.load(configFile);
274         }
275 
276         return initialize(initData);
277     }
278 
279     /**
280      * Creates a communicator using a default configuration.
281      *
282      * @return A new communicator instance.
283      **/
284     public static Communicator
initialize()285     initialize()
286     {
287         return initialize(new InitializationData());
288     }
289 
290     /**
291      * Converts a string to an object identity.
292      *
293      * @param s The string to convert.
294      *
295      * @return The converted object identity.
296      **/
297     public static Identity
stringToIdentity(String s)298     stringToIdentity(String s)
299     {
300         Identity ident = new Identity();
301 
302         //
303         // Find unescaped separator; note that the string may contain an escaped
304         // backslash before the separator.
305         //
306         int slash = -1, pos = 0;
307         while((pos = s.indexOf('/', pos)) != -1)
308         {
309             int escapes = 0;
310             while(pos - escapes > 0 && s.charAt(pos - escapes - 1) == '\\')
311             {
312                 escapes++;
313             }
314 
315             //
316             // We ignore escaped escapes
317             //
318             if(escapes % 2 == 0)
319             {
320                 if(slash == -1)
321                 {
322                     slash = pos;
323                 }
324                 else
325                 {
326                     //
327                     // Extra unescaped slash found.
328                     //
329                     IdentityParseException ex = new IdentityParseException();
330                     ex.str = "unescaped backslash in identity `" + s + "'";
331                     throw ex;
332                 }
333             }
334             pos++;
335         }
336 
337         if(slash == -1)
338         {
339             ident.category = "";
340             try
341             {
342                 ident.name = IceUtilInternal.StringUtil.unescapeString(s, 0, s.length(), "/");
343             }
344             catch(IllegalArgumentException e)
345             {
346                 IdentityParseException ex = new IdentityParseException();
347                 ex.str = "invalid identity name `" + s + "': " + e.getMessage();
348                 throw ex;
349             }
350         }
351         else
352         {
353             try
354             {
355                 ident.category = IceUtilInternal.StringUtil.unescapeString(s, 0, slash, "/");
356             }
357             catch(IllegalArgumentException e)
358             {
359                 IdentityParseException ex = new IdentityParseException();
360                 ex.str = "invalid category in identity `" + s + "': " + e.getMessage();
361                 throw ex;
362             }
363             if(slash + 1 < s.length())
364             {
365                 try
366                 {
367                     ident.name = IceUtilInternal.StringUtil.unescapeString(s, slash + 1, s.length(), "/");
368                 }
369                 catch(IllegalArgumentException e)
370                 {
371                     IdentityParseException ex = new IdentityParseException();
372                     ex.str = "invalid name in identity `" + s + "': " + e.getMessage();
373                     throw ex;
374                 }
375             }
376             else
377             {
378                 ident.name = "";
379             }
380         }
381 
382         return ident;
383     }
384 
385     /**
386      * Converts an object identity to a string.
387      *
388      * @param ident The object identity to convert.
389      *
390      * @param toStringMode Specifies if and how non-printable ASCII characters are escaped in the result.
391      *
392      * @return The string representation of the object identity.
393      **/
identityToString(Identity ident, ToStringMode toStringMode)394     public static String identityToString(Identity ident, ToStringMode toStringMode)
395     {
396         if(ident.category == null || ident.category.length() == 0)
397         {
398             return IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode);
399         }
400         else
401         {
402             return IceUtilInternal.StringUtil.escapeString(ident.category, "/", toStringMode) + '/' +
403                 IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode);
404         }
405     }
406 
407     /**
408      * Converts an object identity to a string.
409      *
410      * @param ident The object identity to convert.
411      *
412      * @return The string representation of the object identity using the default mode (Unicode)
413      **/
identityToString(Identity ident)414     public static String identityToString(Identity ident)
415     {
416         return identityToString(ident, ToStringMode.Unicode);
417     }
418 
419     /**
420      * Compares the object identities of two proxies.
421      *
422      * @param lhs A proxy.
423      * @param rhs A proxy.
424      * @return -1 if the identity in <code>lhs</code> compares
425      * less than the identity in <code>rhs</code>; 0 if the identities
426      * compare equal; 1, otherwise.
427      *
428      * @see ProxyIdentityKey
429      * @see ProxyIdentityFacetKey
430      * @see #proxyIdentityAndFacetCompare
431      **/
432     public static int
proxyIdentityCompare(ObjectPrx lhs, ObjectPrx rhs)433     proxyIdentityCompare(ObjectPrx lhs, ObjectPrx rhs)
434     {
435         if(lhs == null && rhs == null)
436         {
437             return 0;
438         }
439         else if(lhs == null && rhs != null)
440         {
441             return -1;
442         }
443         else if(lhs != null && rhs == null)
444         {
445             return 1;
446         }
447         else
448         {
449             Identity lhsIdentity = lhs.ice_getIdentity();
450             Identity rhsIdentity = rhs.ice_getIdentity();
451             int n;
452             if((n = lhsIdentity.name.compareTo(rhsIdentity.name)) != 0)
453             {
454                 return n;
455             }
456             return lhsIdentity.category.compareTo(rhsIdentity.category);
457         }
458     }
459 
460     /**
461      * Compares the object identities and facets of two proxies.
462      *
463      * @param lhs A proxy.
464      * @param rhs A proxy.
465      * @return -1 if the identity and facet in <code>lhs</code> compare
466      * less than the identity and facet in <code>rhs</code>; 0 if the identities
467      * and facets compare equal; 1, otherwise.
468      *
469      * @see ProxyIdentityFacetKey
470      * @see ProxyIdentityKey
471      * @see #proxyIdentityCompare
472      **/
473     public static int
proxyIdentityAndFacetCompare(ObjectPrx lhs, ObjectPrx rhs)474     proxyIdentityAndFacetCompare(ObjectPrx lhs, ObjectPrx rhs)
475     {
476         if(lhs == null && rhs == null)
477         {
478             return 0;
479         }
480         else if(lhs == null && rhs != null)
481         {
482             return -1;
483         }
484         else if(lhs != null && rhs == null)
485         {
486             return 1;
487         }
488         else
489         {
490             Identity lhsIdentity = lhs.ice_getIdentity();
491             Identity rhsIdentity = rhs.ice_getIdentity();
492             int n;
493             if((n = lhsIdentity.name.compareTo(rhsIdentity.name)) != 0)
494             {
495                 return n;
496             }
497             if((n = lhsIdentity.category.compareTo(rhsIdentity.category)) != 0)
498             {
499                 return n;
500             }
501 
502             String lhsFacet = lhs.ice_getFacet();
503             String rhsFacet = rhs.ice_getFacet();
504             if(lhsFacet == null && rhsFacet == null)
505             {
506                 return 0;
507             }
508             else if(lhsFacet == null)
509             {
510                 return -1;
511             }
512             else if(rhsFacet == null)
513             {
514                 return 1;
515             }
516             return lhsFacet.compareTo(rhsFacet);
517         }
518     }
519 
520     /**
521      * Returns the process-wide logger.
522      *
523      * @return The process-wide logger.
524      **/
525     public static Logger
getProcessLogger()526     getProcessLogger()
527     {
528         synchronized(_processLoggerMutex)
529         {
530             if(_processLogger == null)
531             {
532                 //
533                 // TODO: Would be nice to be able to use process name as prefix by default.
534                 //
535                 _processLogger = new LoggerI("", "");
536             }
537 
538             return _processLogger;
539         }
540     }
541 
542     /**
543      * Changes the process-wide logger.
544      *
545      * @param logger The new process-wide logger.
546      **/
547     public static void
setProcessLogger(Logger logger)548     setProcessLogger(Logger logger)
549     {
550         synchronized(_processLoggerMutex)
551         {
552             _processLogger = logger;
553         }
554     }
555 
556     /**
557      * Returns the Ice version in the form <code>A.B.C</code>, where <code>A</code> indicates the
558      * major version, <code>B</code> indicates the minor version, and <code>C</code> indicates the
559      * patch level.
560      *
561      * @return The Ice version.
562      **/
563     public static String
stringVersion()564     stringVersion()
565     {
566         return "3.7.2"; // "A.B.C", with A=major, B=minor, C=patch
567     }
568 
569     /**
570      * Returns the Ice version as an integer in the form <code>A.BB.CC</code>, where <code>A</code>
571      * indicates the major version, <code>BB</code> indicates the minor version, and <code>CC</code>
572      * indicates the patch level. For example, for Ice 3.3.1, the returned value is 30301.
573      *
574      * @return The Ice version.
575      **/
576     public static int
intVersion()577     intVersion()
578     {
579         return 30702; // AABBCC, with AA=major, BB=minor, CC=patch
580     }
581 
582     /**
583      * Converts a string to a protocol version.
584      *
585      * @param version The string to convert.
586      *
587      * @return The converted protocol version.
588      **/
589     static public Ice.ProtocolVersion
stringToProtocolVersion(String version)590     stringToProtocolVersion(String version)
591     {
592         return new Ice.ProtocolVersion(stringToMajor(version), stringToMinor(version));
593     }
594 
595     /**
596      * Converts a string to an encoding version.
597      *
598      * @param version The string to convert.
599      *
600      * @return The converted object identity.
601      **/
602     static public Ice.EncodingVersion
stringToEncodingVersion(String version)603     stringToEncodingVersion(String version)
604     {
605         return new Ice.EncodingVersion(stringToMajor(version), stringToMinor(version));
606     }
607 
608     /**
609      * Converts a protocol version to a string.
610      *
611      * @param v The protocol version to convert.
612      *
613      * @return The converted string.
614      **/
615     static public String
protocolVersionToString(Ice.ProtocolVersion v)616     protocolVersionToString(Ice.ProtocolVersion v)
617     {
618         return majorMinorToString(v.major, v.minor);
619     }
620 
621     /**
622      * Converts an encoding version to a string.
623      *
624      * @param v The encoding version to convert.
625      *
626      * @return The converted string.
627      **/
628     static public String
encodingVersionToString(Ice.EncodingVersion v)629     encodingVersionToString(Ice.EncodingVersion v)
630     {
631         return majorMinorToString(v.major, v.minor);
632     }
633 
634     /**
635      * Returns the supported Ice protocol version.
636      *
637      * @return The Ice protocol version.
638      **/
639     static public Ice.ProtocolVersion
currentProtocol()640     currentProtocol()
641     {
642         return IceInternal.Protocol.currentProtocol.clone();
643     }
644 
645     /**
646      * Returns the supported Ice encoding version.
647      *
648      * @return The Ice encoding version.
649      **/
650     static public Ice.EncodingVersion
currentEncoding()651     currentEncoding()
652     {
653         return IceInternal.Protocol.currentEncoding.clone();
654     }
655 
656     /**
657      * Translates a Slice type id to a Java class name.
658      *
659      * @param id The Slice type id, such as <code>::Module::Type</code>.
660      * @return The equivalent Java class name, or null if the type id is malformed.
661      **/
typeIdToClass(String id)662     public static String typeIdToClass(String id)
663     {
664         if(!id.startsWith("::"))
665         {
666             return null;
667         }
668 
669         StringBuilder buf = new StringBuilder(id.length());
670 
671         int start = 2;
672         boolean done = false;
673         while(!done)
674         {
675             int end = id.indexOf(':', start);
676             String s;
677             if(end != -1)
678             {
679                 s = id.substring(start, end);
680                 start = end + 2;
681             }
682             else
683             {
684                 s = id.substring(start);
685                 done = true;
686             }
687             if(buf.length() > 0)
688             {
689                 buf.append('.');
690             }
691             buf.append(fixKwd(s));
692         }
693 
694         return buf.toString();
695     }
696 
fixKwd(String name)697     private static String fixKwd(String name)
698     {
699         //
700         // Keyword list. *Must* be kept in alphabetical order. Note that checkedCast and uncheckedCast
701         // are not Java keywords, but are in this list to prevent illegal code being generated if
702         // someone defines Slice operations with that name.
703         //
704         final String[] keywordList =
705         {
706             "abstract", "assert", "boolean", "break", "byte", "case", "catch",
707             "char", "checkedCast", "class", "clone", "const", "continue", "default", "do",
708             "double", "else", "enum", "equals", "extends", "false", "final", "finalize",
709             "finally", "float", "for", "getClass", "goto", "hashCode", "if",
710             "implements", "import", "instanceof", "int", "interface", "long",
711             "native", "new", "notify", "notifyAll", "null", "package", "private",
712             "protected", "public", "return", "short", "static", "strictfp", "super", "switch",
713             "synchronized", "this", "throw", "throws", "toString", "transient",
714             "true", "try", "uncheckedCast", "void", "volatile", "wait", "while"
715         };
716         boolean found =  java.util.Arrays.binarySearch(keywordList, name) >= 0;
717         return found ? "_" + name : name;
718     }
719 
720     static private byte
stringToMajor(String str)721     stringToMajor(String str)
722     {
723         int pos = str.indexOf('.');
724         if(pos == -1)
725         {
726             throw new Ice.VersionParseException("malformed version value `" + str + "'");
727         }
728 
729         String majStr = str.substring(0, pos);
730         int majVersion;
731         try
732         {
733             majVersion = Integer.parseInt(majStr);
734         }
735         catch(NumberFormatException ex)
736         {
737             throw new Ice.VersionParseException("invalid version value `" + str + "'");
738         }
739 
740         if(majVersion < 1 || majVersion > 255)
741         {
742             throw new Ice.VersionParseException("range error in version `" + str + "'");
743         }
744 
745         return (byte)majVersion;
746     }
747 
748     static private byte
stringToMinor(String str)749     stringToMinor(String str)
750     {
751         int pos = str.indexOf('.');
752         if(pos == -1)
753         {
754             throw new Ice.VersionParseException("malformed version value `" + str + "'");
755         }
756 
757         String minStr = str.substring(pos + 1, str.length());
758         int minVersion;
759         try
760         {
761             minVersion = Integer.parseInt(minStr);
762         }
763         catch(NumberFormatException ex)
764         {
765             throw new Ice.VersionParseException("invalid version value `" + str + "'");
766         }
767 
768         if(minVersion < 0 || minVersion > 255)
769         {
770             throw new Ice.VersionParseException("range error in version `" + str + "'");
771         }
772 
773         return (byte)minVersion;
774     }
775 
776     static private String
majorMinorToString(byte major, byte minor)777     majorMinorToString(byte major, byte minor)
778     {
779         StringBuilder str = new StringBuilder();
780         str.append(major < 0 ? major + 255 : (int)major);
781         str.append(".");
782         str.append(minor < 0 ? minor + 255 : (int)minor);
783         return str.toString();
784     }
785 
786     public final static Ice.ProtocolVersion Protocol_1_0 = new Ice.ProtocolVersion((byte)1, (byte)0);
787 
788     public final static Ice.EncodingVersion Encoding_1_0 = new Ice.EncodingVersion((byte)1, (byte)0);
789     public final static Ice.EncodingVersion Encoding_1_1 = new Ice.EncodingVersion((byte)1, (byte)1);
790 
791     private static java.lang.Object _processLoggerMutex = new java.lang.Object();
792     private static Logger _processLogger = null;
793 }
794