Return-Path: Delivered-To: apmail-sling-commits-archive@www.apache.org Received: (qmail 22759 invoked from network); 30 Dec 2009 19:35:01 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 30 Dec 2009 19:35:01 -0000 Received: (qmail 66523 invoked by uid 500); 30 Dec 2009 19:35:01 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 66467 invoked by uid 500); 30 Dec 2009 19:35:00 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 66458 invoked by uid 99); 30 Dec 2009 19:35:00 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Dec 2009 19:35:00 +0000 X-ASF-Spam-Status: No, hits=-2.6 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Dec 2009 19:34:53 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 4D42E23889CB; Wed, 30 Dec 2009 19:34:33 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r894698 - in /sling/trunk: ./ bundles/commons/json/ bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/ bundles/commons/json/src/test/groovy/ bundles/commons/json/src/test/groovy/org/ bundles/commons/json/src/test/groov... Date: Wed, 30 Dec 2009 19:34:32 -0000 To: commits@sling.apache.org From: justin@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091230193433.4D42E23889CB@eris.apache.org> Author: justin Date: Wed Dec 30 19:34:31 2009 New Revision: 894698 URL: http://svn.apache.org/viewvc?rev=894698&view=rev Log: SLING-1257 - adding a Groovy Builder for producing JSON documents Added: sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/ sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/JSONGroovyBuilder.java sling/trunk/bundles/commons/json/src/test/groovy/ sling/trunk/bundles/commons/json/src/test/groovy/org/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/JSONGroovyBuilderTest.groovy sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/ sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/JSONAssert.java sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JSONGroovyBuilderIntegrationTest.java sling/trunk/launchpad/testing/src/test/resources/integration-test/builder.groovy Modified: sling/trunk/bundles/commons/json/pom.xml sling/trunk/launchpad/builder/src/main/bundles/list.xml sling/trunk/parent/pom.xml sling/trunk/pom.xml Modified: sling/trunk/bundles/commons/json/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/json/pom.xml?rev=894698&r1=894697&r2=894698&view=diff ============================================================================== --- sling/trunk/bundles/commons/json/pom.xml (original) +++ sling/trunk/bundles/commons/json/pom.xml Wed Dec 30 19:34:31 2009 @@ -23,7 +23,7 @@ org.apache.sling sling - 8 + 9-SNAPSHOT ../../../parent/pom.xml @@ -48,12 +48,25 @@ true + groovy.*;resolution:=optional,* org.apache.sling.commons.json.*;version=${pom.version} + + org.codehaus.groovy.maven + gmaven-plugin + + + + compile + testCompile + + + + @@ -63,6 +76,11 @@ jcr + org.codehaus.groovy + groovy-all + 1.6.0 + + org.apache.sling org.apache.sling.commons.testing 2.0.2-incubator @@ -72,5 +90,16 @@ junit junit + + org.slf4j + slf4j-api + 1.5.2 + + + org.slf4j + slf4j-simple + 1.5.2 + test + Added: sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/JSONGroovyBuilder.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/JSONGroovyBuilder.java?rev=894698&view=auto ============================================================================== --- sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/JSONGroovyBuilder.java (added) +++ sling/trunk/bundles/commons/json/src/main/java/org/apache/sling/commons/json/groovy/JSONGroovyBuilder.java Wed Dec 30 19:34:31 2009 @@ -0,0 +1,203 @@ +/* + * 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.sling.commons.json.groovy; + +import groovy.lang.Closure; +import groovy.util.BuilderSupport; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import org.apache.sling.commons.json.JSONArray; +import org.apache.sling.commons.json.JSONException; +import org.apache.sling.commons.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Groovy builder for JSON values. + * + * Based on code written by Andres Almiray as + * part of the json-lib project - http://json-lib.sourceforge.net/ + */ +public class JSONGroovyBuilder extends BuilderSupport { + + /** + * The string 'json' which indicates that the root node should be used + * as-is. Otherwise, the root node is wrapped in a JSON object. + */ + private static final String JSON = "json"; + + /** + * A logger instance. + */ + private static final Logger logger = LoggerFactory.getLogger(JSONGroovyBuilder.class); + + /** + * A stack containing the names of created nodes. + */ + protected Stack nodeNames = new Stack(); + + private void addFromMap(JSONObject obj, Map attributes) { + for (Iterator it = attributes.keySet().iterator(); it.hasNext();) { + String key = (String) it.next(); + Object value = resolveValue(attributes.get(key)); + + try { + obj.put(key, value); + } catch (JSONException e) { + } + + } + } + + private Object resolveValue(Object value) { + if (value instanceof Map) { + JSONObject sub = new JSONObject(); + addFromMap(sub, (Map) value); + value = sub; + } else if (value instanceof Closure) { + Object oldCurrent = getCurrent(); + JSONObject sub = new JSONObject(); + setCurrent(sub); + Closure c = (Closure) value; + c.setDelegate(this); + c.call(); + setCurrent(oldCurrent); + value = sub; + } else if (value instanceof List) { + value = new JSONArray((List) value); + } + + return value; + } + + /** + * Create a node with the specified name. + */ + @Override + protected Object createNode(Object name) { + nodeNames.push((String) name); + return new JSONObject(); + } + + @SuppressWarnings("unchecked") + @Override + protected Object createNode(Object name, Map attributes) { + nodeNames.push((String) name); + JSONObject obj = new JSONObject(); + addFromMap(obj, attributes); + return obj; + } + + @SuppressWarnings("unchecked") + @Override + protected Object createNode(Object name, Map attributes, Object value) { + nodeNames.push((String) name); + if (value instanceof Map) { + JSONArray arr = new JSONArray(); + arr.put(new JSONObject(attributes)); + arr.put(new JSONObject((Map) value)); + return arr; + } else { + nodeNames.pop(); + logger.warn("Unhandled createNode(O,M,O). Only able to handle cases where value Object is a Map. name={}, value={}", + new Object[] { name, value }); + return null; + } + } + + @Override + protected Object createNode(Object name, Object value) { + nodeNames.push((String) name); + if (value instanceof List) { + JSONArray arr = new JSONArray(); + for (Object obj : (List) value) { + arr.put(resolveValue(obj)); + } + return arr; + } else if (value instanceof Closure) { + Object oldCurrent = getCurrent(); + JSONObject obj = new JSONObject(); + setCurrent(obj); + Closure c = (Closure) value; + c.setDelegate(this); + c.call(); + setCurrent(oldCurrent); + return obj; + } else if (value instanceof String) { + return value; + } else if (value instanceof Number) { + return value; + } else if (value instanceof Boolean) { + return value; + } else { + System.err.println("Unhandlable class: " + value.getClass()); + nodeNames.pop(); + return null; + } + } + + /** + * Add the child node to the parent, using the name at the top of the node + * names stack. + * + * @param parent the parent node + * @param child the child node + */ + @Override + protected void setParent(Object parent, Object child) { + if (!nodeNames.isEmpty()) { + try { + ((JSONObject) parent).accumulate(nodeNames.pop(), child); + } catch (JSONException e) { + } + } + } + + /** + * On the completion of the top-level node, if the node name isn't 'json', + * create a container object. + * + * @param parent the parent node + * @param child the node which was just created + */ + @Override + protected Object postNodeCompletion(Object parent, Object node) { + if (parent == null && !nodeNames.empty()) { + String rootName = nodeNames.pop(); + if (!JSON.equals(rootName)) { + JSONObject obj = new JSONObject(); + try { + return obj.put(rootName, node); + } catch (JSONException e) { + logger.error("Unable to create container JSON Object", e); + return super.postNodeCompletion(parent, node); + } + } else { + return super.postNodeCompletion(parent, node); + } + } else { + return super.postNodeCompletion(parent, node); + } + } + + protected boolean log = false; + +} Added: sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/JSONGroovyBuilderTest.groovy URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/JSONGroovyBuilderTest.groovy?rev=894698&view=auto ============================================================================== --- sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/JSONGroovyBuilderTest.groovy (added) +++ sling/trunk/bundles/commons/json/src/test/groovy/org/apache/sling/commons/json/groovy/JSONGroovyBuilderTest.groovy Wed Dec 30 19:34:31 2009 @@ -0,0 +1,315 @@ +/* + * 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.sling.commons.json.groovy; + +import org.apache.sling.commons.json.*; +import org.apache.sling.commons.json.test.*; + +/** + * Test of JSONGroovyBuilder. + * + * Based on code written by Andres Almiray as + * part of the json-lib project - http://json-lib.sourceforge.net/ + */ +public class JSONGroovyBuilderTest extends GroovyTestCase { + JSONGroovyBuilder builder + + void testBuildDefaultRootEmptyObject(){ + def actual = builder.json {} + JSONAssert.assertEquals( new JSONObject(), actual) + } + void testBuildDefaultRootEmptyArray(){ + def actual = builder.json ([]) + JSONAssert.assertEquals( new JSONArray(), actual) + } + void testBuildDefaultRootObjectWithClosure(){ + def actual = builder.json { + string "json" + integer 1 + bool true + } + def expected = new JSONObject() + .put("string","json") + .put("integer",1) + .put("bool",true) + JSONAssert.assertEquals(expected, actual) + assertEquals("json", actual.get("string")) + } + void testBuildDefaultRootObjectWithMap(){ + def actual = builder.json([ + 'string': "json", + 'integer': 1, + 'bool': true + ]) + def expected = new JSONObject() + .put("string","json") + .put("integer",1) + .put("bool",true) + JSONAssert.assertEquals(expected, actual) + } + void testBuildDefaultRootArrayWithList(){ + def actual = builder.json(["json", 1, true]) + def expected = new JSONArray() + .put("json") + .put(1) + .put(true) + JSONAssert.assertEquals(expected, actual) + } + void testBuildDefaultRootNestedObjects(){ + def actual = builder.json { + first { integer 42 } + second { integer 48 } + } + def expected = new JSONObject() + .put( "first", new JSONObject().put("integer",42) ) + .put( "second", new JSONObject().put("integer",48) ) + JSONAssert.assertEquals(expected, actual) + } + void testBuildObjectWithMaps(){ + def actual = builder.json { + books { + book ([title: "The Definitive Guide to Grails", author: "Graeme Rocher"]) + book ([title: "Groovy in Action", author: "Dierk Konig"]) + } + } + def expected = new JSONObject() + .put( "books", new JSONObject() + .put( "book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + .accumulate( "book", new JSONObject() + .put("title", "Groovy in Action") + .put("author", "Dierk Konig") ) + ) + JSONAssert.assertEquals(expected, actual) + } + + void testNonDefaultRootName() { + def actual = builder.books { + book ([title: "The Definitive Guide to Grails", author: "Graeme Rocher"]) + book ([title: "Groovy in Action", author: "Dierk Konig"]) + } + def expected = new JSONObject() + .put("books", new JSONObject() + .put("book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher")) + .accumulate( "book", new JSONObject() + .put("title", "Groovy in Action") + .put("author", "Dierk Konig")) + ) + JSONAssert.assertEquals(expected, actual) + + } + + + void testBuildObjectWithList(){ + def actual = builder.json { + list( + [title: "The Definitive Guide to Grails", author: "Graeme Rocher"], + [title: "Groovy in Action", author: "Dierk Konig"] + ) + } + def expected = new JSONObject().put("list", new JSONArray(). + put(new JSONObject().put("title", "The Definitive Guide to Grails").put("author", "Graeme Rocher")). + put(new JSONObject().put("title", "Groovy in Action").put("author", "Dierk Konig")) + + ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObjectWithClosures(){ + def actual = builder.json { + books { + book { + title "The Definitive Guide to Grails" + author "Graeme Rocher" + } + book { + title "Groovy in Action" + author "Dierk Konig" + } + } + } + def expected = new JSONObject() + .put( "books", new JSONObject() + .put( "book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + .accumulate( "book", new JSONObject() + .put("title", "Groovy in Action") + .put("author", "Dierk Konig") ) + ) + + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObjectWithClosures2(){ + def actual = builder.json { + books { + 2.times { + book { + title "The Definitive Guide to Grails" + author "Graeme Rocher" + } + } + } + } + def expected = new JSONObject() + .put( "books", new JSONObject() + .put( "book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + .accumulate( "book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + ) + + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObjectWithClosures3(){ + def actual = builder.json{ + books { + book { + title "The Definitive Guide to Grails" + author "Graeme Rocher" + } + book { + title "Groovy in Action" + author "Dierk Konig" + } + } + } + def expected = new JSONObject() + .put( "books", new JSONObject() + .put( "book", new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + .accumulate( "book", new JSONObject() + .put("title", "Groovy in Action") + .put("author", "Dierk Konig") ) + ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObjectWithMultipleClosures(){ + def actual = builder.json { + books ([{ + title "The Definitive Guide to Grails" + author "Graeme Rocher" + }, { + title "Groovy in Action" + author "Dierk Konig" + }]) + } + def expected = new JSONObject() + .put( "books", new JSONArray() + .put( new JSONObject() + .put("title", "The Definitive Guide to Grails") + .put("author", "Graeme Rocher") ) + .put( new JSONObject() + .put("title", "Groovy in Action") + .put("author", "Dierk Konig") ) + ) + + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Map_with_Closure(){ + def actual = builder.json([object:{key "value"}]) + def expected = new JSONObject() + .put( "object", new JSONObject() + .put( "key", "value" ) + ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Map_with_Map(){ + def actual = builder.json([object:[key:"value"]]) + def expected = new JSONObject() + .put( "object", new JSONObject() + .put( "key", "value" ) + ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Map_with_List(){ + def actual = builder.json([object: [1,2,3]]) + def expected = new JSONObject() + .put( "object", [1,2,3] ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_List_with_Closure(){ + def actual = builder.json([{key "value"}]) + def expected = new JSONArray() + .put( new JSONObject() + .put( "key", "value" ) + ) + JSONAssert.assertEquals(expected, actual) + } + void testBuildObject_List_with_Map(){ + def actual = builder.json([[key:"value"]]) + def expected = new JSONArray() + .put( new JSONObject() + .put( "key", "value" ) + ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_List_with_List(){ + def actual = builder.json([[1,2,3]]) + def expected = new JSONArray() + .put( [1,2,3] ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Method_with_Map(){ + def actual = builder.json { + node( ['key':"value"] ) + } + def expected = new JSONObject() + .put( "node", new JSONObject().put("key","value") ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Method_with_List(){ + def actual = builder.json { + node( [1,2,3] ) + } + def expected = new JSONObject() + .put( "node", new JSONArray([1,2,3]) ) + JSONAssert.assertEquals(expected, actual) + } + + void testBuildObject_Method_with_Map_multipleArgs(){ + def actual = builder.json { + node( ['key':"value"], ['key':"value"] ) + } + def expected = new JSONObject() + .put( "node", new JSONArray() + .put( new JSONObject().put("key","value") ) + .put( new JSONObject().put("key","value") ) + ) + JSONAssert.assertEquals(expected, actual) + } + + protected void setUp(){ + builder = new JSONGroovyBuilder() + } +} \ No newline at end of file Added: sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/JSONAssert.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/JSONAssert.java?rev=894698&view=auto ============================================================================== --- sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/JSONAssert.java (added) +++ sling/trunk/bundles/commons/json/src/test/java/org/apache/sling/commons/json/test/JSONAssert.java Wed Dec 30 19:34:31 2009 @@ -0,0 +1,183 @@ +/* + * 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.sling.commons.json.test; + +import java.util.Iterator; + +import junit.framework.Assert; + +import org.apache.sling.commons.json.JSONArray; +import org.apache.sling.commons.json.JSONException; +import org.apache.sling.commons.json.JSONObject; + +/** + * Provides assertions on equality for JSON Arrays and Objects. + * + * Based on code written by Andres Almiray as + * part of the json-lib project - http://json-lib.sourceforge.net/ + */ +public class JSONAssert extends Assert { + /** + * Asserts that two JSONArrays are equal. + */ + public static void assertEquals(JSONArray expected, JSONArray actual) + throws JSONException { + assertEquals(null, expected, actual); + } + + /** + * Asserts that two JSONObjects are equal. + */ + public static void assertEquals(JSONObject expected, JSONObject actual) + throws JSONException { + assertEquals(null, expected, actual); + } + + /** + * Asserts that two JSONArrays are equal. + */ + public static void assertEquals(String message, JSONArray expected, + JSONArray actual) throws JSONException { + String header = message == null ? "" : message + ": "; + if (expected == null) { + fail(header + "expected array was null"); + } + if (actual == null) { + fail(header + "actual array was null"); + } + if (expected == actual || expected.equals(actual)) { + return; + } + if (actual.length() != expected.length()) { + fail(header + "arrays sizes differed, expected.length()=" + + expected.length() + " actual.length()=" + actual.length()); + } + + int max = expected.length(); + for (int i = 0; i < max; i++) { + Object o1 = expected.get(i); + Object o2 = actual.get(i); + + // handle nulls + if (JSONObject.NULL.equals(o1)) { + if (JSONObject.NULL.equals(o2)) { + continue; + } else { + fail(header + "arrays first differed at element [" + i + + "];"); + } + } else { + if (JSONObject.NULL.equals(o2)) { + fail(header + "arrays first differed at element [" + i + + "];"); + } + } + + if (o1 instanceof JSONArray && o2 instanceof JSONArray) { + JSONArray e = (JSONArray) o1; + JSONArray a = (JSONArray) o2; + assertEquals(header + "arrays first differed at element " + i + + ";", e, a); + } else if (o1 instanceof JSONObject && o2 instanceof JSONObject) { + assertEquals(header + "arrays first differed at element [" + i + + "];", (JSONObject) o1, (JSONObject) o2); + } else if (o1 instanceof String) { + assertEquals(header + "arrays first differed at element [" + i + + "];", (String) o1, String.valueOf(o2)); + } else if (o2 instanceof String) { + assertEquals(header + "arrays first differed at element [" + i + + "];", String.valueOf(o1), (String) o2); + } else { + assertEquals(header + "arrays first differed at element [" + i + + "];", o1, o2); + } + } + } + + /** + * Asserts that two JSONObjects are equal. + */ + public static void assertEquals(String message, JSONObject expected, + JSONObject actual) throws JSONException { + String header = message == null ? "" : message + ": "; + if (expected == null) { + fail(header + "expected object was null"); + } + if (actual == null) { + fail(header + "actual object was null"); + } + if (expected == actual /* || expected.equals( actual ) */) { + return; + } + + JSONArray expectedNames = expected.names(); + JSONArray actualNames = actual.names(); + + if (expectedNames == null && actualNames == null) { + return; + } + + if (expectedNames == null) { + expectedNames = new JSONArray(); + } + + if (actualNames == null) { + actualNames = new JSONArray(); + } + + assertEquals(header + + "names sizes differed, expected.names().length()=" + + expectedNames.length() + " actual.names().length()=" + + actualNames.length(), expectedNames.length(), actualNames + .length()); + for (Iterator keys = expected.keys(); keys.hasNext();) { + String key = (String) keys.next(); + Object o1 = expected.opt(key); + Object o2 = actual.opt(key); + + if (JSONObject.NULL.equals(o1)) { + if (JSONObject.NULL.equals(o2)) { + continue; + } else { + fail(header + "objects differed at key [" + key + "];"); + } + } else { + if (JSONObject.NULL.equals(o2)) { + fail(header + "objects differed at key [" + key + "];"); + } + } + + if (o1 instanceof JSONObject && o2 instanceof JSONObject) { + assertEquals(header + "objects differed at key [" + key + "];", + (JSONObject) o1, (JSONObject) o2); + } else if (o1 instanceof JSONArray && o2 instanceof JSONArray) { + assertEquals(header + "objects differed at key [" + key + "];", + (JSONArray) o1, (JSONArray) o2); + } else if (o1 instanceof String) { + assertEquals(header + "objects differed at key [" + key + "];", + (String) o1, String.valueOf(o2)); + } else if (o2 instanceof String) { + assertEquals(header + "objects differed at key [" + key + "];", + String.valueOf(o1), (String) o2); + } else { + assertEquals(header + "objects differed at key [" + key + "];", + o1, o2); + } + } + } + +} Modified: sling/trunk/launchpad/builder/src/main/bundles/list.xml URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/builder/src/main/bundles/list.xml?rev=894698&r1=894697&r2=894698&view=diff ============================================================================== --- sling/trunk/launchpad/builder/src/main/bundles/list.xml (original) +++ sling/trunk/launchpad/builder/src/main/bundles/list.xml Wed Dec 30 19:34:31 2009 @@ -164,7 +164,7 @@ org.apache.sling org.apache.sling.commons.json - 2.0.4-incubator + 2.0.5-SNAPSHOT org.apache.felix Added: sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JSONGroovyBuilderIntegrationTest.java URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JSONGroovyBuilderIntegrationTest.java?rev=894698&view=auto ============================================================================== --- sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JSONGroovyBuilderIntegrationTest.java (added) +++ sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/JSONGroovyBuilderIntegrationTest.java Wed Dec 30 19:34:31 2009 @@ -0,0 +1,63 @@ +/* + * 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.sling.launchpad.webapp.integrationtest; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.commons.json.JSONException; +import org.apache.sling.commons.json.JSONObject; +import org.apache.sling.servlets.post.SlingPostConstants; + +public class JSONGroovyBuilderIntegrationTest extends RenderingTestBase { + + private String slingResourceType; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + // set test values + slingResourceType = "integration-test/srt." + System.currentTimeMillis(); + testText = "This is a test " + System.currentTimeMillis(); + + // create the test node, under a path that's specific to this class to allow collisions + final String url = HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + SlingPostConstants.DEFAULT_CREATE_SUFFIX; + final Map props = new HashMap(); + props.put("sling:resourceType", slingResourceType); + props.put("text", testText); + displayUrl = testClient.createNode(url, props); + + // the rendering script goes under /apps in the repository + scriptPath = "/apps/" + slingResourceType; + testClient.mkdirs(WEBDAV_BASE_URL, scriptPath); + } + + public void testJSONGroovyBuilder() throws IOException, JSONException { + final String toDelete = uploadTestScript("builder.groovy","json.groovy"); + try { + final String content = getContent(displayUrl + ".json", CONTENT_TYPE_JSON); + JSONObject jo = new JSONObject(content); + assertEquals("Content contained wrong number of items", 1, jo.length()); + assertEquals("Content contained wrong key", "text", jo.keys().next()); + assertEquals("Content contained wrong data", testText, jo.get("text")); + } finally { + testClient.delete(toDelete); + } + } +} Added: sling/trunk/launchpad/testing/src/test/resources/integration-test/builder.groovy URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/testing/src/test/resources/integration-test/builder.groovy?rev=894698&view=auto ============================================================================== --- sling/trunk/launchpad/testing/src/test/resources/integration-test/builder.groovy (added) +++ sling/trunk/launchpad/testing/src/test/resources/integration-test/builder.groovy Wed Dec 30 19:34:31 2009 @@ -0,0 +1,24 @@ +/* + * 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. + */ + +builder = new org.apache.sling.commons.json.groovy.JSONGroovyBuilder() + +out.write builder.json { + text currentNode.getProperty("text").string +} as String Modified: sling/trunk/parent/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/parent/pom.xml?rev=894698&r1=894697&r2=894698&view=diff ============================================================================== --- sling/trunk/parent/pom.xml (original) +++ sling/trunk/parent/pom.xml Wed Dec 30 19:34:31 2009 @@ -51,7 +51,7 @@ http://sling.apache.org/site/media.data/logo.png - + scm:svn:http://svn.apache.org/repos/asf/sling/trunk/parent @@ -157,7 +157,7 @@ ********************** WARNING (SLING-443) ********************************** -On most platforms, building Apache Sling currently requires setting +On most platforms, building Apache Sling currently requires setting MAVEN_OPTS="-Xmx256M", see https://issues.apache.org/jira/browse/SLING-443 You might get a "java.lang.OutOfMemoryError: Java heap space" if that setting is not correct. @@ -297,6 +297,11 @@ apache-rat-plugin 0.6 + + org.codehaus.groovy.maven + gmaven-plugin + 1.0 + @@ -371,7 +376,7 @@ We should execute this profile manually to make sure that all files in our source code contain proper licenses. This is very important and should not be skipped in any scenario. It is very importnt for us to follow ASF policy. Example: mvn -P prepare-release install - --> + --> rat @@ -447,7 +452,7 @@ - Modified: sling/trunk/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/pom.xml?rev=894698&r1=894697&r2=894698&view=diff ============================================================================== --- sling/trunk/pom.xml (original) +++ sling/trunk/pom.xml Wed Dec 30 19:34:31 2009 @@ -124,9 +124,9 @@ launchpad/base + launchpad/content launchpad/builder launchpad/bundles - launchpad/content launchpad/app launchpad/webapp