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