You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2009/07/30 00:44:29 UTC
svn commit: r799110 [3/7] - in /struts/sandbox/trunk/struts2-json-plugin: ./
src/main/java/org/apache/struts2/json/
src/main/java/org/apache/struts2/json/annotations/
src/main/java/org/apache/struts2/json/rpc/
src/main/java/org/apache/struts2/json/smd/...
Modified: 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=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java Wed Jul 29 22:44:26 2009
@@ -1,502 +1,522 @@
-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;
- }
-}
+/*
+ * $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.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;
+ }
+}
Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONResult.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java Wed Jul 29 22:44:26 2009
@@ -1,395 +1,395 @@
-/*
- * $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.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.regex.Pattern;
-import java.util.zip.GZIPOutputStream;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang.xwork.StringUtils;
-import org.apache.struts2.json.annotations.SMDMethod;
-
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
-
-/**
- * Wrapper for JSONWriter with some utility methods.
- */
-public class JSONUtil {
- final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
- private static final Logger LOG = LoggerFactory.getLogger(JSONUtil.class);
-
- /**
- * Serializes an object into JSON.
- *
- * @param object
- * to be serialized
- * @return JSON string
- * @throws JSONException
- */
- public static String serialize(Object object) throws JSONException {
- JSONWriter writer = new JSONWriter();
-
- return writer.write(object);
- }
-
- /**
- * Serializes an object into JSON, excluding any properties matching any of
- * the regular expressions in the given collection.
- *
- * @param object
- * to be serialized
- * @param excludeProperties
- * Patterns matching properties to exclude
- * @param ignoreHierarchy
- * whether to ignore properties defined on base classes of the
- * root object
- * @return JSON string
- * @throws JSONException
- */
- public static String serialize(Object object, Collection<Pattern> excludeProperties,
- Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties)
- throws JSONException {
- JSONWriter writer = new JSONWriter();
- writer.setIgnoreHierarchy(ignoreHierarchy);
- return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
- }
-
- /**
- * Serializes an object into JSON, excluding any properties matching any of
- * the regular expressions in the given collection.
- *
- * @param object
- * to be serialized
- * @param excludeProperties
- * Patterns matching properties to exclude
- * @param ignoreHierarchy
- * whether to ignore properties defined on base classes of the
- * root object
- * @param enumAsBean
- * whether to serialized enums a Bean or name=value pair
- * @return JSON string
- * @throws JSONException
- */
- public static String serialize(Object object, Collection<Pattern> excludeProperties,
- Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
- boolean excludeNullProperties) throws JSONException {
- JSONWriter writer = new JSONWriter();
- writer.setIgnoreHierarchy(ignoreHierarchy);
- writer.setEnumAsBean(enumAsBean);
- return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
- }
-
- /**
- * Serializes an object into JSON to the given writer.
- *
- * @param writer
- * Writer to serialize the object to
- * @param object
- * object to be serialized
- * @throws IOException
- * @throws JSONException
- */
- public static void serialize(Writer writer, Object object) throws IOException, JSONException {
- writer.write(serialize(object));
- }
-
- /**
- * Serializes an object into JSON to the given writer, excluding any
- * properties matching any of the regular expressions in the given
- * collection.
- *
- * @param writer
- * Writer to serialize the object to
- * @param object
- * object to be serialized
- * @param excludeProperties
- * Patterns matching properties to ignore
- * @throws IOException
- * @throws JSONException
- */
- public static void serialize(Writer writer, Object object, Collection<Pattern> excludeProperties,
- Collection<Pattern> includeProperties, boolean excludeNullProperties) throws IOException,
- JSONException {
- writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties));
- }
-
- /**
- * Deserializes a object from JSON
- *
- * @param json
- * string in JSON
- * @return desrialized object
- * @throws JSONException
- */
- public static Object deserialize(String json) throws JSONException {
- JSONReader reader = new JSONReader();
- return reader.read(json);
- }
-
- /**
- * Deserializes a object from JSON
- *
- * @param reader
- * Reader to read a JSON string from
- * @return deserialized object
- * @throws JSONException
- * when IOException happens
- */
- public static Object deserialize(Reader reader) throws JSONException {
- // read content
- BufferedReader bufferReader = new BufferedReader(reader);
- String line = null;
- StringBuilder buffer = new StringBuilder();
-
- try {
- while ((line = bufferReader.readLine()) != null) {
- buffer.append(line);
- }
- } catch (IOException e) {
- throw new JSONException(e);
- }
-
- return deserialize(buffer.toString());
- }
-
- public static void writeJSONToResponse(SerializationParams serializationParams) throws IOException {
- StringBuilder stringBuilder = new StringBuilder();
- if (StringUtils.isNotBlank(serializationParams.getSerializedJSON()))
- stringBuilder.append(serializationParams.getSerializedJSON());
-
- if (StringUtils.isNotBlank(serializationParams.getWrapPrefix()))
- stringBuilder.insert(0, serializationParams.getWrapPrefix());
- else if (serializationParams.isWrapWithComments()) {
- stringBuilder.insert(0, "/* ");
- stringBuilder.append(" */");
- } else if (serializationParams.isPrefix())
- stringBuilder.insert(0, "{}&& ");
-
- if (StringUtils.isNotBlank(serializationParams.getWrapSuffix()))
- stringBuilder.append(serializationParams.getWrapSuffix());
-
- String json = stringBuilder.toString();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("[JSON]" + json);
- }
-
- HttpServletResponse response = serializationParams.getResponse();
-
- // status or error code
- if (serializationParams.getStatusCode() > 0)
- response.setStatus(serializationParams.getStatusCode());
- else if (serializationParams.getErrorCode() > 0)
- response.sendError(serializationParams.getErrorCode());
-
- // content type
- if (serializationParams.isSmd())
- response.setContentType("application/json-rpc;charset=" + serializationParams.getEncoding());
- else
- response.setContentType(serializationParams.getContentType() + ";charset="
- + serializationParams.getEncoding());
-
- if (serializationParams.isNoCache()) {
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Expires", "0");
- response.setHeader("Pragma", "No-cache");
- }
-
- if (serializationParams.isGzip()) {
- response.addHeader("Content-Encoding", "gzip");
- GZIPOutputStream out = null;
- InputStream in = null;
- try {
- out = new GZIPOutputStream(response.getOutputStream());
- in = new ByteArrayInputStream(json.getBytes());
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0) {
- out.write(buf, 0, len);
- }
- } finally {
- if (in != null)
- in.close();
- if (out != null) {
- out.finish();
- out.close();
- }
- }
-
- } else {
- response.setContentLength(json.getBytes(serializationParams.getEncoding()).length);
- PrintWriter out = response.getWriter();
- out.print(json);
- }
- }
-
- public static List<String> asList(String commaDelim) {
- if ((commaDelim == null) || (commaDelim.trim().length() == 0))
- return null;
- List<String> list = new ArrayList<String>();
- String[] split = commaDelim.split(",");
- for (int i = 0; i < split.length; i++) {
- String trimmed = split[i].trim();
- if (trimmed.length() > 0) {
- list.add(trimmed);
- }
- }
- return list;
- }
-
- /**
- * List visible methods carrying the
- *
- * @SMDMethod annotation
- *
- * @param ignoreInterfaces
- * if true, only the methods of the class are examined. If false,
- * annotations on every interfaces' methods are examined.
- */
- @SuppressWarnings("unchecked")
- public static Method[] listSMDMethods(Class clazz, boolean ignoreInterfaces) {
- final List<Method> methods = new LinkedList<Method>();
- if (ignoreInterfaces) {
- for (Method method : clazz.getMethods()) {
- SMDMethod smdMethodAnnotation = method.getAnnotation(SMDMethod.class);
- if (smdMethodAnnotation != null) {
- methods.add(method);
- }
- }
- } else {
- // recurse the entire superclass/interface hierarchy and add in
- // order encountered
- JSONUtil.visitInterfaces(clazz, new JSONUtil.ClassVisitor() {
- public boolean visit(Class aClass) {
- for (Method method : aClass.getMethods()) {
- SMDMethod smdMethodAnnotation = method.getAnnotation(SMDMethod.class);
- if ((smdMethodAnnotation != null) && !methods.contains(method)) {
- methods.add(method);
- }
- }
- return true;
- }
- });
- }
-
- Method[] methodResult = new Method[methods.size()];
- return methods.toArray(methodResult);
- }
-
- /**
- * Realizes the visit(Class) method called by vistInterfaces for all
- * encountered classes/interfaces
- */
- public static interface ClassVisitor {
-
- /**
- * Called when a new interface/class is encountered
- *
- * @param aClass
- * the encountered class/interface
- * @return true if the recursion should continue, false to stop
- * recursion immediately
- */
- @SuppressWarnings("unchecked")
- boolean visit(Class aClass);
- }
-
- /**
- * Visit all the interfaces realized by the specified object, its
- * superclasses and its interfaces <p/> Visitation is performed in the
- * following order: aClass aClass' interfaces the interface's superclasses
- * (interfaces) aClass' superclass superclass' interfaces superclass'
- * interface's superclasses (interfaces) super-superclass and so on <p/> The
- * Object base class is base excluded. Classes/interfaces are only visited
- * once each
- *
- * @param aClass
- * the class to start recursing upwards from
- * @param visitor
- * this vistor is called for each class/interface encountered
- * @return true if all classes/interfaces were visited, false if it was
- * exited early as specified by a ClassVisitor result
- */
- @SuppressWarnings("unchecked")
- public static boolean visitInterfaces(Class aClass, ClassVisitor visitor) {
- List<Class> classesVisited = new LinkedList<Class>();
- return visitUniqueInterfaces(aClass, visitor, classesVisited);
- }
-
- /**
- * Recursive method to visit all the interfaces of a class (and its
- * superclasses and super-interfaces) if they haven't already been visited.
- * <p/> Always visits itself if it hasn't already been visited
- *
- * @param thisClass
- * the current class to visit (if not already done so)
- * @param classesVisited
- * classes already visited
- * @param visitor
- * this vistor is called for each class/interface encountered
- * @return true if recursion can continue, false if it should be aborted
- */
- private static boolean visitUniqueInterfaces(Class thisClass, ClassVisitor visitor,
- List<Class> classesVisited) {
- boolean okayToContinue = true;
-
- if (!classesVisited.contains(thisClass)) {
- classesVisited.add(thisClass);
- okayToContinue = visitor.visit(thisClass);
-
- if (okayToContinue) {
- Class[] interfaces = thisClass.getInterfaces();
- int index = 0;
- while ((index < interfaces.length) && (okayToContinue)) {
- okayToContinue = visitUniqueInterfaces(interfaces[index++], visitor, classesVisited);
- }
-
- if (okayToContinue) {
- Class superClass = thisClass.getSuperclass();
- if ((superClass != null) && (!Object.class.equals(superClass))) {
- okayToContinue = visitUniqueInterfaces(superClass, visitor, classesVisited);
- }
- }
- }
- }
- return okayToContinue;
- }
-
- public static boolean isGzipInRequest(HttpServletRequest request) {
- String header = request.getHeader("Accept-Encoding");
- return (header != null) && (header.indexOf("gzip") >= 0);
- }
-}
+/*
+ * $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.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPOutputStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.xwork.StringUtils;
+import org.apache.struts2.json.annotations.SMDMethod;
+
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * Wrapper for JSONWriter with some utility methods.
+ */
+public class JSONUtil {
+ final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
+ private static final Logger LOG = LoggerFactory.getLogger(JSONUtil.class);
+
+ /**
+ * Serializes an object into JSON.
+ *
+ * @param object
+ * to be serialized
+ * @return JSON string
+ * @throws JSONException
+ */
+ public static String serialize(Object object) throws JSONException {
+ JSONWriter writer = new JSONWriter();
+
+ return writer.write(object);
+ }
+
+ /**
+ * Serializes an object into JSON, excluding any properties matching any of
+ * the regular expressions in the given collection.
+ *
+ * @param object
+ * to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to exclude
+ * @param ignoreHierarchy
+ * whether to ignore properties defined on base classes of the
+ * root object
+ * @return JSON string
+ * @throws JSONException
+ */
+ public static String serialize(Object object, Collection<Pattern> excludeProperties,
+ Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties)
+ throws JSONException {
+ JSONWriter writer = new JSONWriter();
+ writer.setIgnoreHierarchy(ignoreHierarchy);
+ return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
+ }
+
+ /**
+ * Serializes an object into JSON, excluding any properties matching any of
+ * the regular expressions in the given collection.
+ *
+ * @param object
+ * to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to exclude
+ * @param ignoreHierarchy
+ * whether to ignore properties defined on base classes of the
+ * root object
+ * @param enumAsBean
+ * whether to serialized enums a Bean or name=value pair
+ * @return JSON string
+ * @throws JSONException
+ */
+ public static String serialize(Object object, Collection<Pattern> excludeProperties,
+ Collection<Pattern> includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
+ boolean excludeNullProperties) throws JSONException {
+ JSONWriter writer = new JSONWriter();
+ writer.setIgnoreHierarchy(ignoreHierarchy);
+ writer.setEnumAsBean(enumAsBean);
+ return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
+ }
+
+ /**
+ * Serializes an object into JSON to the given writer.
+ *
+ * @param writer
+ * Writer to serialize the object to
+ * @param object
+ * object to be serialized
+ * @throws IOException
+ * @throws JSONException
+ */
+ public static void serialize(Writer writer, Object object) throws IOException, JSONException {
+ writer.write(serialize(object));
+ }
+
+ /**
+ * Serializes an object into JSON to the given writer, excluding any
+ * properties matching any of the regular expressions in the given
+ * collection.
+ *
+ * @param writer
+ * Writer to serialize the object to
+ * @param object
+ * object to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to ignore
+ * @throws IOException
+ * @throws JSONException
+ */
+ public static void serialize(Writer writer, Object object, Collection<Pattern> excludeProperties,
+ Collection<Pattern> includeProperties, boolean excludeNullProperties) throws IOException,
+ JSONException {
+ writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties));
+ }
+
+ /**
+ * Deserializes a object from JSON
+ *
+ * @param json
+ * string in JSON
+ * @return desrialized object
+ * @throws JSONException
+ */
+ public static Object deserialize(String json) throws JSONException {
+ JSONReader reader = new JSONReader();
+ return reader.read(json);
+ }
+
+ /**
+ * Deserializes a object from JSON
+ *
+ * @param reader
+ * Reader to read a JSON string from
+ * @return deserialized object
+ * @throws JSONException
+ * when IOException happens
+ */
+ public static Object deserialize(Reader reader) throws JSONException {
+ // read content
+ BufferedReader bufferReader = new BufferedReader(reader);
+ String line = null;
+ StringBuilder buffer = new StringBuilder();
+
+ try {
+ while ((line = bufferReader.readLine()) != null) {
+ buffer.append(line);
+ }
+ } catch (IOException e) {
+ throw new JSONException(e);
+ }
+
+ return deserialize(buffer.toString());
+ }
+
+ public static void writeJSONToResponse(SerializationParams serializationParams) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ if (StringUtils.isNotBlank(serializationParams.getSerializedJSON()))
+ stringBuilder.append(serializationParams.getSerializedJSON());
+
+ if (StringUtils.isNotBlank(serializationParams.getWrapPrefix()))
+ stringBuilder.insert(0, serializationParams.getWrapPrefix());
+ else if (serializationParams.isWrapWithComments()) {
+ stringBuilder.insert(0, "/* ");
+ stringBuilder.append(" */");
+ } else if (serializationParams.isPrefix())
+ stringBuilder.insert(0, "{}&& ");
+
+ if (StringUtils.isNotBlank(serializationParams.getWrapSuffix()))
+ stringBuilder.append(serializationParams.getWrapSuffix());
+
+ String json = stringBuilder.toString();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("[JSON]" + json);
+ }
+
+ HttpServletResponse response = serializationParams.getResponse();
+
+ // status or error code
+ if (serializationParams.getStatusCode() > 0)
+ response.setStatus(serializationParams.getStatusCode());
+ else if (serializationParams.getErrorCode() > 0)
+ response.sendError(serializationParams.getErrorCode());
+
+ // content type
+ if (serializationParams.isSmd())
+ response.setContentType("application/json-rpc;charset=" + serializationParams.getEncoding());
+ else
+ response.setContentType(serializationParams.getContentType() + ";charset="
+ + serializationParams.getEncoding());
+
+ if (serializationParams.isNoCache()) {
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("Expires", "0");
+ response.setHeader("Pragma", "No-cache");
+ }
+
+ if (serializationParams.isGzip()) {
+ response.addHeader("Content-Encoding", "gzip");
+ GZIPOutputStream out = null;
+ InputStream in = null;
+ try {
+ out = new GZIPOutputStream(response.getOutputStream());
+ in = new ByteArrayInputStream(json.getBytes());
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ } finally {
+ if (in != null)
+ in.close();
+ if (out != null) {
+ out.finish();
+ out.close();
+ }
+ }
+
+ } else {
+ response.setContentLength(json.getBytes(serializationParams.getEncoding()).length);
+ PrintWriter out = response.getWriter();
+ out.print(json);
+ }
+ }
+
+ public static List<String> asList(String commaDelim) {
+ if ((commaDelim == null) || (commaDelim.trim().length() == 0))
+ return null;
+ List<String> list = new ArrayList<String>();
+ String[] split = commaDelim.split(",");
+ for (int i = 0; i < split.length; i++) {
+ String trimmed = split[i].trim();
+ if (trimmed.length() > 0) {
+ list.add(trimmed);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * List visible methods carrying the
+ *
+ * @SMDMethod annotation
+ *
+ * @param ignoreInterfaces
+ * if true, only the methods of the class are examined. If false,
+ * annotations on every interfaces' methods are examined.
+ */
+ @SuppressWarnings("unchecked")
+ public static Method[] listSMDMethods(Class clazz, boolean ignoreInterfaces) {
+ final List<Method> methods = new LinkedList<Method>();
+ if (ignoreInterfaces) {
+ for (Method method : clazz.getMethods()) {
+ SMDMethod smdMethodAnnotation = method.getAnnotation(SMDMethod.class);
+ if (smdMethodAnnotation != null) {
+ methods.add(method);
+ }
+ }
+ } else {
+ // recurse the entire superclass/interface hierarchy and add in
+ // order encountered
+ JSONUtil.visitInterfaces(clazz, new JSONUtil.ClassVisitor() {
+ public boolean visit(Class aClass) {
+ for (Method method : aClass.getMethods()) {
+ SMDMethod smdMethodAnnotation = method.getAnnotation(SMDMethod.class);
+ if ((smdMethodAnnotation != null) && !methods.contains(method)) {
+ methods.add(method);
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ Method[] methodResult = new Method[methods.size()];
+ return methods.toArray(methodResult);
+ }
+
+ /**
+ * Realizes the visit(Class) method called by vistInterfaces for all
+ * encountered classes/interfaces
+ */
+ public static interface ClassVisitor {
+
+ /**
+ * Called when a new interface/class is encountered
+ *
+ * @param aClass
+ * the encountered class/interface
+ * @return true if the recursion should continue, false to stop
+ * recursion immediately
+ */
+ @SuppressWarnings("unchecked")
+ boolean visit(Class aClass);
+ }
+
+ /**
+ * Visit all the interfaces realized by the specified object, its
+ * superclasses and its interfaces <p/> Visitation is performed in the
+ * following order: aClass aClass' interfaces the interface's superclasses
+ * (interfaces) aClass' superclass superclass' interfaces superclass'
+ * interface's superclasses (interfaces) super-superclass and so on <p/> The
+ * Object base class is base excluded. Classes/interfaces are only visited
+ * once each
+ *
+ * @param aClass
+ * the class to start recursing upwards from
+ * @param visitor
+ * this vistor is called for each class/interface encountered
+ * @return true if all classes/interfaces were visited, false if it was
+ * exited early as specified by a ClassVisitor result
+ */
+ @SuppressWarnings("unchecked")
+ public static boolean visitInterfaces(Class aClass, ClassVisitor visitor) {
+ List<Class> classesVisited = new LinkedList<Class>();
+ return visitUniqueInterfaces(aClass, visitor, classesVisited);
+ }
+
+ /**
+ * Recursive method to visit all the interfaces of a class (and its
+ * superclasses and super-interfaces) if they haven't already been visited.
+ * <p/> Always visits itself if it hasn't already been visited
+ *
+ * @param thisClass
+ * the current class to visit (if not already done so)
+ * @param classesVisited
+ * classes already visited
+ * @param visitor
+ * this vistor is called for each class/interface encountered
+ * @return true if recursion can continue, false if it should be aborted
+ */
+ private static boolean visitUniqueInterfaces(Class thisClass, ClassVisitor visitor,
+ List<Class> classesVisited) {
+ boolean okayToContinue = true;
+
+ if (!classesVisited.contains(thisClass)) {
+ classesVisited.add(thisClass);
+ okayToContinue = visitor.visit(thisClass);
+
+ if (okayToContinue) {
+ Class[] interfaces = thisClass.getInterfaces();
+ int index = 0;
+ while ((index < interfaces.length) && (okayToContinue)) {
+ okayToContinue = visitUniqueInterfaces(interfaces[index++], visitor, classesVisited);
+ }
+
+ if (okayToContinue) {
+ Class superClass = thisClass.getSuperclass();
+ if ((superClass != null) && (!Object.class.equals(superClass))) {
+ okayToContinue = visitUniqueInterfaces(superClass, visitor, classesVisited);
+ }
+ }
+ }
+ }
+ return okayToContinue;
+ }
+
+ public static boolean isGzipInRequest(HttpServletRequest request) {
+ String header = request.getHeader("Accept-Encoding");
+ return (header != null) && (header.indexOf("gzip") >= 0);
+ }
+}
Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONUtil.java
------------------------------------------------------------------------------
svn:keywords = Id