Repository: asterixdb Updated Branches: refs/heads/master 309ef98b8 -> 1fb232d96
Support -version Argument For CC/NC Drivers Output the build version when -version is passed to asterixcc/asterixnc Change-Id: I7ba105f693170ba781897dd2039783e1c5f6544b Reviewed-on: https://asterix-gerrit.ics.uci.edu/1637 Reviewed-by: Till Westmann <[email protected]> Sonar-Qube: Jenkins <[email protected]> Tested-by: Jenkins <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/1fb232d9 Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/1fb232d9 Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/1fb232d9 Branch: refs/heads/master Commit: 1fb232d9621f04bd635e647d5c4a7630279b093f Parents: 309ef98 Author: Michael Blow <[email protected]> Authored: Thu Mar 30 20:11:34 2017 -0400 Committer: Michael Blow <[email protected]> Committed: Thu Mar 30 18:24:03 2017 -0700 ---------------------------------------------------------------------- .../api/http/server/ClusterApiServlet.java | 14 +- .../api/http/server/QueryServiceServlet.java | 2 +- .../asterix/api/http/server/ResultUtil.java | 2 +- .../api/http/server/ShutdownApiServlet.java | 2 +- .../asterix/app/result/ResultPrinter.java | 2 +- .../bootstrap/ApplicationConfigurator.java | 19 ++ .../apache/asterix/common/utils/JSONUtil.java | 178 ------------------- .../hyracks/api/config/IConfigManager.java | 2 + .../control/common/config/ConfigManager.java | 35 ++-- .../org/apache/hyracks/control/nc/NCDriver.java | 4 +- hyracks-fullstack/hyracks/hyracks-util/pom.xml | 8 + .../java/org/apache/hyracks/util/JSONUtil.java | 177 ++++++++++++++++++ 12 files changed, 243 insertions(+), 202 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java index 6b16be1..984eef2 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java @@ -28,12 +28,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpResponseStatus; -import org.apache.asterix.common.utils.JSONUtil; import org.apache.asterix.runtime.utils.AppContextInfo; import org.apache.asterix.runtime.utils.ClusterStateManager; import org.apache.hyracks.api.config.IOption; @@ -44,6 +38,14 @@ import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.api.IServletResponse; import org.apache.hyracks.http.server.AbstractServlet; import org.apache.hyracks.http.server.utils.HttpUtil; +import org.apache.hyracks.util.JSONUtil; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; public class ClusterApiServlet extends AbstractServlet { http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java index 101fa97..faf9968 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java @@ -35,7 +35,6 @@ import org.apache.asterix.common.api.IClusterManagementWork; import org.apache.asterix.common.config.GlobalConfig; import org.apache.asterix.common.context.IStorageComponentProvider; import org.apache.asterix.common.exceptions.AsterixException; -import org.apache.asterix.common.utils.JSONUtil; import org.apache.asterix.compiler.provider.ILangCompilationProvider; import org.apache.asterix.lang.aql.parser.TokenMgrError; import org.apache.asterix.lang.common.base.IParser; @@ -52,6 +51,7 @@ import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendab import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.api.IServletResponse; import org.apache.hyracks.http.server.utils.HttpUtil; +import org.apache.hyracks.util.JSONUtil; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java index 18bd7b6..a257958 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ResultUtil.java @@ -36,7 +36,6 @@ import java.util.stream.Stream; import org.apache.asterix.app.result.ResultHandle; import org.apache.asterix.app.result.ResultPrinter; import org.apache.asterix.app.result.ResultReader; -import org.apache.asterix.common.utils.JSONUtil; import org.apache.asterix.om.types.ARecordType; import org.apache.asterix.translator.IStatementExecutor.Stats; import org.apache.asterix.translator.SessionConfig; @@ -44,6 +43,7 @@ import org.apache.http.ParseException; import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable; import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.util.JSONUtil; import org.apache.log4j.Logger; import com.fasterxml.jackson.databind.ObjectMapper; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java index 3d9602d..fdd106d 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java @@ -28,13 +28,13 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.apache.asterix.common.config.GlobalConfig; -import org.apache.asterix.common.utils.JSONUtil; import org.apache.asterix.runtime.utils.ClusterStateManager; import org.apache.hyracks.api.client.IHyracksClientConnection; import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.api.IServletResponse; import org.apache.hyracks.http.server.AbstractServlet; import org.apache.hyracks.http.server.utils.HttpUtil; +import org.apache.hyracks.util.JSONUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java index 61d0eed..c77ad44 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.StringWriter; import java.nio.ByteBuffer; -import org.apache.asterix.common.utils.JSONUtil; import org.apache.asterix.om.types.ARecordType; import org.apache.asterix.translator.IStatementExecutor.Stats; import org.apache.asterix.translator.SessionConfig; @@ -35,6 +34,7 @@ import org.apache.hyracks.api.comm.IFrameTupleAccessor; import org.apache.hyracks.api.comm.VSizeFrame; import org.apache.hyracks.api.exceptions.HyracksDataException; import org.apache.hyracks.control.nc.resources.memory.FrameManager; +import org.apache.hyracks.util.JSONUtil; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.PrettyPrinter; http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java index 4a5371a..466203c 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java @@ -18,6 +18,11 @@ */ package org.apache.asterix.hyracks.bootstrap; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.Properties; + import org.apache.asterix.common.config.AsterixProperties; import org.apache.hyracks.api.config.IConfigManager; import org.apache.hyracks.control.common.controllers.CCConfig; @@ -34,5 +39,19 @@ class ApplicationConfigurator { ControllerConfig.defaultDir = FileUtil.joinPath(System.getProperty("java.io.tmpdir"), "asterixdb"); NCConfig.defaultAppClass = NCApplication.class.getName(); CCConfig.defaultAppClass = CCApplication.class.getName(); + try { + InputStream propertyStream = ApplicationConfigurator.class.getClassLoader() + .getResourceAsStream("git.properties"); + if (propertyStream != null) { + Properties gitProperties = new Properties(); + gitProperties.load(propertyStream); + StringWriter sw = new StringWriter(); + gitProperties.store(sw, null); + configManager.setVersionString(sw.toString()); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/JSONUtil.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/JSONUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/JSONUtil.java deleted file mode 100644 index 80df260..0000000 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/JSONUtil.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.asterix.common.utils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; - -import java.io.IOException; -import java.util.Iterator; -import java.util.logging.Logger; - -public class JSONUtil { - - private static final Logger LOGGER = Logger.getLogger(JSONUtil.class.getName()); - - private static final String INDENT = "\t"; - - private static final ObjectMapper SORTED_MAPPER = new ObjectMapper(); - - private JSONUtil() { - } - - static { - SORTED_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); - } - - public static String convertNode(final JsonNode node) throws JsonProcessingException { - final Object obj = SORTED_MAPPER.treeToValue(node, Object.class); - final String json = SORTED_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj); - return json; - } - - public static String indent(String str, int initialIndent) { - ObjectMapper om = new ObjectMapper(); - try { - return appendObj(new StringBuilder(), om.readTree(str), initialIndent).toString(); - } catch (IOException e) { - LOGGER.finest(String.valueOf(e)); - LOGGER.finest("Could not indent JSON string, returning the input string: " + str); - return str; - } - } - - private static StringBuilder appendOrd(StringBuilder sb, JsonNode o, int indent) { - if (o.isObject()) { - return appendObj(sb, o, indent); - } else if (o.isArray()) { - return appendAry(sb, o, indent); - } else if (o.isTextual()) { - return quoteAndEscape(sb, o.asText()); - } else if (o.isNull() || o.isIntegralNumber() || o.isBoolean()) { - return sb.append(String.valueOf(o)); - } - throw new UnsupportedOperationException(o.getClass().getSimpleName()); - } - - private static StringBuilder appendObj(StringBuilder builder, JsonNode jobj, int indent) { - StringBuilder sb = builder.append("{\n"); - boolean first = true; - for (Iterator<JsonNode> it = jobj.iterator(); it.hasNext();) { - final String key = it.next().asText(); - if (first) { - first = false; - } else { - sb = sb.append(",\n"); - } - sb = indent(sb, indent + 1); - sb = quote(sb, key); - sb = sb.append(": "); - if (jobj.get(key).isArray()) { - sb = appendAry(sb, jobj.get(key), indent + 1); - } else if (jobj.get(key).isObject()) { - sb = appendObj(sb, jobj.get(key), indent + 1); - } else { - sb = appendOrd(sb, jobj.get(key), indent + 1); - } - } - sb = sb.append("\n"); - return indent(sb, indent).append("}"); - } - - private static StringBuilder appendAry(StringBuilder builder, JsonNode jarr, int indent) { - StringBuilder sb = builder.append("[\n"); - for (int i = 0; i < jarr.size(); ++i) { - if (i > 0) { - sb = sb.append(",\n"); - } - sb = indent(sb, indent + 1); - if (jarr.get(i).isArray()) { - sb = appendAry(sb, jarr.get(i), indent + 1); - } else if (jarr.get(i).isObject()) { - sb = appendObj(sb, jarr.get(i), indent + 1); - } else { - sb = appendOrd(sb, jarr.get(i), indent + 1); - } - } - sb = sb.append("\n"); - return indent(sb, indent).append("]"); - } - - private static StringBuilder quote(StringBuilder sb, String str) { - return sb.append('"').append(str).append('"'); - } - - private static StringBuilder indent(StringBuilder sb, int i) { - int indent = i; - while (indent > 0) { - sb.append(INDENT); - --indent; - } - return sb; - } - - public static String quoteAndEscape(String str) { - return quoteAndEscape(new StringBuilder(), str).toString(); - } - - private static StringBuilder quoteAndEscape(StringBuilder sb, String str) { - return escape(sb.append('"'), str).append('"'); - } - - public static String escape(String str) { - return escape(new StringBuilder(), str).toString(); - } - - public static StringBuilder escape(StringBuilder sb, String str) { - for (int i = 0; i < str.length(); ++i) { - appendEsc(sb, str.charAt(i)); - } - return sb; - } - - private static StringBuilder appendEsc(StringBuilder sb, char c) { - CharSequence cs = esc(c); - return cs != null ? sb.append(cs) : sb.append(c); - } - - public static CharSequence esc(char c) { - switch (c) { - case '"': - return "\\\""; - case '\\': - return "\\\\"; - case '/': - return "\\/"; - case '\b': - return "\\b"; - case '\n': - return "\\n"; - case '\f': - return "\\f"; - case '\r': - return "\\r"; - case '\t': - return "\\t"; - default: - return null; - } - } -} http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IConfigManager.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IConfigManager.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IConfigManager.java index 3944820..777f7a7 100644 --- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IConfigManager.java +++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/config/IConfigManager.java @@ -62,4 +62,6 @@ public interface IConfigManager { void addCmdLineSections(Section... sections); void setUsageFilter(OptionHandlerFilter usageFilter); + + void setVersionString(String versionString); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java index 04cf704..63163bb 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/config/ConfigManager.java @@ -82,6 +82,7 @@ public class ConfigManager implements IConfigManager, Serializable { private transient OptionHandlerFilter usageFilter; private transient SortedMap<Integer, List<IConfigurator>> configurators = new TreeMap<>(); private boolean configured; + private String versionString = "version undefined"; public ConfigManager() { this(null); @@ -173,6 +174,11 @@ public class ConfigManager implements IConfigManager, Serializable { } } + @Override + public void setVersionString(String versionString) { + this.versionString = versionString; + } + public IOption lookupOption(String section, String key) { Map<String, IOption> map = getSectionOptionMap(Section.parseSectionName(section)); return map == null ? null : map.get(key); @@ -242,25 +248,27 @@ public class ConfigManager implements IConfigManager, Serializable { new Args4jArgument()); } LOGGER.fine("parsing cmdline: " + Arrays.toString(args)); + if (args == null || args.length == 0) { + LOGGER.info("no command line args supplied"); + return appArgs; + } try { - if (args == null || args.length == 0) { - LOGGER.info("no command line args supplied"); - return appArgs; - } cmdLineParser.parseArgument(args); - if (bean.help) { - ConfigUtils.printUsage(cmdLineParser, usageFilter, System.err); - System.exit(0); - } } catch (CmdLineException e) { - if (bean.help) { - ConfigUtils.printUsage(cmdLineParser, usageFilter, System.err); - System.exit(0); - } else { + if (!bean.help) { ConfigUtils.printUsage(e, usageFilter, System.err); throw e; + } else { + LOGGER.log(Level.FINE, "Ignoring parse exception due to -help", e); } } + if (bean.help) { + ConfigUtils.printUsage(cmdLineParser, usageFilter, System.err); + System.exit(0); + } else if (bean.version) { + System.err.println(versionString); + System.exit(0); + } return appArgs; } @@ -549,5 +557,8 @@ public class ConfigManager implements IConfigManager, Serializable { private static class Args4jBean { @Option(name = "-help", help = true) boolean help; + + @Option(name = "-version", help = true) + boolean version; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java index d36586f..9d649f6 100644 --- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java +++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NCDriver.java @@ -44,8 +44,8 @@ public class NCDriver { application.registerConfig(configManager); NCConfig ncConfig = new NCConfig(nodeId, configManager); final NodeControllerService ncService = new NodeControllerService(ncConfig, application); - if (LOGGER.isLoggable(Level.SEVERE)) { - LOGGER.severe("Setting uncaught exception handler " + ncService.getLifeCycleComponentManager()); + if (LOGGER.isLoggable(Level.INFO)) { + LOGGER.info("Setting uncaught exception handler " + ncService.getLifeCycleComponentManager()); } Thread.currentThread().setUncaughtExceptionHandler(ncService.getLifeCycleComponentManager()); ncService.start(); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/hyracks-fullstack/hyracks/hyracks-util/pom.xml ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-util/pom.xml b/hyracks-fullstack/hyracks/hyracks-util/pom.xml index 864bd8e..420ce79 100644 --- a/hyracks-fullstack/hyracks/hyracks-util/pom.xml +++ b/hyracks-fullstack/hyracks/hyracks-util/pom.xml @@ -51,6 +51,14 @@ <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1fb232d9/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/JSONUtil.java ---------------------------------------------------------------------- diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/JSONUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/JSONUtil.java new file mode 100644 index 0000000..7075417 --- /dev/null +++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/JSONUtil.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.hyracks.util; + +import java.io.IOException; +import java.util.Iterator; +import java.util.logging.Logger; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public class JSONUtil { + + private static final Logger LOGGER = Logger.getLogger(JSONUtil.class.getName()); + + private static final String INDENT = "\t"; + + private static final ObjectMapper SORTED_MAPPER = new ObjectMapper(); + + private JSONUtil() { + } + + static { + SORTED_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + } + + public static String convertNode(final JsonNode node) throws JsonProcessingException { + final Object obj = SORTED_MAPPER.treeToValue(node, Object.class); + return SORTED_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj); + } + + public static String indent(String str, int initialIndent) { + ObjectMapper om = new ObjectMapper(); + try { + return appendObj(new StringBuilder(), om.readTree(str), initialIndent).toString(); + } catch (IOException e) { + LOGGER.finest(String.valueOf(e)); + LOGGER.finest("Could not indent JSON string, returning the input string: " + str); + return str; + } + } + + private static StringBuilder appendOrd(StringBuilder sb, JsonNode o, int indent) { + if (o.isObject()) { + return appendObj(sb, o, indent); + } else if (o.isArray()) { + return appendAry(sb, o, indent); + } else if (o.isTextual()) { + return quoteAndEscape(sb, o.asText()); + } else if (o.isNull() || o.isIntegralNumber() || o.isBoolean()) { + return sb.append(String.valueOf(o)); + } + throw new UnsupportedOperationException(o.getClass().getSimpleName()); + } + + private static StringBuilder appendObj(StringBuilder builder, JsonNode jobj, int indent) { + StringBuilder sb = builder.append("{\n"); + boolean first = true; + for (Iterator<JsonNode> it = jobj.iterator(); it.hasNext();) { + final String key = it.next().asText(); + if (first) { + first = false; + } else { + sb = sb.append(",\n"); + } + sb = indent(sb, indent + 1); + sb = quote(sb, key); + sb = sb.append(": "); + if (jobj.get(key).isArray()) { + sb = appendAry(sb, jobj.get(key), indent + 1); + } else if (jobj.get(key).isObject()) { + sb = appendObj(sb, jobj.get(key), indent + 1); + } else { + sb = appendOrd(sb, jobj.get(key), indent + 1); + } + } + sb = sb.append("\n"); + return indent(sb, indent).append("}"); + } + + private static StringBuilder appendAry(StringBuilder builder, JsonNode jarr, int indent) { + StringBuilder sb = builder.append("[\n"); + for (int i = 0; i < jarr.size(); ++i) { + if (i > 0) { + sb = sb.append(",\n"); + } + sb = indent(sb, indent + 1); + if (jarr.get(i).isArray()) { + sb = appendAry(sb, jarr.get(i), indent + 1); + } else if (jarr.get(i).isObject()) { + sb = appendObj(sb, jarr.get(i), indent + 1); + } else { + sb = appendOrd(sb, jarr.get(i), indent + 1); + } + } + sb = sb.append("\n"); + return indent(sb, indent).append("]"); + } + + private static StringBuilder quote(StringBuilder sb, String str) { + return sb.append('"').append(str).append('"'); + } + + private static StringBuilder indent(StringBuilder sb, int i) { + int indent = i; + while (indent > 0) { + sb.append(INDENT); + --indent; + } + return sb; + } + + public static String quoteAndEscape(String str) { + return quoteAndEscape(new StringBuilder(), str).toString(); + } + + private static StringBuilder quoteAndEscape(StringBuilder sb, String str) { + return escape(sb.append('"'), str).append('"'); + } + + public static String escape(String str) { + return escape(new StringBuilder(), str).toString(); + } + + public static StringBuilder escape(StringBuilder sb, String str) { + for (int i = 0; i < str.length(); ++i) { + appendEsc(sb, str.charAt(i)); + } + return sb; + } + + private static StringBuilder appendEsc(StringBuilder sb, char c) { + CharSequence cs = esc(c); + return cs != null ? sb.append(cs) : sb.append(c); + } + + public static CharSequence esc(char c) { + switch (c) { + case '"': + return "\\\""; + case '\\': + return "\\\\"; + case '/': + return "\\/"; + case '\b': + return "\\b"; + case '\n': + return "\\n"; + case '\f': + return "\\f"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + default: + return null; + } + } +}
