/** * Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com> */ package org.deephacks.confit.internal.core.property.typesafe.impl; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.deephacks.confit.internal.core.property.typesafe.ConfigException; import org.deephacks.confit.internal.core.property.typesafe.ConfigOrigin; /** This is public just for the "typesafe" package to use, don't touch it */ final public class ConfigImplUtil { static boolean equalsHandlingNull(Object a, Object b) { if (a == null && b != null) return false; else if (a != null && b == null) return false; else if (a == b) // catches null == null plus optimizes identity case return true; else return a.equals(b); } /** * This is public ONLY for use by the "typesafe" package, DO NOT USE this ABI * may change. */ public static String renderJsonString(String s) { StringBuilder sb = new StringBuilder(); sb.append('"'); for (int i = 0; i < s.length(); ++i) { char c = s.charAt(i); switch (c) { case '"': sb.append("\\\""); break; case '\\': sb.append("\\\\"); break; case '\n': sb.append("\\n"); break; case '\b': sb.append("\\b"); break; case '\f': sb.append("\\f"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; default: if (Character.isISOControl(c)) sb.append(String.format("\\u%04x", (int) c)); else sb.append(c); } } sb.append('"'); return sb.toString(); } static String renderStringUnquotedIfPossible(String s) { // this can quote unnecessarily as long as it never fails to quote when // necessary if (s.length() == 0) return renderJsonString(s); int first = s.codePointAt(0); if (Character.isDigit(first)) return renderJsonString(s); if (s.startsWith("include") || s.startsWith("true") || s.startsWith("false") || s.startsWith("null") || s.contains("//")) return renderJsonString(s); // only unquote if it's pure alphanumeric for (int i = 0; i < s.length(); ++i) { char c = s.charAt(i); if (!(Character.isLetter(c) || Character.isDigit(c))) return renderJsonString(s); } return s; } static boolean isWhitespace(int codepoint) { switch (codepoint) { // try to hit the most common ASCII ones first, then the nonbreaking // spaces that Java brokenly leaves out of isWhitespace. case ' ': case '\n': case '\u00A0': case '\u2007': case '\u202F': // this one is the BOM, see // http://www.unicode.org/faq/utf_bom.html#BOM // we just accept it as a zero-width nonbreaking space. case '\uFEFF': return true; default: return Character.isWhitespace(codepoint); } } /** This is public just for the "typesafe" package to use, don't touch it! */ public static String unicodeTrim(String s) { // this is dumb because it looks like there aren't any whitespace // characters that need surrogate encoding. But, points for // pedantic correctness! It's future-proof or something. // String.trim() actually is broken, since there are plenty of // non-ASCII whitespace characters. final int length = s.length(); if (length == 0) return s; int start = 0; while (start < length) { char c = s.charAt(start); if (c == ' ' || c == '\n') { start += 1; } else { int cp = s.codePointAt(start); if (isWhitespace(cp)) start += Character.charCount(cp); else break; } } int end = length; while (end > start) { char c = s.charAt(end - 1); if (c == ' ' || c == '\n') { --end; } else { int cp; int delta; if (Character.isLowSurrogate(c)) { cp = s.codePointAt(end - 2); delta = 2; } else { cp = s.codePointAt(end - 1); delta = 1; } if (isWhitespace(cp)) end -= delta; else break; } } return s.substring(start, end); } /** This is public just for the "typesafe" package to use, don't touch it! */ public static ConfigException extractInitializerError(ExceptionInInitializerError e) { Throwable cause = e.getCause(); if (cause != null && cause instanceof ConfigException) { return (ConfigException) cause; } else { throw e; } } static File urlToFile(URL url) { // this isn't really right, clearly, but not sure what to do. try { // this will properly handle hex escapes, etc. return new File(url.toURI()); } catch (URISyntaxException e) { // this handles some stuff like file:///c:/Whatever/ // apparently but mangles handling of hex escapes return new File(url.getPath()); } catch (IllegalArgumentException e) { // file://foo with double slash causes // IllegalArgumentException "url has an authority component" return new File(url.getPath()); } } /** * This is public ONLY for use by the "typesafe" package, DO NOT USE this ABI * may change. You can use the version in ConfigUtil instead. */ public static String joinPath(String... elements) { return (new Path(elements)).render(); } /** * This is public ONLY for use by the "typesafe" package, DO NOT USE this ABI * may change. You can use the version in ConfigUtil instead. */ public static String joinPath(List<String> elements) { return joinPath(elements.toArray(new String[0])); } /** * This is public ONLY for use by the "typesafe" package, DO NOT USE this ABI * may change. You can use the version in ConfigUtil instead. */ public static List<String> splitPath(String path) { Path p = Path.newPath(path); List<String> elements = new ArrayList<String>(); while (p != null) { elements.add(p.first()); p = p.remainder(); } return elements; } public static ConfigOrigin readOrigin(ObjectInputStream in) throws IOException { return SerializedConfigValue.readOrigin(in, null); } public static void writeOrigin(ObjectOutputStream out, ConfigOrigin origin) throws IOException { SerializedConfigValue.writeOrigin(new DataOutputStream(out), (SimpleConfigOrigin) origin, null); } }