001    /**
002     * Copyright (c) 2000-2013 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.portal.freemarker;
016    
017    import com.liferay.portal.kernel.template.StringTemplateResource;
018    import com.liferay.portal.kernel.template.TemplateConstants;
019    import com.liferay.portal.kernel.template.TemplateException;
020    import com.liferay.portal.kernel.template.TemplateResource;
021    import com.liferay.portal.template.AbstractTemplate;
022    import com.liferay.portal.template.TemplateContextHelper;
023    import com.liferay.portal.template.TemplateResourceThreadLocal;
024    import com.liferay.portal.util.PropsValues;
025    
026    import freemarker.core.ParseException;
027    
028    import freemarker.template.Configuration;
029    import freemarker.template.Template;
030    
031    import java.io.Writer;
032    
033    import java.security.AccessController;
034    import java.security.PrivilegedActionException;
035    import java.security.PrivilegedExceptionAction;
036    
037    import java.util.Map;
038    
039    /**
040     * @author Mika Koivisto
041     * @author Tina Tian
042     */
043    public class FreeMarkerTemplate extends AbstractTemplate {
044    
045            public FreeMarkerTemplate(
046                    TemplateResource templateResource,
047                    TemplateResource errorTemplateResource, Map<String, Object> context,
048                    Configuration configuration,
049                    TemplateContextHelper templateContextHelper, boolean privileged) {
050    
051                    super(
052                            templateResource, errorTemplateResource, context,
053                            templateContextHelper, TemplateConstants.LANG_TYPE_FTL,
054                            PropsValues.FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL);
055    
056                    _configuration = configuration;
057                    _privileged = privileged;
058            }
059    
060            @Override
061            protected void handleException(Exception exception, Writer writer)
062                    throws TemplateException {
063    
064                    if ((exception instanceof ParseException) ||
065                            (exception instanceof freemarker.template.TemplateException)) {
066    
067                            put("exception", exception.getMessage());
068    
069                            if (templateResource instanceof StringTemplateResource) {
070                                    StringTemplateResource stringTemplateResource =
071                                            (StringTemplateResource)templateResource;
072    
073                                    put("script", stringTemplateResource.getContent());
074                            }
075    
076                            if (exception instanceof ParseException) {
077                                    ParseException pe = (ParseException)exception;
078    
079                                    put("column", pe.getColumnNumber());
080                                    put("line", pe.getLineNumber());
081                            }
082    
083                            try {
084                                    processTemplate(errorTemplateResource, writer);
085                            }
086                            catch (Exception e) {
087                                    throw new TemplateException(
088                                            "Unable to process FreeMarker template " +
089                                                    errorTemplateResource.getTemplateId(),
090                                            e);
091                            }
092                    }
093                    else {
094                            throw new TemplateException(
095                                    "Unable to process FreeMarker template " +
096                                            templateResource.getTemplateId(),
097                                    exception);
098                    }
099            }
100    
101            @Override
102            protected void processTemplate(
103                            TemplateResource templateResource, Writer writer)
104                    throws Exception {
105    
106                    TemplateResourceThreadLocal.setTemplateResource(
107                            TemplateConstants.LANG_TYPE_FTL, templateResource);
108    
109                    try {
110                            Template template = null;
111    
112                            if (_privileged) {
113                                    template = AccessController.doPrivileged(
114                                            new TemplatePrivilegedExceptionAction(templateResource));
115                            }
116                            else {
117                                    template = _configuration.getTemplate(
118                                            getTemplateResourceUUID(templateResource),
119                                            TemplateConstants.DEFAUT_ENCODING);
120                            }
121    
122                            template.process(context, writer);
123                    }
124                    catch (PrivilegedActionException pae) {
125                            throw pae.getException();
126                    }
127                    finally {
128                            TemplateResourceThreadLocal.setTemplateResource(
129                                    TemplateConstants.LANG_TYPE_FTL, null);
130                    }
131            }
132    
133            private Configuration _configuration;
134            private boolean _privileged;
135    
136            private class TemplatePrivilegedExceptionAction
137                    implements PrivilegedExceptionAction<Template> {
138    
139                    public TemplatePrivilegedExceptionAction(
140                            TemplateResource templateResource) {
141    
142                            _templateResource = templateResource;
143                    }
144    
145                    @Override
146                    public Template run() throws Exception {
147                            return _configuration.getTemplate(
148                                    getTemplateResourceUUID(_templateResource),
149                                    TemplateConstants.DEFAUT_ENCODING);
150                    }
151    
152                    private TemplateResource _templateResource;
153    
154            }
155    
156    }