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  
20  package org.apache.myfaces.shared_orchestra.config;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  import org.apache.myfaces.shared_orchestra.util.ClassUtils;
26  import javax.faces.context.ExternalContext;
27  import javax.servlet.ServletContext;
28  
29  /**
30   * Holds all configuration init parameters (from web.xml) that are independent
31   * from the core implementation. The parameters in this class are available to
32   * all shared, component and implementation classes.
33   * See RuntimeConfig for configuration infos that come from the faces-config
34   * files and are needed by the core implementation.
35   *
36   * MyfacesConfig is meant for components that implement some of the extended features
37   * of MyFaces. Anyhow, using the MyFaces JSF implementation is no precondition for using
38   * MyfacesConfig in custom components. Upon using another JSF implementation
39   * (or omitting the extended init parameters) all config properties will simply have
40   * their default values.
41   *
42   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
43   * @version $Revision: 682429 $ $Date: 2008-08-04 10:55:32 -0500 (Mon, 04 Aug 2008) $
44   */
45  public class MyfacesConfig
46  {
47      private static final Log log = LogFactory.getLog(MyfacesConfig.class);
48  
49      private static final String APPLICATION_MAP_PARAM_NAME = MyfacesConfig.class.getName();
50  
51      public static final String INIT_PARAM_CONFIG_REFRESH_PERIOD = "org.apache.myfaces.CONFIG_REFRESH_PERIOD";
52      public static final long INIT_PARAM_CONFIG_REFRESH_PERIOD_DEFAULT = 2;
53  
54      public static final String  INIT_PARAM_RESOURCE_VIRTUAL_PATH = "org.apache.myfaces.RESOURCE_VIRTUAL_PATH";
55      public static final String  INIT_PARAM_RESOURCE_VIRTUAL_PATH_DEFAULT = "/faces/myFacesExtensionResource";
56  
57      private static final String  INIT_PARAM_PRETTY_HTML = "org.apache.myfaces.PRETTY_HTML";
58      private static final boolean INIT_PARAM_PRETTY_HTML_DEFAULT = true;
59  
60      private static final String  INIT_PARAM_ALLOW_JAVASCRIPT = "org.apache.myfaces.ALLOW_JAVASCRIPT";
61      private static final boolean INIT_PARAM_ALLOW_JAVASCRIPT_DEFAULT = true;
62  
63      private static final String  INIT_PARAM_DETECT_JAVASCRIPT = "org.apache.myfaces.DETECT_JAVASCRIPT";
64      private static final boolean INIT_PARAM_DETECT_JAVASCRIPT_DEFAULT = false;
65  
66      private static final String  INIT_PARAM_AUTO_SCROLL = "org.apache.myfaces.AUTO_SCROLL";
67      private static final boolean INIT_PARAM_AUTO_SCROLL_DEFAULT = false;
68  
69      private static final String INIT_PARAM_ADD_RESOURCE_CLASS = "org.apache.myfaces.ADD_RESOURCE_CLASS";
70      private static final String INIT_PARAM_ADD_RESOURCE_CLASS_DEFAULT = "org.apache.myfaces.renderkit.html.util.DefaultAddResource";
71  
72      private static final String  INIT_CHECK_EXTENSIONS_FILTER = "org.apache.myfaces.CHECK_EXTENSIONS_FILTER";
73      private static final boolean INIT_CHECK_EXTENSIONS_FILTER_DEFAULT = true;
74  
75      private static final String INIT_READONLY_AS_DISABLED_FOR_SELECT = "org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS";
76      private static final boolean INIT_READONLY_AS_DISABLED_FOR_SELECT_DEFAULT = true;
77  
78      private static final String  INIT_PARAM_RENDER_VIEWSTATE_ID = "org.apache.myfaces.RENDER_VIEWSTATE_ID";
79      private static final boolean INIT_PARAM_RENDER_VIEWSTATE_ID_DEFAULT = true;
80  
81      private static final String  INIT_PARAM_STRICT_XHTML_LINKS = "org.apache.myfaces.STRICT_XHTML_LINKS";
82      private static final boolean INIT_PARAM_STRICT_XHTML_LINKS_DEFAULT = true;
83  
84      private boolean _prettyHtml;
85      private boolean _detectJavascript;
86      private boolean _allowJavascript;
87      private boolean _autoScroll;
88      private long _configRefreshPeriod;
89      private String _addResourceClass;
90      private String _resourceVirtualPath;
91      private boolean _checkExtensionsFilter;
92      private boolean _readonlyAsDisabledForSelect;
93      private boolean _renderViewStateId;
94      private boolean _strictXhtmlLinks;
95  
96      private static final boolean TOMAHAWK_AVAILABLE;
97      private static final boolean MYFACES_IMPL_AVAILABLE;
98      private static final boolean RI_IMPL_AVAILABLE;
99      
100     static
101     {
102         boolean tomahawkAvailable;
103         try
104         {
105             ClassUtils.classForName("org.apache.myfaces.webapp.filter.ExtensionsFilter");
106             tomahawkAvailable = true;
107         }
108         catch (ClassNotFoundException e)
109         {
110             tomahawkAvailable = false;
111         }
112         TOMAHAWK_AVAILABLE = tomahawkAvailable;
113     }
114 
115     static
116     {
117         boolean myfacesImplAvailable;
118         try
119         {
120             ClassUtils.classForName("org.apache.myfaces.application.ApplicationImpl");
121             myfacesImplAvailable = true;
122         }
123         catch (ClassNotFoundException e)
124         {
125             myfacesImplAvailable = false;
126         }
127         MYFACES_IMPL_AVAILABLE = myfacesImplAvailable;
128     }
129 
130     static
131     {
132         boolean riImplAvailable;
133         try
134         {
135             ClassUtils.classForName("com.sun.faces.application.ApplicationImpl");
136             riImplAvailable = true;
137         }
138         catch (ClassNotFoundException e)
139         {
140             riImplAvailable = false;
141         }
142         RI_IMPL_AVAILABLE = riImplAvailable;
143     }
144     
145     public static MyfacesConfig getCurrentInstance(ExternalContext extCtx)
146     {
147         MyfacesConfig myfacesConfig = (MyfacesConfig)extCtx
148                                         .getApplicationMap().get(APPLICATION_MAP_PARAM_NAME);
149         if (myfacesConfig == null) 
150         {
151             
152             myfacesConfig = createAndInitializeMyFacesConfig(extCtx);
153             
154             extCtx.getApplicationMap().put(APPLICATION_MAP_PARAM_NAME, myfacesConfig);
155             
156         }
157 
158         return myfacesConfig;
159     }
160 
161     private static MyfacesConfig createAndInitializeMyFacesConfig(ExternalContext extCtx) {
162         MyfacesConfig myfacesConfig = new MyfacesConfig();
163 
164         myfacesConfig.setPrettyHtml(getBooleanInitParameter(extCtx, INIT_PARAM_PRETTY_HTML,
165                                                             INIT_PARAM_PRETTY_HTML_DEFAULT));
166         myfacesConfig.setAllowJavascript(getBooleanInitParameter(extCtx, INIT_PARAM_ALLOW_JAVASCRIPT,
167                                                                  INIT_PARAM_ALLOW_JAVASCRIPT_DEFAULT));
168 
169         myfacesConfig.setReadonlyAsDisabledForSelect(getBooleanInitParameter(extCtx, INIT_READONLY_AS_DISABLED_FOR_SELECT,
170                                                                  INIT_READONLY_AS_DISABLED_FOR_SELECT_DEFAULT));
171         myfacesConfig.setRenderViewStateId(getBooleanInitParameter(extCtx, INIT_PARAM_RENDER_VIEWSTATE_ID,
172                                                                    INIT_PARAM_RENDER_VIEWSTATE_ID_DEFAULT));
173         myfacesConfig.setStrictXhtmlLinks(getBooleanInitParameter(extCtx, INIT_PARAM_STRICT_XHTML_LINKS,
174                                                                   INIT_PARAM_STRICT_XHTML_LINKS_DEFAULT));
175 
176         myfacesConfig.setConfigRefreshPeriod(getLongInitParameter(extCtx, INIT_PARAM_CONFIG_REFRESH_PERIOD,
177                 INIT_PARAM_CONFIG_REFRESH_PERIOD_DEFAULT));
178 
179         if (TOMAHAWK_AVAILABLE)
180         {
181             myfacesConfig.setDetectJavascript(getBooleanInitParameter(extCtx, INIT_PARAM_DETECT_JAVASCRIPT,
182                 INIT_PARAM_DETECT_JAVASCRIPT_DEFAULT));
183             myfacesConfig.setAutoScroll(getBooleanInitParameter(extCtx, INIT_PARAM_AUTO_SCROLL,
184                     INIT_PARAM_AUTO_SCROLL_DEFAULT));
185             myfacesConfig.setAddResourceClass(getStringInitParameter(extCtx, INIT_PARAM_ADD_RESOURCE_CLASS,
186                                                                      INIT_PARAM_ADD_RESOURCE_CLASS_DEFAULT));
187             myfacesConfig.setResourceVirtualPath(getStringInitParameter(extCtx, INIT_PARAM_RESOURCE_VIRTUAL_PATH,
188                     INIT_PARAM_RESOURCE_VIRTUAL_PATH_DEFAULT));
189 
190             myfacesConfig.setCheckExtensionsFilter(getBooleanInitParameter(extCtx, INIT_CHECK_EXTENSIONS_FILTER,
191                     INIT_CHECK_EXTENSIONS_FILTER_DEFAULT));
192         }
193         else
194         {
195             if (log.isInfoEnabled())
196             {
197                 log.info("Tomahawk jar not available. Autoscrolling, DetectJavascript, AddResourceClass and CheckExtensionsFilter are disabled now.");
198             }
199         }
200 
201         if(RI_IMPL_AVAILABLE)
202         {
203             if(log.isInfoEnabled())
204             {
205                 log.info("Starting up Tomahawk on the RI-JSF-Implementation.");
206             }
207         }
208 
209         if(MYFACES_IMPL_AVAILABLE)
210         {
211             if(log.isInfoEnabled())
212             {
213                 log.info("Starting up Tomahawk on the MyFaces-JSF-Implementation");
214             }
215         }
216 
217         if(RI_IMPL_AVAILABLE && MYFACES_IMPL_AVAILABLE)
218         {
219             log.error("Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.");
220         }
221         return myfacesConfig;
222     }
223 
224     private static boolean getBooleanInitParameter(ExternalContext externalContext,
225                                                    String paramName,
226                                                    boolean defaultValue)
227     {
228         String strValue = externalContext.getInitParameter(paramName);
229         if (strValue == null)
230         {
231             if (log.isInfoEnabled()) log.info("No context init parameter '" + paramName + "' found, using default value " + defaultValue);
232             return defaultValue;
233         }
234         else if (strValue.equalsIgnoreCase("true") || strValue.equalsIgnoreCase("on") || strValue.equalsIgnoreCase("yes"))
235         {
236             return true;
237         }
238         else if (strValue.equalsIgnoreCase("false") || strValue.equalsIgnoreCase("off") || strValue.equalsIgnoreCase("no"))
239         {
240             return false;
241         }
242         else
243         {
244             if (log.isWarnEnabled()) log.warn("Wrong context init parameter '" + paramName + "' (='" + strValue + "'), using default value " + defaultValue);
245             return defaultValue;
246         }
247     }
248 
249     private static long getLongInitParameter(ExternalContext externalContext,
250                                                    String paramName,
251                                                    long defaultValue)
252     {
253         String strValue = externalContext.getInitParameter(paramName);
254         if (strValue == null)
255         {
256             if (log.isInfoEnabled()) log.info("No context init parameter '" + paramName + "' found, using default value " + defaultValue);
257             return defaultValue;
258         }
259         else
260         {
261             try {
262                 return Long.parseLong(strValue);
263             } catch (NumberFormatException e) {
264                 if (log.isWarnEnabled()) log.warn("Wrong context init parameter '" + paramName + "' (='" + strValue + "'), using default value " + defaultValue);
265             }
266             return defaultValue;
267         }
268     }
269 
270     private static String getStringInitParameter(ExternalContext externalContext,
271                                                  String paramName,
272                                                  String defaultValue)
273     {
274         String strValue = externalContext.getInitParameter(paramName);
275         if (strValue == null)
276         {
277             if (log.isInfoEnabled()) log.info("No context init parameter '" + paramName + "' found, using default value " + defaultValue); //defaultValue==null should not be a problem here
278             return defaultValue;
279         }
280         else
281         {
282             return strValue;
283         }
284     }
285 
286      private void setResourceVirtualPath( String resourceVirtualPath )
287      {
288          this._resourceVirtualPath = resourceVirtualPath;
289      }
290 
291      public String getResourceVirtualPath()
292      {
293          return this._resourceVirtualPath;
294      }
295 
296     public boolean isPrettyHtml()
297     {
298         return _prettyHtml;
299     }
300 
301     private void setPrettyHtml(boolean prettyHtml)
302     {
303         _prettyHtml = prettyHtml;
304     }
305 
306     public boolean isDetectJavascript()
307     {
308         return _detectJavascript;
309     }
310 
311     private void setDetectJavascript(boolean detectJavascript)
312     {
313         _detectJavascript = detectJavascript;
314     }
315 
316     private void setReadonlyAsDisabledForSelect(boolean readonlyAsDisabledForSelect)
317     {
318         _readonlyAsDisabledForSelect = readonlyAsDisabledForSelect;
319     }
320 
321     public boolean isReadonlyAsDisabledForSelect()
322     {
323         return _readonlyAsDisabledForSelect;
324     }
325 
326     /**
327      * JSF API 1.2 defines a "javax.faces.ViewState" client parameter, that must be rendered as both the "name"
328      * and the "id" attribute of the hidden input that is rendered for the purpose of state saving
329      * (see <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/javax/faces/render/ResponseStateManager.html#VIEW_STATE_PARAM">API</a>).
330      * Actually this causes duplicate id attributes and thus invalid XHTML pages when multiple forms are rendered on
331      * one page. With the {@link #INIT_PARAM_RENDER_VIEWSTATE_ID} context parameter you can tune this behaviour.
332      * <br/>Set it to
333      * <ul><li>true - to render JSF 1.2 compliant id attributes (that might cause invalid XHTML), or</li>
334      * <li>false - to omit rendering of the id attribute (which is only needed for very special AJAX/Javascript components)</li></ul>
335      * Default value is: true (for backwards compatibility and JSF 1.2 compliancy) 
336      * @return true, if the client state hidden input "javax.faces.ViewState" id attribute should be rendered
337      */
338     public boolean isRenderViewStateId() {
339         return _renderViewStateId;
340     }
341 
342     public void setRenderViewStateId(boolean renderViewStateId) {
343         _renderViewStateId = renderViewStateId;
344     }
345 
346     /**
347      * <p>W3C recommends to use the "&amp;amp;" entity instead of a plain "&amp;" character within HTML.
348      * This also applies to attribute values and thus to the "href" attribute of &lt;a&gt; elements as well.
349      * Even more, when XHTML is used as output the usage of plain "&amp;" characters is forbidden and would lead to
350      * invalid XML code.
351      * Therefore, since version 1.1.6 MyFaces renders the correct "&amp;amp;" entity for links.</p>
352      * <p>The init parameter
353      * {@link #INIT_PARAM_STRICT_XHTML_LINKS} makes it possible to restore the old behaviour and to make MyFaces
354      * "bug compatible" to the Sun RI which renders plain "&amp;" chars in links as well.</p>
355      * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3.2">HTML 4.01 Specification</a>
356      * @see <a href="http://issues.apache.org/jira/browse/MYFACES-1774">Jira: MYFACES-1774</a>
357      * @return true if ampersand characters ("&amp;") should be correctly rendered as "&amp;amp;" entities within link urls (=default),
358      *         false for old (XHTML incompatible) behaviour
359      */
360     public boolean isStrictXhtmlLinks() {
361         return _strictXhtmlLinks;
362     }
363 
364     public void setStrictXhtmlLinks(boolean strictXhtmlLinks) {
365         _strictXhtmlLinks = strictXhtmlLinks;
366     }
367 
368     public boolean isTomahawkAvailable()
369     {
370         return TOMAHAWK_AVAILABLE;
371     }
372 
373     public boolean isMyfacesImplAvailable()
374     {
375         return MYFACES_IMPL_AVAILABLE;
376     }
377 
378     public boolean isRiImplAvailable()
379     {
380         return RI_IMPL_AVAILABLE;
381     }
382 
383     /**
384      * Do not use this in renderers directly!
385      * You should use {@link org.apache.myfaces.shared_orchestra.renderkit.html.util.JavascriptUtils#isJavascriptAllowed}
386      * to determine if javascript is allowed or not.
387      */
388     public boolean isAllowJavascript()
389     {
390         return _allowJavascript;
391     }
392 
393     private void setAllowJavascript(boolean allowJavascript)
394     {
395         _allowJavascript = allowJavascript;
396     }
397 
398     public boolean isAutoScroll()
399     {
400         return _autoScroll;
401     }
402 
403     private void setAutoScroll(boolean autoScroll)
404     {
405         _autoScroll = autoScroll;
406     }
407 
408     private void setAddResourceClass(String addResourceClass)
409     {
410         _addResourceClass = addResourceClass;
411     }
412 
413     public String getAddResourceClass()
414     {
415         return _addResourceClass;
416     }
417 
418     /**
419      * ExtensionFilter needs access to AddResourceClass init param without having
420      * an ExternalContext at hand.
421      */
422     public static String getAddResourceClassFromServletContext(ServletContext servletContext)
423     {
424         String addResourceClass = servletContext.getInitParameter(INIT_PARAM_ADD_RESOURCE_CLASS);
425         if (addResourceClass == null)
426         {
427             return INIT_PARAM_ADD_RESOURCE_CLASS_DEFAULT;
428         }
429         else
430         {
431             return addResourceClass;
432         }
433     }
434 
435     /**
436      * Should the environment be checked so that the ExtensionsFilter will work properly. 
437      */
438     public boolean isCheckExtensionsFilter()
439     {
440         return _checkExtensionsFilter;
441     }
442 
443     public void setCheckExtensionsFilter(boolean extensionsFilter)
444     {
445         _checkExtensionsFilter = extensionsFilter;
446     }
447 
448     public long getConfigRefreshPeriod() {
449         return _configRefreshPeriod;
450     }
451 
452     public void setConfigRefreshPeriod(long configRefreshPeriod) {
453         _configRefreshPeriod = configRefreshPeriod;
454     }
455 }