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