1
19
20 package com.liferay.portlet;
21
22 import com.liferay.portal.kernel.language.LanguageUtil;
23 import com.liferay.portal.kernel.log.Log;
24 import com.liferay.portal.kernel.log.LogFactoryUtil;
25 import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
26 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
27 import com.liferay.portal.kernel.portlet.PortletFilterUtil;
28 import com.liferay.portal.kernel.servlet.PortletServlet;
29 import com.liferay.portal.kernel.servlet.StringServletResponse;
30 import com.liferay.portal.kernel.util.ClassUtil;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.JavaConstants;
33 import com.liferay.portal.kernel.util.StringPool;
34 import com.liferay.portal.kernel.util.Time;
35 import com.liferay.portal.model.Layout;
36 import com.liferay.portal.tools.deploy.PortletDeployer;
37 import com.liferay.portal.util.WebKeys;
38
39 import com.sun.portal.portletcontainer.appengine.filter.FilterChainImpl;
40
41 import java.io.IOException;
42
43 import java.util.ArrayList;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Set;
48
49 import javax.portlet.ActionRequest;
50 import javax.portlet.ActionResponse;
51 import javax.portlet.EventRequest;
52 import javax.portlet.EventResponse;
53 import javax.portlet.Portlet;
54 import javax.portlet.PortletConfig;
55 import javax.portlet.PortletContext;
56 import javax.portlet.PortletException;
57 import javax.portlet.PortletRequest;
58 import javax.portlet.PortletSession;
59 import javax.portlet.RenderRequest;
60 import javax.portlet.RenderResponse;
61 import javax.portlet.ResourceRequest;
62 import javax.portlet.ResourceResponse;
63 import javax.portlet.filter.ActionFilter;
64 import javax.portlet.filter.EventFilter;
65 import javax.portlet.filter.FilterChain;
66 import javax.portlet.filter.PortletFilter;
67 import javax.portlet.filter.RenderFilter;
68 import javax.portlet.filter.ResourceFilter;
69
70 import javax.servlet.RequestDispatcher;
71 import javax.servlet.ServletException;
72 import javax.servlet.http.HttpServletRequest;
73 import javax.servlet.http.HttpServletResponse;
74 import javax.servlet.http.HttpSession;
75
76 import org.apache.commons.lang.time.StopWatch;
77
78
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 ClassLoader getPortletClassLoader() {
213 return (ClassLoader)_portletContextImpl.getAttribute(
214 PortletServlet.PORTLET_CLASS_LOADER);
215 }
216
217 public PortletConfigImpl getPortletConfig() {
218 return _portletConfigImpl;
219 }
220
221 public PortletContextImpl getPortletContext() {
222 return _portletContextImpl;
223 }
224
225 public Portlet getPortletInstance() {
226 return _portlet;
227 }
228
229 public Integer getExpCache() {
230 return _expCache;
231 }
232
233 public void init(PortletConfig portletConfig) throws PortletException {
234 _portletConfigImpl = (PortletConfigImpl)portletConfig;
235
236 Thread currentThread = Thread.currentThread();
237
238 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
239
240 ClassLoader portletClassLoader = getPortletClassLoader();
241
242 try {
243 if (portletClassLoader != null) {
244 currentThread.setContextClassLoader(portletClassLoader);
245 }
246
247 _portlet.init(portletConfig);
248 }
249 finally {
250 if (portletClassLoader != null) {
251 currentThread.setContextClassLoader(contextClassLoader);
252 }
253 }
254
255 _destroyable = true;
256 }
257
258 public boolean isDestroyable() {
259 return _destroyable;
260 }
261
262 public boolean isFacesPortlet() {
263 return _facesPortlet;
264 }
265
266 public boolean isStrutsBridgePortlet() {
267 return _strutsBridgePortlet;
268 }
269
270 public boolean isStrutsPortlet() {
271 return _strutsPortlet;
272 }
273
274 public void prepare(
275 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
276 PortletContext portletContext)
277 throws PortletException {
278
279 _portletModel = portletModel;
280 _portletId = _portletModel.getPortletId();
281 _portlet = portlet;
282 _portletContextImpl = (PortletContextImpl)portletContext;
283
284 if (_log.isDebugEnabled()) {
285 _log.debug(
286 "Create root cache wrapper for " +
287 _portletContextImpl.getPortlet().getPortletId());
288 }
289
290 if (portletModel.isRemote()) {
291 return;
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 path =
590 StringPool.SLASH + _portletConfigImpl.getPortletName() +
591 "/invoke";
592
593 RequestDispatcher requestDispatcher =
594 _portletContextImpl.getServletContext().getRequestDispatcher(
595 path);
596
597 HttpServletRequest request = portletRequest.getHttpServletRequest();
598 HttpServletResponse response =
599 portletResponse.getHttpServletResponse();
600
601 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
602 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
603 request.setAttribute(
604 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
605
606 try {
607
608
611 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
612 requestDispatcher.forward(request, response);
613 }
614 else {
615 requestDispatcher.include(request, response);
616 }
617 }
618 catch (ServletException se) {
619 Throwable cause = se.getRootCause();
620
621 if (cause instanceof PortletException) {
622 throw (PortletException)cause;
623 }
624
625 throw new PortletException(cause);
626 }
627 }
628 else {
629 PortletFilterUtil.doFilter(
630 portletRequest, portletResponse, lifecycle, filterChain);
631 }
632
633 Map<String, String[]> properties = portletResponse.getProperties();
634
635 if ((properties != null) && (properties.size() > 0)) {
636 if (_expCache != null) {
637 String[] expCache = properties.get(
638 RenderResponse.EXPIRATION_CACHE);
639
640 if ((expCache != null) && (expCache.length > 0) &&
641 (expCache[0] != null)) {
642
643 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
644 }
645 }
646 }
647 }
648
649 protected void invokeAction(
650 ActionRequest actionRequest, ActionResponse actionResponse)
651 throws IOException, PortletException {
652
653 LiferayPortletRequest portletRequest =
654 (LiferayPortletRequest)actionRequest;
655 LiferayPortletResponse portletResponse =
656 (LiferayPortletResponse)actionResponse;
657
658 List<ActionFilter> actionFilters =
659 _actionFiltersMap.get(_getPortletId(portletResponse));
660
661 invoke(
662 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
663 actionFilters);
664 }
665
666 protected void invokeEvent(
667 EventRequest eventRequest, EventResponse eventResponse)
668 throws IOException, PortletException {
669
670 LiferayPortletRequest portletRequest =
671 (LiferayPortletRequest)eventRequest;
672 LiferayPortletResponse portletResponse =
673 (LiferayPortletResponse)eventResponse;
674
675 String portletId = _getPortletId(portletResponse);
676
677 List<EventFilter> eventFilters = _eventFiltersMap.get(portletId);
678
679 invoke(
680 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
681 eventFilters);
682 }
683
684 protected String invokeRender(
685 RenderRequest renderRequest, RenderResponse renderResponse)
686 throws IOException, PortletException {
687
688 LiferayPortletRequest portletRequest =
689 (LiferayPortletRequest)renderRequest;
690 LiferayPortletResponse portletResponse =
691 (LiferayPortletResponse)renderResponse;
692
693 String portletId = _getPortletId(portletResponse);
694
695 List<RenderFilter> renderFilters = _renderFiltersMap.get(portletId);
696
697 invoke(
698 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
699 renderFilters);
700
701 RenderResponseImpl renderResponseImpl =
702 (RenderResponseImpl)renderResponse;
703
704 return renderResponseImpl.getTitle();
705 }
706
707 protected void invokeResource(
708 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
709 throws IOException, PortletException {
710
711 LiferayPortletRequest portletRequest =
712 (LiferayPortletRequest)resourceRequest;
713 LiferayPortletResponse portletResponse =
714 (LiferayPortletResponse)resourceResponse;
715
716 String portletId = _getPortletId(portletResponse);
717
718 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
719 portletId);
720
721 invoke(
722 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
723 resourceFilters);
724 }
725
726 protected void removePortletFilters() {
727 _actionFiltersMap.remove(_portletId);
728 _eventFiltersMap.remove(_portletId);
729 _renderFiltersMap.remove(_portletId);
730 _resourceFiltersMap.remove(_portletId);
731 }
732
733 private String _getPortletId(LiferayPortletResponse portletResponse) {
734 PortletResponseImpl portletResponseImpl =
735 (PortletResponseImpl)portletResponse;
736
737 com.liferay.portal.model.Portlet portlet =
738 portletResponseImpl.getPortlet();
739
740 return portlet.getPortletId();
741 }
742
743 private static Log _log = LogFactoryUtil.getLog(InvokerPortletImpl.class);
744
745 private com.liferay.portal.model.Portlet _portletModel;
746 private String _portletId;
747 private Portlet _portlet;
748 private PortletConfigImpl _portletConfigImpl;
749 private PortletContextImpl _portletContextImpl;
750 private Integer _expCache;
751 private boolean _destroyable;
752 private boolean _facesPortlet;
753 private boolean _strutsPortlet;
754 private boolean _strutsBridgePortlet;
755 private Map<String, List<ActionFilter>> _actionFiltersMap =
756 new HashMap<String, List<ActionFilter>>();
757 private Map<String, List<EventFilter>> _eventFiltersMap =
758 new HashMap<String, List<EventFilter>>();
759 private Map<String, List<RenderFilter>> _renderFiltersMap =
760 new HashMap<String, List<RenderFilter>>();
761 private Map<String, List<ResourceFilter>> _resourceFiltersMap =
762 new HashMap<String, List<ResourceFilter>>();
763
764 }