001    /**
002     * Copyright (c) 2000-present 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.template;
016    
017    import com.liferay.portal.deploy.sandbox.SandboxHandler;
018    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
019    import com.liferay.portal.kernel.cache.PortalCache;
020    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
021    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
022    import com.liferay.portal.kernel.template.StringTemplateResource;
023    import com.liferay.portal.kernel.template.Template;
024    import com.liferay.portal.kernel.template.TemplateConstants;
025    import com.liferay.portal.kernel.template.TemplateException;
026    import com.liferay.portal.kernel.template.TemplateResource;
027    import com.liferay.portal.kernel.template.TemplateResourceLoader;
028    import com.liferay.portal.kernel.template.URLTemplateResource;
029    import com.liferay.portal.kernel.util.StringBundler;
030    import com.liferay.portal.kernel.util.StringPool;
031    
032    import java.io.Serializable;
033    import java.io.Writer;
034    
035    import java.util.HashMap;
036    import java.util.Map;
037    import java.util.Set;
038    
039    import javax.servlet.http.HttpServletRequest;
040    
041    /**
042     * @author Tina Tian
043     */
044    public abstract class AbstractTemplate implements Template {
045    
046            public AbstractTemplate(
047                    TemplateResource templateResource,
048                    TemplateResource errorTemplateResource, Map<String, Object> context,
049                    TemplateContextHelper templateContextHelper, String templateManagerName,
050                    long interval) {
051    
052                    if (templateResource == null) {
053                            throw new IllegalArgumentException("Template resource is null");
054                    }
055    
056                    if (templateContextHelper == null) {
057                            throw new IllegalArgumentException(
058                                    "Template context helper is null");
059                    }
060    
061                    if (templateManagerName == null) {
062                            throw new IllegalArgumentException("Template manager name is null");
063                    }
064    
065                    this.templateResource = templateResource;
066                    this.errorTemplateResource = errorTemplateResource;
067    
068                    this.context = new HashMap<String, Object>();
069    
070                    if (context != null) {
071                            for (Map.Entry<String, Object> entry : context.entrySet()) {
072                                    put(entry.getKey(), entry.getValue());
073                            }
074                    }
075    
076                    _templateContextHelper = templateContextHelper;
077    
078                    if (interval != 0) {
079                            _cacheTemplateResource(templateManagerName);
080                    }
081            }
082    
083            @Override
084            public void doProcessTemplate(Writer writer) throws Exception {
085                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
086    
087                    put(TemplateConstants.WRITER, unsyncStringWriter);
088    
089                    processTemplate(templateResource, unsyncStringWriter);
090    
091                    StringBundler sb = unsyncStringWriter.getStringBundler();
092    
093                    sb.writeTo(writer);
094            }
095    
096            @Override
097            public Object get(String key) {
098                    if (key == null) {
099                            return null;
100                    }
101    
102                    return context.get(key);
103            }
104    
105            @Override
106            public String[] getKeys() {
107                    Set<String> keys = context.keySet();
108    
109                    return keys.toArray(new String[keys.size()]);
110            }
111    
112            @Override
113            public void prepare(HttpServletRequest request) {
114                    _templateContextHelper.prepare(this, request);
115            }
116    
117            @Override
118            public void processTemplate(Writer writer) throws TemplateException {
119                    if (errorTemplateResource == null) {
120                            try {
121                                    processTemplate(templateResource, writer);
122    
123                                    return;
124                            }
125                            catch (Exception e) {
126                                    throw new TemplateException(
127                                            "Unable to process template " +
128                                                    templateResource.getTemplateId(),
129                                            e);
130                            }
131                    }
132    
133                    Writer oldWriter = (Writer)get(TemplateConstants.WRITER);
134    
135                    try {
136                            doProcessTemplate(writer);
137                    }
138                    catch (Exception e) {
139                            put(TemplateConstants.WRITER, writer);
140    
141                            handleException(e, writer);
142                    }
143                    finally {
144                            put(TemplateConstants.WRITER, oldWriter);
145                    }
146            }
147    
148            @Override
149            public void put(String key, Object value) {
150                    if ((key == null) || (value == null)) {
151                            return;
152                    }
153    
154                    context.put(key, value);
155            }
156    
157            protected String getTemplateResourceUUID(
158                    TemplateResource templateResource) {
159    
160                    return TemplateConstants.TEMPLATE_RESOURCE_UUID_PREFIX.concat(
161                            StringPool.POUND).concat(templateResource.getTemplateId());
162            }
163    
164            protected abstract void handleException(Exception exception, Writer writer)
165                    throws TemplateException;
166    
167            protected abstract void processTemplate(
168                            TemplateResource templateResource, Writer writer)
169                    throws Exception;
170    
171            protected Map<String, Object> context;
172            protected TemplateResource errorTemplateResource;
173            protected TemplateResource templateResource;
174    
175            private void _cacheTemplateResource(String templateManagerName) {
176                    String templateId = templateResource.getTemplateId();
177    
178                    if (templateManagerName.equals(TemplateConstants.LANG_TYPE_VM) &&
179                            templateId.contains(SandboxHandler.SANDBOX_MARKER)) {
180    
181                            return;
182                    }
183    
184                    if (!(templateResource instanceof CacheTemplateResource) &&
185                            !(templateResource instanceof StringTemplateResource)) {
186    
187                            templateResource = new CacheTemplateResource(templateResource);
188                    }
189    
190                    String cacheName = TemplateResourceLoader.class.getName();
191    
192                    cacheName = cacheName.concat(StringPool.PERIOD).concat(
193                            templateManagerName);
194    
195                    PortalCache<String, Serializable> portalCache = _getPortalCache(
196                            templateResource, cacheName);
197    
198                    Object object = portalCache.get(templateResource.getTemplateId());
199    
200                    if ((object == null) || !templateResource.equals(object)) {
201                            portalCache.put(templateResource.getTemplateId(), templateResource);
202                    }
203    
204                    if (errorTemplateResource == null) {
205                            return;
206                    }
207    
208                    String errorTemplateId = errorTemplateResource.getTemplateId();
209    
210                    if (templateManagerName.equals(TemplateConstants.LANG_TYPE_VM) &&
211                            errorTemplateId.contains(SandboxHandler.SANDBOX_MARKER)) {
212    
213                            return;
214                    }
215    
216                    if (!(errorTemplateResource instanceof CacheTemplateResource) &&
217                            !(errorTemplateResource instanceof StringTemplateResource)) {
218    
219                            errorTemplateResource = new CacheTemplateResource(
220                                    errorTemplateResource);
221                    }
222    
223                    portalCache = _getPortalCache(errorTemplateResource, cacheName);
224    
225                    object = portalCache.get(errorTemplateResource.getTemplateId());
226    
227                    if ((object == null) || !errorTemplateResource.equals(object)) {
228                            portalCache.put(
229                                    errorTemplateResource.getTemplateId(), errorTemplateResource);
230                    }
231            }
232    
233            private PortalCache<String, Serializable> _getPortalCache(
234                    TemplateResource templateResource, String cacheName) {
235    
236                    if (!(templateResource instanceof CacheTemplateResource)) {
237                            return MultiVMPoolUtil.getCache(cacheName);
238                    }
239    
240                    CacheTemplateResource cacheTemplateResource =
241                            (CacheTemplateResource)templateResource;
242    
243                    TemplateResource innerTemplateResource =
244                            cacheTemplateResource.getInnerTemplateResource();
245    
246                    if (innerTemplateResource instanceof URLTemplateResource) {
247                            return SingleVMPoolUtil.getCache(cacheName);
248                    }
249    
250                    return MultiVMPoolUtil.getCache(cacheName);
251            }
252    
253            private final TemplateContextHelper _templateContextHelper;
254    
255    }