001
014
015 package com.liferay.portlet.portletdisplaytemplate.util;
016
017 import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.portletdisplaytemplate.BasePortletDisplayTemplateHandler;
021 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
022 import com.liferay.portal.kernel.servlet.JSPSupportServlet;
023 import com.liferay.portal.kernel.template.TemplateConstants;
024 import com.liferay.portal.kernel.template.TemplateHandler;
025 import com.liferay.portal.kernel.template.TemplateHandlerRegistryUtil;
026 import com.liferay.portal.kernel.template.TemplateVariableGroup;
027 import com.liferay.portal.kernel.util.ArrayUtil;
028 import com.liferay.portal.kernel.util.JavaConstants;
029 import com.liferay.portal.kernel.util.PropsKeys;
030 import com.liferay.portal.kernel.util.ProxyUtil;
031 import com.liferay.portal.kernel.util.Validator;
032 import com.liferay.portal.kernel.util.WebKeys;
033 import com.liferay.portal.model.Group;
034 import com.liferay.portal.service.GroupLocalServiceUtil;
035 import com.liferay.portal.templateparser.Transformer;
036 import com.liferay.portal.theme.ThemeDisplay;
037 import com.liferay.portal.util.PortletKeys;
038 import com.liferay.portlet.PortletURLUtil;
039 import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
040 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
041 import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
042 import com.liferay.taglib.servlet.PipingServletResponse;
043 import com.liferay.taglib.util.VelocityTaglib;
044 import com.liferay.taglib.util.VelocityTaglibImpl;
045 import com.liferay.util.freemarker.FreeMarkerTaglibFactoryUtil;
046
047 import freemarker.ext.beans.BeansWrapper;
048 import freemarker.ext.servlet.HttpRequestHashModel;
049 import freemarker.ext.servlet.ServletContextHashModel;
050
051 import freemarker.template.ObjectWrapper;
052 import freemarker.template.TemplateHashModel;
053 import freemarker.template.TemplateModel;
054 import freemarker.template.TemplateModelException;
055
056 import java.io.IOException;
057
058 import java.lang.reflect.InvocationHandler;
059
060 import java.util.ArrayList;
061 import java.util.HashMap;
062 import java.util.LinkedHashMap;
063 import java.util.List;
064 import java.util.Locale;
065 import java.util.Map;
066
067 import javax.portlet.PortletPreferences;
068 import javax.portlet.PortletURL;
069 import javax.portlet.RenderRequest;
070 import javax.portlet.RenderResponse;
071
072 import javax.servlet.GenericServlet;
073 import javax.servlet.ServletContext;
074 import javax.servlet.http.HttpServletRequest;
075 import javax.servlet.http.HttpServletResponse;
076 import javax.servlet.http.HttpSession;
077
078
083 @DoPrivileged
084 public class PortletDisplayTemplateImpl implements PortletDisplayTemplate {
085
086 @Override
087 public DDMTemplate fetchDDMTemplate(long groupId, String displayStyle) {
088 try {
089 Group group = GroupLocalServiceUtil.getGroup(groupId);
090
091 Group companyGroup = GroupLocalServiceUtil.getCompanyGroup(
092 group.getCompanyId());
093
094 String uuid = getDDMTemplateUuid(displayStyle);
095
096 if (Validator.isNull(uuid)) {
097 return null;
098 }
099
100 try {
101 return
102 DDMTemplateLocalServiceUtil.getDDMTemplateByUuidAndGroupId(
103 uuid, groupId);
104 }
105 catch (NoSuchTemplateException nste) {
106 }
107
108 try {
109 return
110 DDMTemplateLocalServiceUtil.getDDMTemplateByUuidAndGroupId(
111 uuid, companyGroup.getGroupId());
112 }
113 catch (NoSuchTemplateException nste) {
114 }
115 }
116 catch (Exception e) {
117 if (_log.isWarnEnabled()) {
118 _log.warn(e, e);
119 }
120 }
121
122 return null;
123 }
124
125 @Override
126 public long getDDMTemplateGroupId(long groupId) {
127 try {
128 Group group = GroupLocalServiceUtil.getGroup(groupId);
129
130 if (group.isLayout()) {
131 group = group.getParentGroup();
132 }
133
134 if (group.isStagingGroup()) {
135 Group liveGroup = group.getLiveGroup();
136
137 if (!liveGroup.isStagedPortlet(
138 PortletKeys.PORTLET_DISPLAY_TEMPLATES)) {
139
140 return liveGroup.getGroupId();
141 }
142 }
143
144 return group.getGroupId();
145 }
146 catch (Exception e) {
147 if (_log.isWarnEnabled()) {
148 _log.warn(e, e);
149 }
150 }
151
152 return groupId;
153 }
154
155 @Override
156 public String getDDMTemplateUuid(String displayStyle) {
157 if (!displayStyle.startsWith(DISPLAY_STYLE_PREFIX)) {
158 return null;
159 }
160
161 return displayStyle.substring(DISPLAY_STYLE_PREFIX.length());
162 }
163
164 @Override
165 public long getPortletDisplayTemplateDDMTemplateId(
166 long groupId, String displayStyle) {
167
168 long portletDisplayDDMTemplateId = 0;
169
170 long portletDisplayDDMTemplateGroupId = getDDMTemplateGroupId(groupId);
171
172 if (displayStyle.startsWith(DISPLAY_STYLE_PREFIX)) {
173 DDMTemplate portletDisplayDDMTemplate = fetchDDMTemplate(
174 portletDisplayDDMTemplateGroupId, displayStyle);
175
176 if (portletDisplayDDMTemplate != null) {
177 portletDisplayDDMTemplateId =
178 portletDisplayDDMTemplate.getTemplateId();
179 }
180 }
181
182 return portletDisplayDDMTemplateId;
183 }
184
185 @Override
186 public List<TemplateHandler> getPortletDisplayTemplateHandlers() {
187 List<TemplateHandler> templateHandlers =
188 TemplateHandlerRegistryUtil.getTemplateHandlers();
189
190 List<TemplateHandler> portletDisplayTemplateHandlers =
191 new ArrayList<TemplateHandler>();
192
193 for (TemplateHandler templateHandler : templateHandlers) {
194 if (templateHandler instanceof BasePortletDisplayTemplateHandler) {
195 portletDisplayTemplateHandlers.add(templateHandler);
196 }
197 else if (ProxyUtil.isProxyClass(templateHandler.getClass())) {
198 InvocationHandler invocationHandler =
199 ProxyUtil.getInvocationHandler(templateHandler);
200
201 if (invocationHandler instanceof ClassLoaderBeanHandler) {
202 ClassLoaderBeanHandler classLoaderBeanHandler =
203 (ClassLoaderBeanHandler)invocationHandler;
204
205 Object bean = classLoaderBeanHandler.getBean();
206
207 if (bean instanceof BasePortletDisplayTemplateHandler) {
208 portletDisplayTemplateHandlers.add(templateHandler);
209 }
210 }
211 }
212 }
213
214 return portletDisplayTemplateHandlers;
215 }
216
217 @Override
218 public Map<String, TemplateVariableGroup> getTemplateVariableGroups(
219 String language) {
220
221 Map<String, TemplateVariableGroup> templateVariableGroups =
222 new LinkedHashMap<String, TemplateVariableGroup>();
223
224 TemplateVariableGroup fieldsTemplateVariableGroup =
225 new TemplateVariableGroup("fields");
226
227 fieldsTemplateVariableGroup.addCollectionVariable(
228 "entries", List.class, PortletDisplayTemplateConstants.ENTRIES,
229 "entries-item", null, "curEntry", null);
230 fieldsTemplateVariableGroup.addVariable(
231 "entry", null, PortletDisplayTemplateConstants.ENTRY);
232
233 templateVariableGroups.put("fields", fieldsTemplateVariableGroup);
234
235 TemplateVariableGroup generalVariablesTemplateVariableGroup =
236 new TemplateVariableGroup("general-variables");
237
238 generalVariablesTemplateVariableGroup.addVariable(
239 "current-url", String.class,
240 PortletDisplayTemplateConstants.CURRENT_URL);
241 generalVariablesTemplateVariableGroup.addVariable(
242 "locale", Locale.class, PortletDisplayTemplateConstants.LOCALE);
243 generalVariablesTemplateVariableGroup.addVariable(
244 "portlet-preferences", Map.class,
245 PortletDisplayTemplateConstants.PORTLET_PREFERENCES);
246 generalVariablesTemplateVariableGroup.addVariable(
247 "template-id", null, PortletDisplayTemplateConstants.TEMPLATE_ID);
248 generalVariablesTemplateVariableGroup.addVariable(
249 "theme-display", ThemeDisplay.class,
250 PortletDisplayTemplateConstants.THEME_DISPLAY);
251
252 templateVariableGroups.put(
253 "general-variables", generalVariablesTemplateVariableGroup);
254
255 TemplateVariableGroup utilTemplateVariableGroup =
256 new TemplateVariableGroup("util");
257
258 utilTemplateVariableGroup.addVariable(
259 "http-request", HttpServletRequest.class,
260 PortletDisplayTemplateConstants.REQUEST);
261
262 if (language.equals(TemplateConstants.LANG_TYPE_VM)) {
263 utilTemplateVariableGroup.addVariable(
264 "liferay-taglib", VelocityTaglib.class,
265 PortletDisplayTemplateConstants.TAGLIB_LIFERAY);
266 }
267
268 utilTemplateVariableGroup.addVariable(
269 "render-request", RenderRequest.class,
270 PortletDisplayTemplateConstants.RENDER_REQUEST);
271 utilTemplateVariableGroup.addVariable(
272 "render-response", RenderResponse.class,
273 PortletDisplayTemplateConstants.RENDER_RESPONSE);
274
275 templateVariableGroups.put("util", utilTemplateVariableGroup);
276
277 return templateVariableGroups;
278 }
279
280 @Override
281 public String renderDDMTemplate(
282 HttpServletRequest request, HttpServletResponse response,
283 long ddmTemplateId, List<?> entries)
284 throws Exception {
285
286 Map<String, Object> contextObjects = new HashMap<String, Object>();
287
288 return renderDDMTemplate(
289 request, response, ddmTemplateId, entries, contextObjects);
290 }
291
292 @Override
293 public String renderDDMTemplate(
294 HttpServletRequest request, HttpServletResponse response,
295 long ddmTemplateId, List<?> entries,
296 Map<String, Object> contextObjects)
297 throws Exception {
298
299 contextObjects.put(
300 PortletDisplayTemplateConstants.TEMPLATE_ID, ddmTemplateId);
301 contextObjects.put(PortletDisplayTemplateConstants.ENTRIES, entries);
302
303 if (!entries.isEmpty()) {
304 contextObjects.put(
305 PortletDisplayTemplateConstants.ENTRY, entries.get(0));
306 }
307
308 contextObjects.put(
309 PortletDisplayTemplateConstants.LOCALE, request.getLocale());
310
311 contextObjects.put(PortletDisplayTemplateConstants.REQUEST, request);
312
313 RenderRequest renderRequest = (RenderRequest)request.getAttribute(
314 JavaConstants.JAVAX_PORTLET_REQUEST);
315
316 contextObjects.put(
317 PortletDisplayTemplateConstants.RENDER_REQUEST, renderRequest);
318
319 RenderResponse renderResponse = (RenderResponse)request.getAttribute(
320 JavaConstants.JAVAX_PORTLET_RESPONSE);
321
322 contextObjects.put(
323 PortletDisplayTemplateConstants.RENDER_RESPONSE, renderResponse);
324
325 PortletURL currentURL = PortletURLUtil.getCurrent(
326 renderRequest, renderResponse);
327
328 contextObjects.put(
329 PortletDisplayTemplateConstants.CURRENT_URL, currentURL.toString());
330
331 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
332 WebKeys.THEME_DISPLAY);
333
334 contextObjects.put(
335 PortletDisplayTemplateConstants.THEME_DISPLAY, themeDisplay);
336
337
338
339 DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
340 ddmTemplateId);
341
342 contextObjects.put(
343 TemplateConstants.CLASS_NAME_ID, ddmTemplate.getClassNameId());
344
345 String language = ddmTemplate.getLanguage();
346
347 TemplateHandler templateHandler =
348 TemplateHandlerRegistryUtil.getTemplateHandler(
349 ddmTemplate.getClassNameId());
350
351 if (templateHandler instanceof BasePortletDisplayTemplateHandler) {
352 BasePortletDisplayTemplateHandler portletDisplayTemplateHandler =
353 (BasePortletDisplayTemplateHandler)templateHandler;
354
355 Map<String, Object> customContextObjects =
356 portletDisplayTemplateHandler.getCustomContextObjects();
357
358 for (String variableName : customContextObjects.keySet()) {
359 if (contextObjects.containsKey(variableName)) {
360 continue;
361 }
362
363 Object object = customContextObjects.get(variableName);
364
365 if (object instanceof Class) {
366 if (language.equals(TemplateConstants.LANG_TYPE_FTL)) {
367 _addStaticClassSupportFTL(
368 contextObjects, variableName, (Class<?>)object);
369 }
370 else if (language.equals(TemplateConstants.LANG_TYPE_VM)) {
371 _addStaticClassSupportVM(
372 contextObjects, variableName, (Class<?>)object);
373 }
374 }
375 else {
376 contextObjects.put(variableName, object);
377 }
378 }
379 }
380
381
382
383 if (language.equals(TemplateConstants.LANG_TYPE_FTL)) {
384 _addTaglibSupportFTL(contextObjects, request, response);
385 }
386 else if (language.equals(TemplateConstants.LANG_TYPE_VM)) {
387 _addTaglibSupportVM(contextObjects, request, response);
388 }
389
390 contextObjects.putAll(_getPortletPreferences(renderRequest));
391
392 return _transformer.transform(
393 themeDisplay, contextObjects, ddmTemplate.getScript(), language);
394 }
395
396 private void _addStaticClassSupportFTL(
397 Map<String, Object> contextObjects, String variableName,
398 Class<?> variableClass) {
399
400 try {
401 BeansWrapper beansWrapper = BeansWrapper.getDefaultInstance();
402
403 TemplateHashModel templateHashModel =
404 beansWrapper.getStaticModels();
405
406 TemplateModel templateModel = templateHashModel.get(
407 variableClass.getCanonicalName());
408
409 contextObjects.put(variableName, templateModel);
410 }
411 catch (TemplateModelException e) {
412 if (_log.isWarnEnabled()) {
413 _log.warn("Variable " + variableName + " registration fail", e);
414 }
415 }
416 }
417
418 private void _addStaticClassSupportVM(
419 Map<String, Object> contextObjects, String variableName,
420 Class<?> variableClass) {
421
422 contextObjects.put(variableName, variableClass);
423 }
424
425 private void _addTaglibSupportFTL(
426 Map<String, Object> contextObjects, HttpServletRequest request,
427 HttpServletResponse response)
428 throws Exception {
429
430
431
432 GenericServlet genericServlet = new JSPSupportServlet(
433 request.getServletContext());
434
435 ServletContextHashModel servletContextHashModel =
436 new ServletContextHashModel(
437 genericServlet, ObjectWrapper.DEFAULT_WRAPPER);
438
439 contextObjects.put(
440 PortletDisplayTemplateConstants.FREEMARKER_SERVLET_APPLICATION,
441 servletContextHashModel);
442
443
444
445 HttpRequestHashModel requestHashModel = new HttpRequestHashModel(
446 request, response, ObjectWrapper.DEFAULT_WRAPPER);
447
448 contextObjects.put(
449 PortletDisplayTemplateConstants.FREEMARKER_SERVLET_REQUEST,
450 requestHashModel);
451
452
453
454 TemplateHashModel taglibLiferayHash =
455 FreeMarkerTaglibFactoryUtil.createTaglibFactory(
456 request.getServletContext());
457
458 contextObjects.put(
459 PortletDisplayTemplateConstants.TAGLIB_LIFERAY_HASH,
460 taglibLiferayHash);
461 }
462
463 private void _addTaglibSupportVM(
464 Map<String, Object> contextObjects, HttpServletRequest request,
465 HttpServletResponse response) {
466
467 contextObjects.put(
468 PortletDisplayTemplateConstants.TAGLIB_LIFERAY,
469 _getVelocityTaglib(request, response));
470 }
471
472 private Map<String, Object> _getPortletPreferences(
473 RenderRequest renderRequest) {
474
475 Map<String, Object> contextObjects = new HashMap<String, Object>();
476
477 PortletPreferences portletPreferences = renderRequest.getPreferences();
478
479 Map<String, String[]> map = portletPreferences.getMap();
480
481 contextObjects.put(
482 PortletDisplayTemplateConstants.PORTLET_PREFERENCES, map);
483
484 for (Map.Entry<String, String[]> entry : map.entrySet()) {
485 String[] values = entry.getValue();
486
487 if (ArrayUtil.isEmpty(values)) {
488 continue;
489 }
490
491 String value = values[0];
492
493 if (value == null) {
494 continue;
495 }
496
497 contextObjects.put(entry.getKey(), value);
498 }
499
500 return contextObjects;
501 }
502
503 private VelocityTaglib _getVelocityTaglib(
504 HttpServletRequest request, HttpServletResponse response) {
505
506 HttpSession session = request.getSession();
507
508 ServletContext servletContext = session.getServletContext();
509
510 try {
511 VelocityTaglib velocityTaglib = new VelocityTaglibImpl(
512 servletContext, request,
513 new PipingServletResponse(response, response.getWriter()),
514 null);
515
516 return velocityTaglib;
517 }
518 catch (IOException ioe) {
519 throw new IllegalStateException(ioe);
520 }
521 }
522
523 private static final Log _log = LogFactoryUtil.getLog(
524 PortletDisplayTemplateImpl.class);
525
526 private final Transformer _transformer = new Transformer(
527 PropsKeys.DYNAMIC_DATA_LISTS_ERROR_TEMPLATE, true);
528
529 }