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.HashMap;
038    import java.util.Map;
039    import java.util.Set;
040    
041    /**
042     * @author Mika Koivisto
043     * @author Tina Tian
044     */
045    public class FreeMarkerTemplate extends AbstractTemplate {
046    
047            public FreeMarkerTemplate(
048                    TemplateResource templateResource,
049                    TemplateResource errorTemplateResource, Map<String, Object> context,
050                    Configuration configuration,
051                    TemplateContextHelper templateContextHelper, boolean privileged) {
052    
053                    super(
054                            templateResource, errorTemplateResource, templateContextHelper,
055                            TemplateConstants.LANG_TYPE_FTL,
056                            PropsValues.FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL);
057    
058                    _context = new HashMap<String, Object>();
059    
060                    if (context != null) {
061                            for (Map.Entry<String, Object> entry : context.entrySet()) {
062                                    put(entry.getKey(), entry.getValue());
063                            }
064                    }
065    
066                    _configuration = configuration;
067                    _privileged = privileged;
068            }
069    
070            @Override
071            public Object get(String key) {
072                    return _context.get(key);
073            }
074    
075            @Override
076            public String[] getKeys() {
077                    Set<String> keys = _context.keySet();
078    
079                    return keys.toArray(new String[keys.size()]);
080            }
081    
082            @Override
083            public void put(String key, Object value) {
084                    if (value == null) {
085                            return;
086                    }
087    
088                    _context.put(key, value);
089            }
090    
091            @Override
092            protected void handleException(Exception exception, Writer writer)
093                    throws TemplateException {
094    
095                    if ((exception instanceof ParseException) ||
096                            (exception instanceof freemarker.template.TemplateException)) {
097    
098                            put("exception", exception.getMessage());
099    
100                            if (templateResource instanceof StringTemplateResource) {
101                                    StringTemplateResource stringTemplateResource =
102                                            (StringTemplateResource)templateResource;
103    
104                                    put("script", stringTemplateResource.getContent());
105                            }
106    
107                            if (exception instanceof ParseException) {
108                                    ParseException pe = (ParseException)exception;
109    
110                                    put("column", pe.getColumnNumber());
111                                    put("line", pe.getLineNumber());
112                            }
113    
114                            try {
115                                    processTemplate(errorTemplateResource, writer);
116                            }
117                            catch (Exception e) {
118                                    throw new TemplateException(
119                                            "Unable to process FreeMarker template " +
120                                                    errorTemplateResource.getTemplateId(),
121                                            e);
122                            }
123                    }
124                    else {
125                            throw new TemplateException(
126                                    "Unable to process FreeMarker template " +
127                                            templateResource.getTemplateId(),
128                                    exception);
129                    }
130            }
131    
132            @Override
133            protected void processTemplate(
134                            TemplateResource templateResource, Writer writer)
135                    throws Exception {
136    
137                    TemplateResourceThreadLocal.setTemplateResource(
138                            TemplateConstants.LANG_TYPE_FTL, templateResource);
139    
140                    try {
141                            Template template = null;
142    
143                            if (_privileged) {
144                                    template = AccessController.doPrivileged(
145                                            new TemplatePrivilegedExceptionAction(templateResource));
146                            }
147                            else {
148                                    template = _configuration.getTemplate(
149                                            getTemplateResourceUUID(templateResource),
150                                            TemplateConstants.DEFAUT_ENCODING);
151                            }
152    
153                            template.process(_context, writer);
154                    }
155                    catch (PrivilegedActionException pae) {
156                            throw pae.getException();
157                    }
158                    finally {
159                            TemplateResourceThreadLocal.setTemplateResource(
160                                    TemplateConstants.LANG_TYPE_FTL, null);
161                    }
162            }
163    
164            private Configuration _configuration;
165            private Map<String, Object> _context;
166            private boolean _privileged;
167    
168            private class TemplatePrivilegedExceptionAction
169                    implements PrivilegedExceptionAction<Template> {
170    
171                    public TemplatePrivilegedExceptionAction(
172                            TemplateResource templateResource) {
173    
174                            _templateResource = templateResource;
175                    }
176    
177                    @Override
178                    public Template run() throws Exception {
179                            return _configuration.getTemplate(
180                                    getTemplateResourceUUID(_templateResource),
181                                    TemplateConstants.DEFAUT_ENCODING);
182                    }
183    
184                    private TemplateResource _templateResource;
185    
186            }
187    
188    }