View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.taglibs;
35  
36  import info.magnolia.cms.core.AggregationState;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.context.MgnlContext;
39  import info.magnolia.context.WebContext;
40  import info.magnolia.objectfactory.Components;
41  import info.magnolia.rendering.engine.AppendableOnlyOutputProvider;
42  import info.magnolia.rendering.engine.RenderingEngine;
43  
44  import java.io.IOException;
45  import java.util.ArrayList;
46  import java.util.Iterator;
47  import java.util.List;
48  
49  import javax.servlet.http.HttpServletRequest;
50  import javax.servlet.http.HttpServletResponse;
51  import javax.servlet.jsp.tagext.BodyTagSupport;
52  
53  /**
54   * Delegates to an appropriate ParagraphRenderer, or include a JSP.
55   * This is typically used to render a paragraph. Within contentNodeIterator, parameters are provided
56   * automatically by the loop.
57   * @jsp.tag name="includeTemplate" body-content="JSP"
58   *
59   * @author marcel Salathe
60   * @author Sameer Charles
61   * @author Fabrizio Giustina
62   * @version $Revision$ ($Author$)
63   */
64  public class Include extends BodyTagSupport {
65      private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Include.class);
66  
67      protected RenderingEngine renderingEngine = Components.getSingleton(RenderingEngine.class);
68  
69      /**
70       * File to be included (e.g. /templates/jsp/x.jsp).
71       * @deprecated
72       */
73      @Deprecated
74      private String path;
75  
76      /**
77       * Attributes to be passed to the included template (set by nested Attribute tags).
78       */
79      private transient List attributes;
80  
81      /**
82       * The instance contentNode (i.e. paragraph) you wish to show.
83       */
84      // TODO dlipp: use JCR-Api directly
85      private transient Content contentNode;
86  
87      /**
88       * The name of the contentNode (i.e. paragraph) you wish to show.
89       */
90      private String contentNodeName;
91  
92      /**
93       * Set to true if the content should not be rendered in edit mode (edit bars, ...).
94       */
95      private boolean noEditBars = false;
96  
97      /**
98       * @deprecated use the contentNode attribute instead
99       * @see #setContentNode(Content)
100      * @jsp.attribute required="false" rtexprvalue="true" type="info.magnolia.cms.core.Content"
101      */
102     @Deprecated
103     public void setContainer(Content contentNode) {
104         this.setContentNode(contentNode);
105     }
106 
107     /**
108      * @param contentNode the instance contentNode (i.e. paragraph) you wish to show
109      * @jsp.attribute required="false" rtexprvalue="true" type="info.magnolia.cms.core.Content"
110      */
111     public void setContentNode(Content contentNode) {
112         this.contentNode = contentNode;
113     }
114 
115     /**
116      * @deprecated file to be included (e.g. "/templates/jsp/x.jsp").
117      * Just use basic jsp tags (i.e. <jsp:include/>) if you need to include a jsp in your templates.
118      * @jsp.attribute required="false" rtexprvalue="true"
119      */
120     @Deprecated
121     public void setPath(String path) {
122         this.path = path;
123     }
124 
125     /**
126      * The name of the contentNode (i.e. paragraph) you wish to show.
127      * @jsp.attribute required="false" rtexprvalue="true"
128      */
129     public void setContentNodeName(String contentNodeName) {
130         this.contentNodeName = contentNodeName;
131     }
132 
133     /**
134      * @param name name of attribute to pass with the include
135      * @param value value of attribute to pass with the include
136      */
137     public void setAttribute(String name, Object value) {
138         if (attributes == null) {
139             attributes = new ArrayList();
140         }
141         Object[] attributesArray = new Object[]{name, value};
142         attributes.add(attributesArray);
143     }
144 
145     /**
146      * Set to true if the content should not be rendered in edit mode (edit bars, ...).
147      * @jsp.attribute required="false" rtexprvalue="true" type="boolean"
148      */
149     public void setNoEditBars(boolean noEditBars) {
150         this.noEditBars = noEditBars;
151     }
152 
153     @Override
154     public int doAfterBody() {
155         HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
156         if ((attributes != null) && (attributes.size() > 0)) {
157             Iterator i = attributes.iterator();
158             while (i.hasNext()) {
159                 Object[] s = (Object[]) i.next();
160                 req.setAttribute((String) s[0], s[1]);
161             }
162         }
163         return SKIP_BODY;
164     }
165 
166     @Override
167     public int doEndTag() {
168         boolean localContentNodeSet = false;
169         Content oldContentNode = Resource.getLocalContentNode();
170 
171         // remove the collection name - the new anchor point for all tags is the current content
172         String oldLocalContentNodeCollectionName = Resource.getLocalContentNodeCollectionName();
173         Resource.setLocalContentNodeCollectionName(null);
174 
175         try {
176             // get content
177             Content content = this.contentNode;
178             if (content == null) {
179                 // was there a node name passed
180                 if (this.contentNodeName != null) {
181                     content = Resource.getCurrentActivePage().getContent(this.contentNodeName);
182                     if (content != null) {
183                         Resource.setLocalContentNode(content);
184                         localContentNodeSet = true;
185                     }
186                 }
187                 // use current (first local then global)
188                 else {
189                     content = Resource.getLocalContentNode();
190                     if (content == null) {
191                         content = Resource.getGlobalContentNode();
192                         if (content != null) {
193                             Resource.setLocalContentNode(content);
194                             localContentNodeSet = true;
195                         }
196                     }
197                 }
198                 if (content == null) {
199                     throw new Exception("no content node found"); //$NON-NLS-1$
200                 }
201             }
202 
203             if (content != Resource.getCurrentActivePage() && !localContentNodeSet && content != null) {
204                 Resource.setLocalContentNode(content);
205                 localContentNodeSet = true;
206             }
207 
208             final AggregationState aggregationState = MgnlContext.getAggregationState();
209             boolean orgShowPreview = aggregationState.isPreviewMode();
210             if(noEditBars && !orgShowPreview){
211                 aggregationState.setPreviewMode(true);
212             }
213 
214             if (this.path != null) { // TODO
215                 log.warn("You are using the deprecated path attribute of the include tag. Your jsp will be included for now, but you might want to update your code to avoid bad surprises in the future.");
216                 pageContext.include(this.path);
217             } else {
218                 WebContext webContext = MgnlContext.getWebContext();
219                 webContext.setPageContext(pageContext);
220                 webContext.push((HttpServletRequest)pageContext.getRequest(), (HttpServletResponse)pageContext.getResponse());
221                 try {
222                     renderingEngine.render(content.getJCRNode(), new AppendableOnlyOutputProvider(pageContext.getOut()));
223                 } finally{
224                     webContext.pop();
225                     webContext.setPageContext(null);
226                 }
227             }
228             if(noEditBars){
229                 aggregationState.setPreviewMode(orgShowPreview);
230             }
231 
232         } catch (IOException e) {
233             // should never happen
234             throw new RuntimeException(e);
235         } catch (Exception e) {
236             log.error(e.getMessage(), e);
237         }
238 
239         finally {
240             // if we set the local content node we have to reset it again else we keep the node
241             if(localContentNodeSet){
242                 if(oldContentNode != null){
243                     Resource.setLocalContentNode(oldContentNode);
244                 }
245                 else{
246                     Resource.removeLocalContentNode();
247                 }
248             }
249             // reset the former collection name
250             Resource.setLocalContentNodeCollectionName(oldLocalContentNodeCollectionName);
251         }
252 
253         this.removeAttributes();
254         return EVAL_PAGE;
255     }
256 
257     private void removeAttributes() {
258         HttpServletRequest req = (HttpServletRequest) pageContext.getRequest();
259         if ((attributes != null) && (attributes.size() > 0)) {
260             Iterator i = attributes.iterator();
261             while (i.hasNext()) {
262                 Object[] s = (Object[]) i.next();
263                 req.removeAttribute((String) s[0]);
264             }
265         }
266         attributes = null;
267     }
268 
269     @Override
270     public void release() {
271         this.path = null;
272         this.attributes = null;
273         this.contentNode = null;
274         super.release();
275     }
276 
277 }