View Javadoc

1   /*
2    * Copyright 2010 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.fatwire.gst.foundation.taglib;
17  
18  import java.util.Map.Entry;
19  
20  import javax.servlet.jsp.JspException;
21  
22  import COM.FutureTense.Interfaces.ICS;
23  
24  import com.fatwire.gst.foundation.DebugHelper;
25  import com.fatwire.gst.foundation.controller.action.Action;
26  import com.fatwire.gst.foundation.controller.action.ActionLocator;
27  import com.fatwire.gst.foundation.controller.action.ActionLocatorUtils;
28  import com.fatwire.gst.foundation.controller.action.Model;
29  import com.fatwire.gst.foundation.controller.annotation.AnnotationUtils;
30  import com.fatwire.gst.foundation.include.DefaultIncludeService;
31  import com.fatwire.gst.foundation.include.IncludeService;
32  
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  
36  /**
37   * JSP tag that replaces the GsfRoot tag and adds Action support. If the action
38   * name argument is provided, than a Action is looked up and executed.
39   * 
40   * @author Dolf Dijkstra
41   * @since Apr 13, 2011
42   */
43  public class PageTag extends GsfRootTag {
44      static final Log LOG = LogFactory.getLog(PageTag.class.getPackage().getName());
45      static final Log LOG_TIME = LogFactory.getLog(PageTag.class.getPackage().getName() + ".time");
46  
47      /**
48       * 
49       */
50      private static final long serialVersionUID = -5979095889062674072L;
51      private String action;
52      private DefaultIncludeService includeService;
53  
54      /*
55       * (non-Javadoc)
56       * 
57       * @see com.fatwire.gst.foundation.taglib.GsfRootTag#doStartTag()
58       */
59      @Override
60      public int doStartTag() throws JspException {
61          final int r = super.doStartTag();
62  
63          if (action != null) {
64              final ICS ics = getICS();
65  
66              final long start = LOG_TIME.isDebugEnabled() ? System.nanoTime() : 0;
67              final ActionLocator locator = getActionLocator();
68              if (locator == null)
69                  throw new IllegalStateException("The ActionLocator cannot be found.");
70              if("+".equals(action)){
71                  action = ics.ResolveVariables("CS.elementname") + "_action";
72              }
73              final Action a = locator.getAction(ics, action);
74  
75              if (a != null) {
76                  if (LOG_TIME.isDebugEnabled()) {
77  
78                      DebugHelper.printTime(LOG_TIME, "Locating Action " + a.getClass().getName(), start);
79                  }
80  
81                  IncludeService o = AnnotationUtils.findService(a, IncludeService.class);
82                  if (o instanceof DefaultIncludeService) {
83                      includeService = (DefaultIncludeService) o; // TODO:minor
84                                                                  // fix this ugly
85                                                                  // upcast
86                  }
87                  if (includeService == null && LOG.isTraceEnabled()) {
88                      LOG.trace("includeService is null");
89                  }
90                  final long beforeHandleRequest = LOG_TIME.isDebugEnabled() ? System.nanoTime() : 0;
91                  a.handleRequest(ics);
92                  copyModelData(a);
93                  if (LOG_TIME.isDebugEnabled()) {
94                      DebugHelper.printTime(LOG_TIME, "Executing Action " + a.getClass().getName(), beforeHandleRequest);
95                  }
96              } else {
97                  throw new IllegalArgumentException("Action with name '" + action + "' cannot be found.");
98              }
99  
100         }
101         return r;
102     }
103 
104     /**
105      * Copies the data from the Model to the jsp page scope
106      * 
107      * @param a the action to copy from.
108      */
109     private void copyModelData(final Action a) {
110         if (a == null) {
111             return;
112         }
113         final Model model = AnnotationUtils.findService(a, Model.class);
114         if (model == null) {
115             return;
116         }
117         for (final Entry<String, ?> e : model.entries()) {
118             // don't overwrite or worse, delete in case value is null.
119             if (pageContext.getAttribute(e.getKey()) == null) {
120                 pageContext.setAttribute(e.getKey(), e.getValue());
121             }
122         }
123     }
124 
125     /**
126      * @return the ActionLocator
127      */
128     protected ActionLocator getActionLocator() {
129         return ActionLocatorUtils.getActionLocator(pageContext.getServletContext());
130     }
131 
132     /**
133      * @return the action
134      */
135     public String getAction() {
136         return action;
137     }
138 
139     /**
140      * @param action the action to set
141      */
142     public void setAction(final String action) {
143         this.action = action;
144     }
145 
146     /**
147      * This is a discovery method to be used by the IncludeTag class. The
148      * contract is that PageTag and IncludeTag work together and that the
149      * includeService is made available on the PageTag jsp tag as loaded by the
150      * jsp page. An alternative would be to add this object to the
151      * <tt>pageContext</tt>. It was chosen not to do this as maintaining it on
152      * the tag reduces scope and possible intermingling by the accidental
153      * developer.
154      * 
155      * @return the IncludeService
156      */
157     public DefaultIncludeService getJspIncludeService() {
158         return includeService;
159     }
160 
161     /*
162      * (non-Javadoc)
163      * 
164      * @see javax.servlet.jsp.tagext.BodyTagSupport#release()
165      */
166     @Override
167     public void release() {
168         includeService = null;
169         super.release();
170     }
171 }