KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > app > servlet > TemplateContentServlet


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.web.app.servlet;
18
19 import java.io.IOException JavaDoc;
20 import java.net.SocketException JavaDoc;
21 import java.text.MessageFormat JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.http.HttpServletRequest JavaDoc;
27 import javax.servlet.http.HttpServletResponse JavaDoc;
28 import javax.servlet.http.HttpSession JavaDoc;
29 import javax.transaction.UserTransaction JavaDoc;
30
31 import org.alfresco.error.AlfrescoRuntimeException;
32 import org.alfresco.model.ContentModel;
33 import org.alfresco.service.ServiceRegistry;
34 import org.alfresco.service.cmr.repository.NodeRef;
35 import org.alfresco.service.cmr.repository.NodeService;
36 import org.alfresco.service.cmr.repository.StoreRef;
37 import org.alfresco.service.cmr.repository.TemplateException;
38 import org.alfresco.service.cmr.repository.TemplateNode;
39 import org.alfresco.service.cmr.repository.TemplateService;
40 import org.alfresco.service.cmr.security.AccessStatus;
41 import org.alfresco.service.cmr.security.PermissionService;
42 import org.alfresco.web.app.Application;
43 import org.alfresco.web.ui.repo.component.template.DefaultModelHelper;
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46
47 /**
48  * Servlet responsible for streaming content from a template processed against a node directly
49  * to the response stream.
50  * <p>
51  * The URL to the servlet should be generated thus:
52  * <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000
53  * or
54  * <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000/workspace/SpacesStore/0000-0000-0000-0000
55  * <p>
56  * The store protocol, followed by the store ID, followed by the content Node Id used to
57  * identify the node to execute the default template for. The second set of elements encode
58  * the store and node Id of the template to used if a default is not set or not requested.
59  * <p>
60  * The URL may be followed by a 'mimetype' argument specifying the mimetype to return the result as
61  * on the stream. Otherwise it is assumed that HTML is the default response mimetype.
62  * <p>
63  * Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
64  * ?ticket=1234567890
65  * <p>
66  * And/or also followed by the "?guest=true" argument to force guest access login for the URL.
67  *
68  * @author Kevin Roast
69  */

