View Javadoc

1   package org.apache.turbine.modules.pages;
2   
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21   */
22  
23  
24  import java.util.List;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.ecs.Doctype;
30  import org.apache.turbine.Turbine;
31  import org.apache.turbine.TurbineConstants;
32  import org.apache.turbine.modules.Action;
33  import org.apache.turbine.modules.ActionLoader;
34  import org.apache.turbine.modules.Layout;
35  import org.apache.turbine.modules.LayoutLoader;
36  import org.apache.turbine.modules.Page;
37  import org.apache.turbine.modules.Screen;
38  import org.apache.turbine.modules.ScreenLoader;
39  import org.apache.turbine.pipeline.PipelineData;
40  import org.apache.turbine.services.assemblerbroker.TurbineAssemblerBroker;
41  import org.apache.turbine.util.RunData;
42  import org.apache.turbine.util.TurbineException;
43  
44  /**
45   * When building sites using templates, Screens need only be defined
46   * for templates which require dynamic (database or object) data.
47   *
48   * <p>
49   *
50   * This page can be used on sites where the number of Screens can be
51   * much less than the number of templates.  The templates can be
52   * grouped in directories with common layouts.  Screen modules are
53   * then expected to be placed in packages corresponding with the
54   * templates' directories and follow a specific naming scheme.
55   *
56   * <p>
57   *
58   * The template parameter is parsed and and a Screen whose package
59   * matches the templates path and shares the same name minus any
60   * extension and beginning with a capital letter is searched for.  If
61   * not found, a Screen in a package matching the template's path with
62   * name Default is searched for.  If still not found, a Screen with
63   * name Default is looked for in packages corresponding to parent
64   * directories in the template's path until a match is found.
65   *
66   * <p>
67   *
68   * For example if data.getParameters().getString("template") returns
69   * /about_us/directions/driving.wm, the search follows
70   * about_us.directions.Driving, about_us.directions.Default,
71   * about_us.Default, Default, VelocitySiteScreen.
72   *
73   * <p>
74   *
75   * Only one Layout module is used, since it is expected that any
76   * dynamic content will be placed in navigations and screens.  The
77   * layout template to be used is found in a similar way to the Screen.
78   * For example the following paths will be searched in the layouts
79   * subdirectory: /about_us/directions/driving.wm,
80   * /about_us/directions/default.wm, /about_us/default.wm, /default.wm.
81   *
82   * <p>
83   *
84   * This approach allows a site with largely static content to be
85   * updated and added to regularly by those with little Java
86   * experience.
87   *
88   * <p>
89   *
90   * The code is an almost a complete clone of the FreeMarkerSitePage
91   * written by John McNally.  I've only modified it for Template use.
92   *
93   * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
94   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
95   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
96   * @version $Id: DefaultPage.java 1078552 2011-03-06 19:58:46Z tv $
97   */
98  public class DefaultPage
99      extends Page
100 {
101     /** Logging */
102     protected Log log = LogFactory.getLog(this.getClass());
103 
104     protected ActionLoader actionLoader;
105     protected ScreenLoader screenLoader;
106     protected LayoutLoader layoutLoader;
107 
108     /**
109      * Default constructor
110      */
111     public DefaultPage()
112     {
113         super();
114 
115         this.actionLoader = (ActionLoader)TurbineAssemblerBroker.getLoader(Action.NAME);
116         this.screenLoader = (ScreenLoader)TurbineAssemblerBroker.getLoader(Screen.NAME);
117         this.layoutLoader = (LayoutLoader)TurbineAssemblerBroker.getLoader(Layout.NAME);
118     }
119 
120     /**
121      * Builds the Page.
122      *
123      * @deprecated Use PipelineData version instead
124      * @param data Turbine information.
125      * @exception Exception, a generic exception.
126      */
127     @Deprecated
128     @Override
129     public void doBuild(RunData data)
130             throws Exception
131     {
132         // Template pages can use this to set up the context, so it is
133         // available to the Action and Screen.  It does nothing here.
134         doBuildBeforeAction(data);
135 
136         // If an action has been defined, execute it here.  Actions
137         // can re-define the template definition.
138         if (data.hasAction())
139         {
140             actionLoader.exec(data, data.getAction());
141         }
142 
143         // if a redirect was setup in data, don't do anything else
144         if (StringUtils.isNotEmpty(data.getRedirectURI()))
145         {
146             return;
147         }
148 
149         // Set the default doctype from the value given in
150         // TurbineResources.properties.
151         setDefaultDoctype(data);
152 
153         // Template pages can use this to set up default templates and
154         // associated class modules.  It does nothing here.
155         doBuildAfterAction(data);
156 
157         String screenName = data.getScreen();
158 
159         log.debug("Building " + screenName);
160 
161         // Ask the Screen for its Layout and then execute the Layout.
162         // The Screen can override the getLayout() method to re-define
163         // the Layout depending on data passed in via the
164         // data.parameters object.
165         Screen aScreen = screenLoader.getAssembler(screenName);
166         String layout = aScreen.getLayout(data);
167 
168         // If the Layout has been set to be null, attempt to execute
169         // the Screen that has been defined.
170         if (layout != null)
171         {
172             layoutLoader.exec(data, layout);
173         }
174         else
175         {
176             screenLoader.exec(data, screenName);
177         }
178 
179         // Do any post build actions (overridable by subclasses -
180         // does nothing here).
181         doPostBuild(data);
182     }
183 
184     /**
185      * Builds the Page.
186      *
187      * @param data Turbine information.
188      * @exception Exception, a generic exception.
189      */
190     @Override
191     public void doBuild(PipelineData pipelineData)
192             throws Exception
193     {
194         RunData data = getRunData(pipelineData);
195         // Template pages can use this to set up the context, so it is
196         // available to the Action and Screen.  It does nothing here.
197         doBuildBeforeAction(pipelineData);
198 
199         // If an action has been defined, execute it here.  Actions
200         // can re-define the template definition.
201         if (data.hasAction())
202         {
203             actionLoader.exec(pipelineData, data.getAction());
204         }
205 
206         // if a redirect was setup in data, don't do anything else
207         if (StringUtils.isNotEmpty(data.getRedirectURI()))
208         {
209             return;
210         }
211 
212         // Set the default doctype from the value given in
213         // TurbineResources.properties.
214         setDefaultDoctype(data);
215 
216         // Template pages can use this to set up default templates and
217         // associated class modules.  It does nothing here.
218         doBuildAfterAction(pipelineData);
219 
220         String screenName = data.getScreen();
221 
222         log.debug("Building " + screenName);
223 
224         // Ask the Screen for its Layout and then execute the Layout.
225         // The Screen can override the getLayout() method to re-define
226         // the Layout depending on data passed in via the
227         // data.parameters object.
228         Screen aScreen = screenLoader.getAssembler(screenName);
229         String layout = aScreen.getLayout(pipelineData);
230 
231         // If the Layout has been set to be null, attempt to execute
232         // the Screen that has been defined.
233         if (layout != null)
234         {
235             layoutLoader.exec(pipelineData, layout);
236         }
237         else
238         {
239             screenLoader.exec(pipelineData, screenName);
240         }
241 
242         // Do any post build actions (overridable by subclasses -
243         // does nothing here).
244         doPostBuild(pipelineData);
245     }
246 
247 
248 
249     /**
250      * Can be used by template Pages to stuff the Context into the
251      * RunData so that it is available to the Action module and the
252      * Screen module via getContext().  It does nothing here.
253      *
254      * @deprecated Use PipelineData version instead
255      * @param data Turbine information.
256      * @exception Exception, a generic exception.
257      */
258     @Deprecated
259     protected void doBuildBeforeAction(RunData data)
260             throws Exception
261     {
262         // do nothing by default
263     }
264 
265     /**
266      * Can be overridden by template Pages to set up data needed to
267      * process a template.  It does nothing here.
268      *
269      * @deprecated Use PipelineData version instead
270      * @param data Turbine information.
271      * @exception Exception, a generic exception.
272      */
273     @Deprecated
274     protected void doBuildAfterAction(RunData data)
275             throws Exception
276     {
277         // do nothing by default
278     }
279 
280     /**
281      * Can be overridden to perform actions when the request is
282      * fully processed. It does nothing here.
283      * @deprecated Use PipelineData version instead
284      * @param data Turbine information.
285      * @exception Exception, a generic exception.
286      */
287     @Deprecated
288     protected void doPostBuild(RunData data)
289             throws Exception
290     {
291         // do nothing by default
292     }
293 
294 
295     /**
296      * Can be used by template Pages to stuff the Context into the
297      * RunData so that it is available to the Action module and the
298      * Screen module via getContext().  It does nothing here.
299      *
300      * @param data Turbine information.
301      * @exception Exception, a generic exception.
302      */
303     protected void doBuildBeforeAction(PipelineData pipelineData)
304             throws Exception
305     {
306         // do nothing by default
307     }
308 
309     /**
310      * Can be overridden by template Pages to set up data needed to
311      * process a template.  It does nothing here.
312      *
313      * @param data Turbine information.
314      * @exception Exception, a generic exception.
315      */
316     protected void doBuildAfterAction(PipelineData pipelineData)
317             throws Exception
318     {
319         // do nothing by default
320     }
321 
322     /**
323      * Can be overridden to perform actions when the request is
324      * fully processed. It does nothing here.
325      *
326      * @param data Turbine information.
327      * @exception Exception, a generic exception.
328      */
329     protected void doPostBuild(PipelineData pipelineData)
330             throws Exception
331     {
332         // do nothing by default
333     }
334 
335     /**
336      * Set the default Doctype.  If Doctype is set to null, it will
337      * not be added.  The default Doctype can be set in
338      * TurbineResources by using the single strings: Html40Strict,
339      * Html40Transitional, or Html40Frameset.  Additionally the
340      * default can be supplied as two strings giving the dtd and uri.
341      *
342      * @param data Turbine information.
343      * @exception Exception, a generic exception.
344      */
345     private void setDefaultDoctype(RunData data)
346             throws Exception
347     {
348         String errMsg =
349                 "default.doctype property not set properly in TurbineResources.properties!";
350         List doctypeProperty =
351             Turbine.getConfiguration().getList(TurbineConstants.DEFAULT_DOCUMENT_TYPE_KEY);
352 
353         if (doctypeProperty != null)
354         {
355             switch(doctypeProperty.size())
356             {
357             case 0:
358                 {
359                     // Don't add a doctype.
360                     break;
361                 }
362             case 1:
363                 {
364                     String doc = (String) doctypeProperty.get(0);
365                     if (doc.equalsIgnoreCase(TurbineConstants.DOCUMENT_TYPE_HTML40TRANSITIONAL))
366                     {
367                         data.getPage().setDoctype(new Doctype.Html40Transitional());
368                     }
369                     else if (doc.equalsIgnoreCase(TurbineConstants.DOCUMENT_TYPE_HTML40STRICT))
370                     {
371                         data.getPage().setDoctype(new Doctype.Html40Strict());
372                     }
373                     else if (doc.equalsIgnoreCase(TurbineConstants.DOCUMENT_TYPE_HTML40FRAMESET))
374                     {
375                         data.getPage().setDoctype(new Doctype.Html40Frameset());
376                     }
377                     else
378                     {
379                         throw new TurbineException(errMsg);
380                     }
381                     break;
382                 }
383             case 2:
384                 {
385                     data.getPage()
386                         .setDoctype(new Doctype()
387                                     .setIdentifier((String) doctypeProperty.get(0))
388                                     .setUri((String) doctypeProperty.get(1)));
389                     break;
390                 }
391             default:
392                 {
393                     throw new TurbineException(errMsg);
394                 }
395             }
396         }
397     }
398 }