struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From musa...@apache.org
Subject svn commit: r799003 [1/4] - in /struts/sandbox/trunk/struts2-json-plugin: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/struts2/ src/main/java/org/apache/struts2/json/ src/main/java/org/apache/st...
Date Wed, 29 Jul 2009 18:33:08 GMT
Author: musachy
Date: Wed Jul 29 18:33:05 2009
New Revision: 799003

URL: http://svn.apache.org/viewvc?rev=799003&view=rev
Log:
Import JSON plugin

Added:
    struts/sandbox/trunk/struts2-json-plugin/
    struts/sandbox/trunk/struts2-json-plugin/pom.xml
    struts/sandbox/trunk/struts2-json-plugin/src/
    struts/sandbox/trunk/struts2-json-plugin/src/main/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONCleaner.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONException.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONInterceptor.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONPopulator.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONReader.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMD.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethod.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethod.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethodParameter.java
    struts/sandbox/trunk/struts2-json-plugin/src/main/resources/
    struts/sandbox/trunk/struts2-json-plugin/src/main/resources/JsonPlugin.tld
    struts/sandbox/trunk/struts2-json-plugin/src/main/resources/struts-plugin.xml
    struts/sandbox/trunk/struts2-json-plugin/src/test/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/JSONEnumTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/JSONPopulatorTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/JSONResultTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/JSONUtilTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/OtherBean.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/SMDActionTest1.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/SMDActionTest2.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/SMDMethodInterfaceTest.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/SimpleValue.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/TestAction.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/TestAction2.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/TestAction3.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/TestAction4.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/TestUtils.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/WrapperClassBean.java
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-2.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-3.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-4.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-5.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/bad-to-the-bone.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-10.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-2-enum.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-2.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-3.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-4.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-5.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-6.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-7.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-8.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json-9.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/json.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/jsonp-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/nulls-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/prefix-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-1.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-10.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-11.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-12.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-13.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-14.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-15.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-2.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-3.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-4.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-5.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-6.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-7.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-8.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd-9.txt
    struts/sandbox/trunk/struts2-json-plugin/src/test/resources/org/apache/struts2/json/smd.txt

