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