001
014
015 package com.liferay.portal.template;
016
017 import com.liferay.portal.kernel.cache.MultiVMPool;
018 import com.liferay.portal.kernel.cache.PortalCache;
019 import com.liferay.portal.kernel.cache.PortalCacheListener;
020 import com.liferay.portal.kernel.cache.PortalCacheListenerScope;
021 import com.liferay.portal.kernel.cache.SingleVMPool;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025 import com.liferay.portal.kernel.template.ClassLoaderTemplateResource;
026 import com.liferay.portal.kernel.template.TemplateException;
027 import com.liferay.portal.kernel.template.TemplateResource;
028 import com.liferay.portal.kernel.template.TemplateResourceLoader;
029 import com.liferay.portal.kernel.template.URLTemplateResource;
030 import com.liferay.portal.kernel.util.InstanceFactory;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.Validator;
033
034 import java.io.IOException;
035 import java.io.ObjectInput;
036 import java.io.ObjectOutput;
037 import java.io.Reader;
038
039 import java.util.HashSet;
040 import java.util.Set;
041
042
045 @DoPrivileged
046 public class DefaultTemplateResourceLoader implements TemplateResourceLoader {
047
048 public DefaultTemplateResourceLoader(
049 String name, String[] templateResourceParserClassNames,
050 long modificationCheckInterval, MultiVMPool multiVMPool,
051 SingleVMPool singleVMPool) {
052
053 if (Validator.isNull(name)) {
054 throw new IllegalArgumentException(
055 "Template resource loader name is null");
056 }
057
058 if (templateResourceParserClassNames == null) {
059 throw new IllegalArgumentException(
060 "Template resource parser class names is null");
061 }
062
063 _name = name;
064
065 for (String templateResourceParserClassName :
066 templateResourceParserClassNames) {
067
068 try {
069 TemplateResourceParser templateResourceParser =
070 (TemplateResourceParser)InstanceFactory.newInstance(
071 templateResourceParserClassName);
072
073 _templateResourceParsers.add(templateResourceParser);
074 }
075 catch (Exception e) {
076 _log.error(e, e);
077 }
078 }
079
080 _modificationCheckInterval = modificationCheckInterval;
081
082 _multiVMPool = multiVMPool;
083
084 String portalCacheName = TemplateResourceLoader.class.getName();
085
086 portalCacheName = portalCacheName.concat(
087 StringPool.PERIOD).concat(name);
088
089 _multiVMPortalCache =
090 (PortalCache<String, TemplateResource>)_multiVMPool.getPortalCache(
091 portalCacheName);
092
093 PortalCacheListener<String, TemplateResource> cacheListener =
094 new TemplateResourcePortalCacheListener(name);
095
096 _multiVMPortalCache.registerPortalCacheListener(
097 cacheListener, PortalCacheListenerScope.ALL);
098
099 _singleVMPool = singleVMPool;
100
101 _singleVMPortalCache =
102 (PortalCache<String, TemplateResource>)_singleVMPool.getPortalCache(
103 portalCacheName);
104
105 _singleVMPortalCache.registerPortalCacheListener(
106 cacheListener, PortalCacheListenerScope.ALL);
107 }
108
109 @Override
110 public void clearCache() {
111 _multiVMPortalCache.removeAll();
112 _singleVMPortalCache.removeAll();
113 }
114
115 @Override
116 public void clearCache(String templateId) {
117 _multiVMPortalCache.remove(templateId);
118 _singleVMPortalCache.remove(templateId);
119 }
120
121 @Override
122 public void destroy() {
123 _multiVMPool.removePortalCache(
124 _multiVMPortalCache.getPortalCacheName());
125 _singleVMPool.removePortalCache(
126 _singleVMPortalCache.getPortalCacheName());
127
128 _templateResourceParsers.clear();
129 }
130
131 @Override
132 public String getName() {
133 return _name;
134 }
135
136 @Override
137 public TemplateResource getTemplateResource(String templateId) {
138 if (_modificationCheckInterval == 0) {
139 return _loadFromParser(templateId);
140 }
141
142 TemplateResource templateResource = _loadFromCache(templateId);
143
144 if (templateResource != null) {
145 if (templateResource instanceof NullHolderTemplateResource) {
146 return null;
147 }
148
149 return templateResource;
150 }
151
152 templateResource = _loadFromParser(templateId);
153
154 _updateCache(templateId, templateResource);
155
156 return templateResource;
157 }
158
159 @Override
160 public boolean hasTemplateResource(String templateId) {
161 TemplateResource templateResource = getTemplateResource(templateId);
162
163 if (templateResource != null) {
164 return true;
165 }
166
167 return false;
168 }
169
170 private TemplateResource _getTemplateResource() {
171 TemplateResource templateResource =
172 TemplateResourceThreadLocal.getTemplateResource(_name);
173
174 if (templateResource instanceof CacheTemplateResource) {
175 CacheTemplateResource cacheTemplateResource =
176 (CacheTemplateResource)templateResource;
177
178 return cacheTemplateResource.getInnerTemplateResource();
179 }
180
181 return templateResource;
182 }
183
184 private Set<TemplateResourceParser> _getTemplateResourceParsers() {
185 TemplateResource templateResource = _getTemplateResource();
186
187 if ((templateResource != null) &&
188 (templateResource instanceof ClassLoaderTemplateResource)) {
189
190 ClassLoaderTemplateResource classLoaderTemplateResource =
191 (ClassLoaderTemplateResource)templateResource;
192
193 ClassLoaderResourceParser classLoaderResourceParser =
194 new ClassLoaderResourceParser(
195 classLoaderTemplateResource.getClassLoader());
196
197 Set<TemplateResourceParser> templateResourceParsers = new HashSet<>(
198 _templateResourceParsers);
199
200 templateResourceParsers.add(classLoaderResourceParser);
201
202 return templateResourceParsers;
203 }
204
205 return _templateResourceParsers;
206 }
207
208 private TemplateResource _loadFromCache(
209 PortalCache<String, TemplateResource> portalCache, String templateId) {
210
211 Object object = portalCache.get(templateId);
212
213 if (object == null) {
214 return null;
215 }
216
217 if (!(object instanceof TemplateResource)) {
218 portalCache.remove(templateId);
219
220 if (_log.isWarnEnabled()) {
221 _log.warn(
222 "Remove template " + templateId +
223 " because it is not a template resource");
224 }
225
226 return null;
227 }
228
229 TemplateResource templateResource = (TemplateResource)object;
230
231 if (_modificationCheckInterval > 0) {
232 long expireTime =
233 templateResource.getLastModified() + _modificationCheckInterval;
234
235 if (System.currentTimeMillis() > expireTime) {
236 portalCache.remove(templateId);
237
238 templateResource = _nullHolderTemplateResource;
239
240 if (_log.isDebugEnabled()) {
241 _log.debug(
242 "Remove expired template resource " + templateId);
243 }
244 }
245 }
246
247 return templateResource;
248 }
249
250 private TemplateResource _loadFromCache(String templateId) {
251 TemplateResource templateResource = _loadFromCache(
252 _singleVMPortalCache, templateId);
253
254 if (templateResource != null) {
255 if (templateResource == _nullHolderTemplateResource) {
256 return null;
257 }
258
259 return templateResource;
260 }
261
262 templateResource = _loadFromCache(_multiVMPortalCache, templateId);
263
264 if ((templateResource == null) ||
265 (templateResource == _nullHolderTemplateResource)) {
266
267 return null;
268 }
269
270 return templateResource;
271 }
272
273 private TemplateResource _loadFromParser(String templateId) {
274 Set<TemplateResourceParser> templateResourceParsers =
275 _getTemplateResourceParsers();
276
277 for (TemplateResourceParser templateResourceParser :
278 templateResourceParsers) {
279
280 try {
281 TemplateResource templateResource =
282 templateResourceParser.getTemplateResource(templateId);
283
284 if (templateResource != null) {
285 if (_modificationCheckInterval != 0) {
286 templateResource = new CacheTemplateResource(
287 templateResource);
288 }
289
290 return templateResource;
291 }
292 }
293 catch (TemplateException te) {
294 if (_log.isWarnEnabled()) {
295 _log.warn(
296 "Unable to parse template " + templateId +
297 " with parser " + templateResourceParser,
298 te);
299 }
300 }
301 }
302
303 return null;
304 }
305
306 private void _updateCache(
307 String templateId, TemplateResource templateResource) {
308
309 if (templateResource == null) {
310 _singleVMPortalCache.put(
311 templateId, new NullHolderTemplateResource());
312
313 return;
314 }
315
316 CacheTemplateResource cacheTemplateResource =
317 (CacheTemplateResource)templateResource;
318
319 TemplateResource innerTemplateResource =
320 cacheTemplateResource.getInnerTemplateResource();
321
322 if (innerTemplateResource instanceof URLTemplateResource) {
323 _singleVMPortalCache.put(templateId, templateResource);
324
325 return;
326 }
327
328 _multiVMPortalCache.put(templateId, templateResource);
329 }
330
331 private static final Log _log = LogFactoryUtil.getLog(
332 DefaultTemplateResourceLoader.class);
333
334 private static final NullHolderTemplateResource
335 _nullHolderTemplateResource = new NullHolderTemplateResource();
336
337 private long _modificationCheckInterval;
338 private final MultiVMPool _multiVMPool;
339 private final PortalCache<String, TemplateResource> _multiVMPortalCache;
340 private final String _name;
341 private final SingleVMPool _singleVMPool;
342 private final PortalCache<String, TemplateResource> _singleVMPortalCache;
343 private final Set<TemplateResourceParser> _templateResourceParsers =
344 new HashSet<>();
345
346 private static class NullHolderTemplateResource
347 implements TemplateResource {
348
349
353 public NullHolderTemplateResource() {
354 }
355
356 @Override
357 public long getLastModified() {
358 return _lastModified;
359 }
360
361 @Override
362 public Reader getReader() {
363 return null;
364 }
365
366 @Override
367 public String getTemplateId() {
368 return null;
369 }
370
371 @Override
372 public void readExternal(ObjectInput objectInput) throws IOException {
373 _lastModified = objectInput.readLong();
374 }
375
376 @Override
377 public void writeExternal(ObjectOutput objectOutput)
378 throws IOException {
379
380 objectOutput.writeLong(_lastModified);
381 }
382
383 private long _lastModified = System.currentTimeMillis();
384
385 }
386
387 }