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