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