1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.journal.util;
16  
17  import com.liferay.portal.freemarker.JournalTemplateLoader;
18  import com.liferay.portal.kernel.exception.SystemException;
19  import com.liferay.portal.kernel.freemarker.FreeMarkerContext;
20  import com.liferay.portal.kernel.freemarker.FreeMarkerEngineUtil;
21  import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.LocaleUtil;
24  import com.liferay.portal.kernel.util.StringPool;
25  import com.liferay.portal.kernel.xml.Document;
26  import com.liferay.portal.kernel.xml.DocumentException;
27  import com.liferay.portal.kernel.xml.Element;
28  import com.liferay.portal.kernel.xml.SAXReaderUtil;
29  import com.liferay.portal.model.Company;
30  import com.liferay.portal.security.permission.PermissionThreadLocal;
31  import com.liferay.portal.service.CompanyLocalServiceUtil;
32  import com.liferay.portal.theme.ThemeDisplay;
33  import com.liferay.portal.util.ContentUtil;
34  import com.liferay.portal.util.PropsValues;
35  import com.liferay.portlet.journal.TransformException;
36  import com.liferay.util.PwdGenerator;
37  
38  import freemarker.core.ParseException;
39  
40  import freemarker.template.TemplateException;
41  
42  import java.io.IOException;
43  
44  import java.util.List;
45  import java.util.Map;
46  
47  /**
48   * <a href="FreeMarkerTemplateParser.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Mika Koivisto
51   */
52  public class FreeMarkerTemplateParser extends VelocityTemplateParser {
53  
54      public String doTransform(
55              ThemeDisplay themeDisplay, Map<String, String> tokens,
56              String viewMode, String languageId, String xml, String script)
57          throws Exception {
58  
59          UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
60  
61          boolean load = false;
62  
63          try {
64              FreeMarkerContext freeMarkerContext =
65                  FreeMarkerEngineUtil.getWrappedRestrictedToolsContext();
66  
67              Document doc = SAXReaderUtil.read(xml);
68  
69              Element root = doc.getRootElement();
70  
71              List<TemplateNode> nodes = extractDynamicContents(
72                  themeDisplay, root);
73  
74              for (TemplateNode node : nodes) {
75                  freeMarkerContext.put(node.getName(), node);
76              }
77  
78              freeMarkerContext.put(
79                  "xmlRequest", root.element("request").asXML());
80              freeMarkerContext.put(
81                  "request", insertRequestVariables(root.element("request")));
82  
83              long companyId = GetterUtil.getLong(tokens.get("company_id"));
84              Company company = CompanyLocalServiceUtil.getCompanyById(companyId);
85              long groupId = GetterUtil.getLong(tokens.get("group_id"));
86              String templateId = tokens.get("template_id");
87              String journalTemplatesPath =
88                  JournalTemplateLoader.JOURNAL_SEPARATOR + StringPool.SLASH +
89                      companyId + StringPool.SLASH + groupId;
90              String randomNamespace =
91                  PwdGenerator.getPassword(PwdGenerator.KEY3, 4) +
92                      StringPool.UNDERLINE;
93  
94              freeMarkerContext.put("company", company);
95              freeMarkerContext.put("companyId", String.valueOf(companyId));
96              freeMarkerContext.put("groupId", String.valueOf(groupId));
97              freeMarkerContext.put("journalTemplatesPath", journalTemplatesPath);
98              freeMarkerContext.put("viewMode", viewMode);
99              freeMarkerContext.put(
100                 "locale", LocaleUtil.fromLanguageId(languageId));
101             freeMarkerContext.put(
102                 "permissionChecker",
103                 PermissionThreadLocal.getPermissionChecker());
104             freeMarkerContext.put("randomNamespace", randomNamespace);
105 
106             script = injectEditInPlace(xml, script);
107 
108             try {
109                 String freeMarkerTemplateId = companyId + groupId + templateId;
110 
111                 load = FreeMarkerEngineUtil.mergeTemplate(
112                     freeMarkerTemplateId, script, freeMarkerContext,
113                     unsyncStringWriter);
114             }
115             catch (SystemException se) {
116                 if (se.getCause() instanceof TemplateException) {
117                     TemplateException te = (TemplateException)se.getCause();
118 
119                     freeMarkerContext.put("exception", te.getMessage());
120                     freeMarkerContext.put("script", script);
121 
122                     String freeMarkerTemplateId =
123                         PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER;
124                     String freemarkerTemplateContent =
125                         ContentUtil.get(
126                             PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER);
127 
128                     unsyncStringWriter = new UnsyncStringWriter();
129 
130                     load = FreeMarkerEngineUtil.mergeTemplate(
131                         freeMarkerTemplateId, freemarkerTemplateContent,
132                         freeMarkerContext, unsyncStringWriter);
133                 }
134                 else {
135                     throw se;
136                 }
137             }
138             catch (ParseException pe) {
139                 freeMarkerContext.put("exception", pe.getMessage());
140                 freeMarkerContext.put("script", script);
141 
142                 freeMarkerContext.put("column", new Integer(
143                     pe.getColumnNumber()));
144                 freeMarkerContext.put("line", new Integer(
145                     pe.getLineNumber()));
146 
147                 String freeMarkerTemplateId =
148                     PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER;
149                 String freemarkerTemplateContent =
150                     ContentUtil.get(
151                         PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER);
152 
153                 unsyncStringWriter = new UnsyncStringWriter();
154 
155                 load = FreeMarkerEngineUtil.mergeTemplate(
156                     freeMarkerTemplateId, freemarkerTemplateContent,
157                     freeMarkerContext, unsyncStringWriter);
158             }
159         }
160         catch (Exception e) {
161             if (e instanceof DocumentException) {
162                 throw new TransformException("Unable to read XML document", e);
163             }
164             else if (e instanceof IOException) {
165                 throw new TransformException(
166                     "Error reading freemarker template", e);
167             }
168             else if (e instanceof TransformException) {
169                 throw (TransformException) e;
170             }
171             else {
172                 throw new TransformException("Unhandled exception", e);
173             }
174         }
175 
176         if (!load) {
177             throw new TransformException(
178                 "Unable to dynamically load freemarker transform script");
179         }
180 
181         return unsyncStringWriter.toString();
182     }
183 
184 }