Coverage Report - org.apache.myfaces.shared_impl.renderkit.RendererUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
RendererUtils
0%
0/412
0%
0/282
0
RendererUtils$1
0%
0/5
0%
0/4
0
RendererUtils$PassThroughAsStringConverter
0%
0/5
N/A
0
 
 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 org.apache.myfaces.shared_impl.renderkit;
 20  
 
 21  
 import java.io.ByteArrayOutputStream;
 22  
 import java.io.FileNotFoundException;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.Serializable;
 26  
 import java.lang.reflect.Array;
 27  
 import java.util.ArrayList;
 28  
 import java.util.Collections;
 29  
 import java.util.Date;
 30  
 import java.util.HashSet;
 31  
 import java.util.Iterator;
 32  
 import java.util.List;
 33  
 import java.util.Map;
 34  
 import java.util.Set;
 35  
 
 36  
 import javax.el.ValueExpression;
 37  
 import javax.faces.FacesException;
 38  
 import javax.faces.FactoryFinder;
 39  
 import javax.faces.component.EditableValueHolder;
 40  
 import javax.faces.component.NamingContainer;
 41  
 import javax.faces.component.UIComponent;
 42  
 import javax.faces.component.UIForm;
 43  
 import javax.faces.component.UIInput;
 44  
 import javax.faces.component.UINamingContainer;
 45  
 import javax.faces.component.UIOutput;
 46  
 import javax.faces.component.UISelectMany;
 47  
 import javax.faces.component.UISelectOne;
 48  
 import javax.faces.component.UIViewRoot;
 49  
 import javax.faces.component.ValueHolder;
 50  
 import javax.faces.component.html.HtmlInputText;
 51  
 import javax.faces.context.FacesContext;
 52  
 import javax.faces.convert.Converter;
 53  
 import javax.faces.convert.ConverterException;
 54  
 import javax.faces.el.PropertyNotFoundException;
 55  
 import javax.faces.el.ValueBinding;
 56  
 import javax.faces.event.PhaseId;
 57  
 import javax.faces.model.SelectItem;
 58  
 import javax.faces.render.RenderKit;
 59  
 import javax.faces.render.RenderKitFactory;
 60  
 import javax.faces.render.ResponseStateManager;
 61  
 
 62  
 import org.apache.commons.logging.Log;
 63  
 import org.apache.commons.logging.LogFactory;
 64  
 import org.apache.myfaces.shared_impl.renderkit.html.util.FormInfo;
 65  
 import org.apache.myfaces.shared_impl.util.HashMapUtils;
 66  
 import org.apache.myfaces.shared_impl.util.SelectItemsIterator;
 67  
 
 68  
 /**
 69  
  * @author Manfred Geiler (latest modification by $Author: matzew $)
 70  
  * @version $Revision: 807542 $ $Date: 2009-08-25 05:22:20 -0500 (Tue, 25 Aug 2009) $
 71  
  */
 72  
 public final class RendererUtils
 73  
 {
 74  0
     private RendererUtils(){
 75  
         //nope
 76  0
     }
 77  
     
 78  0
     private static final Log log = LogFactory.getLog(RendererUtils.class);
 79  
 
 80  0
     public static final String SELECT_ITEM_LIST_ATTR = RendererUtils.class.getName() + ".LIST";
 81  
     public static final String EMPTY_STRING = "";
 82  0
     public static final Object NOTHING = new Serializable() {
 83  
         public boolean equals(final Object o)
 84  
         {
 85  0
             if (o != null)
 86  
             {
 87  0
                 if (o.getClass().equals(this.getClass()))
 88  
                 {
 89  0
                     return true;
 90  
                 }
 91  
             }
 92  0
             return false;
 93  
         }
 94  
     };
 95  
 
 96  
     public static final String ACTION_FOR_LIST = "org.apache.myfaces.ActionForList";
 97  
     public static final String ACTION_FOR_PHASE_LIST = "org.apache.myfaces.ActionForPhaseList";
 98  
 
 99  
     public static final String SEQUENCE_PARAM = "jsf_sequence";
 100  
 
 101  0
     private static final String RENDER_KIT_IMPL = RendererUtils.class.getName() + ".RenderKitImpl";
 102  
 
 103  
     public static String getPathToComponent(UIComponent component)
 104  
     {
 105  0
         StringBuffer buf = new StringBuffer();
 106  
 
 107  0
         if(component == null)
 108  
         {
 109  0
             buf.append("{Component-Path : ");
 110  0
             buf.append("[null]}");
 111  0
             return buf.toString();
 112  
         }
 113  
 
 114  0
         getPathToComponent(component,buf);
 115  
 
 116  0
         buf.insert(0,"{Component-Path : ");
 117  0
         buf.append("}");
 118  
 
 119  0
         return buf.toString();
 120  
     }
 121  
 
 122  
     private static void getPathToComponent(UIComponent component, StringBuffer buf)
 123  
     {
 124  0
         if(component == null)
 125  0
             return;
 126  
 
 127  0
         StringBuffer intBuf = new StringBuffer();
 128  
 
 129  0
         intBuf.append("[Class: ");
 130  0
         intBuf.append(component.getClass().getName());
 131  0
         if(component instanceof UIViewRoot)
 132  
         {
 133  0
             intBuf.append(",ViewId: ");
 134  0
             intBuf.append(((UIViewRoot) component).getViewId());
 135  
         }
 136  
         else
 137  
         {
 138  0
             intBuf.append(",Id: ");
 139  0
             intBuf.append(component.getId());
 140  
         }
 141  0
         intBuf.append("]");
 142  
 
 143  0
         buf.insert(0,intBuf.toString());
 144  
 
 145  0
         getPathToComponent(component.getParent(), buf);
 146  0
     }
 147  
 
 148  
     public static String getConcatenatedId(FacesContext context, UIComponent container,
 149  
                                            String clientId)
 150  
     {
 151  0
         UIComponent child = container.findComponent(clientId);
 152  
 
 153  0
         if(child == null)
 154  0
                 return clientId;
 155  
 
 156  0
         return getConcatenatedId(context, child);
 157  
     }
 158  
 
 159  
     public static String getConcatenatedId(FacesContext context, UIComponent component)
 160  
     {
 161  0
         if (context == null) throw new NullPointerException("context");
 162  
 
 163  0
         StringBuffer idBuf = new StringBuffer();
 164  
 
 165  0
         idBuf.append(component.getId());
 166  
 
 167  
         UIComponent parent;
 168  
 
 169  0
         while((parent = component.getParent())!=null)
 170  
         {
 171  0
             if(parent instanceof NamingContainer)
 172  
             {
 173  0
                 idBuf.insert(0,NamingContainer.SEPARATOR_CHAR);
 174  0
                 idBuf.insert(0,parent.getId());
 175  
             }
 176  
         }
 177  
 
 178  0
         return idBuf.toString();
 179  
     }
 180  
 
 181  
     public static Boolean getBooleanValue(UIComponent component)
 182  
     {
 183  0
         Object value = getObjectValue(component);
 184  
         // Try to convert to Boolean if it is a String
 185  0
         if (value instanceof  String) {
 186  0
             value = Boolean.valueOf((String)value);
 187  
         }
 188  
         
 189  0
         if (value==null || value instanceof Boolean)
 190  
         {
 191  0
             return (Boolean) value;
 192  
         }
 193  
 
 194  0
         throw new IllegalArgumentException("Expected submitted value of type Boolean for Component : "+
 195  
                     getPathToComponent(component));
 196  
         
 197  
     }
 198  
 
 199  
     public static Date getDateValue(UIComponent component)
 200  
     {
 201  0
         Object value = getObjectValue(component);
 202  0
         if (value==null || value instanceof Date)
 203  
         {
 204  0
             return (Date) value;
 205  
         }
 206  
 
 207  0
         throw new IllegalArgumentException("Expected submitted value of type Date for component : "
 208  
                 +getPathToComponent(component));
 209  
     }
 210  
 
 211  
     public static Object getObjectValue(UIComponent component)
 212  
     {
 213  0
         if (!(component instanceof ValueHolder))
 214  
         {
 215  0
             throw new IllegalArgumentException("Component : "+
 216  
                     getPathToComponent(component)+"is not a ValueHolder");
 217  
         }
 218  
 
 219  0
         if (component instanceof EditableValueHolder)
 220  
         {
 221  0
             Object value = ((EditableValueHolder)component).getSubmittedValue();
 222  0
             if(value != null && !NOTHING.equals(value))
 223  
             {
 224  0
                 return value;
 225  
             }
 226  
         }
 227  
 
 228  0
         return ((ValueHolder)component).getValue();
 229  
     }
 230  
 
 231  
     @Deprecated
 232  
     public static String getStringValue(FacesContext context, ValueBinding vb)
 233  
     {
 234  0
         Object value = vb.getValue(context);
 235  0
         if (value != null)
 236  
         {
 237  0
             return value.toString();
 238  
         }
 239  0
         return null;
 240  
     }
 241  
 
 242  
     public static String getStringValue(FacesContext context, ValueExpression ve)
 243  
     {
 244  0
         Object value = ve.getValue(context.getELContext());
 245  0
         if (value != null)
 246  
         {
 247  0
             return value.toString();
 248  
         }
 249  0
         return null;
 250  
     }
 251  
 
 252  
     public static String getStringValue(FacesContext facesContext,
 253  
                                         UIComponent component)
 254  
     {
 255  
         try
 256  
         {
 257  0
             if (!(component instanceof ValueHolder))
 258  
             {
 259  0
                 throw new IllegalArgumentException("Component : "+getPathToComponent(component)+"is not a ValueHolder");
 260  
             }
 261  
 
 262  0
             if (component instanceof EditableValueHolder)
 263  
             {
 264  0
                 Object submittedValue = ((EditableValueHolder)component).getSubmittedValue();
 265  0
                 if (submittedValue != null)
 266  
                 {
 267  0
                     if (submittedValue instanceof String)
 268  
                     {
 269  0
                         if (log.isDebugEnabled()) log.debug("returning 1 '" + submittedValue + "'");
 270  0
                         return (String)submittedValue;
 271  
                     }
 272  
 
 273  0
                     throw new IllegalArgumentException("Expected submitted value of type String for component : "
 274  
                             +getPathToComponent(component));
 275  
                 }
 276  
             }
 277  
 
 278  
             Object value;
 279  
 
 280  0
             if(component instanceof EditableValueHolder) {
 281  
 
 282  0
                 EditableValueHolder holder = (EditableValueHolder) component;
 283  
                 
 284  0
                 if(holder.isLocalValueSet()) {
 285  0
                     value = holder.getLocalValue();
 286  
                 } else {
 287  0
                     value = getValue(component);
 288  
                 }
 289  0
             }
 290  
             else {
 291  0
                 value = getValue(component);
 292  
             }
 293  
 
 294  0
             Converter converter = ((ValueHolder)component).getConverter();
 295  0
             if (converter == null  && value != null)
 296  
             {
 297  
 
 298  
                 try
 299  
                 {
 300  0
                     converter = facesContext.getApplication().createConverter(value.getClass());
 301  0
                     if (log.isDebugEnabled()) log.debug("the created converter is " + converter);
 302  
                 }
 303  0
                 catch (FacesException e)
 304  
                 {
 305  0
                     log.error("No converter for class " + value.getClass().getName() + " found (component id=" + component.getId() + ").");
 306  
                     // converter stays null
 307  0
                 }
 308  
             }
 309  
 
 310  0
             if (converter == null)
 311  
             {
 312  0
                 if (value == null)
 313  
                 {
 314  0
                     if (log.isDebugEnabled()) log.debug("returning an empty string");
 315  0
                     return "";
 316  
                 }
 317  
 
 318  0
                 if (log.isDebugEnabled()) log.debug("returning an .toString");
 319  0
                 return value.toString();
 320  
                 
 321  
             }
 322  
 
 323  0
             if (log.isDebugEnabled()) log.debug("returning converter get as string " + converter);
 324  0
             return converter.getAsString(facesContext, component, value);
 325  
             
 326  
         }
 327  0
         catch(PropertyNotFoundException ex)
 328  
         {
 329  0
             log.error("Property not found - called by component : "+getPathToComponent(component),ex);
 330  
 
 331  0
             throw ex;
 332  
         }
 333  
     }
 334  
 
 335  
     private static Object getValue(UIComponent component) {
 336  
         Object value;
 337  
         try
 338  
         {
 339  0
             value = ((ValueHolder) component).getValue();
 340  
         }
 341  0
         catch(Exception ex)
 342  
         {
 343  0
             throw new FacesException("Could not retrieve value of component with path : "+
 344  
                     getPathToComponent(component),ex);
 345  0
         }
 346  0
         return value;
 347  
     }
 348  
 
 349  
     /**
 350  
      * See JSF Spec. 8.5 Table 8-1
 351  
      * @param value
 352  
      * @return boolean
 353  
      */
 354  
     public static boolean isDefaultAttributeValue(Object value)
 355  
     {
 356  0
         if (value == null)
 357  
         {
 358  0
             return true;
 359  
         }
 360  0
         else if (value instanceof Boolean)
 361  
         {
 362  0
             return !((Boolean) value).booleanValue();
 363  
         }
 364  0
         else if (value instanceof Number)
 365  
         {
 366  0
             if (value instanceof Integer)
 367  
             {
 368  0
                 return ((Number)value).intValue() == Integer.MIN_VALUE;
 369  
             }
 370  0
             else if (value instanceof Double)
 371  
             {
 372  0
                 return ((Number)value).doubleValue() == Double.MIN_VALUE;
 373  
             }
 374  0
             else if (value instanceof Long)
 375  
             {
 376  0
                 return ((Number)value).longValue() == Long.MIN_VALUE;
 377  
             }
 378  0
             else if (value instanceof Byte)
 379  
             {
 380  0
                 return ((Number)value).byteValue() == Byte.MIN_VALUE;
 381  
             }
 382  0
             else if (value instanceof Float)
 383  
             {
 384  0
                 return ((Number)value).floatValue() == Float.MIN_VALUE;
 385  
             }
 386  0
             else if (value instanceof Short)
 387  
             {
 388  0
                 return ((Number)value).shortValue() == Short.MIN_VALUE;
 389  
             }
 390  
         }
 391  0
         return false;
 392  
     }
 393  
 
 394  
     /**
 395  
      * Find the proper Converter for the given UIOutput component.
 396  
      * @return the Converter or null if no Converter specified or needed
 397  
      * @throws FacesException if the Converter could not be created
 398  
      */
 399  
     public static Converter findUIOutputConverter(FacesContext facesContext,
 400  
                                                   UIOutput component)
 401  
             throws FacesException
 402  
     {
 403  0
         return _SharedRendererUtils.findUIOutputConverter(facesContext, component);
 404  
     }
 405  
 
 406  
 
 407  
     /**
 408  
      * Find proper Converter for the entries in the associated List or Array of
 409  
      * the given UISelectMany as specified in API Doc of UISelectMany.
 410  
      * @return the Converter or null if no Converter specified or needed
 411  
      * @throws FacesException if the Converter could not be created
 412  
      */
 413  
     public static Converter findUISelectManyConverter(FacesContext facesContext,
 414  
                                                       UISelectMany component)
 415  
     {
 416  0
         Converter converter = component.getConverter();
 417  0
         if (converter != null) return converter;
 418  
 
 419  
         //Try to find out by value binding
 420  0
         ValueExpression vb = component.getValueExpression("value");
 421  0
         if (vb == null) return null;
 422  
 
 423  
         //By some strange reason vb.getType(facesContext.getELContext());
 424  
         //does not return the same as vb.getValue(facesContext.getELContext()).getClass(),
 425  
         //so we need to use this instead.
 426  0
         Class valueType = null;
 427  0
         Object value = vb.getValue(facesContext.getELContext()); 
 428  0
         valueType = (value != null) ? value.getClass() :
 429  
             vb.getType(facesContext.getELContext()) ;
 430  
         
 431  0
         if (valueType == null) return null;
 432  
         
 433  0
         if (List.class.isAssignableFrom(valueType))
 434  
         {
 435  
             //According to API Doc of UISelectMany the assumed entry type for a List is String
 436  
             //--> so basically no converter needed
 437  
 
 438  
             // However, if the List contains something other than Strings, we can attempt
 439  
             // to find a suitable converter. In JDK 1.4, we can try to find out what the List
 440  
             // contains by looking at the SelectItem value of the first item. With generics in
 441  
             // JDK 1.5, it would be much easier to determine the type.
 442  
 
 443  0
             List selectItems = RendererUtils.internalGetSelectItemList(component);
 444  
 
 445  0
             if (selectItems != null && selectItems.size() > 0)
 446  
             {
 447  0
                 SelectItem selectItem = (SelectItem) selectItems.get(0);
 448  0
                 Class listComponentType = selectItem.getValue().getClass();
 449  
 
 450  
                     try
 451  
                     {
 452  0
                         return facesContext.getApplication().createConverter(listComponentType);
 453  
                     }
 454  0
                     catch (FacesException e)
 455  
                     {
 456  0
                         log.error("No Converter for type " + listComponentType.getName() + " found", e);
 457  0
                         return null;
 458  
                     }
 459  
 
 460  
             }
 461  
 
 462  0
             return null;
 463  
         }
 464  
 
 465  0
         if (!valueType.isArray())
 466  
         {
 467  0
             throw new IllegalArgumentException("ValueBinding for UISelectMany : "+getPathToComponent(component)+" must be of type List or Array");
 468  
         }
 469  
 
 470  0
         Class arrayComponentType = valueType.getComponentType();
 471  0
         if (String.class.equals(arrayComponentType)) return null;    //No converter needed for String type
 472  0
         if (Object.class.equals(arrayComponentType)) return null;    //There is no converter for Object class
 473  
 
 474  
         try
 475  
         {
 476  0
             return facesContext.getApplication().createConverter(arrayComponentType);
 477  
         }
 478  0
         catch (FacesException e)
 479  
         {
 480  0
             log.error("No Converter for type " + arrayComponentType.getName() + " found", e);
 481  0
             return null;
 482  
         }
 483  
     }
 484  
 
 485  
 
 486  
     public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass)
 487  
     {
 488  0
         if(facesContext == null)
 489  0
             throw new NullPointerException("facesContext may not be null");
 490  0
         if(uiComponent == null)
 491  0
             throw new NullPointerException("uiComponent may not be null");
 492  
 
 493  
         //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
 494  
         // why isAssignableFrom with additional getClass method call if isInstance does the same?
 495  0
         if (compClass != null && !(compClass.isInstance(uiComponent)))
 496  
         {
 497  0
             throw new IllegalArgumentException("uiComponent : "+getPathToComponent(uiComponent)+
 498  
                     " is not instance of "+compClass.getName()+" as it should be");
 499  
         }
 500  0
     }
 501  
 
 502  
 
 503  
     public static void renderChildren(FacesContext facesContext, UIComponent component)
 504  
             throws IOException
 505  
     {
 506  0
         if (component.getChildCount() > 0)
 507  
         {
 508  0
             for (Iterator it = component.getChildren().iterator(); it.hasNext(); )
 509  
             {
 510  0
                 UIComponent child = (UIComponent)it.next();
 511  0
                 renderChild(facesContext, child);
 512  0
             }
 513  
         }
 514  0
     }
 515  
 
 516  
 
 517  
     public static void renderChild(FacesContext facesContext, UIComponent child)
 518  
             throws IOException
 519  
     {
 520  0
         if (!child.isRendered())
 521  
         {
 522  0
             return;
 523  
         }
 524  
 
 525  0
         child.encodeBegin(facesContext);
 526  0
         if (child.getRendersChildren())
 527  
         {
 528  0
             child.encodeChildren(facesContext);
 529  
         }
 530  
         else
 531  
         {
 532  0
             renderChildren(facesContext, child);
 533  
         }
 534  0
         child.encodeEnd(facesContext);
 535  0
     }
 536  
 
 537  
 
 538  
 
 539  
     /**
 540  
      * @param uiSelectOne
 541  
      * @return List of SelectItem Objects
 542  
      */
 543  
     public static List getSelectItemList(UISelectOne uiSelectOne)
 544  
     {
 545  0
         return internalGetSelectItemList(uiSelectOne);
 546  
     }
 547  
 
 548  
     /**
 549  
      * @param uiSelectMany
 550  
      * @return List of SelectItem Objects
 551  
      */
 552  
     public static List getSelectItemList(UISelectMany uiSelectMany)
 553  
     {
 554  0
         return internalGetSelectItemList(uiSelectMany);
 555  
     }
 556  
 
 557  
     private static List internalGetSelectItemList(UIComponent uiComponent)
 558  
     {
 559  
         /* TODO: Shall we cache the list in a component attribute?
 560  
         ArrayList list = (ArrayList)uiComponent.getAttributes().get(SELECT_ITEM_LIST_ATTR);
 561  
         if (list != null)
 562  
         {
 563  
             return list;
 564  
         }
 565  
          */
 566  
         
 567  0
         List list = new ArrayList();
 568  
         
 569  0
         for (Iterator iter = new SelectItemsIterator(uiComponent); iter.hasNext();)
 570  
         {
 571  0
             list.add(iter.next());            
 572  
         }        
 573  0
         return list;
 574  
     }
 575  
 
 576  
 
 577  
     /**
 578  
      * Convenient utility method that returns the currently submitted values of
 579  
      * a UISelectMany component as a Set, of which the contains method can then be
 580  
      * easily used to determine if a select item is currently selected.
 581  
      * Calling the contains method of this Set with the renderable (String converted) item value
 582  
      * as argument returns true if this item is selected.
 583  
      * @param uiSelectMany
 584  
      * @return Set containing all currently selected values
 585  
      */
 586  
     public static Set getSubmittedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
 587  
     {
 588  0
         Object submittedValues = uiSelectMany.getSubmittedValue();
 589  0
         if (submittedValues == null)
 590  
         {
 591  0
             return null;
 592  
         }
 593  
 
 594  0
         if(converter != null) {
 595  0
             converter = new PassThroughAsStringConverter(converter);
 596  
         }
 597  
 
 598  0
         return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, submittedValues);
 599  
     }
 600  
 
 601  
 
 602  
     /**
 603  
      * Convenient utility method that returns the currently selected values of
 604  
      * a UISelectMany component as a Set, of which the contains method can then be
 605  
      * easily used to determine if a value is currently selected.
 606  
      * Calling the contains method of this Set with the item value
 607  
      * as argument returns true if this item is selected.
 608  
      * @param uiSelectMany
 609  
      * @return Set containing all currently selected values
 610  
      */
 611  
     public static Set getSelectedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
 612  
     {
 613  0
         Object selectedValues = uiSelectMany.getValue();
 614  
 
 615  0
         return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, selectedValues);
 616  
     }
 617  
 
 618  
 
 619  
     /**
 620  
      * Convenient utility method that returns the currently given value as String,
 621  
      * using the given converter.
 622  
      * Especially usefull for dealing with primitive types.
 623  
      */
 624  
     public static String getConvertedStringValue(FacesContext context,
 625  
             UIComponent component, Converter converter, Object value) {
 626  0
         if (converter == null) {
 627  0
             if (value == null) {
 628  0
                 return "";
 629  0
             } else if (value instanceof String) {
 630  0
                 return (String) value;
 631  0
             } else if (RendererUtils.NOTHING.equals(value)) {
 632  0
                 return "";
 633  
             } else {
 634  0
                 throw new IllegalArgumentException(
 635  
                         "Value is no String (class=" + value.getClass().getName() + ", value=" + value + ") and component "
 636  
                                 + component.getClientId(context) +"with path: "
 637  
                                 + getPathToComponent(component)
 638  
                                 + " does not have a Converter");
 639  
             }
 640  
         }
 641  
 
 642  0
         if (RendererUtils.NOTHING.equals(value))
 643  
         {
 644  0
             return converter.getAsString(context, component, "");
 645  
         }
 646  
         else
 647  
         {
 648  0
             return converter.getAsString(context, component, value);
 649  
         }
 650  
     }
 651  
 
 652  
 
 653  
     /**
 654  
      * Convenient utility method that returns the currently given SelectItem value
 655  
      * as String, using the given converter.
 656  
      * Especially usefull for dealing with primitive types.
 657  
      */
 658  
     public static String getConvertedStringValue(FacesContext context,
 659  
             UIComponent component, Converter converter, SelectItem selectItem) {
 660  0
         return getConvertedStringValue(context, component, converter, selectItem.getValue());
 661  
     }
 662  
 
 663  
 
 664  
     private static Set internalSubmittedOrSelectedValuesAsSet(FacesContext context,
 665  
             UIComponent component, Converter converter, UISelectMany uiSelectMany,
 666  
             Object values)
 667  
     {
 668  0
         if (values == null || EMPTY_STRING.equals(values))
 669  
         {
 670  0
             return Collections.EMPTY_SET;
 671  
         }
 672  0
         else if (values instanceof Object[])
 673  
         {
 674  
             //Object array
 675  0
             Object[] ar = (Object[])values;
 676  0
             if (ar.length == 0)
 677  
             {
 678  0
                 return Collections.EMPTY_SET;
 679  
             }
 680  
 
 681  0
             HashSet set = new HashSet(HashMapUtils.calcCapacity(ar.length));
 682  0
             for (int i = 0; i < ar.length; i++)
 683  
             {
 684  0
                 set.add( getConvertedStringValue(context, component, converter, ar[i]) );
 685  
             }
 686  0
             return set;
 687  
         }
 688  0
         else if (values.getClass().isArray())
 689  
         {
 690  
             //primitive array
 691  0
             int len = Array.getLength(values);
 692  0
             HashSet set = new HashSet(org.apache.myfaces.shared_impl.util.HashMapUtils.calcCapacity(len));
 693  0
             for (int i = 0; i < len; i++)
 694  
             {
 695  0
                 set.add( getConvertedStringValue(context, component, converter, Array.get(values,i)) );
 696  
             }
 697  0
             return set;
 698  
         }
 699  0
         else if (values instanceof List)
 700  
         {
 701  0
             List lst = (List)values;
 702  0
             if (lst.size() == 0)
 703  
             {
 704  0
                 return Collections.EMPTY_SET;
 705  
             }
 706  
 
 707  0
             HashSet set = new HashSet(HashMapUtils.calcCapacity(lst.size()));
 708  0
             for (Iterator i = lst.iterator(); i.hasNext();)
 709  0
                 set.add(getConvertedStringValue(context, component, converter, i.next()));
 710  
 
 711  0
             return set;
 712  
 
 713  
         }
 714  
         else
 715  
         {
 716  0
             throw new IllegalArgumentException("Value of UISelectMany component with path : "
 717  
                     + getPathToComponent(uiSelectMany) + " is not of type Array or List");
 718  
         }
 719  
     }
 720  
 
 721  
     public static Object getConvertedUISelectOneValue(FacesContext facesContext, UISelectOne output, Object submittedValue){        
 722  0
         if (submittedValue != null && !(submittedValue instanceof String))
 723  
         {
 724  0
             if (RendererUtils.NOTHING.equals(submittedValue))
 725  
             {
 726  0
                 return null;
 727  
             }
 728  0
             throw new IllegalArgumentException("Submitted value of type String for component : "
 729  
                     + getPathToComponent(output) + "expected");
 730  
         }
 731  
         
 732  
         //To be compatible with jsf ri, and according to issue 69
 733  
         //[  Permit the passing of a null value to SelectItem.setValue()  ]
 734  
         //If submittedValue == "" then convert to null.
 735  0
         if ((submittedValue != null) && (submittedValue instanceof String) && ("".equals(submittedValue)))
 736  
         {
 737  
             //Replace "" by null value
 738  0
             submittedValue = null;
 739  
         }
 740  
 
 741  
         Converter converter;
 742  
         try
 743  
         {
 744  0
             converter = findUIOutputConverter(facesContext, output);
 745  
         }
 746  0
         catch (FacesException e)
 747  
         {
 748  0
             throw new ConverterException(e);
 749  0
         }
 750  
 
 751  0
         return converter == null ? submittedValue : converter
 752  
                 .getAsObject(facesContext, output, (String) submittedValue);
 753  
     }
 754  
     
 755  
     public static Object getConvertedUIOutputValue(FacesContext facesContext, UIOutput output, Object submittedValue)
 756  
             throws ConverterException
 757  
     {
 758  0
         if (submittedValue != null && !(submittedValue instanceof String))
 759  
         {
 760  0
             if (RendererUtils.NOTHING.equals(submittedValue))
 761  
             {
 762  0
                 return null;
 763  
             }
 764  0
             throw new IllegalArgumentException("Submitted value of type String for component : "
 765  
                     + getPathToComponent(output) + "expected");
 766  
         }
 767  
 
 768  
         Converter converter;
 769  
         try
 770  
         {
 771  0
             converter = findUIOutputConverter(facesContext, output);
 772  
         }
 773  0
         catch (FacesException e)
 774  
         {
 775  0
             throw new ConverterException(e);
 776  0
         }
 777  
 
 778  0
         return converter == null ? submittedValue : converter
 779  
                 .getAsObject(facesContext, output, (String) submittedValue);
 780  
     }
 781  
 
 782  
     public static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany selectMany,
 783  
             Object submittedValue) throws ConverterException
 784  
     {
 785  0
         if (submittedValue == null)
 786  
         {
 787  0
             return null;
 788  
         }
 789  
 
 790  0
         if (!(submittedValue instanceof String[]))
 791  
         {
 792  0
             throw new ConverterException("Submitted value of type String[] for component : "
 793  
                     + getPathToComponent(selectMany) + "expected");
 794  
         }
 795  
 
 796  0
         return org.apache.myfaces.shared_impl.renderkit._SharedRendererUtils.getConvertedUISelectManyValue(facesContext,
 797  
                 selectMany, (String[]) submittedValue);
 798  
     }
 799  
 
 800  
     public static boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
 801  
     {
 802  0
         Boolean b = (Boolean) component.getAttributes().get(attrName);
 803  0
         return b != null ? b.booleanValue() : defaultValue;
 804  
     }
 805  
 
 806  
     public static int getIntegerAttribute(UIComponent component, String attrName, int defaultValue)
 807  
     {
 808  0
         Integer i = (Integer) component.getAttributes().get(attrName);
 809  0
         return i != null ? i.intValue() : defaultValue;
 810  
     }
 811  
 
 812  
     private static final String TRINIDAD_FORM_COMPONENT_FAMILY = "org.apache.myfaces.trinidad.Form";
 813  
     private static final String ADF_FORM_COMPONENT_FAMILY = "oracle.adf.Form";
 814  
 
 815  
 
 816  
     /**
 817  
      * Find the enclosing form of a component
 818  
      * in the view-tree.
 819  
      * All Subclasses of <code>UIForm</code> and all known
 820  
      * form-families are searched for.
 821  
      * Currently those are the Trinidad form family,
 822  
      * and the (old) ADF Faces form family.
 823  
      * <p/>
 824  
      * There might be additional form families
 825  
      * which have to be explicitly entered here.
 826  
      *
 827  
      * @param uiComponent
 828  
      * @param facesContext
 829  
      * @return FormInfo Information about the form - the form itself and its name.
 830  
      */
 831  
     public static FormInfo findNestingForm(UIComponent uiComponent, FacesContext facesContext)
 832  
     {
 833  0
         UIComponent parent = uiComponent.getParent();
 834  0
         while (parent != null && (!ADF_FORM_COMPONENT_FAMILY.equals(parent.getFamily()) &&
 835  
             !TRINIDAD_FORM_COMPONENT_FAMILY.equals(parent.getFamily()) &&
 836  
             !(parent instanceof UIForm)))
 837  
         {
 838  0
             parent = parent.getParent();
 839  
         }
 840  
 
 841  0
         if (parent != null)
 842  
         {
 843  
             //link is nested inside a form
 844  0
             String formName = parent.getClientId(facesContext);
 845  0
             return new FormInfo(parent, formName);
 846  
         }
 847  
 
 848  0
         return null;
 849  
     }
 850  
 
 851  
     public static boolean getBooleanValue(String attribute, Object value, boolean defaultValue) {
 852  0
         if (value instanceof Boolean) {
 853  0
             return ((Boolean) value).booleanValue();
 854  
         }
 855  0
         else if (value instanceof String) {
 856  0
             return Boolean.valueOf((String) value).booleanValue();
 857  
         }
 858  0
         else if (value != null) {
 859  0
             log.error("value for attribute " + attribute +
 860  
                 " must be instanceof 'Boolean' or 'String', is of type : " + value.getClass());
 861  
 
 862  0
             return defaultValue;
 863  
         }
 864  
 
 865  0
         return defaultValue;
 866  
     }
 867  
 
 868  
     public static void copyHtmlInputTextAttributes(HtmlInputText src, HtmlInputText dest)
 869  
     {
 870  0
         dest.setId(src.getId());
 871  0
         boolean forceId = getBooleanValue(
 872  
             JSFAttr.FORCE_ID_ATTR,
 873  
             src.getAttributes().get(JSFAttr.FORCE_ID_ATTR),
 874  
             false);
 875  0
         if (forceId) {
 876  0
             dest.getAttributes().put(JSFAttr.FORCE_ID_ATTR, Boolean.TRUE);
 877  
         }
 878  0
         dest.setImmediate(src.isImmediate());
 879  0
         dest.setTransient(src.isTransient());
 880  0
         dest.setAccesskey(src.getAccesskey());
 881  0
         dest.setAlt(src.getAlt());
 882  0
         dest.setConverter(src.getConverter());
 883  0
         dest.setDir(src.getDir());
 884  0
         dest.setDisabled(src.isDisabled());
 885  0
         dest.setLang(src.getLang());
 886  0
         dest.setLocalValueSet(src.isLocalValueSet());
 887  0
         dest.setMaxlength(src.getMaxlength());
 888  0
         dest.setOnblur(src.getOnblur());
 889  0
         dest.setOnchange(src.getOnchange());
 890  0
         dest.setOnclick(src.getOnclick());
 891  0
         dest.setOndblclick(src.getOndblclick());
 892  0
         dest.setOnfocus(src.getOnfocus());
 893  0
         dest.setOnkeydown(src.getOnkeydown());
 894  0
         dest.setOnkeypress(src.getOnkeypress());
 895  0
         dest.setOnkeyup(src.getOnkeyup());
 896  0
         dest.setOnmousedown(src.getOnmousedown());
 897  0
         dest.setOnmousemove(src.getOnmousemove());
 898  0
         dest.setOnmouseout(src.getOnmouseout());
 899  0
         dest.setOnmouseover(src.getOnmouseover());
 900  0
         dest.setOnmouseup(src.getOnmouseup());
 901  0
         dest.setOnselect(src.getOnselect());
 902  0
         dest.setReadonly(src.isReadonly());
 903  0
         dest.setRendered(src.isRendered());
 904  0
         dest.setRequired(src.isRequired());
 905  0
         dest.setSize(src.getSize());
 906  0
         dest.setStyle(src.getStyle());
 907  0
         dest.setStyleClass(src.getStyleClass());
 908  0
         dest.setTabindex(src.getTabindex());
 909  0
         dest.setTitle(src.getTitle());
 910  0
         dest.setValidator(src.getValidator());
 911  0
     }
 912  
 
 913  
     public static Integer getViewSequence(FacesContext facescontext)
 914  
     {
 915  0
         Map map = facescontext.getExternalContext().getRequestMap();
 916  0
         Integer sequence = (Integer) map.get(SEQUENCE_PARAM);
 917  0
         if (sequence == null)
 918  
         {
 919  0
             sequence = new Integer(1);
 920  0
             map.put(SEQUENCE_PARAM, sequence);
 921  
 
 922  0
             synchronized (facescontext.getExternalContext().getSession(true))
 923  
             {
 924  0
                 facescontext.getExternalContext().getSessionMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
 925  0
             }
 926  
         }
 927  0
         return sequence;
 928  
     }
 929  
 
 930  
     public static UIComponent findComponent(UIComponent headerComp, Class clazz)
 931  
     {
 932  0
         if (clazz.isAssignableFrom(headerComp.getClass()))
 933  
         {
 934  0
             return headerComp;
 935  
         }
 936  
 
 937  0
         List li = headerComp.getChildren();
 938  
 
 939  0
         for (int i = 0; i < li.size(); i++)
 940  
         {
 941  0
             UIComponent comp = (UIComponent) li.get(i);
 942  
 
 943  
             //recursively iterate through children to find the component
 944  0
             UIComponent lookupComp = findComponent(comp, clazz);
 945  
 
 946  0
             if (lookupComp != null)
 947  0
                 return lookupComp;
 948  
         }
 949  
 
 950  0
         return null;
 951  
     }
 952  
 
 953  
     public static void addOrReplaceChild(UIInput component, UIComponent child)
 954  
     {
 955  0
         List li = component.getChildren();
 956  
 
 957  0
         for (int i = 0; i < li.size(); i++)
 958  
         {
 959  0
             UIComponent oldChild = (UIComponent) li.get(i);
 960  
 
 961  0
             if (oldChild.getId() != null && oldChild.getId().equals(child.getId()))
 962  
             {
 963  0
                 li.set(i, child);
 964  0
                 return;
 965  
             }
 966  
         }
 967  
 
 968  0
         component.getChildren().add(child);
 969  0
     }
 970  
 
 971  
     public static String getClientId(FacesContext facesContext, UIComponent uiComponent, String forAttr)
 972  
     {
 973  0
         UIComponent forComponent = uiComponent.findComponent(forAttr);
 974  0
         if (forComponent == null)
 975  
         {
 976  0
             if (log.isInfoEnabled())
 977  
             {
 978  0
                 log
 979  
                         .info("Unable to find component '"
 980  
                                 + forAttr
 981  
                                 + "' (calling findComponent on component '"
 982  
                                 + uiComponent.getClientId(facesContext)
 983  
                                 + "')."
 984  
                                 + " We'll try to return a guessed client-id anyways -"
 985  
                                 + " this will be a problem if you put the referenced component"
 986  
                                 + " into a different naming-container. If this is the case, you can always use the full client-id.");
 987  
             }
 988  0
             if (forAttr.length() > 0 && forAttr.charAt(0) == UINamingContainer.SEPARATOR_CHAR)
 989  
             {
 990  
                 //absolute id path
 991  0
                 return forAttr.substring(1);
 992  
             }
 993  
 
 994  
             //relative id path, we assume a component on the same level as the label component
 995  0
             String labelClientId = uiComponent.getClientId(facesContext);
 996  0
             int colon = labelClientId.lastIndexOf(UINamingContainer.SEPARATOR_CHAR);
 997  
 
 998  0
             return colon == -1 ? forAttr : labelClientId.substring(0, colon + 1) + forAttr;
 999  
 
 1000  
         }
 1001  
 
 1002  0
         return forComponent.getClientId(facesContext);
 1003  
 
 1004  
     }
 1005  
 
 1006  
     public static List convertIdsToClientIds(String actionFor, FacesContext facesContext, UIComponent component)
 1007  
     {
 1008  0
         List li = new ArrayList();
 1009  
 
 1010  0
         String[] ids = actionFor.split(",");
 1011  
 
 1012  0
         for (int i = 0; i < ids.length; i++)
 1013  
         {
 1014  0
             String trimedId = ids[i].trim();
 1015  0
             if (trimedId.equals("none"))
 1016  0
                 li.add(trimedId);
 1017  
             else
 1018  0
                 li.add(RendererUtils.getClientId(facesContext, component, trimedId));
 1019  
         }
 1020  0
         return li;
 1021  
     }
 1022  
 
 1023  
     public static List convertPhasesToPhasesIds(String actionForPhase)
 1024  
     {
 1025  0
         List li = new ArrayList();
 1026  
 
 1027  0
         if (actionForPhase == null)
 1028  
         {
 1029  0
             return li;
 1030  
         }
 1031  
 
 1032  0
         String[] ids = actionForPhase.split(",");
 1033  
 
 1034  0
         for (int i = 0; i < ids.length; i++)
 1035  
         {
 1036  0
             if (ids[i].equals("PROCESS_VALIDATIONS"))
 1037  
             {
 1038  0
                 li.add(PhaseId.PROCESS_VALIDATIONS);
 1039  
             }
 1040  0
             else if (ids[i].equals("UPDATE_MODEL_VALUES"))
 1041  
             {
 1042  0
                 li.add(PhaseId.UPDATE_MODEL_VALUES);
 1043  
             }
 1044  
         }
 1045  0
         return li;
 1046  
     }
 1047  
 
 1048  
     /**
 1049  
      * Helper method which loads a resource file (such as css) by a given context path and a file name.
 1050  
      * Useful to provide css files (or js files) inline.
 1051  
      * 
 1052  
      * @param ctx <code>FacesContext</code> object to calculate the context path of the web application.
 1053  
      * @param file name of the resource file (e.g. <code>foo.css</code>).
 1054  
      * @return the content of the resource file, or <code>null</code> if no such file is available.
 1055  
      */
 1056  
     public static String loadResourceFile(FacesContext ctx, String file)
 1057  
     {
 1058  
 
 1059  0
         ByteArrayOutputStream content = new ByteArrayOutputStream(10240);
 1060  
 
 1061  0
         InputStream in = null;
 1062  
         try {
 1063  0
             in = ctx.getExternalContext().getResourceAsStream(file);
 1064  0
             if (in == null)
 1065  
             {
 1066  0
                 return null;
 1067  
             }
 1068  
 
 1069  0
             byte[] fileBuffer = new byte[10240];
 1070  
             int read;
 1071  0
             while ((read = in.read(fileBuffer)) > -1)
 1072  
             {
 1073  0
                 content.write(fileBuffer, 0, read);
 1074  
             }
 1075  
         }
 1076  0
         catch (FileNotFoundException e) {
 1077  0
             if (log.isWarnEnabled())
 1078  0
                 log.warn("no such file " + file, e);
 1079  0
             content = null;
 1080  
         }
 1081  0
         catch (IOException e) {
 1082  0
             if (log.isWarnEnabled())
 1083  0
                 log.warn("problems during processing resource " + file, e);
 1084  0
             content = null;
 1085  
         }
 1086  
         finally
 1087  
         {
 1088  0
             try
 1089  
             {
 1090  0
                 content.close();
 1091  
             }
 1092  0
             catch (IOException e)
 1093  
             {
 1094  0
                 log.warn(e.getLocalizedMessage(), e);
 1095  0
             }
 1096  0
             if (in != null)
 1097  
             {
 1098  
                 try
 1099  
                 {
 1100  0
                     in.close();
 1101  
                 }
 1102  0
                 catch (IOException e)
 1103  
                 {
 1104  0
                     log.warn(e.getLocalizedMessage(), e);
 1105  0
                 }
 1106  
             }
 1107  
         }
 1108  
 
 1109  0
         return content.toString();
 1110  
     }
 1111  
 
 1112  
     /**
 1113  
      * check for partial validation or model update attributes being set
 1114  
      * and initialize the request-map accordingly.
 1115  
      * SubForms will work with this information.
 1116  
      */
 1117  
     public static void initPartialValidationAndModelUpdate(UIComponent component, FacesContext facesContext)
 1118  
     {
 1119  0
         String actionFor = (String) component.getAttributes().get("actionFor");
 1120  
 
 1121  0
         if (actionFor != null)
 1122  
         {
 1123  0
             List li = convertIdsToClientIds(actionFor, facesContext, component);
 1124  
 
 1125  0
             facesContext.getExternalContext().getRequestMap().put(ACTION_FOR_LIST, li);
 1126  
 
 1127  0
             String actionForPhase = (String) component.getAttributes().get("actionForPhase");
 1128  
 
 1129  0
             if (actionForPhase != null)
 1130  
             {
 1131  0
                 List phaseList = convertPhasesToPhasesIds(actionForPhase);
 1132  
 
 1133  0
                 facesContext.getExternalContext().getRequestMap().put(ACTION_FOR_PHASE_LIST, phaseList);
 1134  
             }
 1135  
         }
 1136  0
     }
 1137  
 
 1138  
     public static boolean isAdfOrTrinidadForm(UIComponent component) {
 1139  0
         if (component == null)
 1140  0
             return false;
 1141  0
         return ADF_FORM_COMPONENT_FAMILY.equals(component.getFamily()) ||
 1142  
             TRINIDAD_FORM_COMPONENT_FAMILY.equals(component.getFamily());
 1143  
     }
 1144  
 
 1145  
 
 1146  
     /**
 1147  
      * Gets the ResponseStateManager for the renderKit Id provided
 1148  
      */
 1149  
     public static ResponseStateManager getResponseStateManager(FacesContext facesContext, String renderKitId)
 1150  
             throws FacesException
 1151  
     {
 1152  0
         RenderKit renderKit = facesContext.getRenderKit();
 1153  
 
 1154  0
         if (renderKit == null)
 1155  
         {
 1156  
             // look for the renderkit in the request
 1157  0
             Map requestMap = facesContext.getExternalContext().getRequestMap();
 1158  0
             RenderKitFactory factory = (RenderKitFactory) requestMap.get(RENDER_KIT_IMPL);
 1159  
 
 1160  0
             if (factory != null)
 1161  
             {
 1162  0
                 renderKit = factory.getRenderKit(facesContext, renderKitId);
 1163  
             }
 1164  
             else
 1165  
             {
 1166  0
                 factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 1167  
 
 1168  0
                 if (factory == null)
 1169  
                 {
 1170  0
                     throw new IllegalStateException("Factory is null");
 1171  
                 }
 1172  
 
 1173  0
                 requestMap.put(RENDER_KIT_IMPL, factory);
 1174  
 
 1175  0
                 renderKit = factory.getRenderKit(facesContext, renderKitId);
 1176  
             }
 1177  
         }
 1178  
         
 1179  0
         if (renderKit == null)
 1180  
         {
 1181  0
             throw new IllegalArgumentException("Could not find a RenderKit for \"" + renderKitId + "\""); 
 1182  
         }
 1183  
         
 1184  0
         return renderKit.getResponseStateManager();
 1185  
     }
 1186  
 
 1187  
     /**
 1188  
      * Special converter for handling submitted values which don't need to be converted.
 1189  
      *
 1190  
      * @author mathias (latest modification by $Author: matzew $)
 1191  
      * @version $Revision: 807542 $ $Date: 2009-08-25 05:22:20 -0500 (Tue, 25 Aug 2009) $
 1192  
      */
 1193  
     private static class PassThroughAsStringConverter implements Converter
 1194  
     {
 1195  
         private final Converter converter;
 1196  
 
 1197  
         public PassThroughAsStringConverter(Converter converter)
 1198  0
         {
 1199  0
             this.converter = converter;
 1200  0
         }
 1201  
 
 1202  
         public Object getAsObject(FacesContext context, UIComponent component,
 1203  
                 String value) throws ConverterException
 1204  
         {
 1205  0
             return converter.getAsObject(context, component, value);
 1206  
         }
 1207  
 
 1208  
         public String getAsString(FacesContext context, UIComponent component,
 1209  
                 Object value) throws ConverterException
 1210  
         {
 1211  0
             return (String)value;
 1212  
         }
 1213  
 
 1214  
     }
 1215  
 }