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