Commits

Anonymous committed ad66052

XW-507: Fixed RFC3339 SimpleDateFormatter not being thread-safe

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/xwork_1-2@1476e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (1)

src/java/com/opensymphony/xwork/util/XWorkBasicConverter.java

 /*
- * Copyright (c) 2002-2006 by OpenSymphony
+ * Copyright (c) 2002-2007 by OpenSymphony
  * All rights reserved.
  */
 package com.opensymphony.xwork.util;
 import ognl.Ognl;
 import ognl.TypeConverter;
 
-import com.opensymphony.util.TextUtils;
 import com.opensymphony.xwork.ActionContext;
 import com.opensymphony.xwork.XworkException;
+import com.opensymphony.util.TextUtils;
 
 
 /**
  * <!-- START SNIPPET: javadoc -->
+ * XWork will automatically handle the most common type conversion for you.
  * <p/>
- * WebWork will automatically handle the most common type conversion for you. This includes support for converting to
- * and from Strings for each of the following:
- * <p/>
+ * This includes support for converting to and from Strings for each of the following:
  * <ul>
- * <p/>
  * <li>String</li>
- * <p/>
  * <li>boolean / Boolean</li>
- * <p/>
  * <li>char / Character</li>
- * <p/>
  * <li>int / Integer, float / Float, long / Long, double / Double</li>
- * <p/>
- * <li>dates - uses the SHORT format for the Locale associated with the current request</li>
- * <p/>
+ * <li>dates - uses the SHORT or RFC3339 format (<code>yyyy-MM-dd'T'HH:mm:ss</code>) for the Locale associated with the current request</li>
  * <li>arrays - assuming the individual strings can be coverted to the individual items</li>
- * <p/>
  * <li>collections - if not object type can be determined, it is assumed to be a String and a new ArrayList is
  * created</li>
- * <p/>
  * </ul>
  * <p/>
- * <p/> Note that with arrays the type conversion will defer to the type of the array elements and try to convert each
+ * <b>Note:</b> that with arrays the type conversion will defer to the type of the array elements and try to convert each
  * item individually. As with any other type conversion, if the conversion can't be performed the standard type
  * conversion error reporting is used to indicate a problem occured while processing the type conversion.
- * <p/>
  * <!-- END SNIPPET: javadoc -->
  *
  * @author <a href="mailto:plightbo@gmail.com">Pat Lightbody</a>
  */
 public class XWorkBasicConverter extends DefaultTypeConverter {
 
-    private static String MILLISECOND_FORMAT = ".SSS";
-    final private static SimpleDateFormat RFC3399_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
-    
+    private static final String MILLISECOND_FORMAT = ".SSS";
+    private static final String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
+
     public Object convertValue(Map context, Object o, Member member, String s, Object value, Class toType) {
         Object result = null;
 
             } else if (!"".equals(value)) { // we've already tried the types we know
                 result = super.convertValue(context, value, toType);
             }
-            
+
             if (result == null && value != null && !"".equals(value)) {
                 throw new XworkException("Cannot create type " + toType + " from value " + value);
             }
                 SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
                         locale);
 
-                SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt, RFC3399_FORMAT};
+                SimpleDateFormat rfc3339Format = new SimpleDateFormat(RFC3339_FORMAT);
+
+                SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt, rfc3339Format};
                 for (int i = 0; i < fmts.length; i++) {
                     try {
                         check = fmts[i].parse(sa);
                     } catch (ParseException ignore) {
                     }
                 }
-            }
-            else if(java.util.Date.class == toType) {
+             } else if(java.util.Date.class == toType) {
             	Date check = null;
-            	SimpleDateFormat d1 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
-            	SimpleDateFormat d2 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
-            	SimpleDateFormat d3 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
-            	SimpleDateFormat[] dfs = {d1, d2, d3, RFC3399_FORMAT}; //added RFC 3339 date format (XW-473)
-            	for (int i = 0; i < dfs.length; i++) {
-            		try {
-            			check = dfs[i].parse(sa);
-            			df = dfs[i];
-            			if (check != null) {
-            				break;
-            			}
-            		}
-            		catch (ParseException ignore) {
-            		}
-            	}
+                SimpleDateFormat d1 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
+                SimpleDateFormat d2 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
+                SimpleDateFormat d3 = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
+                SimpleDateFormat rfc3339Format = new SimpleDateFormat(RFC3339_FORMAT);
+                SimpleDateFormat[] dfs = {d1, d2, d3, rfc3339Format}; //added RFC 3339 date format (XW-473)
+                for (int i = 0; i < dfs.length; i++) {
+                	try {
+                		check = dfs[i].parse(sa);
+                		df = dfs[i];
+                		if (check != null) {
+                			break;
+                		}
+                	}
+                	catch (ParseException ignore) {
+                	}
+                }
             }
             //final fallback for dates without time
             if (df == null){
             	df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
             }
-
             try {
             	df.setLenient(false); // let's use strict parsing (XW-341)
                 result = df.parse(sa);
                 }
                 numFormat.setGroupingUsed(true);
                 Number number = numFormat.parse(stringValue, parsePos);
-                
+
                 if (parsePos.getIndex() != stringValue.length()) {
                     throw new XworkException("Unparseable number: \"" + stringValue + "\" at position "
                             + parsePos.getIndex());
                 || char.class == type || Character.class == type) {
             return false;
         }
-        
+
         return true;
     }
-    
+
     private String doConvertToString(Map context, Object value) {
         String result = null;