001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.journal.util;
016    
017    import com.liferay.portal.freemarker.JournalTemplateLoader;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.freemarker.FreeMarkerContext;
020    import com.liferay.portal.kernel.freemarker.FreeMarkerEngineUtil;
021    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.DocumentException;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portal.model.Company;
030    import com.liferay.portal.security.permission.PermissionThreadLocal;
031    import com.liferay.portal.service.CompanyLocalServiceUtil;
032    import com.liferay.portal.theme.ThemeDisplay;
033    import com.liferay.portal.util.ContentUtil;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.journal.TransformException;
036    import com.liferay.util.PwdGenerator;
037    
038    import freemarker.core.ParseException;
039    
040    import freemarker.template.TemplateException;
041    
042    import java.io.IOException;
043    
044    import java.util.List;
045    import java.util.Map;
046    
047    /**
048     * @author Mika Koivisto
049     */
050    public class FreeMarkerTemplateParser extends VelocityTemplateParser {
051    
052            public String doTransform(
053                            ThemeDisplay themeDisplay, Map<String, String> tokens,
054                            String viewMode, String languageId, String xml, String script)
055                    throws Exception {
056    
057                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
058    
059                    boolean load = false;
060    
061                    try {
062                            FreeMarkerContext freeMarkerContext =
063                                    FreeMarkerEngineUtil.getWrappedRestrictedToolsContext();
064    
065                            Document doc = SAXReaderUtil.read(xml);
066    
067                            Element root = doc.getRootElement();
068    
069                            List<TemplateNode> nodes = extractDynamicContents(
070                                    themeDisplay, root);
071    
072                            for (TemplateNode node : nodes) {
073                                    freeMarkerContext.put(node.getName(), node);
074                            }
075    
076                            freeMarkerContext.put(
077                                    "xmlRequest", root.element("request").asXML());
078                            freeMarkerContext.put(
079                                    "request", insertRequestVariables(root.element("request")));
080    
081                            long companyId = GetterUtil.getLong(tokens.get("company_id"));
082                            Company company = CompanyLocalServiceUtil.getCompanyById(companyId);
083                            long groupId = GetterUtil.getLong(tokens.get("group_id"));
084                            String templateId = tokens.get("template_id");
085                            String journalTemplatesPath =
086                                    JournalTemplateLoader.JOURNAL_SEPARATOR + StringPool.SLASH +
087                                            companyId + StringPool.SLASH + groupId;
088                            String randomNamespace =
089                                    PwdGenerator.getPassword(PwdGenerator.KEY3, 4) +
090                                            StringPool.UNDERLINE;
091    
092                            freeMarkerContext.put("company", company);
093                            freeMarkerContext.put("companyId", String.valueOf(companyId));
094                            freeMarkerContext.put("groupId", String.valueOf(groupId));
095                            freeMarkerContext.put("journalTemplatesPath", journalTemplatesPath);
096                            freeMarkerContext.put("viewMode", viewMode);
097                            freeMarkerContext.put(
098                                    "locale", LocaleUtil.fromLanguageId(languageId));
099                            freeMarkerContext.put(
100                                    "permissionChecker",
101                                    PermissionThreadLocal.getPermissionChecker());
102                            freeMarkerContext.put("randomNamespace", randomNamespace);
103    
104                            script = injectEditInPlace(xml, script);
105    
106                            try {
107                                    String freeMarkerTemplateId = companyId + groupId + templateId;
108    
109                                    load = FreeMarkerEngineUtil.mergeTemplate(
110                                            freeMarkerTemplateId, script, freeMarkerContext,
111                                            unsyncStringWriter);
112                            }
113                            catch (SystemException se) {
114                                    if (se.getCause() instanceof TemplateException) {
115                                            TemplateException te = (TemplateException)se.getCause();
116    
117                                            freeMarkerContext.put("exception", te.getMessage());
118                                            freeMarkerContext.put("script", script);
119    
120                                            String freeMarkerTemplateId =
121                                                    PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER;
122                                            String freemarkerTemplateContent =
123                                                    ContentUtil.get(
124                                                            PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER);
125    
126                                            unsyncStringWriter = new UnsyncStringWriter();
127    
128                                            load = FreeMarkerEngineUtil.mergeTemplate(
129                                                    freeMarkerTemplateId, freemarkerTemplateContent,
130                                                    freeMarkerContext, unsyncStringWriter);
131                                    }
132                                    else {
133                                            throw se;
134                                    }
135                            }
136                            catch (ParseException pe) {
137                                    freeMarkerContext.put("exception", pe.getMessage());
138                                    freeMarkerContext.put("script", script);
139    
140                                    freeMarkerContext.put("column", new Integer(
141                                            pe.getColumnNumber()));
142                                    freeMarkerContext.put("line", new Integer(
143                                            pe.getLineNumber()));
144    
145                                    String freeMarkerTemplateId =
146                                            PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER;
147                                    String freemarkerTemplateContent =
148                                            ContentUtil.get(
149                                                    PropsValues.JOURNAL_ERROR_TEMPLATE_FREEMARKER);
150    
151                                    unsyncStringWriter = new UnsyncStringWriter();
152    
153                                    load = FreeMarkerEngineUtil.mergeTemplate(
154                                            freeMarkerTemplateId, freemarkerTemplateContent,
155                                            freeMarkerContext, unsyncStringWriter);
156                            }
157                    }
158                    catch (Exception e) {
159                            if (e instanceof DocumentException) {
160                                    throw new TransformException("Unable to read XML document", e);
161                            }
162                            else if (e instanceof IOException) {
163                                    throw new TransformException(
164                                            "Error reading freemarker template", e);
165                            }
166                            else if (e instanceof TransformException) {
167                                    throw (TransformException) e;
168                            }
169                            else {
170                                    throw new TransformException("Unhandled exception", e);
171                            }
172                    }
173    
174                    if (!load) {
175                            throw new TransformException(
176                                    "Unable to dynamically load freemarker transform script");
177                    }
178    
179                    return unsyncStringWriter.toString();
180            }
181    
182    }