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.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 Object get(String key) {
085                    if (key == null) {
086                            return null;
087                    }
088    
089                    return context.get(key);
090            }
091    
092            @Override
093            public String[] getKeys() {
094                    Set<String> keys = context.keySet();
095    
096                    return keys.toArray(new String[keys.size()]);
097            }
098    
099            @Override
100            public void prepare(HttpServletRequest request) {
101                    _templateContextHelper.prepare(this, request);
102            }
103    
104            @Override
105            public void processTemplate(Writer writer) throws TemplateException {
106                    if (errorTemplateResource == null) {
107                            try {
108                                    processTemplate(templateResource, writer);
109    
110                                    return;
111                            }
112                            catch (Exception e) {
113                                    throw new TemplateException(
114                                            "Unable to process template " +
115                                                    templateResource.getTemplateId(),
116                                            e);
117                            }
118                    }
119    
120                    Writer oldWriter = (Writer)get(TemplateConstants.WRITER);
121    
122                    try {
123                            UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
124    
125                            put(TemplateConstants.WRITER, unsyncStringWriter);
126    
127                            processTemplate(templateResource, unsyncStringWriter);
128    
129                            StringBundler sb = unsyncStringWriter.getStringBundler();
130    
131                            sb.writeTo(writer);
132                    }
133                    catch (Exception e) {
134                            put(TemplateConstants.WRITER, writer);
135    
136                            handleException(e, writer);
137                    }
138                    finally {
139                            put(TemplateConstants.WRITER, oldWriter);
140                    }
141            }
142    
143            @Override
144            public void put(String key, Object value) {
145                    if ((key == null) || (value == null)) {
146                            return;
147                    }
148    
149                    context.put(key, value);
150            }
151    
152            protected String getTemplateResourceUUID(
153                    TemplateResource templateResource) {
154    
155                    return TemplateConstants.TEMPLATE_RESOURCE_UUID_PREFIX.concat(
156                            StringPool.POUND).concat(templateResource.getTemplateId());
157            }
158    
159            protected abstract void handleException(Exception exception, Writer writer)
160                    throws TemplateException;
161    
162            protected abstract void processTemplate(
163                            TemplateResource templateResource, Writer writer)
164                    throws Exception;
165    
166            protected Map<String, Object> context;
167            protected TemplateResource errorTemplateResource;
168            protected TemplateResource templateResource;
169    
170            private void _cacheTemplateResource(String templateManagerName) {
171                    String templateId = templateResource.getTemplateId();
172    
173                    if (templateManagerName.equals(TemplateConstants.LANG_TYPE_VM) &&
174                            templateId.contains(SandboxHandler.SANDBOX_MARKER)) {
175    
176                            return;
177                    }
178    
179                    if (!(templateResource instanceof CacheTemplateResource) &&
180                            !(templateResource instanceof StringTemplateResource)) {
181    
182                            templateResource = new CacheTemplateResource(templateResource);
183                    }
184    
185                    String cacheName = TemplateResourceLoader.class.getName();
186    
187                    cacheName = cacheName.concat(StringPool.PERIOD).concat(
188                            templateManagerName);
189    
190                    PortalCache<String, Serializable> portalCache = _getPortalCache(
191                            templateResource, cacheName);
192    
193                    Object object = portalCache.get(templateResource.getTemplateId());
194    
195                    if ((object == null) || !templateResource.equals(object)) {
196                            portalCache.put(templateResource.getTemplateId(), templateResource);
197                    }
198    
199                    if (errorTemplateResource == null) {
200                            return;
201                    }
202    
203                    String errorTemplateId = errorTemplateResource.getTemplateId();
204    
205                    if (templateManagerName.equals(TemplateConstants.LANG_TYPE_VM) &&
206                            errorTemplateId.contains(SandboxHandler.SANDBOX_MARKER)) {
207    
208                            return;
209                    }
210    
211                    if (!(errorTemplateResource instanceof CacheTemplateResource) &&
212                            !(errorTemplateResource instanceof StringTemplateResource)) {
213    
214                            errorTemplateResource = new CacheTemplateResource(
215                                    errorTemplateResource);
216                    }
217    
218                    portalCache = _getPortalCache(errorTemplateResource, cacheName);
219    
220                    object = portalCache.get(errorTemplateResource.getTemplateId());
221    
222                    if ((object == null) || !errorTemplateResource.equals(object)) {
223                            portalCache.put(
224                                    errorTemplateResource.getTemplateId(), errorTemplateResource);
225                    }
226            }
227    
228            private PortalCache<String, Serializable> _getPortalCache(
229                    TemplateResource templateResource, String cacheName) {
230    
231                    if (!(templateResource instanceof CacheTemplateResource)) {
232                            return MultiVMPoolUtil.getCache(cacheName);
233                    }
234    
235                    CacheTemplateResource cacheTemplateResource =
236                            (CacheTemplateResource)templateResource;
237    
238                    TemplateResource innerTemplateResource =
239                            cacheTemplateResource.getInnerTemplateResource();
240    
241                    if (innerTemplateResource instanceof URLTemplateResource) {
242                            return SingleVMPoolUtil.getCache(cacheName);
243                    }
244    
245                    return MultiVMPoolUtil.getCache(cacheName);
246            }
247    
248            private TemplateContextHelper _templateContextHelper;
249    
250    }