70 public class TemplateContentServlet extends BaseServlet
71 {
72    private static final String JavaDoc MIMETYPE_HTML = "text/html";
73
74    private static final long serialVersionUID = -4123407921997235977L;
75    
76    private static Log logger = LogFactory.getLog(TemplateContentServlet.class);
77    
78    private static final String JavaDoc DEFAULT_URL = "/template/{0}/{1}/{2}";
79    private static final String JavaDoc TEMPLATE_URL = "/template/{0}/{1}/{2}/{3}/{4}/{5}";
80    
81    private static final String JavaDoc MSG_ERROR_CONTENT_MISSING = "error_content_missing";
82    
83    private static final String JavaDoc ARG_MIMETYPE = "mimetype";
84    
85    /**
86     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
87     */

88    protected void doGet(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
89       throws ServletException JavaDoc, IOException JavaDoc
90    {
91       String JavaDoc uri = req.getRequestURI();
92       
93       if (logger.isDebugEnabled())
94          logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
95       
96       AuthenticationStatus status = servletAuthenticate(req, res);
97       if (status == AuthenticationStatus.Failure)
98       {
99          return;
100       }
101       
102       StringTokenizer JavaDoc t = new StringTokenizer JavaDoc(uri, "/");
103       int tokenCount = t.countTokens();
104       if (tokenCount < 5)
105       {
106          throw new IllegalArgumentException JavaDoc("Download URL did not contain all required args: " + uri);
107       }
108       
109       t.nextToken(); // skip web app name
110
t.nextToken(); // skip servlet name
111

112       // get NodeRef to the content
113
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
114       NodeRef nodeRef = new NodeRef(storeRef, t.nextToken());
115       
116       // get NodeRef to the template if supplied
117
NodeRef templateRef = null;
118       if (tokenCount >= 8)
119       {
120          storeRef = new StoreRef(t.nextToken(), t.nextToken());
121          templateRef = new NodeRef(storeRef, t.nextToken());
122       }
123       
124       // get the services we need to retrieve the content
125
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
126       NodeService nodeService = serviceRegistry.getNodeService();
127       TemplateService templateService = serviceRegistry.getTemplateService();
128       PermissionService permissionService = serviceRegistry.getPermissionService();
129       
130       // check that the user has at least READ access on any nodes - else redirect to the login page
131
if (permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED ||
132           (templateRef != null && permissionService.hasPermission(templateRef, PermissionService.READ) == AccessStatus.DENIED))
133       {
134          redirectToLoginPage(req, res, getServletContext());
135          return;
136       }
137       
138       String JavaDoc mimetype = MIMETYPE_HTML;
139       if (req.getParameter(ARG_MIMETYPE) != null)
140       {
141          mimetype = req.getParameter(ARG_MIMETYPE);
142       }
143       res.setContentType(mimetype);
144       
145       try
146       {
147          UserTransaction JavaDoc txn = null;
148          try
149          {
150             txn = serviceRegistry.getTransactionService().getUserTransaction(true);
151             txn.begin();
152             
153             // if template not supplied, then use the default against the node
154
if (templateRef == null)
155             {
156                if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPLATABLE))
157                {
158                   templateRef = (NodeRef)nodeService.getProperty(nodeRef, ContentModel.PROP_TEMPLATE);
159                }
160                if (templateRef == null)
161                {
162                   throw new TemplateException("Template reference not set against node or not supplied in URL.");
163                }
164             }
165             
166             // create the model - put the supplied noderef in as space/document as appropriate
167
Object JavaDoc model = getModel(serviceRegistry, req.getSession(), nodeRef);
168             
169             // process the template against the node content directly to the response output stream
170
// assuming the repo is capable of streaming in chunks, this should allow large files
171
// to be streamed directly to the browser response stream.
172
try
173             {
174                templateService.processTemplate(
175                      null,
176                      templateRef.toString(),
177                      model,
178                      res.getWriter());
179                
180                // commit the transaction
181
txn.commit();
182             }
183             catch (SocketException JavaDoc e)
184             {
185                if (e.getMessage().contains("ClientAbortException"))
186                {
187                   // the client cut the connection - our mission was accomplished apart from a little error message
188
logger.error("Client aborted stream read:\n node: " + nodeRef + "\n template: " + templateRef);
189                   try { if (txn != null) {txn.rollback();} } catch (Exception JavaDoc tex) {}
190                }
191                else
192                {
193                   throw e;
194                }
195             }
196          }
197          catch (Throwable JavaDoc txnErr)
198          {
199             try { if (txn != null) {txn.rollback();} } catch (Exception JavaDoc tex) {}
200             throw txnErr;
201          }
202       }
203       catch (Throwable JavaDoc err)
204       {
205          throw new AlfrescoRuntimeException("Error during template servlet processing: " + err.getMessage(), err);
206       }
207    }
208    
209    /**
210     * Build the model that to process the template against.
211     * <p>
212     * The model includes the usual template root objects such as 'companyhome', 'userhome',
213     * 'person' and also includes the node specified on the servlet URL as 'space' and 'document'
214     *
215     * @param services ServiceRegistry required for TemplateNode construction
216     * @param session HttpSession for accessing current User
217     * @param nodeRef NodeRef of the space/document to process template against
218     *
219     * @return an object model ready for executing template against
220     */

221    private Object JavaDoc getModel(ServiceRegistry services, HttpSession JavaDoc session, NodeRef nodeRef)
222    {
223       // build FreeMarker default model and merge
224
Map JavaDoc root = DefaultModelHelper.buildDefaultModel(services, Application.getCurrentUser(session));
225       
226       // put the current NodeRef in as "space" and "document"
227
TemplateNode node = new TemplateNode(nodeRef, services, DefaultModelHelper.imageResolver);
228       root.put("space", node);
229       root.put("document", node);
230       
231       return root;
232    }
233    
234    /**
235     * Helper to generate a URL to process a template against a node.
236     * <p>
237     * The result of the template is supplied returned as the response.
238     *
239     * @param nodeRef NodeRef of the content node to generate URL for (cannot be null)
240     * @param templateRef NodeRef of the template to process against, or null to use default
241     *
242     * @return URL to process the template
243     */

244    public final static String JavaDoc generateURL(NodeRef nodeRef, NodeRef templateRef)
245    {
246       if (templateRef == null)
247       {
248          return MessageFormat.format(DEFAULT_URL, new Object JavaDoc[] {
249                    nodeRef.getStoreRef().getProtocol(),
250                    nodeRef.getStoreRef().getIdentifier(),
251                    nodeRef.getId() } );
252       }
253       else
254       {
255          return MessageFormat.format(TEMPLATE_URL, new Object JavaDoc[] {
256                    nodeRef.getStoreRef().getProtocol(),
257                    nodeRef.getStoreRef().getIdentifier(),
258                    nodeRef.getId(),
259                    templateRef.getStoreRef().getProtocol(),
260                    templateRef.getStoreRef().getIdentifier(),
261                    templateRef.getId()} );
262       }
263    }
264 }
265
Popular Tags