Coverage Report - org.apache.myfaces.shared.renderkit.html.util.ResourceUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ResourceUtils
0%
0/82
0%
0/50
4.2
 
 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.renderkit.html.util;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.HashMap;
 23  
 import java.util.Map;
 24  
 import javax.faces.FacesWrapper;
 25  
 
 26  
 import javax.faces.application.Resource;
 27  
 import javax.faces.component.UIComponent;
 28  
 import javax.faces.context.FacesContext;
 29  
 import javax.faces.context.ResponseWriter;
 30  
 
 31  
 import org.apache.myfaces.shared.config.MyfacesConfig;
 32  
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 33  
 import org.apache.myfaces.shared.renderkit.html.HTML;
 34  
 import org.apache.myfaces.shared.resource.ContractResource;
 35  
 
 36  
 /**
 37  
  * @since 4.0.1
 38  
  */
 39  0
 public class ResourceUtils
 40  
 {
 41  
     public final static String JAVAX_FACES_LIBRARY_NAME = "javax.faces";
 42  
     public final static String JSF_JS_RESOURCE_NAME = "jsf.js";
 43  
 
 44  
     public final static String MYFACES_JS_RESOURCE_NAME = "oamSubmit.js";
 45  
     public final static String MYFACES_JS_RESOURCE_NAME_UNCOMPRESSED = "oamSubmit-uncompressed.js";
 46  
     public final static String MYFACES_LIBRARY_NAME = "org.apache.myfaces";
 47  
     private final static String RENDERED_MYFACES_JS = "org.apache.myfaces.RENDERED_MYFACES_JS";
 48  
 
 49  
     public final static String JSF_MYFACES_JSFJS_MINIMAL = "minimal";
 50  
     public final static String JSF_MYFACES_JSFJS_MINIMAL_MODERN = "minimal-modern";
 51  
     public final static String JSF_MYFACES_JSFJS_NORMAL = "normal";
 52  
     
 53  
     public final static String JSF_UNCOMPRESSED_JS_RESOURCE_NAME = "jsf-uncompressed.js";
 54  
     public final static String JSF_MINIMAL_JS_RESOURCE_NAME = "jsf-minimal.js";
 55  
     public final static String JSF_MINIMAL_MODERN_JS_RESOURCE_NAME = "jsf-minimal-modern.js";
 56  
     
 57  
     public final static String JSF_MYFACES_JSFJS_I18N = "jsf-i18n.js";
 58  
     public final static String JSF_MYFACES_JSFJS_EXPERIMENTAL = "jsf-experimental.js";
 59  
     public final static String JSF_MYFACES_JSFJS_LEGACY = "jsf-legacy.js";
 60  
 
 61  
     private final static String RENDERED_STYLESHEET_RESOURCES_SET = 
 62  
         "org.apache.myfaces.RENDERED_STYLESHEET_RESOURCES_SET";
 63  
     private final static String RENDERED_SCRIPT_RESOURCES_SET = "org.apache.myfaces.RENDERED_SCRIPT_RESOURCES_SET";
 64  
     private final static String RENDERED_JSF_JS = "org.apache.myfaces.RENDERED_JSF_JS";
 65  
     public final static String HEAD_TARGET = "head";
 66  
     public final static String BODY_TARGET = "body";
 67  
     public final static String FORM_TARGET = "form";
 68  
 
 69  
     public static final String JAVAX_FACES_OUTPUT_COMPONENT_TYPE = "javax.faces.Output";
 70  
     public static final String JAVAX_FACES_TEXT_RENDERER_TYPE = "javax.faces.Text";
 71  
     public static final String DEFAULT_SCRIPT_RENDERER_TYPE = "javax.faces.resource.Script";
 72  
     public static final String DEFAULT_STYLESHEET_RENDERER_TYPE = "javax.faces.resource.Stylesheet";
 73  
 
 74  
     /**
 75  
      * Return a set of already rendered resources by this renderer on the current
 76  
      * request. 
 77  
      * 
 78  
      * @param facesContext
 79  
      * @return
 80  
      */
 81  
     @SuppressWarnings("unchecked")
 82  
     private static Map<String, Boolean> getRenderedStylesheetResources(FacesContext facesContext)
 83  
     {
 84  0
         Map<String, Boolean> map = (Map<String, Boolean>) facesContext.getAttributes().get(
 85  
                 RENDERED_STYLESHEET_RESOURCES_SET);
 86  0
         if (map == null)
 87  
         {
 88  0
             map = new HashMap<String, Boolean>();
 89  0
             facesContext.getAttributes().put(RENDERED_STYLESHEET_RESOURCES_SET,map);
 90  
         }
 91  0
         return map;
 92  
     }
 93  
     
 94  
     /**
 95  
      * Return a set of already rendered resources by this renderer on the current
 96  
      * request. 
 97  
      * 
 98  
      * @param facesContext
 99  
      * @return
 100  
      */
 101  
     @SuppressWarnings("unchecked")
 102  
     private static Map<String, Boolean> getRenderedScriptResources(FacesContext facesContext)
 103  
     {
 104  0
         Map<String, Boolean> map = (Map<String, Boolean>) facesContext.getAttributes().get(
 105  
                 RENDERED_SCRIPT_RESOURCES_SET);
 106  0
         if (map == null)
 107  
         {
 108  0
             map = new HashMap<String, Boolean>();
 109  0
             facesContext.getAttributes().put(RENDERED_SCRIPT_RESOURCES_SET,map);
 110  
         }
 111  0
         return map;
 112  
     }
 113  
     
 114  
     public static void markScriptAsRendered(FacesContext facesContext, String libraryName, String resourceName)
 115  
     {
 116  0
         getRenderedScriptResources(facesContext).put(
 117  
                 libraryName != null ? libraryName+'/'+resourceName : resourceName, Boolean.TRUE);
 118  0
         if (JAVAX_FACES_LIBRARY_NAME.equals(libraryName) &&
 119  
             JSF_JS_RESOURCE_NAME.equals(resourceName))
 120  
         {
 121  
             // If we are calling this method, it is expected myfaces core is being used as runtime and note
 122  
             // oamSubmit script is included inside jsf.js, so mark this one too.
 123  0
             getRenderedScriptResources(facesContext).put(
 124  
                     MYFACES_LIBRARY_NAME+'/'+MYFACES_JS_RESOURCE_NAME, Boolean.TRUE);
 125  
         }
 126  0
     }
 127  
     
 128  
     public static void markStylesheetAsRendered(FacesContext facesContext, String libraryName, String resourceName)
 129  
     {
 130  0
         getRenderedStylesheetResources(facesContext).put(
 131  
                 libraryName != null ? libraryName+'/'+resourceName : resourceName, Boolean.TRUE);
 132  0
     }
 133  
     
 134  
     public static boolean isRenderedScript(FacesContext facesContext, String libraryName, String resourceName)
 135  
     {
 136  0
         return getRenderedScriptResources(facesContext).containsKey(
 137  
                 libraryName != null ? libraryName+'/'+resourceName : resourceName);
 138  
     }
 139  
     
 140  
     public static boolean isRenderedStylesheet(FacesContext facesContext, String libraryName, String resourceName)
 141  
     {
 142  0
         return getRenderedStylesheetResources(facesContext).containsKey(
 143  
                 libraryName != null ? libraryName+'/'+resourceName : resourceName);
 144  
     }
 145  
     
 146  
     public static void writeScriptInline(FacesContext facesContext, ResponseWriter writer, String libraryName, 
 147  
             String resourceName) throws IOException
 148  
     {
 149  0
         if (!ResourceUtils.isRenderedScript(facesContext, libraryName, resourceName))
 150  
         {
 151  0
             if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRiImplAvailable())
 152  
             {
 153  
                 //Use more compatible way.
 154  0
                 UIComponent outputScript = facesContext.getApplication().
 155  
                     createComponent(facesContext, JAVAX_FACES_OUTPUT_COMPONENT_TYPE, DEFAULT_SCRIPT_RENDERER_TYPE);
 156  0
                 outputScript.getAttributes().put(JSFAttr.NAME_ATTR, resourceName);
 157  0
                 outputScript.getAttributes().put(JSFAttr.LIBRARY_ATTR, libraryName);
 158  0
                 outputScript.encodeAll(facesContext);
 159  0
             }
 160  
             else
 161  
             {
 162  
                 //Fast shortcut, don't create component instance and do what HtmlScriptRenderer do.
 163  0
                 Resource resource = facesContext.getApplication().getResourceHandler().createResource(
 164  
                         resourceName, libraryName);
 165  0
                 markScriptAsRendered(facesContext, libraryName, resourceName);
 166  0
                 writer.startElement(HTML.SCRIPT_ELEM, null);
 167  0
                 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT , null);
 168  0
                 writer.writeURIAttribute(HTML.SRC_ATTR, resource.getRequestPath(), null);
 169  0
                 writer.endElement(HTML.SCRIPT_ELEM);
 170  
             }
 171  
         }
 172  0
     }
 173  
     
 174  
     public static void renderDefaultJsfJsInlineIfNecessary(FacesContext facesContext, ResponseWriter writer) 
 175  
         throws IOException
 176  
     {
 177  0
         if (facesContext.getAttributes().containsKey(RENDERED_JSF_JS))
 178  
         {
 179  0
             return;
 180  
         }
 181  
         
 182  
         // Check first if we have lucky, we are using myfaces and the script has
 183  
         // been previously rendered
 184  0
         if (isRenderedScript(facesContext, JAVAX_FACES_LIBRARY_NAME, JSF_JS_RESOURCE_NAME))
 185  
         {
 186  0
             facesContext.getAttributes().put(RENDERED_JSF_JS, Boolean.TRUE);
 187  0
             return;
 188  
         }
 189  
 
 190  
         // Check if this is an ajax request. If so, we don't need to include it, because that was
 191  
         // already done and in the worst case, jsf script was already loaded on the page.
 192  0
         if (facesContext.getPartialViewContext() != null && 
 193  
                 (facesContext.getPartialViewContext().isPartialRequest() ||
 194  
                  facesContext.getPartialViewContext().isAjaxRequest() )
 195  
             )
 196  
         {
 197  0
             return;
 198  
         }
 199  
         
 200  
 
 201  
         // Here we have two cases:
 202  
         // 1. The standard script could be put in another target (body or form).
 203  
         // 2. RI is used so it is not used our set to check for rendered resources
 204  
         //    and we don't have access to that one.
 205  
         // 
 206  
         // Check if we have the resource registered on UIViewRoot "body" or "form" target
 207  
         // is not safe, because the page could not use h:body or h:form. 
 208  
         // Anyway, there is no clear reason why page authors could do the first one, 
 209  
         // but the second one could be.
 210  
         //
 211  
         // Finally we need to force render the script. If the script has been already rendered
 212  
         // (RI used and rendered as a h:outputScript not relocated), nothing will happen because the default
 213  
         // script renderer will check if the script has been rendered first.
 214  0
         if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRiImplAvailable())
 215  
         {
 216  
             //Use more compatible way.
 217  0
             UIComponent outputScript = facesContext.getApplication().
 218  
                     createComponent(facesContext, JAVAX_FACES_OUTPUT_COMPONENT_TYPE, DEFAULT_SCRIPT_RENDERER_TYPE);
 219  0
             outputScript.getAttributes().put(JSFAttr.NAME_ATTR, JSF_JS_RESOURCE_NAME);
 220  0
             outputScript.getAttributes().put(JSFAttr.LIBRARY_ATTR, JAVAX_FACES_LIBRARY_NAME);
 221  0
             outputScript.encodeAll(facesContext);
 222  0
         }
 223  
         else
 224  
         {
 225  
             //Fast shortcut, don't create component instance and do what HtmlScriptRenderer do.
 226  0
             Resource resource = facesContext.getApplication().getResourceHandler().createResource(
 227  
                     JSF_JS_RESOURCE_NAME, JAVAX_FACES_LIBRARY_NAME);
 228  0
             markScriptAsRendered(facesContext, JAVAX_FACES_LIBRARY_NAME, JSF_JS_RESOURCE_NAME);
 229  0
             writer.startElement(HTML.SCRIPT_ELEM, null);
 230  0
             writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
 231  0
             writer.writeURIAttribute(HTML.SRC_ATTR, resource.getRequestPath(), null);
 232  0
             writer.endElement(HTML.SCRIPT_ELEM);
 233  
         }
 234  
 
 235  
         //mark as rendered
 236  0
         facesContext.getAttributes().put(RENDERED_JSF_JS, Boolean.TRUE);
 237  0
         return;
 238  
     }
 239  
 
 240  
     public static void renderMyfacesJSInlineIfNecessary(FacesContext facesContext, ResponseWriter writer)
 241  
         throws IOException
 242  
     {
 243  0
         if (facesContext.getAttributes().containsKey(RENDERED_MYFACES_JS))
 244  
         {
 245  0
             return;
 246  
         }
 247  
 
 248  
 
 249  
         //we only are allowed to do this on partial requests
 250  
         //because on normal requests a static viewroot still could mean that a full page refresh is performed
 251  
         //only in a ppr case this means we have the script already loaded and parsed
 252  0
         if (facesContext.getPartialViewContext() != null && 
 253  
                 (facesContext.getPartialViewContext().isPartialRequest() ||
 254  
                  facesContext.getPartialViewContext().isAjaxRequest() )
 255  
             )
 256  
         {
 257  0
             return;
 258  
         }
 259  
         // Check first if we have lucky, we are using myfaces and the script has
 260  
         // been previously rendered
 261  0
         if (isRenderedScript(facesContext, MYFACES_LIBRARY_NAME, MYFACES_JS_RESOURCE_NAME))
 262  
         {
 263  0
             facesContext.getAttributes().put(RENDERED_MYFACES_JS, Boolean.TRUE);
 264  0
             return;
 265  
         }
 266  
 
 267  
         // Here we have two cases:
 268  
         // 1. The standard script could be put in another target (body or form).
 269  
         // 2. RI is used so it is not used our set to check for rendered resources
 270  
         //    and we don't have access to that one.
 271  
         //
 272  
         // Check if we have the resource registered on UIViewRoot "body" or "form" target
 273  
         // is not safe, because the page could not use h:body or h:form.
 274  
         // Anyway, there is no clear reason why page authors could do the first one,
 275  
         // but the second one could be.
 276  
         //
 277  
         // Finally we need to force render the script. If the script has been already rendered
 278  
         // (RI used and rendered as a h:outputScript not relocated), nothing will happen because the default
 279  
         // script renderer will check if the script has been rendered first.
 280  0
         if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isRiImplAvailable())
 281  
         {
 282  
             //Use more compatible way.
 283  0
             UIComponent outputScript = facesContext.getApplication().
 284  
                     createComponent(facesContext, JAVAX_FACES_OUTPUT_COMPONENT_TYPE, DEFAULT_SCRIPT_RENDERER_TYPE);
 285  0
             outputScript.getAttributes().put(JSFAttr.NAME_ATTR, MYFACES_JS_RESOURCE_NAME);
 286  0
             outputScript.getAttributes().put(JSFAttr.LIBRARY_ATTR, MYFACES_LIBRARY_NAME);
 287  0
             outputScript.encodeAll(facesContext);
 288  0
         }
 289  
         else
 290  
         {
 291  
             //Fast shortcut, don't create component instance and do what HtmlScriptRenderer do.
 292  0
             Resource resource = facesContext.getApplication().getResourceHandler().createResource(
 293  
                     MYFACES_JS_RESOURCE_NAME, MYFACES_LIBRARY_NAME);
 294  0
             markScriptAsRendered(facesContext, MYFACES_LIBRARY_NAME, MYFACES_JS_RESOURCE_NAME);
 295  0
             writer.startElement(HTML.SCRIPT_ELEM, null);
 296  0
             writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
 297  0
             writer.writeURIAttribute(HTML.SRC_ATTR, resource.getRequestPath(), null);
 298  0
             writer.endElement(HTML.SCRIPT_ELEM);
 299  
         }
 300  
 
 301  
         //mark as rendered
 302  0
         facesContext.getAttributes().put(RENDERED_MYFACES_JS, Boolean.TRUE);
 303  0
         return;
 304  
     }
 305  
 
 306  
     public static String getContractName(Resource resource)
 307  
     {
 308  0
         while (resource != null)
 309  
         {
 310  0
             if (resource instanceof ContractResource)
 311  
             {
 312  0
                 return ((ContractResource)resource).getContractName();
 313  
             }
 314  0
             else if (resource instanceof FacesWrapper)
 315  
             {
 316  0
                 resource = (Resource)((FacesWrapper)resource).getWrapped();
 317  
             }
 318  
             else
 319  
             {
 320  0
                 resource = null;
 321  
             }
 322  
         }
 323  0
         return null;
 324  
     }
 325  
 }