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>
+ * <!-- START SNIPPET: example -->
+ * <result name="success" type="json" />
+ * <!-- END SNIPPET: example -->
+ * </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;
+ }
+}
|