001    /**
002     * Copyright (c) 2000-2012 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.util.HashMap;
034    import java.util.Map;
035    
036    /**
037     * @author Mika Koivisto
038     * @author Tina Tian
039     */
040    public class FreeMarkerTemplate extends AbstractTemplate {
041    
042            public FreeMarkerTemplate(
043                    TemplateResource templateResource,
044                    TemplateResource errorTemplateResource, Map<String, Object> context,
045                    Configuration configuration,
046                    TemplateContextHelper templateContextHelper) {
047    
048                    super(
049                            templateResource, errorTemplateResource, templateContextHelper,
050                            TemplateConstants.LANG_TYPE_FTL,
051                            PropsValues.FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL);
052    
053                    _context = new HashMap<String, Object>();
054    
055                    if (context != null) {
056                            for (Map.Entry<String, Object> entry : context.entrySet()) {
057                                    put(entry.getKey(), entry.getValue());
058                            }
059                    }
060    
061                    _configuration = configuration;
062            }
063    
064            public Object get(String key) {
065                    return _context.get(key);
066            }
067    
068            public void put(String key, Object value) {
069                    if (value == null) {
070                            return;
071                    }
072    
073                    _context.put(key, value);
074            }
075    
076            @Override
077            protected void handleException(Exception exception, Writer writer)
078                    throws TemplateException {
079    
080                    if ((exception instanceof ParseException) ||
081                            (exception instanceof freemarker.template.TemplateException)) {
082    
083                            put("exception", exception.getMessage());
084    
085                            if (templateResource instanceof StringTemplateResource) {
086                                    StringTemplateResource stringTemplateResource =
087                                            (StringTemplateResource)templateResource;
088    
089                                    put("script", stringTemplateResource.getContent());
090                            }
091    
092                            if (exception instanceof ParseException) {
093                                    ParseException pe = (ParseException)exception;
094    
095                                    put("column", pe.getColumnNumber());
096                                    put("line", pe.getLineNumber());
097                            }
098    
099                            try {
100                                    processTemplate(errorTemplateResource, writer);
101                            }
102                            catch (Exception e) {
103                                    throw new TemplateException(
104                                            "Unable to process FreeMarker template " +
105                                                    errorTemplateResource.getTemplateId(),
106                                            e);
107                            }
108                    }
109                    else {
110                            throw new TemplateException(
111                                    "Unable to process FreeMarker template " +
112                                            templateResource.getTemplateId(),
113                                    exception);
114                    }
115            }
116    
117            @Override
118            protected void processTemplate(
119                            TemplateResource templateResource, Writer writer)
120                    throws Exception {
121    
122                    TemplateResourceThreadLocal.setTemplateResource(
123                            TemplateConstants.LANG_TYPE_FTL, templateResource);
124    
125                    try {
126                            Template template = _configuration.getTemplate(
127                                    getTemplateResourceUUID(templateResource),
128                                    TemplateConstants.DEFAUT_ENCODING);
129    
130                            template.process(_context, writer);
131                    }
132                    finally {
133                            TemplateResourceThreadLocal.setTemplateResource(
134                                    TemplateConstants.LANG_TYPE_FTL, null);
135                    }
136            }
137    
138            private Configuration _configuration;
139            private Map<String, Object> _context;
140    
141    }