1
22
23 package com.liferay.portlet;
24
25 import com.liferay.portal.kernel.language.LanguageUtil;
26 import com.liferay.portal.kernel.log.Log;
27 import com.liferay.portal.kernel.log.LogFactoryUtil;
28 import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
29 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
30 import com.liferay.portal.kernel.portlet.PortletFilterUtil;
31 import com.liferay.portal.kernel.servlet.PortletServlet;
32 import com.liferay.portal.kernel.servlet.StringServletResponse;
33 import com.liferay.portal.kernel.util.ClassUtil;
34 import com.liferay.portal.kernel.util.GetterUtil;
35 import com.liferay.portal.kernel.util.JavaConstants;
36 import com.liferay.portal.kernel.util.StringPool;
37 import com.liferay.portal.kernel.util.Time;
38 import com.liferay.portal.model.Layout;
39 import com.liferay.portal.tools.PortletDeployer;
40 import com.liferay.portal.util.WebKeys;
41
42 import java.io.IOException;
43
44 import java.util.ArrayList;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49
50 import javax.portlet.ActionRequest;
51 import javax.portlet.ActionResponse;
52 import javax.portlet.EventRequest;
53 import javax.portlet.EventResponse;
54 import javax.portlet.Portlet;
55 import javax.portlet.PortletConfig;
56 import javax.portlet.PortletContext;
57 import javax.portlet.PortletException;
58 import javax.portlet.PortletRequest;
59 import javax.portlet.PortletSession;
60 import javax.portlet.RenderRequest;
61 import javax.portlet.RenderResponse;
62 import javax.portlet.ResourceRequest;
63 import javax.portlet.ResourceResponse;
64 import javax.portlet.filter.ActionFilter;
65 import javax.portlet.filter.EventFilter;
66 import javax.portlet.filter.FilterChain;
67 import javax.portlet.filter.PortletFilter;
68 import javax.portlet.filter.RenderFilter;
69 import javax.portlet.filter.ResourceFilter;
70
71 import javax.servlet.RequestDispatcher;
72 import javax.servlet.ServletException;
73 import javax.servlet.http.HttpServletRequest;
74 import javax.servlet.http.HttpServletResponse;
75 import javax.servlet.http.HttpSession;
76
77 import org.apache.commons.lang.time.StopWatch;
78
79
85 public class InvokerPortletImpl implements InvokerPortlet {
86
87 public static void clearResponse(
88 HttpSession session, long plid, String portletId, String languageId) {
89
90 String sesResponseId = encodeResponseKey(plid, portletId, languageId);
91
92 getResponses(session).remove(sesResponseId);
93 }
94
95 public static void clearResponses(HttpSession session) {
96 getResponses(session).clear();
97 }
98
99 public static void clearResponses(PortletSession session) {
100 getResponses(session).clear();
101 }
102
103 public static String encodeResponseKey(
104 long plid, String portletId, String languageId) {
105
106 StringBuilder sb = new StringBuilder();
107
108 sb.append(plid);
109 sb.append(StringPool.UNDERLINE);
110 sb.append(portletId);
111 sb.append(StringPool.UNDERLINE);
112 sb.append(languageId);
113
114 return sb.toString();
115 }
116
117 public static Map<String, InvokerPortletResponse> getResponses(
118 HttpSession session) {
119
120 Map<String, InvokerPortletResponse> responses =
121 (Map<String, InvokerPortletResponse>)session.getAttribute(
122 WebKeys.CACHE_PORTLET_RESPONSES);
123
124 if (responses == null) {
125 responses = new HashMap<String, InvokerPortletResponse>();
126
127 session.setAttribute(WebKeys.CACHE_PORTLET_RESPONSES, responses);
128 }
129
130 return responses;
131 }
132
133 public static Map<String, InvokerPortletResponse> getResponses(
134 PortletSession portletSession) {
135
136 return getResponses(
137 ((PortletSessionImpl)portletSession).getHttpSession());
138 }
139
140 public InvokerPortlet create(
141 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
142 PortletContext portletContext)
143 throws PortletException {
144
145 try {
146 InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
147
148 invokerPortlet.prepare(portletModel, portlet, portletContext);
149
150 return invokerPortlet;
151 }
152 catch (PortletException pe) {
153 throw pe;
154 }
155 catch (Exception e) {
156 throw new PortletException(e);
157 }
158 }
159
160 public InvokerPortlet create(
161 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
162 PortletConfig portletConfig, PortletContext portletContext,
163 boolean facesPortlet, boolean strutsPortlet,
164 boolean strutsBridgePortlet)
165 throws PortletException {
166
167 try {
168 InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
169
170 invokerPortlet.prepare(
171 portletModel, portlet, portletConfig, portletContext,
172 facesPortlet, strutsPortlet, strutsBridgePortlet);
173
174 return invokerPortlet;
175 }
176 catch (PortletException pe) {
177 throw pe;
178 }
179 catch (Exception e) {
180 throw new PortletException(e);
181 }
182 }
183
184 public void destroy() {
185 if (_destroyable) {
186 Thread currentThread = Thread.currentThread();
187
188 ClassLoader contextClassLoader =
189 currentThread.getContextClassLoader();
190
191 ClassLoader portletClassLoader = getPortletClassLoader();
192
193 try {
194 if (portletClassLoader != null) {
195 currentThread.setContextClassLoader(portletClassLoader);
196 }
197
198 removePortletFilters();
199
200 _portlet.destroy();
201 }
202 finally {
203 if (portletClassLoader != null) {
204 currentThread.setContextClassLoader(contextClassLoader);
205 }
206 }
207 }
208
209 _destroyable = false;
210 }
211
212 public Portlet getPortlet() {
213 return _portlet;
214 }
215
216 public ClassLoader getPortletClassLoader() {
217 return (ClassLoader)_portletContextImpl.getAttribute(
218 PortletServlet.PORTLET_CLASS_LOADER);
219 }
220
221 public PortletConfigImpl getPortletConfig() {
222 return _portletConfigImpl;
223 }
224
225 public PortletContextImpl getPortletContext() {
226 return _portletContextImpl;
227 }
228
229 public Portlet getPortletInstance() {
230 return _portlet;
231 }
232
233 public Integer getExpCache() {
234 return _expCache;
235 }
236
237 public void init(PortletConfig portletConfig) throws PortletException {
238 _portletConfigImpl = (PortletConfigImpl)portletConfig;
239
240 Thread currentThread = Thread.currentThread();
241
242 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
243
244 ClassLoader portletClassLoader = getPortletClassLoader();
245
246 try {
247 if (portletClassLoader != null) {
248 currentThread.setContextClassLoader(portletClassLoader);
249 }
250
251 _portlet.init(portletConfig);
252 }
253 finally {
254 if (portletClassLoader != null) {
255 currentThread.setContextClassLoader(contextClassLoader);
256 }
257 }
258
259 _destroyable = true;
260 }
261
262 public boolean isDestroyable() {
263 return _destroyable;
264 }
265
266 public boolean isFacesPortlet() {
267 return _facesPortlet;
268 }
269
270 public boolean isStrutsBridgePortlet() {
271 return _strutsBridgePortlet;
272 }
273
274 public boolean isStrutsPortlet() {
275 return _strutsPortlet;
276 }
277
278 public void prepare(
279 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
280 PortletContext portletContext)
281 throws PortletException {
282
283 _portletModel = portletModel;
284 _portletId = _portletModel.getPortletId();
285 _portlet = portlet;
286 _portletContextImpl = (PortletContextImpl)portletContext;
287
288 if (_log.isDebugEnabled()) {
289 _log.debug(
290 "Create root cache wrapper for " +
291 _portletContextImpl.getPortlet().getPortletId());
292 }
293
294 if (ClassUtil.isSubclass(
295 _portlet.getClass(), PortletDeployer.JSF_MYFACES) ||
296 ClassUtil.isSubclass(
297 _portlet.getClass(), PortletDeployer.JSF_STANDARD) ||
298 ClassUtil.isSubclass(
299 _portlet.getClass(), PortletDeployer.JSF_SUN)) {
300
301 _facesPortlet = true;
302 }
303
304 _strutsPortlet = ClassUtil.isSubclass(
305 portlet.getClass(), StrutsPortlet.class);
306 _strutsBridgePortlet = ClassUtil.isSubclass(
307 portlet.getClass(),
308 "org.apache.portals.bridges.struts.StrutsPortlet");
309 _expCache = portletModel.getExpCache();
310 setPortletFilters();
311 }
312
313 public void prepare(
314 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
315 PortletConfig portletConfig, PortletContext portletContext,
316 boolean facesPortlet, boolean strutsPortlet,
317 boolean strutsBridgePortlet)
318 throws PortletException {
319
320
322 _portletModel = portletModel;
323 _portlet = portlet;
324 _portletId = _portletModel.getPortletId();
325 _portletContextImpl = (PortletContextImpl)portletContext;
326 _facesPortlet = facesPortlet;
327 _strutsPortlet = strutsPortlet;
328 _strutsBridgePortlet = strutsBridgePortlet;
329 _expCache = portletModel.getExpCache();
330 setPortletFilters();
331
332 if (_log.isDebugEnabled()) {
333 _log.debug(
334 "Create instance cache wrapper for " +
335 _portletContextImpl.getPortlet().getPortletId());
336 }
337
338
340 _portletConfigImpl = (PortletConfigImpl)portletConfig;
341 }
342
343 public void processAction(
344 ActionRequest actionRequest, ActionResponse actionResponse)
345 throws IOException {
346
347 StopWatch stopWatch = null;
348
349 if (_log.isDebugEnabled()) {
350 stopWatch = new StopWatch();
351
352 stopWatch.start();
353 }
354
355 try {
356 invokeAction(actionRequest, actionResponse);
357 }
358 catch (PortletException pe) {
359 actionRequest.setAttribute(
360 _portletId + PortletException.class.getName(), pe);
361 }
362
363 if (_log.isDebugEnabled()) {
364 _log.debug(
365 "processAction for " + _portletId + " takes " +
366 stopWatch.getTime() + " ms");
367 }
368 }
369
370 public void processEvent(
371 EventRequest eventRequest, EventResponse eventResponse)
372 throws IOException, PortletException {
373
374 StopWatch stopWatch = null;
375
376 if (_log.isDebugEnabled()) {
377 stopWatch = new StopWatch();
378
379 stopWatch.start();
380 }
381
382 invokeEvent(eventRequest, eventResponse);
383
384 if (_log.isDebugEnabled()) {
385 _log.debug(
386 "processEvent for " + _portletId + " takes " +
387 stopWatch.getTime() + " ms");
388 }
389 }
390
391 public void render(
392 RenderRequest renderRequest, RenderResponse renderResponse)
393 throws IOException, PortletException {
394
395 PortletException portletException =
396 (PortletException)renderRequest.getAttribute(
397 _portletId + PortletException.class.getName());
398
399 if (portletException != null) {
400 throw portletException;
401 }
402
403 StopWatch stopWatch = null;
404
405 if (_log.isDebugEnabled()) {
406 stopWatch = new StopWatch();
407
408 stopWatch.start();
409 }
410
411 String remoteUser = renderRequest.getRemoteUser();
412
413 if ((remoteUser == null) || (_expCache == null) ||
414 (_expCache.intValue() == 0)) {
415
416 invokeRender(renderRequest, renderResponse);
417 }
418 else {
419 RenderResponseImpl renderResponseImpl =
420 (RenderResponseImpl)renderResponse;
421
422 StringServletResponse stringResponse = (StringServletResponse)
423 renderResponseImpl.getHttpServletResponse();
424
425 PortletSession portletSession = renderRequest.getPortletSession();
426
427 long now = System.currentTimeMillis();
428
429 Layout layout = (Layout)renderRequest.getAttribute(WebKeys.LAYOUT);
430
431 Map<String, InvokerPortletResponse> sessionResponses =
432 getResponses(portletSession);
433
434 String sessionResponseId = encodeResponseKey(
435 layout.getPlid(), _portletId,
436 LanguageUtil.getLanguageId(renderRequest));
437
438 InvokerPortletResponse response = sessionResponses.get(
439 sessionResponseId);
440
441 if (response == null) {
442 String title = invokeRender(renderRequest, renderResponse);
443
444 response = new InvokerPortletResponse(
445 title, stringResponse.getString(),
446 now + Time.SECOND * _expCache.intValue());
447
448 sessionResponses.put(sessionResponseId, response);
449 }
450 else if ((response.getTime() < now) &&
451 (_expCache.intValue() > 0)) {
452
453 String title = invokeRender(renderRequest, renderResponse);
454
455 response.setTitle(title);
456 response.setContent(stringResponse.getString());
457 response.setTime(now + Time.SECOND * _expCache.intValue());
458 }
459 else {
460 renderResponseImpl.setTitle(response.getTitle());
461 stringResponse.getWriter().print(response.getContent());
462 }
463 }
464
465 Map<String, String[]> properties =
466 ((RenderResponseImpl)renderResponse).getProperties();
467
468 if (properties.containsKey("clear-request-parameters")) {
469 Map<String, String[]> renderParameters =
470 ((RenderRequestImpl)renderRequest).getRenderParameters();
471
472 renderParameters.clear();
473 }
474
475 if (_log.isDebugEnabled()) {
476 _log.debug(
477 "render for " + _portletId + " takes " + stopWatch.getTime() +
478 " ms");
479 }
480 }
481
482 public void serveResource(
483 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
484 throws IOException {
485
486 StopWatch stopWatch = null;
487
488 if (_log.isDebugEnabled()) {
489 stopWatch = new StopWatch();
490
491 stopWatch.start();
492 }
493
494 try {
495 invokeResource(resourceRequest, resourceResponse);
496 }
497 catch (PortletException pe) {
498 resourceRequest.setAttribute(
499 _portletId + PortletException.class.getName(), pe);
500 }
501
502 if (_log.isDebugEnabled()) {
503 _log.debug(
504 "serveResource for " + _portletId + " takes " +
505 stopWatch.getTime() + " ms");
506 }
507 }
508
509 public void setPortletFilters() throws PortletException {
510 removePortletFilters();
511
512 Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
513 _portletModel.getPortletFilters();
514
515 for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
516 portletFilters.entrySet()) {
517
518 com.liferay.portal.model.PortletFilter portletFilterModel =
519 entry.getValue();
520
521 PortletFilter portletFilter = PortletFilterFactory.create(
522 portletFilterModel, _portletContextImpl);
523
524 Set<String> lifecycles = portletFilterModel.getLifecycles();
525
526 if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
527 List<ActionFilter> actionFilters = _actionFiltersMap.get(
528 _portletId);
529
530 if (actionFilters == null) {
531 actionFilters = new ArrayList<ActionFilter>();
532 }
533
534 actionFilters.add((ActionFilter)portletFilter);
535
536 _actionFiltersMap.put(_portletId, actionFilters);
537 }
538
539 if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
540 List<EventFilter> eventFilters = _eventFiltersMap.get(
541 _portletId);
542
543 if (eventFilters == null) {
544 eventFilters = new ArrayList<EventFilter>();
545 }
546
547 eventFilters.add((EventFilter)portletFilter);
548
549 _eventFiltersMap.put(_portletId, eventFilters);
550 }
551
552 if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
553 List<RenderFilter> renderFilters = _renderFiltersMap.get(
554 _portletId);
555
556 if (renderFilters == null) {
557 renderFilters = new ArrayList<RenderFilter>();
558 }
559
560 renderFilters.add((RenderFilter)portletFilter);
561
562 _renderFiltersMap.put(_portletId, renderFilters);
563 }
564
565 if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
566 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
567 _portletId);
568
569 if (resourceFilters == null) {
570 resourceFilters = new ArrayList<ResourceFilter>();
571 }
572
573 resourceFilters.add((ResourceFilter)portletFilter);
574
575 _resourceFiltersMap.put(_portletId, resourceFilters);
576 }
577 }
578 }
579
580 protected void invoke(
581 LiferayPortletRequest portletRequest,
582 LiferayPortletResponse portletResponse, String lifecycle,
583 List<? extends PortletFilter> filters)
584 throws IOException, PortletException {
585
586 FilterChain filterChain = new FilterChainImpl(_portlet, filters);
587
588 if (_portletConfigImpl.isWARFile()) {
589 String invokerPortletName = _portletConfigImpl.getInitParameter(
590 INIT_INVOKER_PORTLET_NAME);
591
592 if (invokerPortletName == null) {
593 invokerPortletName = _portletConfigImpl.getPortletName();
594 }
595
596 String path = StringPool.SLASH + invokerPortletName + "/invoke";
597
598 RequestDispatcher requestDispatcher =
599 _portletContextImpl.getServletContext().getRequestDispatcher(
600 path);
601
602 HttpServletRequest request = portletRequest.getHttpServletRequest();
603 HttpServletResponse response =
604 portletResponse.getHttpServletResponse();
605
606 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
607 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
608 request.setAttribute(
609 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
610
611 try {
612
613
616 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
617 requestDispatcher.forward(request, response);
618 }
619 else {
620 requestDispatcher.include(request, response);
621 }
622 }
623 catch (ServletException se) {
624 Throwable cause = se.getRootCause();
625
626 if (cause instanceof PortletException) {
627 throw (PortletException)cause;
628 }
629
630 throw new PortletException(cause);
631 }
632 }
633 else {
634 PortletFilterUtil.doFilter(
635 portletRequest, portletResponse, lifecycle, filterChain);
636 }
637
638 Map<String, String[]> properties = portletResponse.getProperties();
639
640 if ((properties != null) && (properties.size() > 0)) {
641 if (_expCache != null) {
642 String[] expCache = properties.get(
643 RenderResponse.EXPIRATION_CACHE);
644
645 if ((expCache != null) && (expCache.length > 0) &&
646 (expCache[0] != null)) {
647
648 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
649 }
650 }
651 }
652 }
653
654 protected void invokeAction(
655 ActionRequest actionRequest, ActionResponse actionResponse)
656 throws IOException, PortletException {
657
658 LiferayPortletRequest portletRequest =
659 (LiferayPortletRequest)actionRequest;
660 LiferayPortletResponse portletResponse =
661 (LiferayPortletResponse)actionResponse;
662
663 String portletId = _getPortletId(portletResponse);
664
665 List<ActionFilter> actionFilters = _actionFiltersMap.get(portletId);
666
667 invoke(
668 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
669 actionFilters);
670 }
671
672 protected void invokeEvent(
673 EventRequest eventRequest, EventResponse eventResponse)
674 throws IOException, PortletException {
675
676 LiferayPortletRequest portletRequest =
677 (LiferayPortletRequest)eventRequest;
678 LiferayPortletResponse portletResponse =
679 (LiferayPortletResponse)eventResponse;
680
681 String portletId = _getPortletId(portletResponse);
682
683 List<EventFilter> eventFilters = _eventFiltersMap.get(portletId);
684
685 invoke(
686 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
687 eventFilters);
688 }
689
690 protected String invokeRender(
691 RenderRequest renderRequest, RenderResponse renderResponse)
692 throws IOException, PortletException {
693
694 LiferayPortletRequest portletRequest =
695 (LiferayPortletRequest)renderRequest;
696 LiferayPortletResponse portletResponse =
697 (LiferayPortletResponse)renderResponse;
698
699 String portletId = _getPortletId(portletResponse);
700
701 List<RenderFilter> renderFilters = _renderFiltersMap.get(portletId);
702
703 invoke(
704 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
705 renderFilters);
706
707 RenderResponseImpl renderResponseImpl =
708 (RenderResponseImpl)renderResponse;
709
710 return renderResponseImpl.getTitle();
711 }
712
713 protected void invokeResource(
714 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
715 throws IOException, PortletException {
716
717 LiferayPortletRequest portletRequest =
718 (LiferayPortletRequest)resourceRequest;
719 LiferayPortletResponse portletResponse =
720 (LiferayPortletResponse)resourceResponse;
721
722 String portletId = _getPortletId(portletResponse);
723
724 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
725 portletId);
726
727 invoke(
728 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
729 resourceFilters);
730 }
731
732 protected void removePortletFilters() {
733 _actionFiltersMap.remove(_portletId);
734 _eventFiltersMap.remove(_portletId);
735 _renderFiltersMap.remove(_portletId);
736 _resourceFiltersMap.remove(_portletId);
737 }
738
739 private String _getPortletId(LiferayPortletResponse portletResponse) {
740 PortletResponseImpl portletResponseImpl =
741 (PortletResponseImpl)portletResponse;
742
743 com.liferay.portal.model.Portlet portlet =
744 portletResponseImpl.getPortlet();
745
746 return portlet.getPortletId();
747 }
748
749 private static Log _log = LogFactoryUtil.getLog(InvokerPortletImpl.class);
750
751 private com.liferay.portal.model.Portlet _portletModel;
752 private String _portletId;
753 private Portlet _portlet;
754 private PortletConfigImpl _portletConfigImpl;
755 private PortletContextImpl _portletContextImpl;
756 private Integer _expCache;
757 private boolean _destroyable;
758 private boolean _facesPortlet;
759 private boolean _strutsPortlet;
760 private boolean _strutsBridgePortlet;
761 private Map<String, List<ActionFilter>> _actionFiltersMap =
762 new HashMap<String, List<ActionFilter>>();
763 private Map<String, List<EventFilter>> _eventFiltersMap =
764 new HashMap<String, List<EventFilter>>();
765 private Map<String, List<RenderFilter>> _renderFiltersMap =
766 new HashMap<String, List<RenderFilter>>();
767 private Map<String, List<ResourceFilter>> _resourceFiltersMap =
768 new HashMap<String, List<ResourceFilter>>();
769
770 }