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.facelets.compiler;
20  
21  import java.util.List;
22  import java.util.logging.Level;
23  import java.util.logging.Logger;
24  import javax.faces.application.ViewHandler;
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.UIViewRoot;
27  import javax.faces.context.ExternalContext;
28  import javax.faces.context.FacesContext;
29  import javax.faces.context.FacesContextWrapper;
30  import javax.faces.view.facelets.TagDecorator;
31  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
32  import org.apache.myfaces.config.RuntimeConfig;
33  import org.apache.myfaces.config.element.ComponentTagDeclaration;
34  import org.apache.myfaces.config.element.facelets.FaceletTagLibrary;
35  import org.apache.myfaces.shared.config.MyfacesConfig;
36  import org.apache.myfaces.shared.util.WebConfigParamUtils;
37  import org.apache.myfaces.view.facelets.tag.ComponentTagDeclarationLibrary;
38  import org.apache.myfaces.view.facelets.tag.TagLibrary;
39  import org.apache.myfaces.view.facelets.tag.composite.CompositeLibrary;
40  import org.apache.myfaces.view.facelets.tag.composite.CompositeResourceLibrary;
41  import org.apache.myfaces.view.facelets.tag.jsf.JsfLibrary;
42  import org.apache.myfaces.view.facelets.tag.jsf.PassThroughLibrary;
43  import org.apache.myfaces.view.facelets.tag.jsf.core.CoreLibrary;
44  import org.apache.myfaces.view.facelets.tag.jsf.html.HtmlLibrary;
45  import org.apache.myfaces.view.facelets.tag.jstl.core.JstlCoreLibrary;
46  import org.apache.myfaces.view.facelets.tag.jstl.core.LegacyJstlCoreLibrary;
47  import org.apache.myfaces.view.facelets.tag.jstl.fn.JstlFnLibrary;
48  import org.apache.myfaces.view.facelets.tag.ui.LegacyUILibrary;
49  import org.apache.myfaces.view.facelets.tag.ui.UILibrary;
50  import org.apache.myfaces.view.facelets.util.ReflectionUtil;
51  
52  /**
53   * Perform initialization steps for facelets compiler
54   *
55   * @since 2.2
56   */
57  public class FaceletsCompilerSupport
58  {
59      private static final Logger log = Logger.getLogger(FaceletsCompilerSupport.class.getName());
60      
61      /**
62       * Set of class names, separated by ';', implementing TagDecorator interface, used to transform
63       * a view definition in a facelet abstract syntax tree, that is used later to generate a component tree.
64       */
65      @JSFWebConfigParam(since = "2.0", deprecated = true)
66      private final static String PARAM_DECORATORS_DEPRECATED = "facelets.DECORATORS";
67  
68      private final static String[] PARAMS_DECORATORS = {ViewHandler.FACELETS_DECORATORS_PARAM_NAME, 
69          PARAM_DECORATORS_DEPRECATED};
70      
71      /**
72       * Skip comments found on a facelet file.
73       */
74      @JSFWebConfigParam(since = "2.0", deprecated = true)
75      private final static String PARAM_SKIP_COMMENTS_DEPRECATED = "facelets.SKIP_COMMENTS";
76  
77      private final static String[] PARAMS_SKIP_COMMENTS = {ViewHandler.FACELETS_SKIP_COMMENTS_PARAM_NAME,
78          PARAM_SKIP_COMMENTS_DEPRECATED};
79      
80      /**
81       * Load the various tag libraries for Facelets.
82       *
83       * @param context
84       *            the current FacesContext
85       * @param compiler
86       *            the page compiler
87       */
88      public void loadLibraries(FacesContext context, Compiler compiler)
89      {
90          ExternalContext eContext = context.getExternalContext();
91          MyfacesConfig config = MyfacesConfig.getCurrentInstance(eContext);
92  
93          // Initialize Runtime Libraries
94          compiler.addTagLibrary(new CoreLibrary());
95          compiler.addTagLibrary(new HtmlLibrary());
96          if (config.isStrictJsf2FaceletsCompatibility())
97          {
98              compiler.addTagLibrary(new LegacyUILibrary());
99              compiler.addTagLibrary(new LegacyJstlCoreLibrary());
100             compiler.addTagLibrary(new LegacyJstlCoreLibrary(JstlCoreLibrary.ALTERNATIVE_NAMESPACE));
101         }
102         else
103         {
104             compiler.addTagLibrary(new UILibrary());
105             compiler.addTagLibrary(new JstlCoreLibrary());
106             compiler.addTagLibrary(new JstlCoreLibrary(JstlCoreLibrary.ALTERNATIVE_NAMESPACE));            
107         }
108         compiler.addTagLibrary(new JstlFnLibrary());
109         compiler.addTagLibrary(new CompositeLibrary());
110         compiler.addTagLibrary(new CompositeResourceLibrary(context,
111             CompositeResourceLibrary.NAMESPACE_PREFIX));
112         compiler.addTagLibrary(new CompositeResourceLibrary(context,
113             CompositeResourceLibrary.ALIAS_NAMESPACE_PREFIX));
114         compiler.addTagLibrary(new JsfLibrary());
115         compiler.addTagLibrary(new PassThroughLibrary());
116         
117         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(eContext);
118         if (!runtimeConfig.getComponentTagDeclarations().isEmpty())
119         {
120             // Set a dummy view root, to avoid Application.createComponent() to fail
121             ComponentTagDeclarationLibrary componentTagDeclarationLibrary = new ComponentTagDeclarationLibrary();
122             
123             LoadComponentTagDeclarationFacesContextWrapper wrappedFacesContext = 
124                 new LoadComponentTagDeclarationFacesContextWrapper(context);
125             try
126             {
127                 wrappedFacesContext.setWrapperAsCurrentFacesContext();
128                 UIViewRoot root = new UIViewRoot();
129                 root.setRenderKitId("HTML_BASIC");
130                 wrappedFacesContext.setViewRoot(new UIViewRoot());
131                 
132                 for (ComponentTagDeclaration declaration : runtimeConfig.getComponentTagDeclarations())
133                 {
134                     // We have here probably an inconsistency, because the annotation does not
135                     // have a default renderer type. Let the renderer type be null will cause problems 
136                     // later, because application.createComponent() may not scan the renderer class if
137                     // a rendererType is not provided. The easy way to overcome this situation is create
138                     // a dummy instance and check its rendererType. If is set the renderer if any will be
139                     // scanned for annotations, if not it just do things as usual. It is unlikely to create
140                     // a component and does not set a default renderer type if is required.
141                     UIComponent component = context.getApplication().createComponent(declaration.getComponentType());
142                     componentTagDeclarationLibrary.addComponent(declaration.getNamespace(), 
143                             declaration.getTagName(), declaration.getComponentType(), component.getRendererType());
144                 }
145             }
146             finally
147             {
148                 wrappedFacesContext.restoreCurrentFacesContext();
149             }
150             compiler.addTagLibrary(componentTagDeclarationLibrary);
151         }
152         
153         List<FaceletTagLibrary> faceletTagLibraries = runtimeConfig.getFaceletTagLibraries();
154         for (FaceletTagLibrary faceletTagLibrary : faceletTagLibraries)
155         {
156             //Create TagLibrary here, populate and add it to the compiler.
157             TagLibrary tl = TagLibraryConfig.create(context, faceletTagLibrary);
158             if (tl != null)
159             {
160                 compiler.addTagLibrary(tl);
161             }
162         }
163     }
164     
165     /**
166      * Load the various decorators for Facelets.
167      *
168      * @param context
169      *            the current FacesContext
170      * @param compiler
171      *            the page compiler
172      */
173     public void loadDecorators(FacesContext context, Compiler compiler)
174     {
175         String param = WebConfigParamUtils.getStringInitParameter(context.getExternalContext(), PARAMS_DECORATORS);
176         if (param != null)
177         {
178             for (String decorator : param.split(";"))
179             {
180                 try
181                 {
182                     compiler.addTagDecorator((TagDecorator) ReflectionUtil.forName(decorator).newInstance());
183                     if (log.isLoggable(Level.FINE))
184                     {
185                         log.fine("Successfully loaded decorator: " + decorator);
186                     }
187                 }
188                 catch (Exception e)
189                 {
190                     log.log(Level.SEVERE, "Error Loading decorator: " + decorator, e);
191                 }
192             }
193         }
194     }
195     
196     public void loadOptions(FacesContext context, Compiler compiler)
197     {
198         ExternalContext eContext = context.getExternalContext();
199 
200         // skip comments?
201         compiler.setTrimmingComments(WebConfigParamUtils.getBooleanInitParameter(
202                 eContext, PARAMS_SKIP_COMMENTS, false));
203         
204         compiler.setFaceletsProcessingConfigurations(
205                 RuntimeConfig.getCurrentInstance(
206                         context.getExternalContext()).getFaceletProcessingConfigurations());
207     }
208     
209     private static class LoadComponentTagDeclarationFacesContextWrapper 
210         extends FacesContextWrapper
211     {
212         private FacesContext delegate;
213         private UIViewRoot root;
214 
215         public LoadComponentTagDeclarationFacesContextWrapper(FacesContext delegate)
216         {
217             this.delegate = delegate;
218         }
219 
220         @Override
221         public UIViewRoot getViewRoot()
222         {
223             return root;
224         }
225 
226         @Override
227         public void setViewRoot(UIViewRoot root)
228         {
229             this.root = root;
230         }
231         
232         @Override
233         public FacesContext getWrapped()
234         {
235             return delegate;
236         }
237         
238         void setWrapperAsCurrentFacesContext()
239         {
240             setCurrentInstance(this);
241         }
242         
243         void restoreCurrentFacesContext()
244         {
245             setCurrentInstance(delegate);
246         }
247     }
248 
249 }