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 [4/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/JSONWriter.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java Wed Jul 29 22:44:26 2009
@@ -1,549 +1,549 @@
-/*
- * $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.beans.BeanInfo;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.text.CharacterIterator;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.text.StringCharacterIterator;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Stack;
-import java.util.regex.Pattern;
-
-import org.apache.struts2.json.annotations.JSON;
-
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
-
-/**
- * <p>
- * Serializes an object into JavaScript Object Notation (JSON). If cyclic
- * references are detected they will be nulled out.
- * </p>
- */
-class JSONWriter {
-    private static final Logger LOG = LoggerFactory.getLogger(JSONWriter.class);
-
-    /**
-     * By default, enums are serialzied as name=value pairs
-     */
-    public static final boolean ENUM_AS_BEAN_DEFAULT = false;
-
-    static char[] hex = "0123456789ABCDEF".toCharArray();
-    private StringBuilder buf = new StringBuilder();
-    private Stack stack = new Stack();
-    private boolean ignoreHierarchy = true;
-    private Object root;
-    private boolean buildExpr = true;
-    private String exprStack = "";
-    private Collection<Pattern> excludeProperties;
-    private Collection<Pattern> includeProperties;
-    private DateFormat formatter;
-    private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
-    private boolean excludeNullProperties;
-
-    /**
-     * @param object
-     *            Object to be serialized into JSON
-     * @return JSON string for object
-     * @throws JSONException
-     */
-    public String write(Object object) throws JSONException {
-        return this.write(object, null, null, false);
-    }
-
-    /**
-     * @param object
-     *            Object to be serialized into JSON
-     * @return JSON string for object
-     * @throws JSONException
-     */
-    public String write(Object object, Collection<Pattern> excludeProperties,
-            Collection<Pattern> includeProperties, boolean excludeNullProperties) throws JSONException {
-        this.excludeNullProperties = excludeNullProperties;
-        this.buf.setLength(0);
-        this.root = object;
-        this.exprStack = "";
-        this.buildExpr = ((excludeProperties != null) && !excludeProperties.isEmpty())
-                || ((includeProperties != null) && !includeProperties.isEmpty());
-        this.excludeProperties = excludeProperties;
-        this.includeProperties = includeProperties;
-        this.value(object, null);
-
-        return this.buf.toString();
-    }
-
-    /**
-     * Detect cyclic references
-     */
-    private void value(Object object, Method method) throws JSONException {
-        if (object == null) {
-            this.add("null");
-
-            return;
-        }
-
-        if (this.stack.contains(object)) {
-            Class clazz = object.getClass();
-
-            // cyclic reference
-            if (clazz.isPrimitive() || clazz.equals(String.class)) {
-                this.process(object, method);
-            } else {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Cyclic reference detected on " + object);
-                }
-
-                this.add("null");
-            }
-
-            return;
-        }
-
-        this.process(object, method);
-    }
-
-    /**
-     * Serialize object into json
-     */
-    private void process(Object object, Method method) throws JSONException {
-        this.stack.push(object);
-
-        if (object instanceof Class) {
-            this.string(object);
-        } else if (object instanceof Boolean) {
-            this.bool(((Boolean) object).booleanValue());
-        } else if (object instanceof Number) {
-            this.add(object);
-        } else if (object instanceof String) {
-            this.string(object);
-        } else if (object instanceof Character) {
-            this.string(object);
-        } else if (object instanceof Map) {
-            this.map((Map) object, method);
-        } else if (object.getClass().isArray()) {
-            this.array(object, method);
-        } else if (object instanceof Iterable) {
-            this.array(((Iterable) object).iterator(), method);
-        } else if (object instanceof Date) {
-            this.date((Date) object, method);
-        } else if (object instanceof Calendar) {
-            this.date(((Calendar) object).getTime(), method);
-        } else if (object instanceof Locale) {
-            this.string(object);
-        } else if (object instanceof Enum) {
-            this.enumeration((Enum) object);
-        } else {
-            this.bean(object);
-        }
-
-        this.stack.pop();
-    }
-
-    /**
-     * Instrospect bean and serialize its properties
-     */
-    private void bean(Object object) throws JSONException {
-        this.add("{");
-
-        BeanInfo info;
-
-        try {
-            Class clazz = object.getClass();
-
-            info = ((object == this.root) && this.ignoreHierarchy) ? Introspector.getBeanInfo(clazz, clazz
-                    .getSuperclass()) : Introspector.getBeanInfo(clazz);
-
-            PropertyDescriptor[] props = info.getPropertyDescriptors();
-
-            boolean hasData = false;
-            for (int i = 0; i < props.length; ++i) {
-                PropertyDescriptor prop = props[i];
-                String name = prop.getName();
-                Method accessor = prop.getReadMethod();
-                Method baseAccessor = null;
-                if (clazz.getName().indexOf("$$EnhancerByCGLIB$$") > -1) {
-                    try {
-                        baseAccessor = Class.forName(
-                                clazz.getName().substring(0, clazz.getName().indexOf("$$"))).getMethod(
-                                accessor.getName(), accessor.getParameterTypes());
-                    } catch (Exception ex) {
-                        LOG.debug(ex.getMessage(), ex);
-                    }
-                } else
-                    baseAccessor = accessor;
-
-                if (baseAccessor != null) {
-
-                    JSON json = baseAccessor.getAnnotation(JSON.class);
-                    if (json != null) {
-                        if (!json.serialize())
-                            continue;
-                        else if (json.name().length() > 0)
-                            name = json.name();
-                    }
-
-                    // ignore "class" and others
-                    if (this.shouldExcludeProperty(clazz, prop)) {
-                        continue;
-                    }
-                    String expr = null;
-                    if (this.buildExpr) {
-                        expr = this.expandExpr(name);
-                        if (this.shouldExcludeProperty(expr)) {
-                            continue;
-                        }
-                        expr = this.setExprStack(expr);
-                    }
-
-                    Object value = accessor.invoke(object, new Object[0]);
-                    boolean propertyPrinted = this.add(name, value, accessor, hasData);
-                    hasData = hasData || propertyPrinted;
-                    if (this.buildExpr) {
-                        this.setExprStack(expr);
-                    }
-                }
-            }
-
-            // special-case handling for an Enumeration - include the name() as
-            // a property */
-            if (object instanceof Enum) {
-                Object value = ((Enum) object).name();
-                this.add("_name", value, object.getClass().getMethod("name"), hasData);
-            }
-        } catch (Exception e) {
-            throw new JSONException(e);
-        }
-
-        this.add("}");
-    }
-
-    /**
-     * Instrospect an Enum and serialize it as a name/value pair or as a bean
-     * including all its own properties
-     */
-    private void enumeration(Enum enumeration) throws JSONException {
-        if (enumAsBean) {
-            this.bean(enumeration);
-        } else {
-            this.string(enumeration.name());
-        }
-    }
-
-    /**
-     * Ignore "class" field
-     */
-    private boolean shouldExcludeProperty(Class clazz, PropertyDescriptor prop) throws SecurityException,
-            NoSuchFieldException {
-        String name = prop.getName();
-
-        if (name.equals("class") || name.equals("declaringClass") || name.equals("cachedSuperClass")
-                || name.equals("metaClass")) {
-            return true;
-        }
-
-        return false;
-    }
-
-    private String expandExpr(int i) {
-        return this.exprStack + "[" + i + "]";
-    }
-
-    private String expandExpr(String property) {
-        if (this.exprStack.length() == 0)
-            return property;
-        return this.exprStack + "." + property;
-    }
-
-    private String setExprStack(String expr) {
-        String s = this.exprStack;
-        this.exprStack = expr;
-        return s;
-    }
-
-    private boolean shouldExcludeProperty(String expr) {
-        if (this.excludeProperties != null) {
-            for (Pattern pattern : this.excludeProperties) {
-                if (pattern.matcher(expr).matches()) {
-                    if (LOG.isDebugEnabled())
-                        LOG.debug("Ignoring property because of exclude rule: " + expr);
-                    return true;
-                }
-            }
-        }
-
-        if (this.includeProperties != null) {
-            for (Pattern pattern : this.includeProperties) {
-                if (pattern.matcher(expr).matches()) {
-                    return false;
-                }
-            }
-
-            if (LOG.isDebugEnabled())
-                LOG.debug("Ignoring property because of include rule:  " + expr);
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Add name/value pair to buffer
-     */
-    private boolean add(String name, Object value, Method method, boolean hasData) throws JSONException {
-        if (!excludeNullProperties || (value != null)) {
-            if (hasData) {
-                this.add(',');
-            }
-            this.add('"');
-            this.add(name);
-            this.add("\":");
-            this.value(value, method);
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Add map to buffer
-     */
-    private void map(Map map, Method method) throws JSONException {
-        this.add("{");
-
-        Iterator it = map.entrySet().iterator();
-
-        boolean warnedNonString = false; // one report per map
-        boolean hasData = false;
-        while (it.hasNext()) {
-            Map.Entry entry = (Map.Entry) it.next();
-            Object key = entry.getKey();
-            String expr = null;
-            if (this.buildExpr) {
-                if (key == null) {
-                    LOG.error("Cannot build expression for null key in " + this.exprStack);
-                    continue;
-                } else {
-                    expr = this.expandExpr(key.toString());
-                    if (this.shouldExcludeProperty(expr)) {
-                        continue;
-                    }
-                    expr = this.setExprStack(expr);
-                }
-            }
-            if (hasData) {
-                this.add(',');
-            }
-            hasData = true;
-            if (!warnedNonString && !(key instanceof String)) {
-                LOG.warn("JavaScript doesn't support non-String keys, using toString() on "
-                        + key.getClass().getName());
-                warnedNonString = true;
-            }
-            this.value(key.toString(), method);
-            this.add(":");
-            this.value(entry.getValue(), method);
-            if (this.buildExpr) {
-                this.setExprStack(expr);
-            }
-        }
-
-        this.add("}");
-    }
-
-    /**
-     * Add date to buffer
-     */
-    private void date(Date date, Method method) {
-        JSON json = null;
-        if (method != null)
-            json = method.getAnnotation(JSON.class);
-        if (this.formatter == null)
-            this.formatter = new SimpleDateFormat(JSONUtil.RFC3339_FORMAT);
-
-        DateFormat formatter = (json != null) && (json.format().length() > 0) ? new SimpleDateFormat(json
-                .format()) : this.formatter;
-        this.string(formatter.format(date));
-    }
-
-    /**
-     * Add array to buffer
-     */
-    private void array(Iterator it, Method method) throws JSONException {
-        this.add("[");
-
-        boolean hasData = false;
-        for (int i = 0; it.hasNext(); i++) {
-            String expr = null;
-            if (this.buildExpr) {
-                expr = this.expandExpr(i);
-                if (this.shouldExcludeProperty(expr)) {
-                    it.next();
-                    continue;
-                }
-                expr = this.setExprStack(expr);
-            }
-            if (hasData) {
-                this.add(',');
-            }
-            hasData = true;
-            this.value(it.next(), method);
-            if (this.buildExpr) {
-                this.setExprStack(expr);
-            }
-        }
-
-        this.add("]");
-    }
-
-    /**
-     * Add array to buffer
-     */
-    private void array(Object object, Method method) throws JSONException {
-        this.add("[");
-
-        int length = Array.getLength(object);
-
-        boolean hasData = false;
-        for (int i = 0; i < length; ++i) {
-            String expr = null;
-            if (this.buildExpr) {
-                expr = this.expandExpr(i);
-                if (this.shouldExcludeProperty(expr)) {
-                    continue;
-                }
-                expr = this.setExprStack(expr);
-            }
-            if (hasData) {
-                this.add(',');
-            }
-            hasData = true;
-            this.value(Array.get(object, i), method);
-            if (this.buildExpr) {
-                this.setExprStack(expr);
-            }
-        }
-
-        this.add("]");
-    }
-
-    /**
-     * Add boolean to buffer
-     */
-    private void bool(boolean b) {
-        this.add(b ? "true" : "false");
-    }
-
-    /**
-     * escape characters
-     */
-    private void string(Object obj) {
-        this.add('"');
-
-        CharacterIterator it = new StringCharacterIterator(obj.toString());
-
-        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
-            if (c == '"') {
-                this.add("\\\"");
-            } else if (c == '\\') {
-                this.add("\\\\");
-            } else if (c == '/') {
-                this.add("\\/");
-            } else if (c == '\b') {
-                this.add("\\b");
-            } else if (c == '\f') {
-                this.add("\\f");
-            } else if (c == '\n') {
-                this.add("\\n");
-            } else if (c == '\r') {
-                this.add("\\r");
-            } else if (c == '\t') {
-                this.add("\\t");
-            } else if (Character.isISOControl(c)) {
-                this.unicode(c);
-            } else {
-                this.add(c);
-            }
-        }
-
-        this.add('"');
-    }
-
-    /**
-     * Add object to buffer
-     */
-    private void add(Object obj) {
-        this.buf.append(obj);
-    }
-
-    /**
-     * Add char to buffer
-     */
-    private void add(char c) {
-        this.buf.append(c);
-    }
-
-    /**
-     * Represent as unicode
-     * 
-     * @param c
-     *            character to be encoded
-     */
-    private void unicode(char c) {
-        this.add("\\u");
-
-        int n = c;
-
-        for (int i = 0; i < 4; ++i) {
-            int digit = (n & 0xf000) >> 12;
-
-            this.add(hex[digit]);
-            n <<= 4;
-        }
-    }
-
-    public void setIgnoreHierarchy(boolean ignoreHierarchy) {
-        this.ignoreHierarchy = ignoreHierarchy;
-    }
-
-    /**
-     * If true, an Enum is serialized as a bean with a special property
-     * _name=name() as all as all other properties defined within the enum.<br/>
-     * If false, an Enum is serialized as a name=value pair (name=name())
-     * 
-     * @param enumAsBean
-     *            true to serialize an enum as a bean instead of as a name=value
-     *            pair (default=false)
-     */
-    public void setEnumAsBean(boolean enumAsBean) {
-        this.enumAsBean = enumAsBean;
-    }
-}
+/*
+ * $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.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.text.CharacterIterator;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.text.StringCharacterIterator;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Stack;
+import java.util.regex.Pattern;
+
+import org.apache.struts2.json.annotations.JSON;
+
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/**
+ * <p>
+ * Serializes an object into JavaScript Object Notation (JSON). If cyclic
+ * references are detected they will be nulled out.
+ * </p>
+ */
+class JSONWriter {
+    private static final Logger LOG = LoggerFactory.getLogger(JSONWriter.class);
+
+    /**
+     * By default, enums are serialzied as name=value pairs
+     */
+    public static final boolean ENUM_AS_BEAN_DEFAULT = false;
+
+    static char[] hex = "0123456789ABCDEF".toCharArray();
+    private StringBuilder buf = new StringBuilder();
+    private Stack stack = new Stack();
+    private boolean ignoreHierarchy = true;
+    private Object root;
+    private boolean buildExpr = true;
+    private String exprStack = "";
+    private Collection<Pattern> excludeProperties;
+    private Collection<Pattern> includeProperties;
+    private DateFormat formatter;
+    private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
+    private boolean excludeNullProperties;
+
+    /**
+     * @param object
+     *            Object to be serialized into JSON
+     * @return JSON string for object
+     * @throws JSONException
+     */
+    public String write(Object object) throws JSONException {
+        return this.write(object, null, null, false);
+    }
+
+    /**
+     * @param object
+     *            Object to be serialized into JSON
+     * @return JSON string for object
+     * @throws JSONException
+     */
+    public String write(Object object, Collection<Pattern> excludeProperties,
+            Collection<Pattern> includeProperties, boolean excludeNullProperties) throws JSONException {
+        this.excludeNullProperties = excludeNullProperties;
+        this.buf.setLength(0);
+        this.root = object;
+        this.exprStack = "";
+        this.buildExpr = ((excludeProperties != null) && !excludeProperties.isEmpty())
+                || ((includeProperties != null) && !includeProperties.isEmpty());
+        this.excludeProperties = excludeProperties;
+        this.includeProperties = includeProperties;
+        this.value(object, null);
+
+        return this.buf.toString();
+    }
+
+    /**
+     * Detect cyclic references
+     */
+    private void value(Object object, Method method) throws JSONException {
+        if (object == null) {
+            this.add("null");
+
+            return;
+        }
+
+        if (this.stack.contains(object)) {
+            Class clazz = object.getClass();
+
+            // cyclic reference
+            if (clazz.isPrimitive() || clazz.equals(String.class)) {
+                this.process(object, method);
+            } else {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Cyclic reference detected on " + object);
+                }
+
+                this.add("null");
+            }
+
+            return;
+        }
+
+        this.process(object, method);
+    }
+
+    /**
+     * Serialize object into json
+     */
+    private void process(Object object, Method method) throws JSONException {
+        this.stack.push(object);
+
+        if (object instanceof Class) {
+            this.string(object);
+        } else if (object instanceof Boolean) {
+            this.bool(((Boolean) object).booleanValue());
+        } else if (object instanceof Number) {
+            this.add(object);
+        } else if (object instanceof String) {
+            this.string(object);
+        } else if (object instanceof Character) {
+            this.string(object);
+        } else if (object instanceof Map) {
+            this.map((Map) object, method);
+        } else if (object.getClass().isArray()) {
+            this.array(object, method);
+        } else if (object instanceof Iterable) {
+            this.array(((Iterable) object).iterator(), method);
+        } else if (object instanceof Date) {
+            this.date((Date) object, method);
+        } else if (object instanceof Calendar) {
+            this.date(((Calendar) object).getTime(), method);
+        } else if (object instanceof Locale) {
+            this.string(object);
+        } else if (object instanceof Enum) {
+            this.enumeration((Enum) object);
+        } else {
+            this.bean(object);
+        }
+
+        this.stack.pop();
+    }
+
+    /**
+     * Instrospect bean and serialize its properties
+     */
+    private void bean(Object object) throws JSONException {
+        this.add("{");
+
+        BeanInfo info;
+
+        try {
+            Class clazz = object.getClass();
+
+            info = ((object == this.root) && this.ignoreHierarchy) ? Introspector.getBeanInfo(clazz, clazz
+                    .getSuperclass()) : Introspector.getBeanInfo(clazz);
+
+            PropertyDescriptor[] props = info.getPropertyDescriptors();
+
+            boolean hasData = false;
+            for (int i = 0; i < props.length; ++i) {
+                PropertyDescriptor prop = props[i];
+                String name = prop.getName();
+                Method accessor = prop.getReadMethod();
+                Method baseAccessor = null;
+                if (clazz.getName().indexOf("$$EnhancerByCGLIB$$") > -1) {
+                    try {
+                        baseAccessor = Class.forName(
+                                clazz.getName().substring(0, clazz.getName().indexOf("$$"))).getMethod(
+                                accessor.getName(), accessor.getParameterTypes());
+                    } catch (Exception ex) {
+                        LOG.debug(ex.getMessage(), ex);
+                    }
+                } else
+                    baseAccessor = accessor;
+
+                if (baseAccessor != null) {
+
+                    JSON json = baseAccessor.getAnnotation(JSON.class);
+                    if (json != null) {
+                        if (!json.serialize())
+                            continue;
+                        else if (json.name().length() > 0)
+                            name = json.name();
+                    }
+
+                    // ignore "class" and others
+                    if (this.shouldExcludeProperty(clazz, prop)) {
+                        continue;
+                    }
+                    String expr = null;
+                    if (this.buildExpr) {
+                        expr = this.expandExpr(name);
+                        if (this.shouldExcludeProperty(expr)) {
+                            continue;
+                        }
+                        expr = this.setExprStack(expr);
+                    }
+
+                    Object value = accessor.invoke(object, new Object[0]);
+                    boolean propertyPrinted = this.add(name, value, accessor, hasData);
+                    hasData = hasData || propertyPrinted;
+                    if (this.buildExpr) {
+                        this.setExprStack(expr);
+                    }
+                }
+            }
+
+            // special-case handling for an Enumeration - include the name() as
+            // a property */
+            if (object instanceof Enum) {
+                Object value = ((Enum) object).name();
+                this.add("_name", value, object.getClass().getMethod("name"), hasData);
+            }
+        } catch (Exception e) {
+            throw new JSONException(e);
+        }
+
+        this.add("}");
+    }
+
+    /**
+     * Instrospect an Enum and serialize it as a name/value pair or as a bean
+     * including all its own properties
+     */
+    private void enumeration(Enum enumeration) throws JSONException {
+        if (enumAsBean) {
+            this.bean(enumeration);
+        } else {
+            this.string(enumeration.name());
+        }
+    }
+
+    /**
+     * Ignore "class" field
+     */
+    private boolean shouldExcludeProperty(Class clazz, PropertyDescriptor prop) throws SecurityException,
+            NoSuchFieldException {
+        String name = prop.getName();
+
+        if (name.equals("class") || name.equals("declaringClass") || name.equals("cachedSuperClass")
+                || name.equals("metaClass")) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private String expandExpr(int i) {
+        return this.exprStack + "[" + i + "]";
+    }
+
+    private String expandExpr(String property) {
+        if (this.exprStack.length() == 0)
+            return property;
+        return this.exprStack + "." + property;
+    }
+
+    private String setExprStack(String expr) {
+        String s = this.exprStack;
+        this.exprStack = expr;
+        return s;
+    }
+
+    private boolean shouldExcludeProperty(String expr) {
+        if (this.excludeProperties != null) {
+            for (Pattern pattern : this.excludeProperties) {
+                if (pattern.matcher(expr).matches()) {
+                    if (LOG.isDebugEnabled())
+                        LOG.debug("Ignoring property because of exclude rule: " + expr);
+                    return true;
+                }
+            }
+        }
+
+        if (this.includeProperties != null) {
+            for (Pattern pattern : this.includeProperties) {
+                if (pattern.matcher(expr).matches()) {
+                    return false;
+                }
+            }
+
+            if (LOG.isDebugEnabled())
+                LOG.debug("Ignoring property because of include rule:  " + expr);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Add name/value pair to buffer
+     */
+    private boolean add(String name, Object value, Method method, boolean hasData) throws JSONException {
+        if (!excludeNullProperties || (value != null)) {
+            if (hasData) {
+                this.add(',');
+            }
+            this.add('"');
+            this.add(name);
+            this.add("\":");
+            this.value(value, method);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Add map to buffer
+     */
+    private void map(Map map, Method method) throws JSONException {
+        this.add("{");
+
+        Iterator it = map.entrySet().iterator();
+
+        boolean warnedNonString = false; // one report per map
+        boolean hasData = false;
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            Object key = entry.getKey();
+            String expr = null;
+            if (this.buildExpr) {
+                if (key == null) {
+                    LOG.error("Cannot build expression for null key in " + this.exprStack);
+                    continue;
+                } else {
+                    expr = this.expandExpr(key.toString());
+                    if (this.shouldExcludeProperty(expr)) {
+                        continue;
+                    }
+                    expr = this.setExprStack(expr);
+                }
+            }
+            if (hasData) {
+                this.add(',');
+            }
+            hasData = true;
+            if (!warnedNonString && !(key instanceof String)) {
+                LOG.warn("JavaScript doesn't support non-String keys, using toString() on "
+                        + key.getClass().getName());
+                warnedNonString = true;
+            }
+            this.value(key.toString(), method);
+            this.add(":");
+            this.value(entry.getValue(), method);
+            if (this.buildExpr) {
+                this.setExprStack(expr);
+            }
+        }
+
+        this.add("}");
+    }
+
+    /**
+     * Add date to buffer
+     */
+    private void date(Date date, Method method) {
+        JSON json = null;
+        if (method != null)
+            json = method.getAnnotation(JSON.class);
+        if (this.formatter == null)
+            this.formatter = new SimpleDateFormat(JSONUtil.RFC3339_FORMAT);
+
+        DateFormat formatter = (json != null) && (json.format().length() > 0) ? new SimpleDateFormat(json
+                .format()) : this.formatter;
+        this.string(formatter.format(date));
+    }
+
+    /**
+     * Add array to buffer
+     */
+    private void array(Iterator it, Method method) throws JSONException {
+        this.add("[");
+
+        boolean hasData = false;
+        for (int i = 0; it.hasNext(); i++) {
+            String expr = null;
+            if (this.buildExpr) {
+                expr = this.expandExpr(i);
+                if (this.shouldExcludeProperty(expr)) {
+                    it.next();
+                    continue;
+                }
+                expr = this.setExprStack(expr);
+            }
+            if (hasData) {
+                this.add(',');
+            }
+            hasData = true;
+            this.value(it.next(), method);
+            if (this.buildExpr) {
+                this.setExprStack(expr);
+            }
+        }
+
+        this.add("]");
+    }
+
+    /**
+     * Add array to buffer
+     */
+    private void array(Object object, Method method) throws JSONException {
+        this.add("[");
+
+        int length = Array.getLength(object);
+
+        boolean hasData = false;
+        for (int i = 0; i < length; ++i) {
+            String expr = null;
+            if (this.buildExpr) {
+                expr = this.expandExpr(i);
+                if (this.shouldExcludeProperty(expr)) {
+                    continue;
+                }
+                expr = this.setExprStack(expr);
+            }
+            if (hasData) {
+                this.add(',');
+            }
+            hasData = true;
+            this.value(Array.get(object, i), method);
+            if (this.buildExpr) {
+                this.setExprStack(expr);
+            }
+        }
+
+        this.add("]");
+    }
+
+    /**
+     * Add boolean to buffer
+     */
+    private void bool(boolean b) {
+        this.add(b ? "true" : "false");
+    }
+
+    /**
+     * escape characters
+     */
+    private void string(Object obj) {
+        this.add('"');
+
+        CharacterIterator it = new StringCharacterIterator(obj.toString());
+
+        for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
+            if (c == '"') {
+                this.add("\\\"");
+            } else if (c == '\\') {
+                this.add("\\\\");
+            } else if (c == '/') {
+                this.add("\\/");
+            } else if (c == '\b') {
+                this.add("\\b");
+            } else if (c == '\f') {
+                this.add("\\f");
+            } else if (c == '\n') {
+                this.add("\\n");
+            } else if (c == '\r') {
+                this.add("\\r");
+            } else if (c == '\t') {
+                this.add("\\t");
+            } else if (Character.isISOControl(c)) {
+                this.unicode(c);
+            } else {
+                this.add(c);
+            }
+        }
+
+        this.add('"');
+    }
+
+    /**
+     * Add object to buffer
+     */
+    private void add(Object obj) {
+        this.buf.append(obj);
+    }
+
+    /**
+     * Add char to buffer
+     */
+    private void add(char c) {
+        this.buf.append(c);
+    }
+
+    /**
+     * Represent as unicode
+     * 
+     * @param c
+     *            character to be encoded
+     */
+    private void unicode(char c) {
+        this.add("\\u");
+
+        int n = c;
+
+        for (int i = 0; i < 4; ++i) {
+            int digit = (n & 0xf000) >> 12;
+
+            this.add(hex[digit]);
+            n <<= 4;
+        }
+    }
+
+    public void setIgnoreHierarchy(boolean ignoreHierarchy) {
+        this.ignoreHierarchy = ignoreHierarchy;
+    }
+
+    /**
+     * If true, an Enum is serialized as a bean with a special property
+     * _name=name() as all as all other properties defined within the enum.<br/>
+     * If false, an Enum is serialized as a name=value pair (name=name())
+     * 
+     * @param enumAsBean
+     *            true to serialize an enum as a bean instead of as a name=value
+     *            pair (default=false)
+     */
+    public void setEnumAsBean(boolean enumAsBean) {
+        this.enumAsBean = enumAsBean;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/JSONWriter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java Wed Jul 29 22:44:26 2009
@@ -1,100 +1,120 @@
-package org.apache.struts2.json;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang.xwork.StringUtils;
-
-public class SerializationParams {
-    private static final String DEFAULT_CONTENT_TYPE = "application/json";
-
-    private final HttpServletResponse response;
-    private final String encoding;
-    private final boolean wrapWithComments;
-    private final String serializedJSON;
-    private final boolean smd;
-    private final boolean gzip;
-    private final boolean noCache;
-    private final int statusCode;
-    private final int errorCode;
-    private final boolean prefix;
-    private String contentType = DEFAULT_CONTENT_TYPE;
-    private String wrapPrefix;
-    private String wrapSuffix;
-
-    public SerializationParams(HttpServletResponse response, String encoding, boolean wrapWithComments,
-            String serializedJSON, boolean smd, boolean gzip, boolean noCache, int statusCode, int errorCode,
-            boolean prefix, String contentType, String wrapPrefix, String wrapSuffix) {
-        this.response = response;
-        this.encoding = encoding;
-        this.wrapWithComments = wrapWithComments;
-        this.serializedJSON = serializedJSON;
-        this.smd = smd;
-        this.gzip = gzip;
-        this.noCache = noCache;
-        this.statusCode = statusCode;
-        this.errorCode = errorCode;
-        this.prefix = prefix;
-        this.contentType = StringUtils.defaultString(contentType, DEFAULT_CONTENT_TYPE);
-        this.wrapPrefix = wrapPrefix;
-        this.wrapSuffix = wrapSuffix;
-    }
-
-    public SerializationParams(HttpServletResponse response, String defaultEncoding,
-            boolean wrapWithComments, String json, boolean b, boolean b1, boolean noCache, int i, int i1,
-            boolean prefix, String contentType) {
-        this(response, defaultEncoding, wrapWithComments, json, b, b1, noCache, i, i1, prefix, contentType,
-                null, null);
-    }
-
-    public String getWrapSuffix() {
-        return wrapSuffix;
-    }
-
-    public String getWrapPrefix() {
-        return wrapPrefix;
-    }
-
-    public HttpServletResponse getResponse() {
-        return response;
-    }
-
-    public String getEncoding() {
-        return encoding;
-    }
-
-    public boolean isWrapWithComments() {
-        return wrapWithComments;
-    }
-
-    public String getSerializedJSON() {
-        return serializedJSON;
-    }
-
-    public boolean isSmd() {
-        return smd;
-    }
-
-    public boolean isGzip() {
-        return gzip;
-    }
-
-    public boolean isNoCache() {
-        return noCache;
-    }
-
-    public int getStatusCode() {
-        return statusCode;
-    }
-
-    public int getErrorCode() {
-        return errorCode;
-    }
-
-    public boolean isPrefix() {
-        return prefix;
-    }
-
-    public String getContentType() {
-        return contentType;
-    }
-}
+/*
+ * $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 javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.xwork.StringUtils;
+
+public class SerializationParams {
+    private static final String DEFAULT_CONTENT_TYPE = "application/json";
+
+    private final HttpServletResponse response;
+    private final String encoding;
+    private final boolean wrapWithComments;
+    private final String serializedJSON;
+    private final boolean smd;
+    private final boolean gzip;
+    private final boolean noCache;
+    private final int statusCode;
+    private final int errorCode;
+    private final boolean prefix;
+    private String contentType = DEFAULT_CONTENT_TYPE;
+    private String wrapPrefix;
+    private String wrapSuffix;
+
+    public SerializationParams(HttpServletResponse response, String encoding, boolean wrapWithComments,
+            String serializedJSON, boolean smd, boolean gzip, boolean noCache, int statusCode, int errorCode,
+            boolean prefix, String contentType, String wrapPrefix, String wrapSuffix) {
+        this.response = response;
+        this.encoding = encoding;
+        this.wrapWithComments = wrapWithComments;
+        this.serializedJSON = serializedJSON;
+        this.smd = smd;
+        this.gzip = gzip;
+        this.noCache = noCache;
+        this.statusCode = statusCode;
+        this.errorCode = errorCode;
+        this.prefix = prefix;
+        this.contentType = StringUtils.defaultString(contentType, DEFAULT_CONTENT_TYPE);
+        this.wrapPrefix = wrapPrefix;
+        this.wrapSuffix = wrapSuffix;
+    }
+
+    public SerializationParams(HttpServletResponse response, String defaultEncoding,
+            boolean wrapWithComments, String json, boolean b, boolean b1, boolean noCache, int i, int i1,
+            boolean prefix, String contentType) {
+        this(response, defaultEncoding, wrapWithComments, json, b, b1, noCache, i, i1, prefix, contentType,
+                null, null);
+    }
+
+    public String getWrapSuffix() {
+        return wrapSuffix;
+    }
+
+    public String getWrapPrefix() {
+        return wrapPrefix;
+    }
+
+    public HttpServletResponse getResponse() {
+        return response;
+    }
+
+    public String getEncoding() {
+        return encoding;
+    }
+
+    public boolean isWrapWithComments() {
+        return wrapWithComments;
+    }
+
+    public String getSerializedJSON() {
+        return serializedJSON;
+    }
+
+    public boolean isSmd() {
+        return smd;
+    }
+
+    public boolean isGzip() {
+        return gzip;
+    }
+
+    public boolean isNoCache() {
+        return noCache;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    public boolean isPrefix() {
+        return prefix;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/SerializationParams.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java Wed Jul 29 22:44:26 2009
@@ -1,18 +1,41 @@
-package org.apache.struts2.json.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface JSON {
-    String name() default "";
-
-    boolean serialize() default true;
-
-    boolean deserialize() default true;
-
-    String format() default "";
-}
+/*
+ * $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.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/*
+ * Annotation used to customize serialization
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JSON {
+    String name() default "";
+
+    boolean serialize() default true;
+
+    boolean deserialize() default true;
+
+    String format() default "";
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/JSON.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMD.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMD.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethod.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java Wed Jul 29 22:44:26 2009
@@ -1,3 +1,23 @@
+/*
+ * $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.annotations;
 
 import java.lang.annotation.ElementType;

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/annotations/SMDMethodParameter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java Wed Jul 29 22:44:26 2009
@@ -1,86 +1,109 @@
-package org.apache.struts2.json.rpc;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
-
-public class RPCError {
-    private static final Logger LOG = LoggerFactory.getLogger(RPCError.class);
-
-    private int code;
-    private String name;
-    private String message;
-    private String stack;
-
-    public RPCError() {
-    }
-
-    public RPCError(String message, int code) {
-        this.code = code;
-        this.message = message;
-
-        LOG.error(message);
-    }
-
-    public RPCError(String message, RPCErrorCode code) {
-        this(message, code.code());
-    }
-
-    public RPCError(Throwable t, int code, boolean debug) {
-        while (t.getCause() != null) {
-            t = t.getCause();
-        }
-
-        this.code = code;
-        this.message = t.getMessage();
-        this.name = t.getClass().getName();
-
-        if (debug) {
-            StringWriter s = new StringWriter();
-            PrintWriter w = new PrintWriter(s);
-            t.printStackTrace(w);
-            w.flush();
-            this.stack = s.toString();
-        }
-
-        LOG.error(t.getMessage(), t);
-    }
-
-    public RPCError(Throwable t, RPCErrorCode code, boolean debug) {
-        this(t, code.code(), debug);
-    }
-
-    public int getCode() {
-        return code;
-    }
-
-    public void setCode(int code) {
-        this.code = code;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public String getStack() {
-        return stack;
-    }
-
-    public void setStack(String stack) {
-        this.stack = stack;
-    }
-}
+/*
+ * $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.rpc;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
+
+/*
+ * Used to serialize RPC Errors
+ */
+public class RPCError {
+    private static final Logger LOG = LoggerFactory.getLogger(RPCError.class);
+
+    private int code;
+    private String name;
+    private String message;
+    private String stack;
+
+    public RPCError() {
+    }
+
+    public RPCError(String message, int code) {
+        this.code = code;
+        this.message = message;
+
+        LOG.error(message);
+    }
+
+    public RPCError(String message, RPCErrorCode code) {
+        this(message, code.code());
+    }
+
+    public RPCError(Throwable t, int code, boolean debug) {
+        while (t.getCause() != null) {
+            t = t.getCause();
+        }
+
+        this.code = code;
+        this.message = t.getMessage();
+        this.name = t.getClass().getName();
+
+        if (debug) {
+            StringWriter s = new StringWriter();
+            PrintWriter w = new PrintWriter(s);
+            t.printStackTrace(w);
+            w.flush();
+            this.stack = s.toString();
+        }
+
+        LOG.error(t.getMessage(), t);
+    }
+
+    public RPCError(Throwable t, RPCErrorCode code, boolean debug) {
+        this(t, code.code(), debug);
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getStack() {
+        return stack;
+    }
+
+    public void setStack(String stack) {
+        this.stack = stack;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCError.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java Wed Jul 29 22:44:26 2009
@@ -1,25 +1,47 @@
-package org.apache.struts2.json.rpc;
-
-public enum RPCErrorCode {
-    MISSING_METHOD(100, "'method' parameter is missing in request"), MISSING_ID(100,
-            "'id' parameter is missing in request"), INVALID_PROCEDURE_CALL(0, "Invalid procedure call"), METHOD_NOT_FOUND(
-            101, "Procedure not found"), PARAMETERS_MISMATCH(102,
-            "Parameters count in request does not patch parameters count on method"), EXCEPTION(103,
-            "An exception was thrown"), SMD_DISABLED(104, "SMD is disabled");
-
-    private int code;
-    private String message;
-
-    RPCErrorCode(int code, String message) {
-        this.code = code;
-        this.message = message;
-    }
-
-    public int code() {
-        return code;
-    }
-
-    public String message() {
-        return this.message;
-    }
-}
+/*
+ * $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.rpc;
+
+public enum RPCErrorCode {
+    MISSING_METHOD(100, "'method' parameter is missing in request"),
+    MISSING_ID(100, "'id' parameter is missing in request"),
+    INVALID_PROCEDURE_CALL(0, "Invalid procedure call"),
+    METHOD_NOT_FOUND(101, "Procedure not found"),
+    PARAMETERS_MISMATCH(102, "Parameters count in request does not patch parameters count on method"),
+    EXCEPTION(103, "An exception was thrown"),
+    SMD_DISABLED(104, "SMD is disabled");
+
+    private int code;
+    private String message;
+
+    RPCErrorCode(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int code() {
+        return code;
+    }
+
+    public String message() {
+        return this.message;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCErrorCode.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java Wed Jul 29 22:44:26 2009
@@ -1,34 +1,54 @@
-package org.apache.struts2.json.rpc;
-
-/**
- * Class that will be serialized as a response to an RPC call
- */
-public class RPCResponse {
-    private String id;
-    private Object result;
-    private RPCError error;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public Object getResult() {
-        return result;
-    }
-
-    public void setResult(Object result) {
-        this.result = result;
-    }
-
-    public RPCError getError() {
-        return error;
-    }
-
-    public void setError(RPCError error) {
-        this.error = error;
-    }
-}
+/*
+ * $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.rpc;
+
+/**
+ * Class that will be serialized as a response to an RPC call
+ */
+public class RPCResponse {
+    private String id;
+    private Object result;
+    private RPCError error;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Object getResult() {
+        return result;
+    }
+
+    public void setResult(Object result) {
+        this.result = result;
+    }
+
+    public RPCError getError() {
+        return error;
+    }
+
+    public void setError(RPCError error) {
+        this.error = error;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/rpc/RPCResponse.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java Wed Jul 29 22:44:26 2009
@@ -23,6 +23,9 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+/*
+ * HOlds SMD declarations for a class
+ */
 public class SMD {
     public static final String DEFAULT_VERSION = ".1";
     public static final String DEFAULT_SERVICE_TYPE = "JSON-RPC";

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMD.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethod.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethodParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/java/org/apache/struts2/json/smd/SMDMethodParameter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/resources/JsonPlugin.tld
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/resources/JsonPlugin.tld
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/resources/struts-plugin.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/main/resources/struts-plugin.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java Wed Jul 29 22:44:26 2009
@@ -1,8 +1,28 @@
-package org.apache.struts2.json;
-
-/**
- * An enumeration for JSON serialization testing
- */
-public enum AnEnum {
-    ValueA, ValueB, ValueC
-}
+/*
+ * $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;
+
+/**
+ * An enumeration for JSON serialization testing
+ */
+public enum AnEnum {
+    ValueA, ValueB, ValueC
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnum.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java Wed Jul 29 22:44:26 2009
@@ -1,25 +1,45 @@
-package org.apache.struts2.json;
-
-/**
- * A more complicated Enum with additional properties.
- */
-public enum AnEnumBean {
-
-    One("A", "B"), Two("C", "D"), Three("E", "F");
-
-    private String propA;
-    private String propB;
-
-    AnEnumBean(String propA, String propB) {
-        this.propA = propA;
-        this.propB = propB;
-    }
-
-    public String getPropA() {
-        return propA;
-    }
-
-    public String getPropB() {
-        return propB;
-    }
-}
+/*
+ * $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;
+
+/**
+ * A more complicated Enum with additional properties.
+ */
+public enum AnEnumBean {
+
+    One("A", "B"), Two("C", "D"), Three("E", "F");
+
+    private String propA;
+    private String propB;
+
+    AnEnumBean(String propA, String propB) {
+        this.propA = propA;
+        this.propB = propB;
+    }
+
+    public String getPropA() {
+        return propA;
+    }
+
+    public String getPropB() {
+        return propB;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/AnEnumBean.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java?rev=799110&r1=799109&r2=799110&view=diff
==============================================================================
--- struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java (original)
+++ struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java Wed Jul 29 22:44:26 2009
@@ -1,131 +1,151 @@
-package org.apache.struts2.json;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-public class Bean {
-    private String stringField;
-    private int intField;
-    private boolean booleanField;
-    private char charField;
-    private long longField;
-    private float floatField;
-    private double doubleField;
-    private Object objectField;
-    private byte byteField;
-    private AnEnum enumField;
-    private AnEnumBean enumBean;
-    private BigDecimal bigDecimal;
-    private BigInteger bigInteger;
-
-    /**
-     * @return the byteField
-     */
-    public byte getByteField() {
-        return this.byteField;
-    }
-
-    /**
-     * @param byteField
-     *            the byteField to set
-     */
-    public void setByteField(byte byteField) {
-        this.byteField = byteField;
-    }
-
-    public boolean isBooleanField() {
-        return this.booleanField;
-    }
-
-    public void setBooleanField(boolean booleanField) {
-        this.booleanField = booleanField;
-    }
-
-    public char getCharField() {
-        return this.charField;
-    }
-
-    public void setCharField(char charField) {
-        this.charField = charField;
-    }
-
-    public double getDoubleField() {
-        return this.doubleField;
-    }
-
-    public void setDoubleField(double doubleField) {
-        this.doubleField = doubleField;
-    }
-
-    public float getFloatField() {
-        return this.floatField;
-    }
-
-    public void setFloatField(float floatField) {
-        this.floatField = floatField;
-    }
-
-    public int getIntField() {
-        return this.intField;
-    }
-
-    public void setIntField(int intField) {
-        this.intField = intField;
-    }
-
-    public long getLongField() {
-        return this.longField;
-    }
-
-    public void setLongField(long longField) {
-        this.longField = longField;
-    }
-
-    public Object getObjectField() {
-        return this.objectField;
-    }
-
-    public void setObjectField(Object objectField) {
-        this.objectField = objectField;
-    }
-
-    public String getStringField() {
-        return this.stringField;
-    }
-
-    public void setStringField(String stringField) {
-        this.stringField = stringField;
-    }
-
-    public AnEnum getEnumField() {
-        return enumField;
-    }
-
-    public void setEnumField(AnEnum enumField) {
-        this.enumField = enumField;
-    }
-
-    public AnEnumBean getEnumBean() {
-        return enumBean;
-    }
-
-    public void setEnumBean(AnEnumBean enumBean) {
-        this.enumBean = enumBean;
-    }
-
-    public BigInteger getBigInteger() {
-        return bigInteger;
-    }
-
-    public void setBigInteger(BigInteger bigInteger) {
-        this.bigInteger = bigInteger;
-    }
-
-    public BigDecimal getBigDecimal() {
-        return bigDecimal;
-    }
-
-    public void setBigDecimal(BigDecimal bigDecimal) {
-        this.bigDecimal = bigDecimal;
-    }
-}
+/*
+ * $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.math.BigDecimal;
+import java.math.BigInteger;
+
+public class Bean {
+    private String stringField;
+    private int intField;
+    private boolean booleanField;
+    private char charField;
+    private long longField;
+    private float floatField;
+    private double doubleField;
+    private Object objectField;
+    private byte byteField;
+    private AnEnum enumField;
+    private AnEnumBean enumBean;
+    private BigDecimal bigDecimal;
+    private BigInteger bigInteger;
+
+    /**
+     * @return the byteField
+     */
+    public byte getByteField() {
+        return this.byteField;
+    }
+
+    /**
+     * @param byteField
+     *            the byteField to set
+     */
+    public void setByteField(byte byteField) {
+        this.byteField = byteField;
+    }
+
+    public boolean isBooleanField() {
+        return this.booleanField;
+    }
+
+    public void setBooleanField(boolean booleanField) {
+        this.booleanField = booleanField;
+    }
+
+    public char getCharField() {
+        return this.charField;
+    }
+
+    public void setCharField(char charField) {
+        this.charField = charField;
+    }
+
+    public double getDoubleField() {
+        return this.doubleField;
+    }
+
+    public void setDoubleField(double doubleField) {
+        this.doubleField = doubleField;
+    }
+
+    public float getFloatField() {
+        return this.floatField;
+    }
+
+    public void setFloatField(float floatField) {
+        this.floatField = floatField;
+    }
+
+    public int getIntField() {
+        return this.intField;
+    }
+
+    public void setIntField(int intField) {
+        this.intField = intField;
+    }
+
+    public long getLongField() {
+        return this.longField;
+    }
+
+    public void setLongField(long longField) {
+        this.longField = longField;
+    }
+
+    public Object getObjectField() {
+        return this.objectField;
+    }
+
+    public void setObjectField(Object objectField) {
+        this.objectField = objectField;
+    }
+
+    public String getStringField() {
+        return this.stringField;
+    }
+
+    public void setStringField(String stringField) {
+        this.stringField = stringField;
+    }
+
+    public AnEnum getEnumField() {
+        return enumField;
+    }
+
+    public void setEnumField(AnEnum enumField) {
+        this.enumField = enumField;
+    }
+
+    public AnEnumBean getEnumBean() {
+        return enumBean;
+    }
+
+    public void setEnumBean(AnEnumBean enumBean) {
+        this.enumBean = enumBean;
+    }
+
+    public BigInteger getBigInteger() {
+        return bigInteger;
+    }
+
+    public void setBigInteger(BigInteger bigInteger) {
+        this.bigInteger = bigInteger;
+    }
+
+    public BigDecimal getBigDecimal() {
+        return bigDecimal;
+    }
+
+    public void setBigDecimal(BigDecimal bigDecimal) {
+        this.bigDecimal = bigDecimal;
+    }
+}

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: struts/sandbox/trunk/struts2-json-plugin/src/test/java/org/apache/struts2/json/Bean.java
------------------------------------------------------------------------------
    svn:keywords = Id