diff options
Diffstat (limited to 'java-compat/src')
15 files changed, 351 insertions, 158 deletions
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java index 72d7031cc94..97543a77755 100644 --- a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java +++ b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java @@ -369,7 +369,7 @@ public class SessionFactoryHelper { StringBuilder sb = new StringBuilder(); sb.append("\""); - sb.append(Ice.Util.identityToString(ident)); + sb.append(Ice.Util.identityToString(ident, Ice.ToStringMode.Unicode)); sb.append("\":"); sb.append(_protocol + " -p "); sb.append(getPortInternal()); diff --git a/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java index 5523f7663b4..8ca4682639c 100644 --- a/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java +++ b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java @@ -78,7 +78,7 @@ public final class CommunicatorI implements Communicator public String identityToString(Ice.Identity ident) { - return Ice.Util.identityToString(ident); + return Ice.Util.identityToString(ident, _instance.toStringMode()); } @Override diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java index 1aeef2206fa..53abcf4b4b6 100644 --- a/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java +++ b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java @@ -980,7 +980,8 @@ public final class ObjectAdapterI implements ObjectAdapter if(_routerInfo.getAdapter() != null) { throw new AlreadyRegisteredException("object adapter with router", - Ice.Util.identityToString(router.ice_getIdentity())); + Ice.Util.identityToString(router.ice_getIdentity(), + _instance.toStringMode())); } // diff --git a/java-compat/src/Ice/src/main/java/Ice/Util.java b/java-compat/src/Ice/src/main/java/Ice/Util.java index 3c2b04d8fd4..a758a316e00 100644 --- a/java-compat/src/Ice/src/main/java/Ice/Util.java +++ b/java-compat/src/Ice/src/main/java/Ice/Util.java @@ -324,23 +324,37 @@ public final class Util * * @param ident The object identity to convert. * + * @param toStringMode Specifies if and how non-printable ASCII characters are escaped in the result. + * * @return The string representation of the object identity. **/ - public static String - identityToString(Identity ident) + public static String identityToString(Identity ident, ToStringMode toStringMode) { if(ident.category == null || ident.category.length() == 0) { - return IceUtilInternal.StringUtil.escapeString(ident.name, "/"); + return IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode); } else { - return IceUtilInternal.StringUtil.escapeString(ident.category, "/") + '/' + - IceUtilInternal.StringUtil.escapeString(ident.name, "/"); + return IceUtilInternal.StringUtil.escapeString(ident.category, "/", toStringMode) + '/' + + IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode); } } /** + * Converts an object identity to a string. + * + * @param ident The object identity to convert. + * + * @return The string representation of the object identity using the default mode (Unicode) + **/ + // public static String identityToString(Identity ident) + // { + // return identityToString(ident, ToStringMode.Unicode); + // } + + + /** * Compares the object identities of two proxies. * * @param lhs A proxy. diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java index 095948736e3..5b9f377d807 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java @@ -319,7 +319,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb public String getIdentity() { - return Ice.Util.identityToString(_current.id); + return _current.adapter.getCommunicator().identityToString(_current.id); } final private Ice.Current _current; @@ -428,7 +428,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb catch(Exception ex) { // Either a fixed proxy or the communicator is destroyed. - os.append(Ice.Util.identityToString(_proxy.ice_getIdentity())); + os.append(_proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity())); os.append(" [").append(_operation).append(']'); } _id = os.toString(); @@ -458,7 +458,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb { if(_proxy != null) { - return Ice.Util.identityToString(_proxy.ice_getIdentity()); + return _proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity()); } else { diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java index 1e1b4c4dfa8..2723ce7a7b7 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java @@ -236,8 +236,8 @@ class IncomingBase IceUtilInternal.OutputBase out = new IceUtilInternal.OutputBase(pw); out.setUseTab(false); out.print("dispatch exception:"); - out.print("\nidentity: " + Ice.Util.identityToString(_current.id)); - out.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, "")); + out.print("\nidentity: " + Ice.Util.identityToString(_current.id, _instance.toStringMode())); + out.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, "", _instance.toStringMode())); out.print("\noperation: " + _current.operation); if(_current.con != null) { diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Instance.java b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java index 30b78609ca8..997b64313f6 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/Instance.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java @@ -393,6 +393,13 @@ public final class Instance implements Ice.ClassResolver return _batchAutoFlushSize; } + public Ice.ToStringMode + toStringMode() + { + // No mutex lock, immutable + return _toStringMode; + } + public int cacheMessageBuffers() { @@ -1018,6 +1025,24 @@ public final class Instance implements Ice.ClassResolver } } + String toStringModeStr = _initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode"); + if(toStringModeStr.equals("Unicode")) + { + _toStringMode = Ice.ToStringMode.Unicode; + } + else if(toStringModeStr.equals("ASCII")) + { + _toStringMode = Ice.ToStringMode.ASCII; + } + else if(toStringModeStr.equals("Compat")) + { + _toStringMode = Ice.ToStringMode.Compat; + } + else + { + throw new Ice.InitializationException("The value for Ice.ToStringMode must be Unicode, ASCII or Compat"); + } + _implicitContext = Ice.ImplicitContextI.create(_initData.properties.getProperty("Ice.ImplicitContext")); _routerManager = new RouterManager(); @@ -1820,6 +1845,7 @@ public final class Instance implements Ice.ClassResolver private final DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy(). private final int _messageSizeMax; // Immutable, not reset by destroy(). private final int _batchAutoFlushSize; // Immutable, not reset by destroy(). + private final Ice.ToStringMode _toStringMode; // Immutable, not reset by destroy(). private final int _cacheMessageBuffers; // Immutable, not reset by destroy(). private final ACMConfig _clientACM; // Immutable, not reset by destroy(). private final ACMConfig _serverACM; // Immutable, not reset by destroy(). diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java index 82c4dea0e25..65f0c20840c 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java @@ -466,7 +466,7 @@ public final class LocatorInfo else { s.append("object = "); - s.append(Ice.Util.identityToString(ref.getIdentity())); + s.append(Ice.Util.identityToString(ref.getIdentity(), ref.getInstance().toStringMode())); s.append("\n"); } @@ -518,13 +518,13 @@ public final class LocatorInfo StringBuilder s = new StringBuilder(128); s.append("object not found\n"); s.append("object = "); - s.append(Ice.Util.identityToString(ref.getIdentity())); + s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode())); instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString()); } Ice.NotRegisteredException e = new Ice.NotRegisteredException(); e.kindOfObject = "object"; - e.id = Ice.Util.identityToString(ref.getIdentity()); + e.id = Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()); throw e; } catch(Ice.NotRegisteredException ex) @@ -547,7 +547,7 @@ public final class LocatorInfo else { s.append("object = "); - s.append(Ice.Util.identityToString(ref.getIdentity())); + s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode())); s.append("\n"); } s.append("reason = " + ex); @@ -591,7 +591,7 @@ public final class LocatorInfo { s.append("object\n"); s.append("object = "); - s.append(Ice.Util.identityToString(ref.getIdentity())); + s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode())); s.append("\n"); } instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString()); @@ -630,7 +630,7 @@ public final class LocatorInfo StringBuilder s = new StringBuilder(128); s.append("searching for object by id\n"); s.append("object = "); - s.append(Ice.Util.identityToString(ref.getIdentity())); + s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode())); instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString()); } diff --git a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java index 78fca903d04..54e72359604 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Aug 18 20:28:56 2016 +// Generated by makeprops.py from file PropertyNames.xml, Tue Oct 18 11:39:01 2016 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -165,6 +165,7 @@ public final class PropertyNames new Property("Ice\\.ThreadPool\\.Server\\.ThreadIdleTime", false, null), new Property("Ice\\.ThreadPool\\.Server\\.ThreadPriority", false, null), new Property("Ice\\.ThreadPriority", false, null), + new Property("Ice\\.ToStringMode", false, null), new Property("Ice\\.Trace\\.Admin\\.Properties", false, null), new Property("Ice\\.Trace\\.Admin\\.Logger", false, null), new Property("Ice\\.Trace\\.Locator", false, null), @@ -980,7 +981,7 @@ public final class PropertyNames new Property("IceSSL\\.DHParams", false, null), new Property("IceSSL\\.EntropyDaemon", false, null), new Property("IceSSL\\.FindCert", false, null), - new Property("IceSSL\\.FindCert\\.[^\\s]+", true, "IceSSL.FindCert"), + new Property("IceSSL\\.FindCert\\.[^\\s]+", true, null), new Property("IceSSL\\.InitOpenSSL", false, null), new Property("IceSSL\\.KeyFile", true, null), new Property("IceSSL\\.Keychain", false, null), diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Reference.java b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java index b7ea1dd2f32..48ac1b0788a 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/Reference.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java @@ -306,13 +306,18 @@ public abstract class Reference implements Cloneable // StringBuilder s = new StringBuilder(128); + Ice.ToStringMode toStringMode = _instance.toStringMode(); + final String separators = " :@"; + + String id = Ice.Util.identityToString(_identity, toStringMode); + // // If the encoded identity string contains characters which // the reference parser uses as separators, then we enclose // the identity string in quotes. // - String id = Ice.Util.identityToString(_identity); - if(IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1) + + if(IceUtilInternal.StringUtil.findFirstOf(id, separators) != -1) { s.append('"'); s.append(id); @@ -331,8 +336,8 @@ public abstract class Reference implements Cloneable // the facet string in quotes. // s.append(" -f "); - String fs = IceUtilInternal.StringUtil.escapeString(_facet, ""); - if(IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1) + String fs = IceUtilInternal.StringUtil.escapeString(_facet, "", toStringMode); + if(IceUtilInternal.StringUtil.findFirstOf(fs, separators) != -1) { s.append('"'); s.append(fs); @@ -481,16 +486,16 @@ public abstract class Reference implements Cloneable @Override public Reference clone() { - Reference c = null; - try - { - c = (Reference)super.clone(); - } - catch(CloneNotSupportedException ex) - { - assert false; - } - return c; + Reference c = null; + try + { + c = (Reference)super.clone(); + } + catch(CloneNotSupportedException ex) + { + assert false; + } + return c; } protected int _hashValue; diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java index 688b2ca9935..bdca554000a 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java @@ -353,7 +353,7 @@ public class RoutableReference extends Reference // the reference parser uses as separators, then we enclose // the adapter id string in quotes. // - String a = IceUtilInternal.StringUtil.escapeString(_adapterId, null); + String a = IceUtilInternal.StringUtil.escapeString(_adapterId, null, getInstance().toStringMode()); if(IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1) { s.append('"'); diff --git a/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java index 2789304f276..aa74865221c 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java @@ -32,11 +32,11 @@ public final class ServantManager if(m.containsKey(facet)) { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, _instance.toStringMode()); ex.kindOfObject = "servant"; if(facet.length() > 0) { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "", _instance.toStringMode()); } throw ex; } @@ -77,11 +77,11 @@ public final class ServantManager if(m == null || (obj = m.remove(facet)) == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, _instance.toStringMode()); ex.kindOfObject = "servant"; if(facet.length() > 0) { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "", _instance.toStringMode()); } throw ex; } @@ -120,7 +120,7 @@ public final class ServantManager if(m == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, _instance.toStringMode()); ex.kindOfObject = "servant"; throw ex; } @@ -218,7 +218,7 @@ public final class ServantManager if(l != null) { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); - ex.id = IceUtilInternal.StringUtil.escapeString(category, ""); + ex.id = IceUtilInternal.StringUtil.escapeString(category, "", _instance.toStringMode()); ex.kindOfObject = "servant locator"; throw ex; } @@ -236,7 +236,7 @@ public final class ServantManager if(l == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = IceUtilInternal.StringUtil.escapeString(category, ""); + ex.id = IceUtilInternal.StringUtil.escapeString(category, "", _instance.toStringMode()); ex.kindOfObject = "servant locator"; throw ex; } diff --git a/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java index 2ff165c475d..d50797350e5 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java @@ -166,15 +166,21 @@ public final class TraceUtil { try { + Ice.ToStringMode toStringMode = Ice.ToStringMode.Unicode; + if(stream.instance() != null) + { + toStringMode = stream.instance().toStringMode(); + } + Ice.Identity identity = new Ice.Identity(); identity.__read(stream); - out.write("\nidentity = " + Ice.Util.identityToString(identity)); + out.write("\nidentity = " + Ice.Util.identityToString(identity, toStringMode)); String[] facet = stream.readStringSeq(); out.write("\nfacet = "); if(facet.length > 0) { - out.write(IceUtilInternal.StringUtil.escapeString(facet[0], "")); + out.write(IceUtilInternal.StringUtil.escapeString(facet[0], "", toStringMode)); } String operation = stream.readString(); diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java index 953359c5c4b..5c274db2375 100644 --- a/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java +++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java @@ -75,97 +75,119 @@ public final class StringUtil return -1; } - // - // Write the byte b as an escape sequence if it isn't a printable ASCII - // character and append the escape sequence to sb. Additional characters - // that should be escaped can be passed in special. If b is any of these - // characters, b is preceded by a backslash in sb. - // private static void - encodeChar(byte b, StringBuilder sb, String special) + encodeChar(char c, StringBuilder sb, String special, Ice.ToStringMode toStringMode) { - switch(b) + switch(c) { - case (byte)'\\': + case '\\': { sb.append("\\\\"); break; } - case (byte)'\'': + case '\'': { sb.append("\\'"); break; } - case (byte)'"': + case '"': { sb.append("\\\""); break; } - case (byte)'\b': + case '\b': { sb.append("\\b"); break; } - case (byte)'\f': + case '\f': { sb.append("\\f"); break; } - case (byte)'\n': + case '\n': { sb.append("\\n"); break; } - case (byte)'\r': + case '\r': { sb.append("\\r"); break; } - case (byte)'\t': + case '\t': { sb.append("\\t"); break; } default: { - if(!(b >= 32 && b <= 126)) - { - sb.append('\\'); - String octal = Integer.toOctalString(b < 0 ? b + 256 : b); - // - // Add leading zeroes so that we avoid problems during - // decoding. For example, consider the encoded string - // \0013 (i.e., a character with value 1 followed by - // the character '3'). If the leading zeroes were omitted, - // the result would be incorrectly interpreted by the - // decoder as a single character with value 11. - // - for(int j = octal.length(); j < 3; j++) - { - sb.append('0'); - } - sb.append(octal); - } - else if(special != null && special.indexOf((char)b) != -1) + if(special != null && special.indexOf(c) != -1) { sb.append('\\'); - sb.append((char)b); + sb.append(c); } else { - sb.append((char)b); + if(c < 32 || c > 126) + { + if(toStringMode == Ice.ToStringMode.Compat) + { + // + // When ToStringMode=Compat, c is a UTF-8 byte + // + assert(c < 256); + + sb.append('\\'); + String octal = Integer.toOctalString(c); + // + // Add leading zeroes so that we avoid problems during + // decoding. For example, consider the encoded string + // \0013 (i.e., a character with value 1 followed by + // the character '3'). If the leading zeroes were omitted, + // the result would be incorrectly interpreted by the + // decoder as a single character with value 11. + // + for(int j = octal.length(); j < 3; j++) + { + sb.append('0'); + } + sb.append(octal); + } + else if(c < 32 || c == 127 || toStringMode == Ice.ToStringMode.ASCII) + { + // append \\unnnn + sb.append("\\u"); + String hex = Integer.toHexString(c); + for(int j = hex.length(); j < 4; j++) + { + sb.append('0'); + } + sb.append(hex); + } + else + { + // keep as is + sb.append(c); + } + } + else + { + // printable ASCII character + sb.append(c); + } } + break; } } } // - // Add escape sequences (such as "\n", or "\007") to make a string - // readable in ASCII. Any characters that appear in special are - // prefixed with a backlash in the returned string. + // Add escape sequences (like "\n" to the input string) + // The second parameter adds characters to escape, and can be empty. // public static String - escapeString(String s, String special) + escapeString(String s, String special, Ice.ToStringMode toStringMode) { if(special != null) { @@ -178,31 +200,72 @@ public final class StringUtil } } - byte[] bytes = null; - try + if(toStringMode == Ice.ToStringMode.Compat) { - bytes = s.getBytes("UTF8"); + // Encode UTF-8 bytes + + byte[] bytes = null; + try + { + bytes = s.getBytes("UTF8"); + } + catch(java.io.UnsupportedEncodingException ex) + { + assert(false); + return null; + } + + StringBuilder result = new StringBuilder(bytes.length); + for(int i = 0; i < bytes.length; i++) + { + encodeChar((char)(bytes[i] & 0xFF), result, special, toStringMode); + } + + return result.toString(); } - catch(java.io.UnsupportedEncodingException ex) + else { - assert(false); - return null; - } + StringBuilder result = new StringBuilder(s.length()); - StringBuilder result = new StringBuilder(bytes.length); - for(int i = 0; i < bytes.length; i++) - { - encodeChar(bytes[i], result, special); - } + for(int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + if(toStringMode == Ice.ToStringMode.Unicode || !Character.isSurrogate(c)) + { + encodeChar(c, result, special, toStringMode); + } + else + { + assert(toStringMode == Ice.ToStringMode.ASCII && Character.isSurrogate(c)); + if(i + 1 == s.length()) + { + throw new IllegalArgumentException("High surrogate without low surrogate"); + } + else + { + i++; + int codePoint = Character.toCodePoint(c, s.charAt(i)); + // append \Unnnnnnnn + result.append("\\U"); + String hex = Integer.toHexString(codePoint); + for(int j = hex.length(); j < 8; j++) + { + result.append('0'); + } + result.append(hex); + } + } + } - return result.toString(); + return result.toString(); + } } private static char checkChar(String s, int pos) { char c = s.charAt(pos); - if(!(c >= 32 && c <= 126)) + if(c < 32 || c == 127) { String msg; if(pos > 0) @@ -213,28 +276,27 @@ public final class StringUtil { msg = "first character"; } - msg += " is not a printable ASCII character (ordinal " + (int)c + ")"; + msg += " has invalid ordinal value " + (int)c; throw new IllegalArgumentException(msg); } return c; } // - // Decode the character or escape sequence starting at start and return it. - // newStart is set to the index of the first character following the decoded character + // Decode the character or escape sequence starting at start and appends it to result; + // returns the index of the first character following the decoded character // or escape sequence. // - private static char decodeChar(String s, int start, int end, Ice.Holder<Integer> nextStart) + private static int + decodeChar(String s, int start, int end, StringBuilder result) { assert(start >= 0); assert(start < end); assert(end <= s.length()); - char c; - if(s.charAt(start) != '\\') { - c = checkChar(s, start++); + result.append(checkChar(s, start++)); } else { @@ -242,45 +304,98 @@ public final class StringUtil { throw new IllegalArgumentException("trailing backslash"); } - switch(s.charAt(++start)) + + char c = s.charAt(++start); + + switch(c) { case '\\': case '\'': case '"': { - c = s.charAt(start++); + ++start; + result.append(c); break; } case 'b': { ++start; - c = '\b'; + result.append('\b'); break; } case 'f': { ++start; - c = '\f'; + result.append('\f'); break; } case 'n': { ++start; - c = '\n'; + result.append('\n'); break; } case 'r': { ++start; - c = '\r'; + result.append('\r'); break; } case 't': { ++start; - c = '\t'; + result.append('\t'); break; } + case 'u': + case 'U': + { + int codePoint = 0; + boolean inBMP = (c == 'u'); + int size = inBMP ? 4 : 8; + ++start; + while(size > 0 && start < end) + { + c = s.charAt(start++); + int charVal = 0; + if(c >= '0' && c <= '9') + { + charVal = c - '0'; + } + else if(c >= 'a' && c <= 'f') + { + charVal = 10 + (c - 'a'); + } + else if(c >= 'A' && c <= 'F') + { + charVal = 10 + (c - 'A'); + } + else + { + break; // while + } + codePoint = codePoint * 16 + charVal; + --size; + } + if(size > 0) + { + throw new IllegalArgumentException("Invalid universal character name: too few hex digits"); + } + if(inBMP && Character.isSurrogate((char)codePoint)) + { + throw new IllegalArgumentException("A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead"); + } + if(inBMP || Character.isBmpCodePoint(codePoint)) + { + result.append((char)codePoint); + } + else + { + result.append(Character.toChars(codePoint)); + } + break; + } + case '0': case '1': case '2': @@ -290,49 +405,71 @@ public final class StringUtil case '6': case '7': { - int val = 0; - for(int j = 0; j < 3 && start < end; ++j) + // UTF-8 byte sequence encoded with octal escapes + + byte[] arr = new byte[end - start]; + int i = 0; + boolean done = false; + while(!done) { - int charVal = s.charAt(start++) - '0'; - if(charVal < 0 || charVal > 7) + int val = 0; + for(int j = 0; j < 3 && start < end; ++j) { - --start; - break; + int charVal = s.charAt(start++) - '0'; + if(charVal < 0 || charVal > 7) + { + --start; + if(j == 0) + { + // first character after escape is not 0-7: + done = true; + --start; // go back to the previous backslash + } + break; // for + } + val = val * 8 + charVal; } - val = val * 8 + charVal; + + if(!done) + { + if(val > 255) + { + String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range"; + throw new IllegalArgumentException(msg); + } + arr[i++] = (byte)val; + + if((start + 1 < end) && s.charAt(start) == '\\') + { + start++; + // loop, read next octal escape sequence + } + else + { + done = true; + } + } + } + + try + { + result.append(new String(arr, 0, i, "UTF8")); } - if(val > 255) + catch(java.io.UnsupportedEncodingException ex) { - String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range"; - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("unsupported encoding", ex); } - c = (char)val; break; } default: { - c = checkChar(s, start++); + result.append(checkChar(s, start++)); break; } } } - nextStart.value = start; - return c; - } - // - // Remove escape sequences from s and append the result to sb. - // Return true if successful, false otherwise. - // - private static void - decodeString(String s, int start, int end, StringBuilder sb) - { - Ice.Holder<Integer> nextStart = new Ice.Holder<Integer>(); - while(start < end) - { - sb.append(decodeChar(s, start, end, nextStart)); - start = nextStart.value; - } + return start; } // @@ -344,26 +481,29 @@ public final class StringUtil { assert(start >= 0 && start <= end && end <= s.length()); - StringBuilder sb = new StringBuilder(end - start); - decodeString(s, start, end, sb); - String decodedString = sb.toString(); - - byte[] arr = new byte[decodedString.length()]; - for(int i = 0; i < arr.length; ++i) - { - arr[i] = (byte)decodedString.charAt(i); - } - - try + // Optimization for strings without escapes + int p = s.indexOf('\\', start); + if(p == -1 || p >= end) { - return new String(arr, 0, arr.length, "UTF8"); + p = start; + while(p < end) + { + checkChar(s, p++); + } + return s.substring(start, end); } - catch(java.io.UnsupportedEncodingException ex) + else { - throw new IllegalArgumentException("unsupported encoding", ex); + StringBuilder sb = new StringBuilder(end - start); + while(start < end) + { + start = decodeChar(s, start, end, sb); + } + return sb.toString(); } } + // // Join a list of strings using the given delimiter. // diff --git a/java-compat/src/IceBox/src/main/java/IceBox/Admin.java b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java index 52e39ee771e..0b363f83c6a 100644 --- a/java-compat/src/IceBox/src/main/java/IceBox/Admin.java +++ b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java @@ -84,7 +84,7 @@ public final class Admin return 1; } - managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" :" + managerEndpoints; + managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" :" + managerEndpoints; } else { @@ -95,7 +95,7 @@ public final class Admin return 1; } - managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" @" + managerAdapterId; + managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" @" + managerAdapterId; } base = communicator().stringToProxy(managerProxy); |