View Javadoc

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.resource;
20  
21  import java.io.InputStream;
22  import java.net.URL;
23  
24  import javax.faces.application.ProjectStage;
25  import javax.faces.context.FacesContext;
26  
27  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
28  import org.apache.myfaces.shared.resource.AliasResourceMetaImpl;
29  import org.apache.myfaces.shared.resource.ResourceLoader;
30  import org.apache.myfaces.shared.resource.ResourceMeta;
31  import org.apache.myfaces.shared.resource.ResourceMetaImpl;
32  import org.apache.myfaces.shared.util.ClassUtils;
33  import org.apache.myfaces.shared.util.WebConfigParamUtils;
34  import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
35  
36  /**
37   * A resource loader implementation which loads resources from the thread ClassLoader.
38   */
39  public class InternalClassLoaderResourceLoader extends ResourceLoader
40  {
41  
42      /**
43       * If this param is true and the project stage is development mode,
44       * the source javascript files will be loaded separately instead have
45       * all in just one file, to preserve line numbers and make javascript
46       * debugging of the default jsf javascript file more simple.
47       */
48      @JSFWebConfigParam(since = "2.0.1", defaultValue = "false", expectedValues = "true,false", group = "render")
49      public static final String USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS
50              = "org.apache.myfaces.USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS";
51  
52      /**
53       * Define the mode used for jsf.js file:
54       * <ul>
55       * <li>normal : contains everything, including jsf-i18n.js, jsf-experimental.js and jsf-legacy.js</li>
56       * <li>minimal-modern : is the core jsf with a baseline of ie9+,
57       * without jsf-i18n.js, jsf-experimental.js and jsf-legacy.js</li>
58       * <li>minimal: which is the same with a baseline of ie6, without jsf-i18n.js, jsf-experimental.js</li>
59       * </ul>
60       * <p>If org.apache.myfaces.USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS param is set to true and project stage
61       * is Development, this param is ignored.</p>
62       */
63      @JSFWebConfigParam(since = "2.0.10,2.1.4", defaultValue = "normal",
64                         expectedValues = "normal, minimal-modern, minimal", group = "render")
65      public static final String MYFACES_JSF_MODE = "org.apache.myfaces.JSF_JS_MODE";
66      
67      private final boolean _useMultipleJsFilesForJsfUncompressedJs;
68      private final String _jsfMode;
69      private final boolean _developmentStage;
70  
71      public InternalClassLoaderResourceLoader(String prefix)
72      {
73          super(prefix);
74          _useMultipleJsFilesForJsfUncompressedJs
75                  = WebConfigParamUtils.getBooleanInitParameter(FacesContext.getCurrentInstance().getExternalContext(),
76                      USE_MULTIPLE_JS_FILES_FOR_JSF_UNCOMPRESSED_JS, false);
77  
78          _jsfMode = WebConfigParamUtils.getStringInitParameter(FacesContext.getCurrentInstance().getExternalContext(),
79                      MYFACES_JSF_MODE, ResourceUtils.JSF_MYFACES_JSFJS_NORMAL);
80          _developmentStage = FacesContext.getCurrentInstance().isProjectStage(ProjectStage.Development);
81      }
82  
83      @Override
84      public String getLibraryVersion(String path)
85      {
86          return null;
87      }
88  
89      @Override
90      public InputStream getResourceInputStream(ResourceMeta resourceMeta)
91      {
92          InputStream is;
93          if (getPrefix() != null && !"".equals(getPrefix()))
94          {
95              String name = getPrefix() + '/' + resourceMeta.getResourceIdentifier();
96              is = getClassLoader().getResourceAsStream(name);
97              if (is == null)
98              {
99                  is = this.getClass().getClassLoader().getResourceAsStream(name);
100             }
101             return is;
102         }
103         else
104         {
105             is = getClassLoader().getResourceAsStream(resourceMeta.getResourceIdentifier());
106             if (is == null)
107             {
108                 is = this.getClass().getClassLoader().getResourceAsStream(resourceMeta.getResourceIdentifier());
109             }
110             return is;
111         }
112     }
113 
114     public URL getResourceURL(String resourceId)
115     {
116         URL url;
117         if (getPrefix() != null && !"".equals(getPrefix()))
118         {
119             String name = getPrefix() + '/' + resourceId;
120             url = getClassLoader().getResource(name);
121             if (url == null)
122             {
123                 url = this.getClass().getClassLoader().getResource(name);
124             }
125             return url;
126         }
127         else
128         {
129             url = getClassLoader().getResource(resourceId);
130             if (url == null)
131             {
132                 url = this.getClass().getClassLoader().getResource(resourceId);
133             }
134             return url;
135         }
136     }
137     
138     @Override
139     public URL getResourceURL(ResourceMeta resourceMeta)
140     {
141         return getResourceURL(resourceMeta.getResourceIdentifier());
142     }
143 
144     @Override
145     public String getResourceVersion(String path)
146     {
147         return null;
148     }
149 
150     @Override
151     public ResourceMeta createResourceMeta(String prefix, String libraryName, String libraryVersion,
152                                            String resourceName, String resourceVersion)
153     {
154         //handle jsf.js
155         final boolean javaxFacesLib = libraryName != null &&
156         ResourceUtils.JAVAX_FACES_LIBRARY_NAME.equals(libraryName);
157         final boolean javaxFaces = javaxFacesLib &&
158                 ResourceUtils.JSF_JS_RESOURCE_NAME.equals(resourceName);
159 
160         if (javaxFaces)
161         {
162             if (_developmentStage)
163             {
164                 if (_useMultipleJsFilesForJsfUncompressedJs)
165                 {
166                     return new AliasResourceMetaImpl(prefix, libraryName, libraryVersion,
167                             resourceName, resourceVersion, ResourceUtils.JSF_UNCOMPRESSED_JS_RESOURCE_NAME, true);
168                 }
169                 else
170                 {
171                     //normall we would have to take care about the standard jsf.js case also
172                     //but our standard resource loader takes care of it,
173                     // because this part is only called in debugging mode
174                     //in production only in debugging
175                     return new AliasResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion,
176                                                      "jsf-uncompressed-full.js", false);
177                 }
178             }
179             else if (_jsfMode.equals(ResourceUtils.JSF_MYFACES_JSFJS_MINIMAL) )
180             {
181                 return new AliasResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion,
182                         ResourceUtils.JSF_MINIMAL_JS_RESOURCE_NAME, false);
183             }
184             else if (_jsfMode.equals(ResourceUtils.JSF_MYFACES_JSFJS_MINIMAL_MODERN) )
185             {
186                 return new AliasResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion,
187                         ResourceUtils.JSF_MINIMAL_MODERN_JS_RESOURCE_NAME, false);
188             }
189             else
190             {
191                 return null;
192             }
193         }
194         else if (javaxFacesLib && !_developmentStage && !_jsfMode.equals(ResourceUtils.JSF_MYFACES_JSFJS_NORMAL) &&
195                                    (ResourceUtils.JSF_MYFACES_JSFJS_I18N.equals(resourceName) ||
196                                    ResourceUtils.JSF_MYFACES_JSFJS_EXPERIMENTAL.equals(resourceName) ||
197                                    ResourceUtils.JSF_MYFACES_JSFJS_LEGACY.equals(resourceName)) )
198         {
199             return new ResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion);
200         }
201         else if (_developmentStage && libraryName != null &&
202                 ResourceUtils.MYFACES_LIBRARY_NAME.equals(libraryName) &&
203                 ResourceUtils.MYFACES_JS_RESOURCE_NAME.equals(resourceName))
204         {
205             //handle the oamSubmit.js
206             return new AliasResourceMetaImpl(prefix, libraryName, libraryVersion,
207                     resourceName, resourceVersion, ResourceUtils.MYFACES_JS_RESOURCE_NAME_UNCOMPRESSED, true);
208         }
209         else if (_developmentStage && libraryName != null && libraryName.startsWith("org.apache.myfaces.core"))
210         {
211             return new ResourceMetaImpl(prefix, libraryName, libraryVersion, resourceName, resourceVersion);
212         }
213         else
214         {
215             return null;
216         }
217     }
218 
219     /**
220      * Returns the ClassLoader to use when looking up resources under the top level package. By default, this is the
221      * context class loader.
222      *
223      * @return the ClassLoader used to lookup resources
224      */
225     protected ClassLoader getClassLoader()
226     {
227         return ClassUtils.getContextClassLoader();
228     }
229 
230     @Override
231     public boolean libraryExists(String libraryName)
232     {
233         if (getPrefix() != null && !"".equals(getPrefix()))
234         {
235             URL url = getClassLoader().getResource(getPrefix() + '/' + libraryName);
236             if (url == null)
237             {
238                 url = this.getClass().getClassLoader().getResource(getPrefix() + '/' + libraryName);
239             }
240             if (url != null)
241             {
242                 return true;
243             }
244         }
245         else
246         {
247             URL url = getClassLoader().getResource(libraryName);
248             if (url == null)
249             {
250                 url = this.getClass().getClassLoader().getResource(libraryName);
251             }
252             if (url != null)
253             {
254                 return true;
255             }
256         }
257         return false;
258     }
259 
260 }