|
Author: doogie
Date: Wed Feb 10 22:47:30 2010 New Revision: 908712 URL: http://svn.apache.org/viewvc?rev=908712&view=rev Log: JSON reading/writing. May seem like it is uneeded, but a later commit will add support for this becoming more extensible. Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/json/ ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSON.jj ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSONWriter.java ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/ ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/JSONTests.java Modified: ofbiz/trunk/framework/base/build.xml Modified: ofbiz/trunk/framework/base/build.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/build.xml?rev=908712&r1=908711&r2=908712&view=diff ============================================================================== --- ofbiz/trunk/framework/base/build.xml (original) +++ ofbiz/trunk/framework/base/build.xml Wed Feb 10 22:47:30 2010 @@ -39,6 +39,7 @@ <filelist id="test.classes" dir="${src.dir}"> <file name="org/ofbiz/base/util/test/IndentingWriterTests.java"/> + <file name="org/ofbiz/base/json/test/JSONTests.java"/> <file name="org/ofbiz/base/conversion/test/MiscTests.java"/> <file name="org/ofbiz/base/util/test/UtilIOTests.java"/> <file name="org/ofbiz/base/test/BaseUnitTests.java"/> @@ -66,6 +67,14 @@ </patternset> </target> + <target name="gen-src"> + <ofbiz-javacc dir="org/ofbiz/base/json" file="JSON"/> + </target> + + <target name="classes" depends="prepare,gen-src"> + <javac16/> + </target> + <target name="jar" depends="classes"> <jar jarfile="${build.dir}/lib/${name}.jar"> <fileset dir="${build.dir}/classes"/> Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSON.jj URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSON.jj?rev=908712&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSON.jj (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSON.jj Wed Feb 10 22:47:30 2010 @@ -0,0 +1,320 @@ +/******************************************************************************* + * 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. + *******************************************************************************/ +options { + ERROR_REPORTING = true; + STATIC = false; +// DEBUG_PARSER = true; +// DEBUG_LOOKAHEAD = true; +// DEBUG_TOKEN_MANAGER = true; + LOOKAHEAD = 1; +// CHOICE_AMBIGUITY_CHECK = 3; +// OTHER_AMBIGUITY_CHECK = 3; +} + +PARSER_BEGIN(JSON) + +package org.ofbiz.base.json; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javolution.util.FastMap; + +import org.ofbiz.base.util.UtilIO; + +public class JSON { + private boolean allowResolve; + + public JSON(String fileName) { + this(System.in); + try { ReInit(new FileInputStream(new File(fileName))); } + catch(Exception e) { e.printStackTrace(); } +// allowed[TEXT] = 1; +// allowed[FIRST_COLUMN_TEXT] = 1; + } + + public JSON allowResolve(boolean allowResolve) { + this.allowResolve = allowResolve; + token_source.SwitchTo(allowResolve ? RESOLVE : DEFAULT); + return this; + } +} + +PARSER_END(JSON) +TOKEN_MGR_DECLS: { + protected LinkedList stateStack = new LinkedList(); + protected StringBuilder statePrefix = new StringBuilder(); + + protected void pushState(int state) { + //System.err.println(statePrefix + "push: " + lexStateNames[curLexState] + " -> " + lexStateNames[state]); + stateStack.add(curLexState); + statePrefix.append(' '); + SwitchTo(state); + } + + protected void popState() { + int oldState = (Integer) stateStack.removeLast(); + statePrefix.setLength(statePrefix.length() - 1); + //System.err.println(statePrefix + "pop: " + lexStateNames[curLexState] + " -> " + lexStateNames[oldState]); + SwitchTo(oldState); + } +} +<DEFAULT,RESOLVE> +TOKEN: +{ + <OBJECT_BEGIN: "{"> +| <OBJECT_END: "}"> +| <ARRAY_BEGIN: "["> +| <ARRAY_END: "]"> +| <ITEM_SEP: ","> +| <KEY_SEP: ":"> +| <TRUE: "true"> +| <FALSE: "false"> +| <NULL: "null"> +| <WHOLE_NUMBER: + <NUMBER_PREFIX> + > +| <FLOAT_NUMBER: + <NUMBER_PREFIX> + ("." (["0"-"9"])*)? + ( + ["e", "E"] + (["+", "-"])? + (["0"-"9"])+ + )? + > +| <#NUMBER_PREFIX: + (["-"])? + ( + "0" + | ["1"-"9"] (["0"-"9"])* + ) + > +} + +<DEFAULT,RESOLVE,IN_RESOLVE_VALUE> +TOKEN: +{ + <STRING_START: "\""> { pushState(IN_STRING); } +} + +<IN_RESOLVE_VALUE> +TOKEN: +{ + <CLOSE_PAREN: ")"> { popState(); } +} + +<RESOLVE> +TOKEN: +{ + <RESOLVE_BEGIN: "resolve("> { pushState(IN_RESOLVE_VALUE); } +} + +<IN_STRING> +TOKEN: +{ + <CHARACTER: (~["\"","\\","\u0000"-"\u001f"])+> +| <STRING_END: "\""> { popState(); } +| <CONTROL_CHAR: "\\" ["\"", "\\", "/", "b","f","n","r","t"]> +| <UNICODE: "\\u" + ["a"-"f", "A"-"F", "0"-"9"] + ["a"-"f", "A"-"F", "0"-"9"] + ["a"-"f", "A"-"F", "0"-"9"] + ["a"-"f", "A"-"F", "0"-"9"] + > +} + +<DEFAULT,RESOLVE> +SKIP: +{ + <WHITESPACE: [" ", "\r", "\n", "\t"]> +} + +<*> +MORE: +{ + <COMMENT_START: "/*"> { if (curLexState != IN_COMMENT) pushState(IN_COMMENT); } +} + +<IN_COMMENT> +MORE: +{ + <(~[])> +} + +<IN_COMMENT> +MORE: +{ + <COMMENT_END: "*/"> { popState(); } +} + +Object JSONValue(): +{ Object value; } +{ + value=JSONItem() + <EOF> + { return value; } +} + +Object JSONItem(): +{ Object value; } +{ + ( + value=JSONString() + | value=JSONLong() + | value=JSONFloat() + | value=JSONObject() + | value=JSONArray() + | value=True() + | value=False() + | value=Null() + | value=JSONResolve() + ) + { return value; } +} + +Object JSONResolve(): +{ + String name, value; +} +{ + <RESOLVE_BEGIN> + value=JSONString() + <CLOSE_PAREN> + { + try { + return UtilIO.readObject(value.toCharArray()); + } catch (ClassNotFoundException e) { + throw generateParseException(); + } catch (IOException e) { + throw generateParseException(); + } + } +} +String JSONString(): +{ + StringBuilder sb = new StringBuilder(); +} +{ + <STRING_START> ( + <CHARACTER> { sb.append(getToken(0).image); } + | <CONTROL_CHAR> { + switch (getToken(0).image.charAt(1)) { + case '"': sb.append('"'); break; + case '\\': sb.append('\\'); break; + case '/': sb.append('/'); break; + case 'b': sb.append('\b'); break; + case 'f': sb.append('\f'); break; + case 'n': sb.append('\n'); break; + case 'r': sb.append('\r'); break; + case 't': sb.append('\t'); break; + } + } + | <UNICODE> { + int v = Integer.parseInt(getToken(0).image.substring(2), 16); + sb.append((char) v); + } + )* + <STRING_END> + { return sb.toString(); } +} + +Long JSONLong(): +{} +{ + try { + <WHOLE_NUMBER> { return new Long(getToken(0).image); } + } catch (NumberFormatException e) { + throw generateParseException(); + } +} + +Double JSONFloat(): +{} +{ + try { + <FLOAT_NUMBER> { return new Double(getToken(0).image); } + } catch (NumberFormatException e) { + throw generateParseException(); + } +} + +Map<String, Object> JSONObject(): +{ + Map<String, Object> map = FastMap.newInstance(); +} +{ + <OBJECT_BEGIN> + (<ITEM_SEP>)* + (JSONObjectEntry(map))? (<ITEM_SEP> (JSONObjectEntry(map))?)* + <OBJECT_END> + { return map; } +} + +void JSONObjectEntry(Map<String, Object> map): +{ + String key; + Object value; +} +{ + key=JSONString() <KEY_SEP> value=JSONItem() + { map.put(key, value); } +} + +List JSONArray(): +{ + ArrayList<Object> list = new ArrayList<Object>(); + Object value; +} +{ + <ARRAY_BEGIN> + (<ITEM_SEP>)* + ( + value=JSONItem() { list.add(value); } + ( + <ITEM_SEP> + (value=JSONItem() { list.add(value); })? + )* + )? + <ARRAY_END> + { return list; } +} + +Boolean True(): +{} +{ + <TRUE> { return Boolean.TRUE; } +} + +Boolean False(): +{} +{ + <FALSE> { return Boolean.FALSE; } +} + +Object Null(): +{} +{ + <NULL> { return null; } +} Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSONWriter.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSONWriter.java?rev=908712&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSONWriter.java (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/json/JSONWriter.java Wed Feb 10 22:47:30 2010 @@ -0,0 +1,224 @@ +/******************************************************************************* + * 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.ofbiz.base.json; + +import java.io.IOException; +import java.io.Writer; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +import org.ofbiz.base.util.IndentingWriter; +import org.ofbiz.base.util.UtilIO; + +public class JSONWriter { + private final IndentingWriter writer; + private final FallbackHandler fallbackHandler; + + public JSONWriter(IndentingWriter writer) { + this(writer, StandardFallbackHandler); + } + + public JSONWriter(IndentingWriter writer, FallbackHandler fallbackHandler) { + this.writer = writer; + this.fallbackHandler = fallbackHandler; + } + + public JSONWriter(Writer writer) { + this(writer instanceof IndentingWriter ? (IndentingWriter) writer : new IndentingWriter(writer)); + } + + public JSONWriter(Writer writer, FallbackHandler fallbackHandler) { + this(writer instanceof IndentingWriter ? (IndentingWriter) writer : new IndentingWriter(writer), fallbackHandler); + } + + public IndentingWriter getWriter() { + return writer; + } + + public JSONWriter close() throws IOException { + getWriter().close(); + return this; + } + + public JSONWriter write(byte b) throws IOException { + writer.write(Byte.toString(b)); + return this; + } + + public JSONWriter write(short s) throws IOException { + writer.write(Short.toString(s)); + return this; + } + + public JSONWriter write(int i) throws IOException { + writer.write(Integer.toString(i)); + return this; + } + + public JSONWriter write(long l) throws IOException { + writer.write(Long.toString(l)); + return this; + } + + public JSONWriter write(float f) throws IOException { + writer.write(Float.toString(f)); + return this; + } + + public JSONWriter write(double d) throws IOException { + writer.write(Double.toString(d)); + return this; + } + + public JSONWriter write(char c) throws IOException { + write(Character.toString(c)); + return this; + } + + public JSONWriter write(String s) throws IOException { + writer.write('"'); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\\': writer.write("\\\\"); continue; + case '/': writer.write("\\/"); continue; + case '"': writer.write("\\\""); continue; + case '\b': writer.write("\\b"); continue; + case '\f': writer.write("\\f"); continue; + case '\n': writer.write("\\n"); continue; + case '\r': writer.write("\\r"); continue; + case '\t': writer.write("\\t"); continue; + } + if (32 <= c && c >= 256) { + writer.write("\\u"); + String n = Integer.toString((int) c, 16); + for (int j = 4 - n.length(); j > 0; j--) writer.write('0'); + writer.write(n); + } else { + writer.write(c); + } + } + writer.write('"'); + return this; + } + + public <K, V> JSONWriter write(Map<K, V> m) throws IOException { + writer.write('{'); + writer.push(); + Iterator<Map.Entry<K, V>> it = m.entrySet().iterator(); + if (it.hasNext()) writer.newline(); + while (it.hasNext()) { + Map.Entry<K, V> entry = it.next(); + write(entry.getKey()); + writer.write(':'); + writer.space(); + write(entry.getValue()); + if (it.hasNext()) writer.write(','); + writer.newline(); + } + writer.pop(); + writer.write('}'); + return this; + } + + public <E> JSONWriter write(Collection<E> c) throws IOException { + writer.write('['); + writer.push(); + Iterator<E> it = c.iterator(); + if (it.hasNext()) writer.newline(); + while (it.hasNext()) { + write(it.next()); + if (it.hasNext()) writer.write(','); + writer.newline(); + } + writer.pop(); + writer.write(']'); + return this; + } + + public <T> JSONWriter write(T... o) throws IOException { + writer.write('['); + writer.push(); + for (int i = 0; i < o.length; i++) { + if (i != 0) writer.write(','); + writer.newline(); + write(o[i]); + } + if (o.length > 0) writer.newline(); + writer.pop(); + writer.write(']'); + return this; + } + + public JSONWriter write(Object o) throws IOException { + if (o == null) { + writer.write("null"); + return this; + } else if (o instanceof Boolean) { + writer.write(((Boolean) o).booleanValue() ? "true" : "false"); + return this; + } else if (o instanceof String) { + return write((String) o); + } else if (o instanceof Map) { + return write((Map) o); + } else if (o instanceof Collection) { + return write((Collection) o); + } else if (o instanceof Byte) { + return write(((Byte) o).byteValue()); + } else if (o instanceof Character) { + return write(((Character) o).charValue()); + } else if (o instanceof Double) { + return write(((Double) o).doubleValue()); + } else if (o instanceof Float) { + return write(((Float) o).floatValue()); + } else if (o instanceof Integer) { + return write(((Integer) o).intValue()); + } else if (o instanceof Long) { + return write(((Long) o).longValue()); + } else if (o instanceof Short) { + return write(((Short) o).shortValue()); + } else if (o.getClass().isArray()) { + return write((Object[]) o); + } else { + fallbackHandler.writeJSON(this, writer, o); + return this; + } + } + + public interface FallbackHandler { + void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException; + } + + public static final FallbackHandler StandardFallbackHandler = new FallbackHandler() { + public void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException { + throw new IOException("Can't write(" + o + ":" + o.getClass() + ")"); + } + }; + + public static final FallbackHandler ResolvingFallbackHandler = new FallbackHandler() { + public void writeJSON(JSONWriter json, Writer writer, Object o) throws IOException { + StringBuilder sb = new StringBuilder(); + UtilIO.writeObject(sb, o); + writer.write("resolve("); + json.write(sb.toString()); + writer.write(")"); + } + }; +} Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/JSONTests.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/JSONTests.java?rev=908712&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/JSONTests.java (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/json/test/JSONTests.java Wed Feb 10 22:47:30 2010 @@ -0,0 +1,289 @@ +/******************************************************************************* + * 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.ofbiz.base.json.test; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; + +import org.ofbiz.base.json.JSON; +import org.ofbiz.base.json.JSONConstants; +import org.ofbiz.base.json.JSONWriter; +import org.ofbiz.base.json.ParseException; +import org.ofbiz.base.json.Token; +import org.ofbiz.base.json.TokenMgrError; +import org.ofbiz.base.test.GenericTestCaseBase; + +public class JSONTests extends GenericTestCaseBase { + public JSONTests(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + protected Object parseJSON(String value, boolean allowResolve) throws Exception { + return new JSON(new StringReader(value)).allowResolve(allowResolve).JSONValue(); + } + + protected String getJSON(Object object, boolean allowResolve) throws Exception { + StringWriter writer = new StringWriter(); + JSONWriter jsonWriter; + if (allowResolve) { + jsonWriter = new JSONWriter(writer, JSONWriter.ResolvingFallbackHandler); + } else { + jsonWriter = new JSONWriter(writer); + }; + jsonWriter.write(object); + return writer.toString(); + } + + protected void assertSimpleJSONByte(byte n, String json) throws Exception { + assertSimpleJSON("integer - byte", new Byte(n), json, new Long(n)); + assertSimpleJSONShort((short) n, json); + } + + protected void assertSimpleJSONShort(short n, String json) throws Exception { + assertSimpleJSON("integer - short", new Integer(n), json, new Long(n)); + assertSimpleJSONInteger((int) n, json); + } + + protected void assertSimpleJSONInteger(int n, String json) throws Exception { + assertSimpleJSON("integer - int", new Short((short) n), json, new Long(n)); + assertSimpleJSONLong((long) n, json); + } + + protected void assertSimpleJSONLong(long n, String json) throws Exception { + assertSimpleJSON("integer - long", new Long(n), json, new Long(n)); + } + + protected void assertSimpleJSONFloat(float n, String json) throws Exception { + assertSimpleJSON("float - float", new Float(n), json, new Double(n)); + assertSimpleJSONDouble((double) n, json); + } + + protected void assertSimpleJSONDouble(double n, String json) throws Exception { + assertSimpleJSON("float - double", new Double(n), json); + } + + protected void assertSimpleJSON(String type, Object object, String json) throws Exception { + assertSimpleJSON(type, object, json, object); + } + + protected void assertSimpleJSON(String type, Object before, String json, Object after) throws Exception { + assertEquals("write " + type, json, getJSON(before, false)); + assertEquals("parse " + type, after, parseJSON(json, false)); + } + + protected void assertResolveJSON(String type, Object obj, String json) throws Exception { + assertEquals("write " + type, json, getJSON(obj, true)); + assertEquals("parse " + type, obj, parseJSON(json, true)); + } + + public void testParseBasicTypes() throws Exception { + assertSimpleJSON("character", new Character('c'), "\"c\"", "c"); + assertSimpleJSON("false", Boolean.FALSE, "false"); + assertSimpleJSON("null", null, "null"); + assertSimpleJSON("true", Boolean.TRUE, "true"); + assertSimpleJSON("simple string", "foo", "\"foo\""); + assertSimpleJSONByte((byte) 42, "42"); + assertSimpleJSONFloat(Float.valueOf("1.0625"), "1.0625"); + assertSimpleJSON( + "complex string", + "quote(\") backslash(\\) forwardslash(/) backspace(\b) formfeed(\f) newline(\n) carriagereturn(\r) tab(\t) trademark(\u2122)", + "\"quote(\\\") backslash(\\\\) forwardslash(\\/) backspace(\\b) formfeed(\\f) newline(\\n) carriagereturn(\\r) tab(\\t) trademark(\\u2122)\"" + ); + } + + public void testParseComplexTypes() throws Exception { + assertEquals( + "parse simple array", + list(new Object[] {"foo", new Long(1234), new Double(5.678)}), + parseJSON("[, ,\t,\r,\n,\r\n,\"foo\", 1234, 5.678,]", false) + ); + assertSimpleJSON( + "simple empty list", + list(new Object[] {}), + "[]" + ); + assertSimpleJSON( + "simple empty array", + new Object[] {}, + "[]", + list(new Object[] {}) + ); + assertSimpleJSON( + "simple array->list", + new Object[] {"foo", new Long(1234), new Double(5.678)}, + "[\n \"foo\",\n 1234,\n 5.678\n]", + list(new Object[] {"foo", new Long(1234), new Double(5.678)}) + ); + assertSimpleJSON( + "simple array", + list(new Object[] {"foo", new Long(1234), new Double(5.678)}), + "[\n \"foo\",\n 1234,\n 5.678\n]", + list(new Object[] {"foo", new Long(1234), new Double(5.678)}) + ); + assertEquals( + "parse simple map", + map(new Object[] {"foo", new Long(1234), "bar", new Double(5.678)}), + parseJSON("{, ,\t,\r,\n,\r\n,\"foo\": 1234, \"bar\": 5.678,}", false) + ); + assertSimpleJSON( + "parse map", + map(new Object[] {"foo", new Long(1234), "bar", new Double(5.678)}), + "{\n \"foo\": 1234,\n \"bar\": 5.678\n}" + ); + assertSimpleJSON( + "parse empty map", + map(new Object[] {}), + "{}" + ); + assertEquals( + "parse nested map", + map(new Object[] { + "string", "this is a string", + "integer", new Long(5000), + "double", new Double(3.1415926), + "array", new Object[] { + "string", + new Long(6000) + }, + "list", list(new Object[] { + "nested string", + "something", + }), + "empty-list", new ArrayList(), + "empty-array", new String[0], + "empty-map", new HashMap(), + }), + parseJSON("{\"string\": \"this is a string\", \"integer\": 5000, \"double\": 3.1415926, \"array\": [\"string\", 6000], \"list\": [\"nested string\", \"something\"], \"empty-list\": [], \"empty-array\": [], \"empty-map\": {}}", false) + ); + } + + public void testParseErrors() throws Exception { + for (char c = 1; c < 1024; c++) { + switch (c) { + case '[': + doParseExceptionTest("[:", JSONConstants.KEY_SEP); + break; + case ']': + doParseExceptionTest("]", JSONConstants.ARRAY_END); + break; + case '{': + doParseExceptionTest("{:", JSONConstants.KEY_SEP); + break; + case '}': + doParseExceptionTest("}", JSONConstants.OBJECT_END); + break; + case ':': + doParseExceptionTest(":", JSONConstants.KEY_SEP); + break; + case ',': + doParseExceptionTest(",", JSONConstants.ITEM_SEP); + break; + case '"': + doParseExceptionTest("\"", JSONConstants.EOF); + break; + case 't': + doParseExceptionTest("true:", JSONConstants.KEY_SEP); + break; + case 'f': + doParseExceptionTest("false:", JSONConstants.KEY_SEP); + break; + case 'n': + doParseExceptionTest("null:", JSONConstants.KEY_SEP); + break; + case '-': // numbers + case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + break; + case '\t': + doWhitespaceExceptionTest(Character.toString(c), 8); + break; + case '\n': + case '\r': + case ' ': + doWhitespaceExceptionTest(Character.toString(c), 1); + break; + default: + doTokenMgrErrorTest(c); + break; + } + } + } + + protected void doWhitespaceExceptionTest(String s, int column) { + ParseException caught = null; + try { + new JSON(new StringReader(s)).JSONValue(); + } catch (ParseException e) { + caught = e; + } finally { + assertNotNull("caught exception", caught); + assertNotNull("next token(" + s + ")", caught.currentToken); + Token next = caught.currentToken.next; + assertEquals("next token(" + s + ") is eof", 0, next.kind); + assertEquals("begin line(" + s + ")", 1, next.beginLine); + assertEquals("begin column(" + s + ")", column, next.beginColumn); + } + } + + protected void doParseExceptionTest(String s, int nextKind) { + ParseException caught = null; + try { + new JSON(new StringReader(s)).JSONValue(); + } catch (ParseException e) { + caught = e; + } finally { + assertNotNull("caught exception", caught); + assertNotNull("exception message(" + s + ")", caught.getMessage()); + assertNotNull("next token(" + s + ")", caught.currentToken); + Token next = caught.currentToken.next; + assertEquals("next token(" + s + ") is correct", nextKind, next.kind); + assertEquals("begin line(" + s + ")", 1, next.beginLine); + assertEquals("begin column(" + s + ")", s.length(), next.beginColumn); + } + } + + protected void doTokenMgrErrorTest(char c) throws Exception { + TokenMgrError caught = null; + try { + parseJSON(c + "\"string\"", false); + } catch (TokenMgrError e) { + caught = e; + } finally { + assertNotNull("No TokenMgrError thrown for character(" + ((int) c) + ")", caught); + // FIXME: maybe extend javacc to return more info in TokenMgrError + } + } + + public void testResolve() throws Exception { + assertResolveJSON("url", new URL("http://ofbiz.apache.org"), "resolve(\"java.net.URL:http:\\/\\/ofbiz.apache.org\")"); + } +} |
| Free forum by Nabble | Edit this page |
