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.template;
016    
017    import com.liferay.portal.deploy.sandbox.SandboxHandler;
018    import com.liferay.portal.kernel.cache.CacheListener;
019    import com.liferay.portal.kernel.cache.CacheListenerScope;
020    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
021    import com.liferay.portal.kernel.cache.PortalCache;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
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.util.InstanceFactory;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.Validator;
031    
032    import java.io.IOException;
033    import java.io.ObjectInput;
034    import java.io.ObjectOutput;
035    import java.io.Reader;
036    
037    import java.util.HashSet;
038    import java.util.Set;
039    
040    /**
041     * @author Tina Tian
042     */
043    public class DefaultTemplateResourceLoader implements TemplateResourceLoader {
044    
045            public DefaultTemplateResourceLoader(
046                    String name, String[] templateResourceParserClassNames,
047                    long modificationCheckInterval) {
048    
049                    if (Validator.isNull(name)) {
050                            throw new IllegalArgumentException(
051                                    "Template resource loader name is null");
052                    }
053    
054                    if (templateResourceParserClassNames == null) {
055                            throw new IllegalArgumentException(
056                                    "Template resource parser class names is null");
057                    }
058    
059                    _name = name;
060    
061                    for (String templateResourceParserClassName :
062                                    templateResourceParserClassNames) {
063    
064                            try {
065                                    TemplateResourceParser templateResourceParser =
066                                            (TemplateResourceParser)InstanceFactory.newInstance(
067                                                    templateResourceParserClassName);
068    
069                                    _templateResourceParsers.add(templateResourceParser);
070                            }
071                            catch (Exception e) {
072                                    _log.error(e, e);
073                            }
074                    }
075    
076                    _modificationCheckInterval = modificationCheckInterval;
077    
078                    String cacheName = TemplateResourceLoader.class.getName();
079    
080                    cacheName = cacheName.concat(StringPool.PERIOD).concat(name);
081    
082                    _portalCache = MultiVMPoolUtil.getCache(cacheName);
083    
084                    CacheListener<String, TemplateResource> cacheListener =
085                            new TemplateResourceCacheListener(name);
086    
087                    _portalCache.registerCacheListener(
088                            cacheListener, CacheListenerScope.ALL);
089            }
090    
091            public void clearCache() {
092                    _portalCache.removeAll();
093            }
094    
095            public void clearCache(String templateId) {
096                    _portalCache.remove(templateId);
097            }
098    
099            public void destroy() {
100                    _portalCache.destroy();
101    
102                    _templateResourceParsers.clear();
103            }
104    
105            public String getName() {
106                    return _name;
107            }
108    
109            public TemplateResource getTemplateResource(String templateId) {
110                    TemplateResource templateResource = _loadFromCache(templateId);
111    
112                    if (templateResource != null) {
113                            if (templateResource instanceof NullHolderTemplateResource) {
114                                    return null;
115                            }
116    
117                            return templateResource;
118                    }
119    
120                    templateResource = _loadFromParser(templateId);
121    
122                    if (_modificationCheckInterval != 0) {
123                            if (templateResource == null) {
124                                    _portalCache.put(templateId, new NullHolderTemplateResource());
125                            }
126                            else {
127                                    _portalCache.put(templateId, templateResource);
128                            }
129                    }
130    
131                    return templateResource;
132            }
133    
134            public boolean hasTemplateResource(String templateId) {
135                    TemplateResource templateResource = getTemplateResource(templateId);
136    
137                    if (templateResource != null) {
138                            return true;
139                    }
140    
141                    return false;
142            }
143    
144            private TemplateResource _loadFromCache(String templateId) {
145                    if (_modificationCheckInterval == 0) {
146                            return null;
147                    }
148    
149                    Object object = _portalCache.get(templateId);
150    
151                    if (object == null) {
152                            return null;
153                    }
154    
155                    if (!(object instanceof TemplateResource)) {
156                            _portalCache.remove(templateId);
157    
158                            if (_log.isWarnEnabled()) {
159                                    _log.warn(
160                                            "Remove template " + templateId +
161                                                    " because it is not a template resource");
162                            }
163    
164                            return null;
165                    }
166    
167                    TemplateResource templateResource = (TemplateResource)object;
168    
169                    if (_modificationCheckInterval > 0) {
170                            long expireTime =
171                                    templateResource.getLastModified() + _modificationCheckInterval;
172    
173                            if (System.currentTimeMillis() > expireTime) {
174                                    _portalCache.remove(templateId);
175    
176                                    templateResource = null;
177    
178                                    if (_log.isDebugEnabled()) {
179                                            _log.debug(
180                                                    "Remove expired template resource " + templateId);
181                                    }
182                            }
183                    }
184    
185                    return templateResource;
186            }
187    
188            private TemplateResource _loadFromParser(String templateId) {
189                    for (TemplateResourceParser templateResourceParser :
190                                    _templateResourceParsers) {
191    
192                            try {
193                                    TemplateResource templateResource =
194                                            templateResourceParser.getTemplateResource(templateId);
195    
196                                    if (templateResource != null) {
197                                            if ((_modificationCheckInterval != 0) &&
198                                                    (!_name.equals(TemplateConstants.LANG_TYPE_VM) ||
199                                                     !templateId.contains(
200                                                             SandboxHandler.SANDBOX_MARKER))) {
201    
202                                                    templateResource = new CacheTemplateResource(
203                                                            templateResource);
204                                            }
205    
206                                            return templateResource;
207                                    }
208                            }
209                            catch (TemplateException te) {
210                                    _log.warn(
211                                            "Unable to parse template " + templateId + " with parser " +
212                                                    templateResourceParser,
213                                            te);
214                            }
215                    }
216    
217                    return null;
218            }
219    
220            private static Log _log = LogFactoryUtil.getLog(
221                    DefaultTemplateResourceLoader.class);
222    
223            private long _modificationCheckInterval;
224            private String _name;
225            private PortalCache<String, TemplateResource> _portalCache;
226            private Set<TemplateResourceParser> _templateResourceParsers =
227                    new HashSet<TemplateResourceParser>();
228    
229            private static class NullHolderTemplateResource
230                    implements TemplateResource {
231    
232                    /**
233                     * The empty constructor is required by {@link java.io.Externalizable}.
234                     * Do not use this for any other purpose.
235                     */
236                    public NullHolderTemplateResource() {
237                    }
238    
239                    public long getLastModified() {
240                            return _lastModified;
241                    }
242    
243                    public Reader getReader() {
244                            return null;
245                    }
246    
247                    public String getTemplateId() {
248                            return null;
249                    }
250    
251                    public void readExternal(ObjectInput objectInput) throws IOException {
252                            _lastModified = objectInput.readLong();
253                    }
254    
255                    public void writeExternal(ObjectOutput objectOutput)
256                            throws IOException {
257    
258                            objectOutput.writeLong(_lastModified);
259                    }
260    
261                    private long _lastModified = System.currentTimeMillis();
262    
263            }
264    
265    }