Coverage Report - javax.faces.convert.DoubleConverter
 
Classes in this File Line Coverage Branch Coverage Complexity
DoubleConverter
71%
35/49
57%
22/38
7.6
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package javax.faces.convert;
 20  
 
 21  
 import javax.faces.component.UIComponent;
 22  
 import javax.faces.context.FacesContext;
 23  
 
 24  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFConverter;
 25  
 
 26  
 import java.text.DecimalFormatSymbols;
 27  
 import java.util.Locale;
 28  
 
 29  
 /**
 30  
  * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
 31  
  */
 32  
 @JSFConverter
 33  
 public class DoubleConverter
 34  
         implements Converter
 35  
 {
 36  
     // API FIELDS
 37  
     public static final String CONVERTER_ID = "javax.faces.Double";
 38  
     public static final String STRING_ID = "javax.faces.converter.STRING";
 39  
     public static final String DOUBLE_ID = "javax.faces.converter.DoubleConverter.DOUBLE";
 40  
 
 41  
     // CONSTRUCTORS
 42  
     public DoubleConverter()
 43  6
     {
 44  6
     }
 45  
 
 46  
     // METHODS
 47  
     public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
 48  
     {
 49  20
         if (facesContext == null)
 50  
         {
 51  0
             throw new NullPointerException("facesContext");
 52  
         }
 53  20
         if (uiComponent == null)
 54  
         {
 55  0
             throw new NullPointerException("uiComponent");
 56  
         }
 57  
 
 58  20
         if (value != null)
 59  
         {
 60  20
             value = value.trim();
 61  20
             if (value.length() > 0)
 62  
             {
 63  
                 try
 64  
                 {
 65  20
                     value = fixLocale(facesContext, value);
 66  20
                     return this.stringToDouble(value);
 67  
                 }
 68  12
                 catch (NumberFormatException e)
 69  
                 {
 70  12
                     throw new ConverterException(_MessageUtils.getErrorMessage(facesContext,
 71  
                                    DOUBLE_ID,
 72  
                                    new Object[]{value,"4214",_MessageUtils.getLabel(facesContext, uiComponent)}), e);
 73  
                 }
 74  
 
 75  
             }
 76  
         }
 77  0
         return null;
 78  
     }
 79  
 
 80  
     /**
 81  
      * Since Double.valueOf is not Locale aware, and NumberFormatter
 82  
      * cannot parse E values correctly, we need to make a US Locale
 83  
      * string from our input value.
 84  
      * E.g. '34,383e3' will be translated to '34.383e3' if Locale.DE
 85  
      * is set in the {@link javax.faces.component.UIViewRoot#getLocale()}
 86  
      *
 87  
      * @param facesContext
 88  
      * @param value
 89  
      * @return the 'fixed' value String
 90  
      */
 91  
     private String fixLocale(FacesContext facesContext, String value)
 92  
     {
 93  20
         Locale loc = facesContext.getViewRoot().getLocale();
 94  20
         if (loc == null || loc == Locale.US)
 95  
         {
 96  
             // nothing to fix if we are already using the US Locale
 97  14
             return value;
 98  
         }
 99  
 
 100  
         // TODO: DecimalFormatSymbols.getInstance exists only on JDK 1.6
 101  
         // change it on JSF 2.1
 102  
         //DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);
 103  6
         DecimalFormatSymbols dfs = new DecimalFormatSymbols(loc);
 104  
 
 105  6
         char decSep   = dfs.getDecimalSeparator();
 106  
 
 107  
 
 108  
         // replace decimal separators which are different to '.'
 109  6
         if (decSep != '.' && value.lastIndexOf(decSep) >= 0)
 110  
         {
 111  4
             StringBuffer sbVal = new StringBuffer();
 112  
 
 113  
             // remove all groupSeperators and change the decimalSeperator
 114  34
             for (int i = 0; i < value.length(); i++)
 115  
             {
 116  30
                 if (value.charAt(i) == decSep)
 117  
                 {
 118  4
                     sbVal.append('.'); // we append the Locale.US decimal separator
 119  4
                     continue;
 120  
                 }
 121  
 
 122  
                 // just append all other characters as usual
 123  26
                 sbVal.append(value.charAt(i));
 124  
             }
 125  
 
 126  4
             value = sbVal.toString();
 127  
         }
 128  
 
 129  
         // we need the formatter with the correct Locale of the user
 130  6
         return value;
 131  
     }
 132  
 
 133  
     private Double stringToDouble(String value)
 134  
     {
 135  
         // this is a special hack for a jvm vulnerability with
 136  
         // converting some special double values.
 137  
         // e.g. "2.225073858507201200000e-308"
 138  
         // see MYFACES-3024 for further information
 139  
         // TODO we can remove this hack, once this got fixed in the jvm!
 140  20
         if (value.length() >= 23)
 141  
         {
 142  10
             StringBuffer normalized = new StringBuffer();
 143  290
             for (int i=0; i< value.length(); i++)
 144  
             {
 145  280
                 char c = value.charAt(i);
 146  280
                 if ( c != '.')
 147  
                 {
 148  270
                     normalized.append(c);
 149  
                 }
 150  
             }
 151  
 
 152  10
             String normalizedString = normalized.toString();
 153  10
             if (normalizedString.contains("22250738585072012") && normalizedString.contains("e-"))
 154  
             {
 155  
                 // oops, baaad value!
 156  10
                throw new NumberFormatException("Not Allowed! This value could possibly kill the VM!");
 157  
             }
 158  
         }
 159  
 
 160  
 
 161  10
         return Double.valueOf(value);
 162  
     }
 163  
 
 164  
     public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value)
 165  
     {
 166  0
         if (facesContext == null)
 167  
         {
 168  0
             throw new NullPointerException("facesContext");
 169  
         }
 170  0
         if (uiComponent == null)
 171  
         {
 172  0
             throw new NullPointerException("uiComponent");
 173  
         }
 174  
 
 175  0
         if (value == null)
 176  
         {
 177  0
             return "";
 178  
         }
 179  0
         if (value instanceof String)
 180  
         {
 181  0
             return (String)value;
 182  
         }
 183  
         try
 184  
         {
 185  0
             return Double.toString(((Number)value).doubleValue());
 186  
         }
 187  0
         catch (Exception e)
 188  
         {
 189  0
             throw new ConverterException(_MessageUtils.getErrorMessage(facesContext, STRING_ID,
 190  
                     new Object[]{value,_MessageUtils.getLabel(facesContext, uiComponent)}),e);
 191  
         }
 192  
     }
 193  
 }