You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2016/12/20 16:36:42 UTC
svn commit: r1775317 - in /felix/trunk/configurator/src:
main/java/org/apache/felix/configurator/impl/json/JSMin.java
main/java/org/apache/felix/configurator/impl/json/JSONUtil.java
test/java/org/apache/felix/configurator/impl/json/JSMinTest.java
Author: cziegeler
Date: Tue Dec 20 16:36:41 2016
New Revision: 1775317
URL: http://svn.apache.org/viewvc?rev=1775317&view=rev
Log:
Add JSMin for handling comments in json
Added:
felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java (with props)
felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java (with props)
Modified:
felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java
Added: felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java
URL: http://svn.apache.org/viewvc/felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java?rev=1775317&view=auto
==============================================================================
--- felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java (added)
+++ felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java Tue Dec 20 16:36:41 2016
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ *
+ * <p>
+ * Copyright (c) 2006 John Reilly (www.inconspicuous.org) This work is a
+ * translation from C to Java of jsmin.c published by Douglas Crockford.
+ * Permission is hereby granted to use the Java version under the same
+ * conditions as the jsmin.c on which it is based.
+ * <p>
+ * http://www.crockford.com/javascript/jsmin.html
+ */
+package org.apache.felix.configurator.impl.json;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.io.Writer;
+
+public class JSMin {
+
+ private static final int EOF = -1;
+
+ private final PushbackReader in;
+
+ private final Writer out;
+
+ private int theA;
+
+ private int theB;
+
+ private int theLookahead = EOF;
+
+ private int theX = EOF;
+
+ private int theY = EOF;
+
+ public JSMin(final Reader in, final Writer out) {
+ this.in = new PushbackReader(in);
+ this.out = out;
+ }
+
+ /**
+ * isAlphanum -- return true if the character is a letter, digit, underscore,
+ * dollar sign, or non-ASCII character.
+ */
+ private boolean isAlphanum(final int c) {
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' || c > 126);
+ }
+
+ /**
+ * get -- return the next character from stdin. Watch out for lookahead. If
+ * the character is a control character, translate it to a space or
+ * linefeed.
+ */
+ private int get() throws IOException {
+ int c = theLookahead;
+ theLookahead = EOF;
+ if ( c == EOF ) {
+ c = in.read();
+ }
+
+ if (c >= ' ' || c == '\n' || c == EOF) {
+ return c;
+ }
+
+ if (c == '\r') {
+ return '\n';
+ }
+
+ return ' ';
+ }
+
+ /**
+ * peek -- get the next character without getting it.
+ */
+ private int peek() throws IOException {
+ theLookahead = get();
+ return theLookahead;
+ }
+
+ /**
+ * next -- get the next character, excluding comments. peek() is used to see
+ * if a '/' is followed by a '/' or '*'.
+ */
+ private int next() throws IOException {
+ int c = get();
+ if (c == '/') {
+ switch (peek()) {
+ case '/':
+ for (;;) {
+ c = get();
+ if (c <= '\n') {
+ break;
+ }
+ }
+ break;
+ case '*':
+ get();
+ while (c != ' ') {
+ switch (get()) {
+ case '*':
+ if (peek() == '/') {
+ get();
+ c = ' ';
+ }
+ break;
+ case EOF:
+ throw new IOException("Unterminated comment.");
+ }
+ }
+ break;
+ }
+
+ }
+ theY = theX;
+ theX = c;
+ return c;
+ }
+
+ /**
+ * action -- do something! What you do is determined by the argument:
+ * <ul>
+ * <li>1 Output A. Copy B to A. Get the next B.</li>
+ * <li>2 Copy B to A. Get the next B. (Delete A).</li>
+ * <li>3 Get the next B. (Delete B).</li>
+ * </ul>
+ * action treats a string as a single character. Wow!<br/>
+ * action recognizes a regular expression if it is preceded by ( or , or =.
+ */
+ void action(final int d) throws IOException {
+ switch (d) {
+ case 1:
+ out.write(theA);
+ if ((theY == '\n' || theY == ' ') &&
+ (theA == '+' || theA == '-' || theA == '*' || theA == '/') &&
+ (theB == '+' || theB == '-' || theB == '*' || theB == '/')) {
+ out.write(theY);
+ }
+ case 2:
+ theA = theB;
+
+ if (theA == '\'' || theA == '"' || theA == '`') {
+ for (;;) {
+ out.write(theA);
+ theA = get();
+ if (theA == theB) {
+ break;
+ }
+ if (theA == '\\') {
+ out.write(theA);
+ theA = get();
+ }
+ if ( theA == EOF) {
+ throw new IOException("Unterminated string literal.");
+ }
+ }
+ }
+
+ case 3:
+ theB = next();
+ if (theB == '/'
+ && (theA == '(' || theA == ',' || theA == '=' || theA == ':'
+ || theA == '[' || theA == '!' || theA == '&' || theA == '|'
+ || theA == '?' || theA == '+' || theA == '-' || theA == '~'
+ || theA == '*' || theA == '/' || theA == '{' || theA == '\n')) {
+ out.write(theA);
+ if (theA == '/' || theA == '*') {
+ out.write(' ');
+ }
+ out.write(theB);
+ for (;;) {
+ theA = get();
+ if (theA == '[') {
+ for (;;) {
+ out.write(theA);
+ theA = get();
+ if (theA == ']') {
+ break;
+ }
+ if (theA == '\\') {
+ out.write(theA);
+ theA = get();
+ }
+ if (theA == EOF) {
+ throw new IOException("Unterminated set in Regular Expression literal.");
+ }
+ }
+ } else if (theA == '/') {
+ switch (peek()) {
+ case '/':
+ case '*':
+ throw new IOException("Unterminated set in Regular Expression literal.");
+ }
+ break;
+ } else if (theA == '\\') {
+ out.write(theA);
+ theA = get();
+ } else if (theA == EOF) {
+ throw new IOException("Unterminated Regular Expression literal.");
+ }
+ out.write(theA);
+ }
+ theB = next();
+ }
+ }
+ }
+
+ /**
+ * jsmin -- Copy the input to the output, deleting the characters which are
+ * insignificant to JavaScript. Comments will be removed. Tabs will be
+ * replaced with spaces. Carriage returns will be replaced with linefeeds.
+ * Most spaces and linefeeds will be removed.
+ */
+ public void jsmin() throws IOException {
+ if (peek() == 0xEF) {
+ get();
+ get();
+ get();
+ }
+ theA = '\n';
+ action(3);
+ while (theA != EOF) {
+ switch (theA) {
+ case ' ':
+ action(isAlphanum(theB) ? 1: 2);
+ break;
+ case '\n':
+ switch (theB) {
+ case '{':
+ case '[':
+ case '(':
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ action(1);
+ break;
+ case ' ':
+ action(3);
+ break;
+ default:
+ action(isAlphanum(theB) ? 1: 2);
+ }
+ break;
+ default:
+ switch (theB) {
+ case ' ':
+ action(isAlphanum(theB) ? 1: 3);
+ break;
+ case '\n':
+ switch (theA) {
+ case '}':
+ case ']':
+ case ')':
+ case '+':
+ case '-':
+ case '"':
+ case '\'':
+ case '`':
+ action(1);
+ break;
+ default:
+ action(isAlphanum(theB) ? 1: 3);
+ }
+ break;
+ default:
+ action(1);
+ break;
+ }
+ }
+ }
+ out.flush();
+ }
+}
\ No newline at end of file
Propchange: felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSMin.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Modified: felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java?rev=1775317&r1=1775316&r2=1775317&view=diff
==============================================================================
--- felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java (original)
+++ felix/trunk/configurator/src/main/java/org/apache/felix/configurator/impl/json/JSONUtil.java Tue Dec 20 16:36:41 2016
@@ -19,7 +19,10 @@
package org.apache.felix.configurator.impl.json;
import java.io.IOException;
+import java.io.Reader;
import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -235,7 +238,17 @@ public class JSONUtil {
* @param contents The contents
* @return The parsed JSON object or {@code null} on failure,
*/
- public static JsonObject parseJSON(final String name, final String contents) {
+ public static JsonObject parseJSON(final String name, String contents) {
+ // minify JSON first (remove comments)
+ try (final Reader in = new StringReader(contents);
+ final Writer out = new StringWriter()) {
+ final JSMin min = new JSMin(in, out);
+ min.jsmin();
+ contents = out.toString();
+ } catch ( final IOException ioe) {
+ SystemLogger.error("Invalid JSON from " + name);
+ return null;
+ }
try (final JsonReader reader = Json.createReader(new StringReader(contents)) ) {
final JsonStructure obj = reader.read();
if ( obj != null && obj.getValueType() == ValueType.OBJECT ) {
Added: felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java?rev=1775317&view=auto
==============================================================================
--- felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java (added)
+++ felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java Tue Dec 20 16:36:41 2016
@@ -0,0 +1,46 @@
+/*
+ * 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.felix.configurator.impl.json;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import org.junit.Test;
+
+public class JSMinTest {
+
+ @Test public void simpleTest() throws IOException {
+ final String input = "// Some comment\n" +
+ "{\n"
+ + " \"a\" : 1,\n"
+ + " // another comment\n"
+ + " /** And more\n"
+ + " * comments\n"
+ + " */\n"
+ + " \"b\" : 2\n"
+ + "}\n";
+ final StringWriter w = new StringWriter();
+ final JSMin min = new JSMin(new StringReader(input), w);
+ min.jsmin();
+ assertEquals("\n{\"a\":1,\"b\":2}", w.toString());
+ }
+}
Propchange: felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/configurator/src/test/java/org/apache/felix/configurator/impl/json/JSMinTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url