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.velocity;
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 java.io.Writer;
027    
028    import java.security.AccessController;
029    import java.security.PrivilegedActionException;
030    import java.security.PrivilegedExceptionAction;
031    
032    import org.apache.velocity.Template;
033    import org.apache.velocity.VelocityContext;
034    import org.apache.velocity.app.VelocityEngine;
035    import org.apache.velocity.exception.ParseErrorException;
036    
037    /**
038     * @author Tina Tian
039     */
040    public class VelocityTemplate extends AbstractTemplate {
041    
042            public VelocityTemplate(
043                    TemplateResource templateResource,
044                    TemplateResource errorTemplateResource, VelocityContext velocityContext,
045                    VelocityEngine velocityEngine,
046                    TemplateContextHelper templateContextHelper) {
047    
048                    super(
049                            templateResource, errorTemplateResource, templateContextHelper,
050                            TemplateConstants.LANG_TYPE_VM,
051                            PropsValues.VELOCITY_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL);
052    
053                    if (velocityContext == null) {
054                            _velocityContext = new VelocityContext();
055                    }
056                    else {
057                            _velocityContext = new VelocityContext(velocityContext);
058                    }
059    
060                    _velocityEngine = velocityEngine;
061            }
062    
063            public Object get(String key) {
064                    return _velocityContext.get(key);
065            }
066    
067            public String[] getKeys() {
068                    return (String[])_velocityContext.getKeys();
069            }
070    
071            public void put(String key, Object value) {
072                    if (value == null) {
073                            return;
074                    }
075    
076                    _velocityContext.put(key, value);
077            }
078    
079            @Override
080            protected void handleException(Exception exception, Writer writer)
081                    throws 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 ParseErrorException) {
093                            ParseErrorException pee = (ParseErrorException)exception;
094    
095                            put("column", pee.getColumnNumber());
096                            put("line", pee.getLineNumber());
097                    }
098    
099                    try {
100                            processTemplate(errorTemplateResource, writer);
101                    }
102                    catch (Exception e) {
103                            throw new TemplateException(
104                                    "Unable to process Velocity template " +
105                                            errorTemplateResource.getTemplateId(),
106                                    e);
107                    }
108            }
109    
110            @Override
111            protected void processTemplate(
112                            TemplateResource templateResource, Writer writer)
113                    throws Exception {
114    
115                    TemplateResourceThreadLocal.setTemplateResource(
116                            TemplateConstants.LANG_TYPE_VM, templateResource);
117    
118                    try {
119                            Template template = AccessController.doPrivileged(
120                                    new TemplatePrivilegedExceptionAction(templateResource));
121    
122                            template.merge(_velocityContext, writer);
123                    }
124                    catch (PrivilegedActionException pae) {
125                            throw pae.getException();
126                    }
127                    finally {
128                            TemplateResourceThreadLocal.setTemplateResource(
129                                    TemplateConstants.LANG_TYPE_VM, null);
130                    }
131            }
132    
133            private VelocityContext _velocityContext;
134            private VelocityEngine _velocityEngine;
135    
136            private class TemplatePrivilegedExceptionAction
137                    implements PrivilegedExceptionAction<Template> {
138    
139                    public TemplatePrivilegedExceptionAction(
140                            TemplateResource templateResource) {
141    
142                            _templateResource = templateResource;
143                    }
144    
145                    public Template run() throws Exception {
146                            return _velocityEngine.getTemplate(
147                                    getTemplateResourceUUID(_templateResource),
148                                    TemplateConstants.DEFAUT_ENCODING);
149                    }
150    
151                    private TemplateResource _templateResource;
152    
153            }
154    
155    }