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.view;
20  
21  import java.util.logging.Level;
22  import java.util.logging.Logger;
23  
24  import javax.faces.context.FacesContext;
25  import javax.faces.view.ViewDeclarationLanguage;
26  import javax.faces.view.ViewDeclarationLanguageFactory;
27  
28  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
29  import org.apache.myfaces.shared.config.MyfacesConfig;
30  import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguageStrategy;
31  import org.apache.myfaces.view.jsp.JspViewDeclarationLanguageStrategy;
32  
33  /**
34   * This is the default VDL factory used as of JSF 2.0, it tries to use Facelet VDL whenever possible, 
35   * but fallback on JSP if required.
36   * 
37   * @author Simon Lessard (latest modification by $Author: lu4242 $)
38   * @version $Revision: 1545492 $ $Date: 2013-11-25 20:19:50 -0500 (Mon, 25 Nov 2013) $
39   *
40   * @since 2.0
41   */
42  public class ViewDeclarationLanguageFactoryImpl extends ViewDeclarationLanguageFactory
43  {
44      /**
45       * Disable facelets VDL from the current application project. 
46       */
47      @JSFWebConfigParam(since="2.0", defaultValue="false", expectedValues="true,false", group="viewhandler")
48      public static final String PARAM_DISABLE_JSF_FACELET = "javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER";
49  
50      private static final String FACELETS_1_VIEW_HANDLER = "com.sun.facelets.FaceletViewHandler";
51  
52      private static final Logger LOGGER = Logger.getLogger(ViewDeclarationLanguageFactoryImpl.class.getName());
53      
54      private volatile boolean _initialized;
55      private volatile ViewDeclarationLanguageStrategy[] _supportedLanguages;
56      
57      /**
58       * 
59       */
60      public ViewDeclarationLanguageFactoryImpl()
61      {
62          _initialized = false;
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      public ViewDeclarationLanguage getViewDeclarationLanguage(String viewId)
70      {
71          if (!_initialized)
72          {
73              initialize();
74          }
75          
76          for (ViewDeclarationLanguageStrategy strategy : _supportedLanguages)
77          {
78              if (strategy.handles(viewId))
79              {
80                  return strategy.getViewDeclarationLanguage();
81              }
82          }
83          
84          return null;
85      }
86      
87      /**
88       * Initialize the supported view declaration languages.
89       */
90      private synchronized void initialize()
91      {
92          if (!_initialized)
93          {
94              FacesContext context = FacesContext.getCurrentInstance();
95  
96              if (isFacelets2Enabled(context))
97              {
98                  logWarningIfLegacyFaceletViewHandlerIsPresent(context);
99  
100                 if (MyfacesConfig.getCurrentInstance(
101                         context.getExternalContext()).isSupportJSPAndFacesEL())
102                 {
103                     _supportedLanguages = new ViewDeclarationLanguageStrategy[2];
104                     _supportedLanguages[0] = new FaceletViewDeclarationLanguageStrategy();
105                     _supportedLanguages[1] = new JspViewDeclarationLanguageStrategy();
106                 }
107                 else
108                 {
109                     _supportedLanguages = new ViewDeclarationLanguageStrategy[1];
110                     _supportedLanguages[0] = new FaceletViewDeclarationLanguageStrategy();
111                 }
112             }
113             else
114             {
115                 // Support JSP only
116                 _supportedLanguages = new ViewDeclarationLanguageStrategy[1];
117                 _supportedLanguages[0] = new JspViewDeclarationLanguageStrategy();
118             }
119 
120             _initialized = true;
121         }
122     }
123     
124     /**
125      * Determines if the current application uses Facelets-2.
126      * To accomplish that it looks at the init param javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER,
127      * 
128      * @param context the <code>FacesContext</code>
129      * @return <code>true</code> if the current application uses the built in Facelets-2,
130      *         <code>false</code> otherwise (e.g. it uses Facelets-1 or only JSP).
131      */
132     private boolean isFacelets2Enabled(FacesContext context)
133     {
134         String param = context.getExternalContext().getInitParameter(PARAM_DISABLE_JSF_FACELET);
135         boolean facelets2ParamDisabled = (param != null && Boolean.parseBoolean(param.toLowerCase()));
136         
137         return !facelets2ParamDisabled;
138     }
139     
140     /**
141      * If the Facelets-1 ViewHandler com.sun.facelets.FaceletViewHandler is present <b>AND</b>
142      * the new Facelets-2 is <b>NOT</b> disabled, we log a <code>WARNING</code>. 
143      * 
144      * @param context the <code>FacesContext</code>
145      */
146     private void logWarningIfLegacyFaceletViewHandlerIsPresent(FacesContext context)
147     {
148         boolean facelets1ViewHandlerPresent
149                 = context.getApplication().getViewHandler().getClass().getName().equals(FACELETS_1_VIEW_HANDLER);
150 
151         if (facelets1ViewHandlerPresent)
152         {
153             if (LOGGER.isLoggable(Level.WARNING))
154             {
155                 LOGGER.log(Level.WARNING, "Your faces-config.xml contains the " + FACELETS_1_VIEW_HANDLER + " class."
156                     + "\nYou need to remove it since you have not disabled the \"new\" Facelets-2 version with the "
157                     + PARAM_DISABLE_JSF_FACELET + " context parameter");
158             }
159         }
160     }
161 }