Added: struts/sandbox/trunk/struts2-json-plugin/pom.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/pom.xml?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/pom.xml (added)
+++ struts/sandbox/trunk/struts2-json-plugin/pom.xml Wed Jul 29 18:33:05 2009
@@ -0,0 +1,102 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.struts</groupId>
+        <artifactId>struts2-plugins</artifactId>
+        <version>2.1.8-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.struts</groupId>
+    <artifactId>struts2-json-plugin</artifactId>
+    <packaging>jar</packaging>
+    <name>Struts 2 JSON Plugin</name>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/struts2-json-plugin</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/struts2/struts2-json-plugin</developerConnection>
+        <url>http://svn.apache.org/viewcvs.cgi/struts/sandbox/struts2/struts2-json-plugin</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <inherited>true</inherited>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.apache.struts2.osgi.StrutsActivator</Bundle-Activator>
+                        <manifestLocation>META-INF</manifestLocation>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+
+    </build>
+
+
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.3</version>
+            <scope>test</scope>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.apache.struts</groupId>
+            <artifactId>struts2-core</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.struts</groupId>
+            <artifactId>struts2-junit-plugin</artifactId>
+            <version>${pom.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>jsp-api</artifactId>
+            <version>2.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>2.3</version>
+            <scope>test</scope>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>2.5.5</version>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+</project>

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONCleaner.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONCleaner.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONCleaner.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONCleaner.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,44 @@
+package org.apache.struts2.json;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Isolate the process of cleaning JSON data from the Interceptor class itself.
+ */
+public abstract class JSONCleaner {
+
+    public Object clean(String ognlPrefix, Object data) throws JSONException {
+        if (data == null)
+            return null;
+        else if (data instanceof List)
+            return cleanList(ognlPrefix, data);
+        else if (data instanceof Map)
+            return cleanMap(ognlPrefix, data);
+        else
+            return cleanValue(ognlPrefix, data);
+    }
+
+    protected Object cleanList(String ognlPrefix, Object data) throws JSONException {
+        List list = (List) data;
+        int count = list.size();
+        for (int i = 0; i < count; i++) {
+            list.set(i, clean(ognlPrefix + "[" + i + "]", list.get(i)));
+        }
+        return list;
+    }
+
+    protected Object cleanMap(String ognlPrefix, Object data) throws JSONException {
+        Map map = (Map) data;
+        Iterator iter = map.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry e = (Map.Entry) iter.next();
+            e.setValue(clean((ognlPrefix.length() > 0 ? ognlPrefix + "." : "") + e.getKey(), e.getValue()));
+        }
+        return map;
+    }
+
+    protected abstract Object cleanValue(String ognlName, Object data) throws JSONException;
+
+}

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONException.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONException.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONException.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONException.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.json;
+
+/**
+ * Wrap exceptions throwed by the JSON serializer
+ */
+public class JSONException extends Exception {
+    public JSONException(String message) {
+        super(message);
+    }
+
+    public JSONException(Throwable cause) {
+        super(cause);
+    }
+
+    public JSONException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONInterceptor.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONInterceptor.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONInterceptor.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONInterceptor.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,460 @@
+package org.apache.struts2.json;
+
+import java.beans.IntrospectionException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.json.annotations.SMDMethod;
+import org.apache.struts2.json.rpc.RPCError;
+import org.apache.struts2.json.rpc.RPCErrorCode;
+import org.apache.struts2.json.rpc.RPCResponse;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * Populates an action from a JSON string
+ */
+public class JSONInterceptor implements Interceptor {
+    private static final long serialVersionUID = 4950170304212158803L;
+    private static final Logger LOG = LoggerFactory.getLogger(JSONInterceptor.class);
+    private boolean enableSMD = false;
+    private boolean enableGZIP = false;
+    private boolean wrapWithComments;
+    private boolean prefix;
+    private String defaultEncoding = "ISO-8859-1";
+    private boolean ignoreHierarchy = true;
+    private String root;
+    private List<Pattern> excludeProperties;
+    private List<Pattern> includeProperties;
+    private boolean ignoreSMDMethodInterfaces = true;
+    private JSONPopulator populator = new JSONPopulator();
+    private JSONCleaner dataCleaner = null;
+    private boolean debug = false;
+    private boolean noCache = false;
+    private boolean excludeNullProperties;
+    private String callbackParameter;
+    private String contentType;
+
+    public void destroy() {
+    }
+
+    public void init() {
+    }
+
+    @SuppressWarnings("unchecked")
+    public String intercept(ActionInvocation invocation) throws Exception {
+        HttpServletRequest request = ServletActionContext.getRequest();
+        HttpServletResponse response = ServletActionContext.getResponse();
+        String contentType = request.getHeader("content-type");
+        if (contentType != null) {
+            int iSemicolonIdx;
+            if ((iSemicolonIdx = contentType.indexOf(";")) != -1)
+                contentType = contentType.substring(0, iSemicolonIdx);
+        }
+
+        Object rootObject;
+        if (this.root != null) {
+            ValueStack stack = invocation.getStack();
+            rootObject = stack.findValue(this.root);
+
+            if (rootObject == null) {
+                throw new RuntimeException("Invalid root expression: '" + this.root + "'.");
+            }
+        } else {
+            rootObject = invocation.getAction();
+        }
+
+        if ((contentType != null) && contentType.equalsIgnoreCase("application/json")) {
+            // load JSON object
+            Object obj = JSONUtil.deserialize(request.getReader());
+
+            if (obj instanceof Map) {
+                Map json = (Map) obj;
+
+                // clean up the values
+                if (dataCleaner != null)
+                    dataCleaner.clean("", json);
+
+                // populate fields
+                populator.populateObject(rootObject, json);
+            } else {
+                LOG.error("Unable to deserialize JSON object from request");
+                throw new JSONException("Unable to deserialize JSON object from request");
+            }
+        } else if ((contentType != null) && contentType.equalsIgnoreCase("application/json-rpc")) {
+            Object result;
+            if (this.enableSMD) {
+                // load JSON object
+                Object obj = JSONUtil.deserialize(request.getReader());
+
+                if (obj instanceof Map) {
+                    Map smd = (Map) obj;
+
+                    // invoke method
+                    try {
+                        result = this.invoke(rootObject, smd);
+                    } catch (Exception e) {
+                        RPCResponse rpcResponse = new RPCResponse();
+                        rpcResponse.setId(smd.get("id").toString());
+                        rpcResponse.setError(new RPCError(e, RPCErrorCode.EXCEPTION, debug));
+
+                        result = rpcResponse;
+                    }
+                } else {
+                    String message = "SMD request was not in the right format. See http://json-rpc.org";
+
+                    RPCResponse rpcResponse = new RPCResponse();
+                    rpcResponse.setError(new RPCError(message, RPCErrorCode.INVALID_PROCEDURE_CALL));
+                    result = rpcResponse;
+                }
+
+                String json = JSONUtil.serialize(result, excludeProperties, includeProperties,
+                        ignoreHierarchy, excludeNullProperties);
+                json = addCallbackIfApplicable(request, json);
+                JSONUtil.writeJSONToResponse(new SerializationParams(response, this.defaultEncoding,
+                        this.wrapWithComments, json, true, false, noCache, -1, -1, prefix, contentType));
+
+                return Action.NONE;
+            } else {
+                String message = "Request with content type of 'application/json-rpc' was received but SMD is "
+                        + "not enabled for this interceptor. Set 'enableSMD' to true to enable it";
+
+                RPCResponse rpcResponse = new RPCResponse();
+                rpcResponse.setError(new RPCError(message, RPCErrorCode.SMD_DISABLED));
+                result = rpcResponse;
+            }
+
+            String json = JSONUtil.serialize(result, excludeProperties, includeProperties, ignoreHierarchy,
+                    excludeNullProperties);
+            json = addCallbackIfApplicable(request, json);
+            boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);
+            JSONUtil.writeJSONToResponse(new SerializationParams(response, this.defaultEncoding,
+                    this.wrapWithComments, json, true, writeGzip, noCache, -1, -1, prefix, contentType));
+
+            return Action.NONE;
+        } else {
+            if (LOG.isDebugEnabled()) {
+                LOG
+                        .debug("Content type must be 'application/json' or 'application/json-rpc'. Ignoring request with content type "
+                                + contentType);
+            }
+        }
+
+        return invocation.invoke();
+    }
+
+    @SuppressWarnings("unchecked")
+    public RPCResponse invoke(Object object, Map data) throws IllegalArgumentException,
+            IllegalAccessException, InvocationTargetException, JSONException, InstantiationException,
+            NoSuchMethodException, IntrospectionException {
+
+        RPCResponse response = new RPCResponse();
+
+        // validate id
+        Object id = data.get("id");
+        if (id == null) {
+            String message = "'id' is required for JSON RPC";
+            response.setError(new RPCError(message, RPCErrorCode.METHOD_NOT_FOUND));
+            return response;
+        }
+        // could be a numeric value
+        response.setId(id.toString());
+
+        // the map is going to have: 'params', 'method' and 'id' (what is the id
+        // for?)
+        Class clazz = object.getClass();
+
+        // parameters
+        List parameters = (List) data.get("params");
+        int parameterCount = parameters != null ? parameters.size() : 0;
+
+        // method
+        String methodName = (String) data.get("method");
+        if (methodName == null) {
+            String message = "'method' is required for JSON RPC";
+            response.setError(new RPCError(message, RPCErrorCode.MISSING_METHOD));
+            return response;
+        }
+
+        Method method = this.getMethod(clazz, methodName, parameterCount);
+        if (method == null) {
+            String message = "Method " + methodName + " could not be found in action class.";
+            response.setError(new RPCError(message, RPCErrorCode.METHOD_NOT_FOUND));
+            return response;
+        }
+
+        // parameters
+        if (parameterCount > 0) {
+            Class[] parameterTypes = method.getParameterTypes();
+            Type[] genericTypes = method.getGenericParameterTypes();
+            List invocationParameters = new ArrayList();
+
+            // validate size
+            if (parameterTypes.length != parameterCount) {
+                // size mismatch
+                String message = "Parameter count in request, " + parameterCount
+                        + " do not match expected parameter count for " + methodName + ", "
+                        + parameterTypes.length;
+
+                response.setError(new RPCError(message, RPCErrorCode.PARAMETERS_MISMATCH));
+                return response;
+            }
+
+            // convert parameters
+            for (int i = 0; i < parameters.size(); i++) {
+                Object parameter = parameters.get(i);
+                Class paramType = parameterTypes[i];
+                Type genericType = genericTypes[i];
+
+                // clean up the values
+                if (dataCleaner != null)
+                    parameter = dataCleaner.clean("[" + i + "]", parameter);
+
+                Object converted = populator.convert(paramType, genericType, parameter, method);
+                invocationParameters.add(converted);
+            }
+
+            response.setResult(method.invoke(object, invocationParameters.toArray()));
+        } else {
+            response.setResult(method.invoke(object, new Object[0]));
+        }
+
+        return response;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Method getMethod(Class clazz, String name, int parameterCount) {
+        Method[] smdMethods = JSONUtil.listSMDMethods(clazz, ignoreSMDMethodInterfaces);
+
+        for (Method method : smdMethods) {
+            if (checkSMDMethodSignature(method, name, parameterCount)) {
+                return method;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Look for a method in clazz carrying the SMDMethod annotation with
+     * matching name and parametersCount
+     * 
+     * @return true if matches name and parameterCount
+     */
+    private boolean checkSMDMethodSignature(Method method, String name, int parameterCount) {
+
+        SMDMethod smdMethodAnntotation = method.getAnnotation(SMDMethod.class);
+        if (smdMethodAnntotation != null) {
+            String alias = smdMethodAnntotation.name();
+            boolean paramsMatch = method.getParameterTypes().length == parameterCount;
+            if (((alias.length() == 0) && method.getName().equals(name) && paramsMatch)
+                    || (alias.equals(name) && paramsMatch)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    protected String addCallbackIfApplicable(HttpServletRequest request, String json) {
+        if ((callbackParameter != null) && (callbackParameter.length() > 0)) {
+            String callbackName = request.getParameter(callbackParameter);
+            if ((callbackName != null) && (callbackName.length() > 0))
+                json = callbackName + "(" + json + ")";
+        }
+        return json;
+    }
+
+    public boolean isEnableSMD() {
+        return this.enableSMD;
+    }
+
+    public void setEnableSMD(boolean enableSMD) {
+        this.enableSMD = enableSMD;
+    }
+
+    /**
+     * Ignore annotations on methods in interfaces You may need to set to this
+     * true if your action is a proxy/enhanced as annotations are not inherited
+     */
+    public void setIgnoreSMDMethodInterfaces(boolean ignoreSMDMethodInterfaces) {
+        this.ignoreSMDMethodInterfaces = ignoreSMDMethodInterfaces;
+    }
+
+    /**
+     * Wrap generated JSON with comments. Only used if SMD is enabled.
+     * 
+     * @param wrapWithComments
+     */
+    public void setWrapWithComments(boolean wrapWithComments) {
+        this.wrapWithComments = wrapWithComments;
+    }
+
+    @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
+    public void setDefaultEncoding(String val) {
+        this.defaultEncoding = val;
+    }
+
+    /**
+     * Ignore properties defined on base classes of the root object.
+     * 
+     * @param ignoreHierarchy
+     */
+    public void setIgnoreHierarchy(boolean ignoreHierarchy) {
+        this.ignoreHierarchy = ignoreHierarchy;
+    }
+
+    /**
+     * Sets the root object to be deserialized, defaults to the Action
+     * 
+     * @param root
+     *            OGNL expression of root object to be serialized
+     */
+    public void setRoot(String root) {
+        this.root = root;
+    }
+
+    /**
+     * Sets the JSONPopulator to be used
+     * 
+     * @param populator
+     *            JSONPopulator
+     */
+    public void setJSONPopulator(JSONPopulator populator) {
+        this.populator = populator;
+    }
+
+    /**
+     * Sets the JSONCleaner to be used
+     * 
+     * @param dataCleaner
+     *            JSONCleaner
+     */
+    public void setJSONCleaner(JSONCleaner dataCleaner) {
+        this.dataCleaner = dataCleaner;
+    }
+
+    /**
+     * Turns debugging on or off
+     * 
+     * @param debug
+     *            true or false
+     */
+    public boolean getDebug() {
+        return this.debug;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    /**
+     * Sets a comma-delimited list of regular expressions to match properties
+     * that should be excluded from the JSON output.
+     * 
+     * @param commaDelim
+     *            A comma-delimited list of regular expressions
+     */
+    public void setExcludeProperties(String commaDelim) {
+        List<String> excludePatterns = JSONUtil.asList(commaDelim);
+        if (excludePatterns != null) {
+            this.excludeProperties = new ArrayList<Pattern>(excludePatterns.size());
+            for (String pattern : excludePatterns) {
+                this.excludeProperties.add(Pattern.compile(pattern));
+            }
+        }
+    }
+
+    /**
+     * Sets a comma-delimited list of regular expressions to match properties
+     * that should be included from the JSON output.
+     * 
+     * @param commaDelim
+     *            A comma-delimited list of regular expressions
+     */
+    public void setIncludeProperties(String commaDelim) {
+        List<String> includePatterns = JSONUtil.asList(commaDelim);
+        if (includePatterns != null) {
+            this.includeProperties = new ArrayList<Pattern>(includePatterns.size());
+            for (String pattern : includePatterns) {
+                this.includeProperties.add(Pattern.compile(pattern));
+            }
+        }
+    }
+
+    public boolean isEnableGZIP() {
+        return enableGZIP;
+    }
+
+    /**
+     * Setting this property to "true" will compress the output.
+     * 
+     * @param enableGZIP
+     *            Enable compressed output
+     */
+    public void setEnableGZIP(boolean enableGZIP) {
+        this.enableGZIP = enableGZIP;
+    }
+
+    public boolean isNoCache() {
+        return noCache;
+    }
+
+    /**
+     * Add headers to response to prevent the browser from caching the response
+     * 
+     * @param noCache
+     */
+    public void setNoCache(boolean noCache) {
+        this.noCache = noCache;
+    }
+
+    public boolean isExcludeNullProperties() {
+        return excludeNullProperties;
+    }
+
+    /**
+     * Do not serialize properties with a null value
+     * 
+     * @param excludeNullProperties
+     */
+    public void setExcludeNullProperties(boolean excludeNullProperties) {
+        this.excludeNullProperties = excludeNullProperties;
+    }
+
+    public void setCallbackParameter(String callbackParameter) {
+        this.callbackParameter = callbackParameter;
+    }
+
+    public String getCallbackParameter() {
+        return callbackParameter;
+    }
+
+    /**
+     * Add "{} && " to generated JSON
+     * 
+     * @param prefix
+     */
+    public void setPrefix(boolean prefix) {
+        this.prefix = prefix;
+    }
+
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+}

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONPopulator.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONPopulator.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONPopulator.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONPopulator.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,424 @@
+package org.apache.struts2.json;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.struts2.json.annotations.JSON;
+
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * Isolate the process of populating JSON objects from the Interceptor class
+ * itself.
+ */
+public class JSONPopulator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JSONPopulator.class);
+
+    private String dateFormat = JSONUtil.RFC3339_FORMAT;
+
+    public JSONPopulator() {
+    }
+
+    public JSONPopulator(String dateFormat) {
+        this.dateFormat = dateFormat;
+    }
+
+    public String getDateFormat() {
+        return dateFormat;
+    }
+
+    public void setDateFormat(String dateFormat) {
+        this.dateFormat = dateFormat;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void populateObject(Object object, final Map elements) throws IllegalAccessException,
+            InvocationTargetException, NoSuchMethodException, IntrospectionException,
+            IllegalArgumentException, JSONException, InstantiationException {
+        Class clazz = object.getClass();
+
+        BeanInfo info = Introspector.getBeanInfo(clazz);
+        PropertyDescriptor[] props = info.getPropertyDescriptors();
+
+        // iterate over class fields
+        for (int i = 0; i < props.length; ++i) {
+            PropertyDescriptor prop = props[i];
+            String name = prop.getName();
+
+            if (elements.containsKey(name)) {
+                Object value = elements.get(name);
+                Method method = prop.getWriteMethod();
+
+                if (method != null) {
+                    JSON json = method.getAnnotation(JSON.class);
+                    if ((json != null) && !json.deserialize()) {
+                        continue;
+                    }
+
+                    // use only public setters
+                    if (Modifier.isPublic(method.getModifiers())) {
+                        Class[] paramTypes = method.getParameterTypes();
+                        Type[] genericTypes = method.getGenericParameterTypes();
+
+                        if (paramTypes.length == 1) {
+                            Object convertedValue = this.convert(paramTypes[0], genericTypes[0], value,
+                                    method);
+                            method.invoke(object, new Object[] { convertedValue });
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Object convert(Class clazz, Type type, Object value, Method method)
+            throws IllegalArgumentException, JSONException, IllegalAccessException,
+            InvocationTargetException, InstantiationException, NoSuchMethodException, IntrospectionException {
+
+        if (value == null) {
+            // if it is a java primitive then get a default value, otherwise
+            // leave it as null
+            return clazz.isPrimitive() ? convertPrimitive(clazz, value, method) : null;
+        } else if (isJSONPrimitive(clazz))
+            return convertPrimitive(clazz, value, method);
+        else if (Collection.class.isAssignableFrom(clazz))
+            return convertToCollection(clazz, type, value, method);
+        else if (Map.class.isAssignableFrom(clazz))
+            return convertToMap(clazz, type, value, method);
+        else if (clazz.isArray())
+            return convertToArray(clazz, type, value, method);
+        else if (value instanceof Map) {
+            // nested bean
+            Object convertedValue = clazz.newInstance();
+            this.populateObject(convertedValue, (Map) value);
+            return convertedValue;
+        } else if (BigDecimal.class.equals(clazz)) {
+            return new BigDecimal(value != null ? value.toString() : "0");
+        } else if (BigInteger.class.equals(clazz)) {
+            return new BigInteger(value != null ? value.toString() : "0");
+        } else
+            throw new JSONException("Incompatible types for property " + method.getName());
+    }
+
+    private static boolean isJSONPrimitive(Class clazz) {
+        return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Date.class)
+                || clazz.equals(Boolean.class) || clazz.equals(Byte.class) || clazz.equals(Character.class)
+                || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Integer.class)
+                || clazz.equals(Long.class) || clazz.equals(Short.class) || clazz.equals(Locale.class)
+                || clazz.isEnum();
+    }
+
+    @SuppressWarnings("unchecked")
+    private Object convertToArray(Class clazz, Type type, Object value, Method accessor)
+            throws JSONException, IllegalArgumentException, IllegalAccessException,
+            InvocationTargetException, InstantiationException, NoSuchMethodException, IntrospectionException {
+        if (value == null)
+            return null;
+        else if (value instanceof List) {
+            Class arrayType = clazz.getComponentType();
+            List values = (List) value;
+            Object newArray = Array.newInstance(arrayType, values.size());
+
+            // create an object for each element
+            for (int j = 0; j < values.size(); j++) {
+                Object listValue = values.get(j);
+
+                if (arrayType.equals(Object.class)) {
+                    // Object[]
+                    Array.set(newArray, j, listValue);
+                } else if (isJSONPrimitive(arrayType)) {
+                    // primitive array
+                    Array.set(newArray, j, this.convertPrimitive(arrayType, listValue, accessor));
+                } else if (listValue instanceof Map) {
+                    // array of other class
+                    Object newObject = null;
+                    if (Map.class.isAssignableFrom(arrayType)) {
+                        newObject = convertToMap(arrayType, type, listValue, accessor);
+                    } else if (List.class.isAssignableFrom(arrayType)) {
+                        newObject = convertToCollection(arrayType, type, listValue, accessor);
+                    } else {
+                        newObject = arrayType.newInstance();
+                        this.populateObject(newObject, (Map) listValue);
+                    }
+
+                    Array.set(newArray, j, newObject);
+                } else
+                    throw new JSONException("Incompatible types for property " + accessor.getName());
+            }
+
+            return newArray;
+        } else
+            throw new JSONException("Incompatible types for property " + accessor.getName());
+    }
+
+    @SuppressWarnings("unchecked")
+    private Object convertToCollection(Class clazz, Type type, Object value, Method accessor)
+            throws JSONException, IllegalArgumentException, IllegalAccessException,
+            InvocationTargetException, InstantiationException, NoSuchMethodException, IntrospectionException {
+        if (value == null)
+            return null;
+        else if (value instanceof List) {
+            Class itemClass = Object.class;
+            Type itemType = null;
+            if ((type != null) && (type instanceof ParameterizedType)) {
+                ParameterizedType ptype = (ParameterizedType) type;
+                itemType = ptype.getActualTypeArguments()[0];
+                if (itemType.getClass().equals(Class.class)) {
+                    itemClass = (Class) itemType;
+                } else {
+                    itemClass = (Class) ((ParameterizedType) itemType).getRawType();
+                }
+            }
+            List values = (List) value;
+
+            Collection newCollection = null;
+            try {
+                newCollection = (Collection) clazz.newInstance();
+            } catch (InstantiationException ex) {
+                // fallback if clazz represents an interface or abstract class
+                if (Set.class.isAssignableFrom(clazz)) {
+                    newCollection = new HashSet();
+                } else {
+                    newCollection = new ArrayList();
+                }
+            }
+
+            // create an object for each element
+            for (int j = 0; j < values.size(); j++) {
+                Object listValue = values.get(j);
+
+                if (itemClass.equals(Object.class)) {
+                    // Object[]
+                    newCollection.add(listValue);
+                } else if (isJSONPrimitive(itemClass)) {
+                    // primitive array
+                    newCollection.add(this.convertPrimitive(itemClass, listValue, accessor));
+                } else if (Map.class.isAssignableFrom(itemClass)) {
+                    Object newObject = convertToMap(itemClass, itemType, listValue, accessor);
+                    newCollection.add(newObject);
+                } else if (List.class.isAssignableFrom(itemClass)) {
+                    Object newObject = convertToCollection(itemClass, itemType, listValue, accessor);
+                    newCollection.add(newObject);
+                } else if (listValue instanceof Map) {
+                    // array of beans
+                    Object newObject = itemClass.newInstance();
+                    this.populateObject(newObject, (Map) listValue);
+                    newCollection.add(newObject);
+                } else
+                    throw new JSONException("Incompatible types for property " + accessor.getName());
+            }
+
+            return newCollection;
+        } else
+            throw new JSONException("Incompatible types for property " + accessor.getName());
+    }
+
+    @SuppressWarnings("unchecked")
+    private Object convertToMap(Class clazz, Type type, Object value, Method accessor) throws JSONException,
+            IllegalArgumentException, IllegalAccessException, InvocationTargetException,
+            InstantiationException, NoSuchMethodException, IntrospectionException {
+        if (value == null)
+            return null;
+        else if (value instanceof Map) {
+            Class itemClass = Object.class;
+            Type itemType = null;
+            if ((type != null) && (type instanceof ParameterizedType)) {
+                ParameterizedType ptype = (ParameterizedType) type;
+                itemType = ptype.getActualTypeArguments()[1];
+                if (itemType.getClass().equals(Class.class)) {
+                    itemClass = (Class) itemType;
+                } else {
+                    itemClass = (Class) ((ParameterizedType) itemType).getRawType();
+                }
+            }
+            Map values = (Map) value;
+
+            Map newMap = null;
+            try {
+                newMap = (Map) clazz.newInstance();
+            } catch (InstantiationException ex) {
+                // fallback if clazz represents an interface or abstract class
+                newMap = new HashMap();
+            }
+
+            // create an object for each element
+            Iterator iter = values.entrySet().iterator();
+            while (iter.hasNext()) {
+                Map.Entry entry = (Map.Entry) iter.next();
+                String key = (String) entry.getKey();
+                Object v = entry.getValue();
+
+                if (itemClass.equals(Object.class)) {
+                    // String, Object
+                    newMap.put(key, v);
+                } else if (isJSONPrimitive(itemClass)) {
+                    // primitive map
+                    newMap.put(key, this.convertPrimitive(itemClass, v, accessor));
+                } else if (Map.class.isAssignableFrom(itemClass)) {
+                    Object newObject = convertToMap(itemClass, itemType, v, accessor);
+                    newMap.put(key, newObject);
+                } else if (List.class.isAssignableFrom(itemClass)) {
+                    Object newObject = convertToCollection(itemClass, itemType, v, accessor);
+                    newMap.put(key, newObject);
+                } else if (v instanceof Map) {
+                    // map of beans
+                    Object newObject = itemClass.newInstance();
+                    this.populateObject(newObject, (Map) v);
+                    newMap.put(key, newObject);
+                } else
+                    throw new JSONException("Incompatible types for property " + accessor.getName());
+            }
+
+            return newMap;
+        } else
+            throw new JSONException("Incompatible types for property " + accessor.getName());
+    }
+
+    /**
+     * Converts numbers to the desired class, if possible
+     * 
+     * @throws JSONException
+     */
+    @SuppressWarnings("unchecked")
+    private Object convertPrimitive(Class clazz, Object value, Method method) throws JSONException {
+        if (value == null) {
+            if (Short.TYPE.equals(clazz) || Short.class.equals(clazz))
+                return (short) 0;
+            else if (Byte.TYPE.equals(clazz) || Byte.class.equals(clazz))
+                return (byte) 0;
+            else if (Integer.TYPE.equals(clazz) || Integer.class.equals(clazz))
+                return 0;
+            else if (Long.TYPE.equals(clazz) || Long.class.equals(clazz))
+                return 0L;
+            else if (Float.TYPE.equals(clazz) || Float.class.equals(clazz))
+                return 0f;
+            else if (Double.TYPE.equals(clazz) || Double.class.equals(clazz))
+                return 0d;
+            else if (Boolean.TYPE.equals(clazz) || Boolean.class.equals(clazz))
+                return Boolean.FALSE;
+            else
+                return null;
+        } else if (value instanceof Number) {
+            Number number = (Number) value;
+
+            if (Short.TYPE.equals(clazz))
+                return number.shortValue();
+            else if (Short.class.equals(clazz))
+                return new Short(number.shortValue());
+            else if (Byte.TYPE.equals(clazz))
+                return number.byteValue();
+            else if (Byte.class.equals(clazz))
+                return new Byte(number.byteValue());
+            else if (Integer.TYPE.equals(clazz))
+                return number.intValue();
+            else if (Integer.class.equals(clazz))
+                return new Integer(number.intValue());
+            else if (Long.TYPE.equals(clazz))
+                return number.longValue();
+            else if (Long.class.equals(clazz))
+                return new Long(number.longValue());
+            else if (Float.TYPE.equals(clazz))
+                return number.floatValue();
+            else if (Float.class.equals(clazz))
+                return new Float(number.floatValue());
+            else if (Double.TYPE.equals(clazz))
+                return number.doubleValue();
+            else if (Double.class.equals(clazz))
+                return new Double(number.doubleValue());
+            else if (String.class.equals(clazz))
+                return value.toString();
+        } else if (clazz.equals(Date.class)) {
+            try {
+                JSON json = method.getAnnotation(JSON.class);
+
+                DateFormat formatter = new SimpleDateFormat(
+                        (json != null) && (json.format().length() > 0) ? json.format() : this.dateFormat);
+                return formatter.parse((String) value);
+            } catch (ParseException e) {
+                LOG.error(e.getMessage(), e);
+                throw new JSONException("Unable to parse date from: " + value);
+            }
+        } else if (clazz.isEnum()) {
+            String sValue = (String) value;
+            return Enum.valueOf(clazz, sValue);
+        } else if (value instanceof String) {
+            String sValue = (String) value;
+            if (Boolean.TYPE.equals(clazz))
+                return Boolean.parseBoolean(sValue);
+            else if (Boolean.class.equals(clazz))
+                return Boolean.valueOf(sValue);
+            else if (Short.TYPE.equals(clazz))
+                return Short.parseShort(sValue);
+            else if (Short.class.equals(clazz))
+                return Short.valueOf(sValue);
+            else if (Byte.TYPE.equals(clazz))
+                return Byte.parseByte(sValue);
+            else if (Byte.class.equals(clazz))
+                return Byte.valueOf(sValue);
+            else if (Integer.TYPE.equals(clazz))
+                return Integer.parseInt(sValue);
+            else if (Integer.class.equals(clazz))
+                return Integer.valueOf(sValue);
+            else if (Long.TYPE.equals(clazz))
+                return Long.parseLong(sValue);
+            else if (Long.class.equals(clazz))
+                return Long.valueOf(sValue);
+            else if (Float.TYPE.equals(clazz))
+                return Float.parseFloat(sValue);
+            else if (Float.class.equals(clazz))
+                return Float.valueOf(sValue);
+            else if (Double.TYPE.equals(clazz))
+                return Double.parseDouble(sValue);
+            else if (Double.class.equals(clazz))
+                return Double.valueOf(sValue);
+            else if (Character.TYPE.equals(clazz) || Character.class.equals(clazz)) {
+                char charValue = 0;
+                if (sValue.length() > 0) {
+                    charValue = sValue.charAt(0);
+                }
+                if (Character.TYPE.equals(clazz))
+                    return charValue;
+                else
+                    return new Character(charValue);
+            } else if (clazz.equals(Locale.class)) {
+                String[] components = sValue.split("_", 2);
+                if (components.length == 2) {
+                    return new Locale(components[0], components[1]);
+                } else {
+                    return new Locale(sValue);
+                }
+            } else if (Enum.class.isAssignableFrom(clazz)) {
+                return Enum.valueOf(clazz, sValue);
+            }
+        }
+
+        return value;
+    }
+
+}

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONReader.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONReader.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONReader.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONReader.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,289 @@
+/*
+ * $Id$
+ *
+ * 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.struts2.json;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * Deserializes and object from a JSON string
+ * </p>
+ */
+class JSONReader {
+    private static final Object OBJECT_END = new Object();
+    private static final Object ARRAY_END = new Object();
+    private static final Object COLON = new Object();
+    private static final Object COMMA = new Object();
+    private static Map<Character, Character> escapes = new HashMap<Character, Character>();
+
+    static {
+        escapes.put(new Character('"'), new Character('"'));
+        escapes.put(new Character('\\'), new Character('\\'));
+        escapes.put(new Character('/'), new Character('/'));
+        escapes.put(new Character('b'), new Character('\b'));
+        escapes.put(new Character('f'), new Character('\f'));
+        escapes.put(new Character('n'), new Character('\n'));
+        escapes.put(new Character('r'), new Character('\r'));
+        escapes.put(new Character('t'), new Character('\t'));
+    }
+
+    private CharacterIterator it;
+    private char c;
+    private Object token;
+    private StringBuilder buf = new StringBuilder();
+
+    private char next() {
+        this.c = this.it.next();
+
+        return this.c;
+    }
+
+    private void skipWhiteSpace() {
+        while (Character.isWhitespace(this.c)) {
+            this.next();
+        }
+    }
+
+    public Object read(String string) throws JSONException {
+        this.it = new StringCharacterIterator(string);
+        this.c = this.it.first();
+
+        return this.read();
+    }
+
+    private Object read() throws JSONException {
+        Object ret = null;
+
+        this.skipWhiteSpace();
+
+        if (this.c == '"') {
+            this.next();
+            ret = this.string('"');
+        } else if (this.c == '\'') {
+            this.next();
+            ret = this.string('\'');
+        } else if (this.c == '[') {
+            this.next();
+            ret = this.array();
+        } else if (this.c == ']') {
+            ret = ARRAY_END;
+            this.next();
+        } else if (this.c == ',') {
+            ret = COMMA;
+            this.next();
+        } else if (this.c == '{') {
+            this.next();
+            ret = this.object();
+        } else if (this.c == '}') {
+            ret = OBJECT_END;
+            this.next();
+        } else if (this.c == ':') {
+            ret = COLON;
+            this.next();
+        } else if ((this.c == 't') && (this.next() == 'r') && (this.next() == 'u') && (this.next() == 'e')) {
+            ret = Boolean.TRUE;
+            this.next();
+        } else if ((this.c == 'f') && (this.next() == 'a') && (this.next() == 'l') && (this.next() == 's')
+                && (this.next() == 'e')) {
+            ret = Boolean.FALSE;
+            this.next();
+        } else if ((this.c == 'n') && (this.next() == 'u') && (this.next() == 'l') && (this.next() == 'l')) {
+            ret = null;
+            this.next();
+        } else if (Character.isDigit(this.c) || (this.c == '-')) {
+            ret = this.number();
+        } else {
+            throw buildInvalidInputException();
+        }
+
+        this.token = ret;
+
+        return ret;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map object() throws JSONException {
+        Map ret = new HashMap();
+        Object next = this.read();
+        if (next != OBJECT_END) {
+            String key = (String) next;
+            while (this.token != OBJECT_END) {
+                this.read(); // should be a colon
+
+                if (this.token != OBJECT_END) {
+                    ret.put(key, this.read());
+
+                    if (this.read() == COMMA) {
+                        Object name = this.read();
+
+                        if (name instanceof String) {
+                            key = (String) name;
+                        } else
+                            throw buildInvalidInputException();
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    private JSONException buildInvalidInputException() {
+        return new JSONException("Input string is not well formed JSON (invalid char " + this.c + ")");
+    }
+
+    @SuppressWarnings("unchecked")
+    private List array() throws JSONException {
+        List ret = new ArrayList();
+        Object value = this.read();
+
+        while (this.token != ARRAY_END) {
+            ret.add(value);
+
+            Object read = this.read();
+            if (read == COMMA) {
+                value = this.read();
+            } else if (read != ARRAY_END) {
+                throw buildInvalidInputException();
+            }
+        }
+
+        return ret;
+    }
+
+    private Object number() {
+        this.buf.setLength(0);
+
+        if (this.c == '-') {
+            this.add();
+        }
+
+        this.addDigits();
+
+        if (this.c == '.') {
+            this.add();
+            this.addDigits();
+        }
+
+        if ((this.c == 'e') || (this.c == 'E')) {
+            this.add();
+
+            if ((this.c == '+') || (this.c == '-')) {
+                this.add();
+            }
+
+            this.addDigits();
+        }
+
+        return (this.buf.indexOf(".") >= 0) ? (Object) Double.parseDouble(this.buf.toString())
+                : (Object) Long.parseLong(this.buf.toString());
+    }
+
+    private Object string(char quote) {
+        this.buf.setLength(0);
+
+        while ((this.c != quote) && (this.c != CharacterIterator.DONE)) {
+            if (this.c == '\\') {
+                this.next();
+
+                if (this.c == 'u') {
+                    this.add(this.unicode());
+                } else {
+                    Object value = escapes.get(new Character(this.c));
+
+                    if (value != null) {
+                        this.add(((Character) value).charValue());
+                    }
+                }
+            } else {
+                this.add();
+            }
+        }
+
+        this.next();
+
+        return this.buf.toString();
+    }
+
+    private void add(char cc) {
+        this.buf.append(cc);
+        this.next();
+    }
+
+    private void add() {
+        this.add(this.c);
+    }
+
+    private void addDigits() {
+        while (Character.isDigit(this.c)) {
+            this.add();
+        }
+    }
+
+    private char unicode() {
+        int value = 0;
+
+        for (int i = 0; i < 4; ++i) {
+            switch (this.next()) {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                value = (value << 4) + (this.c - '0');
+
+                break;
+
+            case 'a':
+            case 'b':
+            case 'c':
+            case 'd':
+            case 'e':
+            case 'f':
+                value = (value << 4) + (this.c - 'W');
+
+                break;
+
+            case 'A':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'E':
+            case 'F':
+                value = (value << 4) + (this.c - '7');
+
+                break;
+            }
+        }
+
+        return (char) value;
+    }
+}

Added: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java?rev=799003&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java (added)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java Wed Jul 29 18:33:05 2009
@@ -0,0 +1,502 @@
+package org.apache.struts2.json;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.json.annotations.SMD;
+import org.apache.struts2.json.annotations.SMDMethod;
+import org.apache.struts2.json.annotations.SMDMethodParameter;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * <!-- START SNIPPET: description --> <p/> This result serializes an action
+ * into JSON. <p/> <!-- END SNIPPET: description --> <p/> <p/> <u>Result
+ * parameters:</u> <p/> <!-- START SNIPPET: parameters --> <p/>
+ * <ul>
+ * <p/>
+ * <li>excludeProperties - list of regular expressions matching the properties
+ * to be excluded. The regular expressions are evaluated against the OGNL
+ * expression representation of the properties. </li>
+ * <p/>
+ * </ul>
+ * <p/> <!-- END SNIPPET: parameters --> <p/> <b>Example:</b> <p/>
+ * 
+ * <pre>
+ * &lt;!-- START SNIPPET: example --&gt;
+ * &lt;result name=&quot;success&quot; type=&quot;json&quot; /&gt;
+ * &lt;!-- END SNIPPET: example --&gt;
+ * </pre>
+ */
+public class JSONResult implements Result {
+    private static final long serialVersionUID = 8624350183189931165L;
+    private static final Logger LOG = LoggerFactory.getLogger(JSONResult.class);
+
+    private String defaultEncoding = "ISO-8859-1";
+    private List<Pattern> includeProperties;
+    private List<Pattern> excludeProperties;
+    private String root;
+    private boolean wrapWithComments;
+    private boolean prefix;
+    private boolean enableSMD = false;
+    private boolean enableGZIP = false;
+    private boolean ignoreHierarchy = true;
+    private boolean ignoreInterfaces = true;
+    private boolean enumAsBean = JSONWriter.ENUM_AS_BEAN_DEFAULT;
+    private boolean noCache = false;
+    private boolean excludeNullProperties = false;
+    private int statusCode;
+    private int errorCode;
+    private String callbackParameter;
+    private String contentType;
+    private String wrapPrefix;
+    private String wrapSuffix;
+
+    @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
+    public void setDefaultEncoding(String val) {
+        this.defaultEncoding = val;
+    }
+
+    /**
+     * Gets a list of regular expressions of properties to exclude from the JSON
+     * output.
+     * 
+     * @return A list of compiled regular expression patterns
+     */
+    public List<Pattern> getExcludePropertiesList() {
+        return this.excludeProperties;
+    }
+
+    /**
+     * Sets a comma-delimited list of regular expressions to match properties
+     * that should be excluded from the JSON output.
+     * 
+     * @param commaDelim
+     *            A comma-delimited list of regular expressions
+     */
+    public void setExcludeProperties(String commaDelim) {
+        List<String> excludePatterns = JSONUtil.asList(commaDelim);
+        if (excludePatterns != null) {
+            this.excludeProperties = new ArrayList<Pattern>(excludePatterns.size());
+            for (String pattern : excludePatterns) {
+                this.excludeProperties.add(Pattern.compile(pattern));
+            }
+        }
+    }
+
+    /**
+     * @return the includeProperties
+     */
+    public List<Pattern> getIncludePropertiesList() {
+        return includeProperties;
+    }
+
+    /**
+     * @param includedProperties
+     *            the includeProperties to set
+     */
+    public void setIncludeProperties(String commaDelim) {
+        List<String> includePatterns = JSONUtil.asList(commaDelim);
+        if (includePatterns != null) {
+            this.includeProperties = new ArrayList<Pattern>(includePatterns.size());
+
+            HashMap existingPatterns = new HashMap();
+
+            for (String pattern : includePatterns) {
+                // Compile a pattern for each *unique* "level" of the object
+                // hierarchy specified in the regex.
+                String[] patternPieces = pattern.split("\\\\\\.");
+
+                String patternExpr = "";
+                for (String patternPiece : patternPieces) {
+                    if (patternExpr.length() > 0) {
+                        patternExpr += "\\.";
+                    }
+                    patternExpr += patternPiece;
+
+                    // Check for duplicate patterns so that there is no overlap.
+                    if (!existingPatterns.containsKey(patternExpr)) {
+                        existingPatterns.put(patternExpr, patternExpr);
+
+                        // Add a pattern that does not have the indexed property
+                        // matching (ie. list\[\d+\] becomes list).
+                        if (patternPiece.endsWith("\\]")) {
+                            this.includeProperties.add(Pattern.compile(patternExpr.substring(0, patternPiece
+                                    .lastIndexOf("\\["))));
+
+                            if (LOG.isDebugEnabled())
+                                LOG.debug("Adding include property expression:  "
+                                        + patternExpr.substring(0, patternPiece.lastIndexOf("\\[")));
+                        }
+
+                        this.includeProperties.add(Pattern.compile(patternExpr));
+
+                        if (LOG.isDebugEnabled())
+                            LOG.debug("Adding include property expression:  " + patternExpr);
+                    }
+                }
+            }
+        }
+    }
+
+    public void execute(ActionInvocation invocation) throws Exception {
+        ActionContext actionContext = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
+        HttpServletResponse response = (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE);
+
+        try {
+            String json;
+            Object rootObject;
+            if (this.enableSMD) {
+                // generate SMD
+                rootObject = this.writeSMD(invocation);
+            } else {
+                // generate JSON
+                if (this.root != null) {
+                    ValueStack stack = invocation.getStack();
+                    rootObject = stack.findValue(this.root);
+                } else {
+                    rootObject = invocation.getAction();
+                }
+            }
+            json = JSONUtil.serialize(rootObject, excludeProperties, includeProperties, ignoreHierarchy,
+                    enumAsBean, excludeNullProperties);
+            json = addCallbackIfApplicable(request, json);
+
+            boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);
+
+            writeToResponse(response, json, writeGzip);
+
+        } catch (IOException exception) {
+            LOG.error(exception.getMessage(), exception);
+            throw exception;
+        }
+    }
+
+    protected void writeToResponse(HttpServletResponse response, String json, boolean gzip)
+            throws IOException {
+        JSONUtil.writeJSONToResponse(new SerializationParams(response, getEncoding(), isWrapWithComments(),
+                json, false, gzip, noCache, statusCode, errorCode, prefix, contentType, wrapPrefix,
+                wrapSuffix));
+    }
+
+    @SuppressWarnings("unchecked")
+    protected org.apache.struts2.json.smd.SMD writeSMD(ActionInvocation invocation) {
+        ActionContext actionContext = invocation.getInvocationContext();
+        HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
+
+        // root is based on OGNL expression (action by default)
+        Object rootObject = null;
+        if (this.root != null) {
+            ValueStack stack = invocation.getStack();
+            rootObject = stack.findValue(this.root);
+        } else {
+            rootObject = invocation.getAction();
+        }
+
+        Class clazz = rootObject.getClass();
+        org.apache.struts2.json.smd.SMD smd = new org.apache.struts2.json.smd.SMD();
+        // URL
+        smd.setServiceUrl(request.getRequestURI());
+
+        // customize SMD
+        SMD smdAnnotation = (SMD) clazz.getAnnotation(SMD.class);
+        if (smdAnnotation != null) {
+            smd.setObjectName(smdAnnotation.objectName());
+            smd.setServiceType(smdAnnotation.serviceType());
+            smd.setVersion(smdAnnotation.version());
+        }
+
+        // get public methods
+        Method[] methods = JSONUtil.listSMDMethods(clazz, ignoreInterfaces);
+
+        for (Method method : methods) {
+            SMDMethod smdMethodAnnotation = method.getAnnotation(SMDMethod.class);
+
+            // SMDMethod annotation is required
+            if (((smdMethodAnnotation != null) && !this.shouldExcludeProperty(method.getName()))) {
+                String methodName = smdMethodAnnotation.name().length() == 0 ? method.getName()
+                        : smdMethodAnnotation.name();
+
+                org.apache.struts2.json.smd.SMDMethod smdMethod = new org.apache.struts2.json.smd.SMDMethod(
+                        methodName);
+                smd.addSMDMethod(smdMethod);
+
+                // find params for this method
+                int parametersCount = method.getParameterTypes().length;
+                if (parametersCount > 0) {
+                    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+
+                    for (int i = 0; i < parametersCount; i++) {
+                        // are you ever going to pick shorter names? nope
+                        SMDMethodParameter smdMethodParameterAnnotation = this
+                                .getSMDMethodParameterAnnotation(parameterAnnotations[i]);
+
+                        String paramName = smdMethodParameterAnnotation != null ? smdMethodParameterAnnotation
+                                .name()
+                                : "p" + i;
+
+                        // goog thing this is the end of the hierarchy,
+                        // oitherwise I would need that 21'' LCD ;)
+                        smdMethod.addSMDMethodParameter(new org.apache.struts2.json.smd.SMDMethodParameter(
+                                paramName));
+                    }
+                }
+
+            } else {
+                if (LOG.isDebugEnabled())
+                    LOG.debug("Ignoring property " + method.getName());
+            }
+        }
+        return smd;
+    }
+
+    /**
+     * Find an SMDethodParameter annotation on this array
+     */
+    private org.apache.struts2.json.annotations.SMDMethodParameter getSMDMethodParameterAnnotation(
+            Annotation[] annotations) {
+        for (Annotation annotation : annotations) {
+            if (annotation instanceof org.apache.struts2.json.annotations.SMDMethodParameter)
+                return (org.apache.struts2.json.annotations.SMDMethodParameter) annotation;
+        }
+
+        return null;
+    }
+
+    private boolean shouldExcludeProperty(String expr) {
+        if (this.excludeProperties != null) {
+            for (Pattern pattern : this.excludeProperties) {
+                if (pattern.matcher(expr).matches())
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Retrieve the encoding <p/>
+     * 
+     * @return The encoding associated with this template (defaults to the value
+     *         of 'struts.i18n.encoding' property)
+     */
+    protected String getEncoding() {
+        String encoding = this.defaultEncoding;
+
+        if (encoding == null) {
+            encoding = System.getProperty("file.encoding");
+        }
+
+        if (encoding == null) {
+            encoding = "UTF-8";
+        }
+
+        return encoding;
+    }
+
+    protected String addCallbackIfApplicable(HttpServletRequest request, String json) {
+        if ((callbackParameter != null) && (callbackParameter.length() > 0)) {
+            String callbackName = request.getParameter(callbackParameter);
+            if ((callbackName != null) && (callbackName.length() > 0))
+                json = callbackName + "(" + json + ")";
+        }
+        return json;
+    }
+
+    /**
+     * @return OGNL expression of root object to be serialized
+     */
+    public String getRoot() {
+        return this.root;
+    }
+
+    /**
+     * Sets the root object to be serialized, defaults to the Action
+     * 
+     * @param root
+     *            OGNL expression of root object to be serialized
+     */
+    public void setRoot(String root) {
+        this.root = root;
+    }
+
+    /**
+     * @return Generated JSON must be enclosed in comments
+     */
+    public boolean isWrapWithComments() {
+        return this.wrapWithComments;
+    }
+
+    /**
+     * Wrap generated JSON with comments
+     * 
+     * @param wrapWithComments
+     */
+    public void setWrapWithComments(boolean wrapWithComments) {
+        this.wrapWithComments = wrapWithComments;
+    }
+
+    /**
+     * @return Result has SMD generation enabled
+     */
+    public boolean isEnableSMD() {
+        return this.enableSMD;
+    }
+
+    /**
+     * Enable SMD generation for action, which can be used for JSON-RPC
+     * 
+     * @param enableSMD
+     */
+    public void setEnableSMD(boolean enableSMD) {
+        this.enableSMD = enableSMD;
+    }
+
+    public void setIgnoreHierarchy(boolean ignoreHierarchy) {
+        this.ignoreHierarchy = ignoreHierarchy;
+    }
+
+    /**
+     * Controls whether interfaces should be inspected for method annotations
+     * You may need to set to this true if your action is a proxy as annotations
+     * on methods are not inherited
+     */
+    public void setIgnoreInterfaces(boolean ignoreInterfaces) {
+        this.ignoreInterfaces = ignoreInterfaces;
+    }
+
+    /**
+     * Controls how Enum's are serialized : If true, an Enum is serialized as a
+     * name=value pair (name=name()) (default) If false, an Enum is serialized
+     * as a bean with a special property _name=name()
+     * 
+     * @param enumAsBean
+     */
+    public void setEnumAsBean(boolean enumAsBean) {
+        this.enumAsBean = enumAsBean;
+    }
+
+    public boolean isEnumAsBean() {
+        return enumAsBean;
+    }
+
+    public boolean isEnableGZIP() {
+        return enableGZIP;
+    }
+
+    public void setEnableGZIP(boolean enableGZIP) {
+        this.enableGZIP = enableGZIP;
+    }
+
+    public boolean isNoCache() {
+        return noCache;
+    }
+
+    /**
+     * Add headers to response to prevent the browser from caching the response
+     * 
+     * @param noCache
+     */
+    public void setNoCache(boolean noCache) {
+        this.noCache = noCache;
+    }
+
+    public boolean isIgnoreHierarchy() {
+        return ignoreHierarchy;
+    }
+
+    public boolean isExcludeNullProperties() {
+        return excludeNullProperties;
+    }
+
+    /**
+     * Do not serialize properties with a null value
+     * 
+     * @param excludeNullProperties
+     */
+    public void setExcludeNullProperties(boolean excludeNullProperties) {
+        this.excludeNullProperties = excludeNullProperties;
+    }
+
+    /**
+     * Status code to be set in the response
+     * 
+     * @param statusCode
+     */
+    public void setStatusCode(int statusCode) {
+        this.statusCode = statusCode;
+    }
+
+    /**
+     * Error code to be set in the response
+     * 
+     * @param errorCode
+     */
+    public void setErrorCode(int errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    public void setCallbackParameter(String callbackParameter) {
+        this.callbackParameter = callbackParameter;
+    }
+
+    public String getCallbackParameter() {
+        return callbackParameter;
+    }
+
+    /**
+     * Prefix JSON with "{} &&"
+     * 
+     * @param prefix
+     */
+    public void setPrefix(boolean prefix) {
+        this.prefix = prefix;
+    }
+
+    /**
+     * Content type to be set in the response
+     * 
+     * @param contentType
+     */
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    public String getWrapPrefix() {
+        return wrapPrefix;
+    }
+
+    /**
+     * Text to be inserted at the begining of the response
+     */
+    public void setWrapPrefix(String wrapPrefix) {
+        this.wrapPrefix = wrapPrefix;
+    }
+
+    public String getWrapSuffix() {
+        return wrapSuffix;
+    }
+
+    /**
+     * Text to be inserted at the end of the response
+     */
+    public void setWrapSuffix(String wrapSuffix) {
+        this.wrapSuffix = wrapSuffix;
+    }
+}



Mime
View raw message