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