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