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.deploy.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 (portletModel.isRemote()) {
294 return;
295 }
296
297 if (ClassUtil.isSubclass(
298 _portlet.getClass(), PortletDeployer.JSF_MYFACES) ||
299 ClassUtil.isSubclass(
300 _portlet.getClass(), PortletDeployer.JSF_STANDARD) ||
301 ClassUtil.isSubclass(
302 _portlet.getClass(), PortletDeployer.JSF_SUN)) {
303
304 _facesPortlet = true;
305 }
306
307 _strutsPortlet = ClassUtil.isSubclass(
308 portlet.getClass(), StrutsPortlet.class);
309 _strutsBridgePortlet = ClassUtil.isSubclass(
310 portlet.getClass(),
311 "org.apache.portals.bridges.struts.StrutsPortlet");
312 _expCache = portletModel.getExpCache();
313 setPortletFilters();
314 }
315
316 public void prepare(
317 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
318 PortletConfig portletConfig, PortletContext portletContext,
319 boolean facesPortlet, boolean strutsPortlet,
320 boolean strutsBridgePortlet)
321 throws PortletException {
322
323
325 _portletModel = portletModel;
326 _portlet = portlet;
327 _portletId = _portletModel.getPortletId();
328 _portletContextImpl = (PortletContextImpl)portletContext;
329 _facesPortlet = facesPortlet;
330 _strutsPortlet = strutsPortlet;
331 _strutsBridgePortlet = strutsBridgePortlet;
332 _expCache = portletModel.getExpCache();
333 setPortletFilters();
334
335 if (_log.isDebugEnabled()) {
336 _log.debug(
337 "Create instance cache wrapper for " +
338 _portletContextImpl.getPortlet().getPortletId());
339 }
340
341
343 _portletConfigImpl = (PortletConfigImpl)portletConfig;
344 }
345
346 public void processAction(
347 ActionRequest actionRequest, ActionResponse actionResponse)
348 throws IOException {
349
350 StopWatch stopWatch = null;
351
352 if (_log.isDebugEnabled()) {
353 stopWatch = new StopWatch();
354
355 stopWatch.start();
356 }
357
358 try {
359 invokeAction(actionRequest, actionResponse);
360 }
361 catch (PortletException pe) {
362 actionRequest.setAttribute(
363 _portletId + PortletException.class.getName(), pe);
364 }
365
366 if (_log.isDebugEnabled()) {
367 _log.debug(
368 "processAction for " + _portletId + " takes " +
369 stopWatch.getTime() + " ms");
370 }
371 }
372
373 public void processEvent(
374 EventRequest eventRequest, EventResponse eventResponse)
375 throws IOException, PortletException {
376
377 StopWatch stopWatch = null;
378
379 if (_log.isDebugEnabled()) {
380 stopWatch = new StopWatch();
381
382 stopWatch.start();
383 }
384
385 invokeEvent(eventRequest, eventResponse);
386
387 if (_log.isDebugEnabled()) {
388 _log.debug(
389 "processEvent for " + _portletId + " takes " +
390 stopWatch.getTime() + " ms");
391 }
392 }
393
394 public void render(
395 RenderRequest renderRequest, RenderResponse renderResponse)
396 throws IOException, PortletException {
397
398 PortletException portletException =
399 (PortletException)renderRequest.getAttribute(
400 _portletId + PortletException.class.getName());
401
402 if (portletException != null) {
403 throw portletException;
404 }
405
406 StopWatch stopWatch = null;
407
408 if (_log.isDebugEnabled()) {
409 stopWatch = new StopWatch();
410
411 stopWatch.start();
412 }
413
414 String remoteUser = renderRequest.getRemoteUser();
415
416 if ((remoteUser == null) || (_expCache == null) ||
417 (_expCache.intValue() == 0)) {
418
419 invokeRender(renderRequest, renderResponse);
420 }
421 else {
422 RenderResponseImpl renderResponseImpl =
423 (RenderResponseImpl)renderResponse;
424
425 StringServletResponse stringResponse = (StringServletResponse)
426 renderResponseImpl.getHttpServletResponse();
427
428 PortletSession portletSession = renderRequest.getPortletSession();
429
430 long now = System.currentTimeMillis();
431
432 Layout layout = (Layout)renderRequest.getAttribute(WebKeys.LAYOUT);
433
434 Map<String, InvokerPortletResponse> sessionResponses =
435 getResponses(portletSession);
436
437 String sessionResponseId = encodeResponseKey(
438 layout.getPlid(), _portletId,
439 LanguageUtil.getLanguageId(renderRequest));
440
441 InvokerPortletResponse response = sessionResponses.get(
442 sessionResponseId);
443
444 if (response == null) {
445 String title = invokeRender(renderRequest, renderResponse);
446
447 response = new InvokerPortletResponse(
448 title, stringResponse.getString(),
449 now + Time.SECOND * _expCache.intValue());
450
451 sessionResponses.put(sessionResponseId, response);
452 }
453 else if ((response.getTime() < now) &&
454 (_expCache.intValue() > 0)) {
455
456 String title = invokeRender(renderRequest, renderResponse);
457
458 response.setTitle(title);
459 response.setContent(stringResponse.getString());
460 response.setTime(now + Time.SECOND * _expCache.intValue());
461 }
462 else {
463 renderResponseImpl.setTitle(response.getTitle());
464 stringResponse.getWriter().print(response.getContent());
465 }
466 }
467
468 Map<String, String[]> properties =
469 ((RenderResponseImpl)renderResponse).getProperties();
470
471 if (properties.containsKey("clear-request-parameters")) {
472 Map<String, String[]> renderParameters =
473 ((RenderRequestImpl)renderRequest).getRenderParameters();
474
475 renderParameters.clear();
476 }
477
478 if (_log.isDebugEnabled()) {
479 _log.debug(
480 "render for " + _portletId + " takes " + stopWatch.getTime() +
481 " ms");
482 }
483 }
484
485 public void serveResource(
486 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
487 throws IOException {
488
489 StopWatch stopWatch = null;
490
491 if (_log.isDebugEnabled()) {
492 stopWatch = new StopWatch();
493
494 stopWatch.start();
495 }
496
497 try {
498 invokeResource(resourceRequest, resourceResponse);
499 }
500 catch (PortletException pe) {
501 resourceRequest.setAttribute(
502 _portletId + PortletException.class.getName(), pe);
503 }
504
505 if (_log.isDebugEnabled()) {
506 _log.debug(
507 "serveResource for " + _portletId + " takes " +
508 stopWatch.getTime() + " ms");
509 }
510 }
511
512 public void setPortletFilters() throws PortletException {
513 removePortletFilters();
514
515 Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
516 _portletModel.getPortletFilters();
517
518 for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
519 portletFilters.entrySet()) {
520
521 com.liferay.portal.model.PortletFilter portletFilterModel =
522 entry.getValue();
523
524 PortletFilter portletFilter = PortletFilterFactory.create(
525 portletFilterModel, _portletContextImpl);
526
527 Set<String> lifecycles = portletFilterModel.getLifecycles();
528
529 if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
530 List<ActionFilter> actionFilters = _actionFiltersMap.get(
531 _portletId);
532
533 if (actionFilters == null) {
534 actionFilters = new ArrayList<ActionFilter>();
535 }
536
537 actionFilters.add((ActionFilter)portletFilter);
538
539 _actionFiltersMap.put(_portletId, actionFilters);
540 }
541
542 if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
543 List<EventFilter> eventFilters = _eventFiltersMap.get(
544 _portletId);
545
546 if (eventFilters == null) {
547 eventFilters = new ArrayList<EventFilter>();
548 }
549
550 eventFilters.add((EventFilter)portletFilter);
551
552 _eventFiltersMap.put(_portletId, eventFilters);
553 }
554
555 if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
556 List<RenderFilter> renderFilters = _renderFiltersMap.get(
557 _portletId);
558
559 if (renderFilters == null) {
560 renderFilters = new ArrayList<RenderFilter>();
561 }
562
563 renderFilters.add((RenderFilter)portletFilter);
564
565 _renderFiltersMap.put(_portletId, renderFilters);
566 }
567
568 if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
569 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
570 _portletId);
571
572 if (resourceFilters == null) {
573 resourceFilters = new ArrayList<ResourceFilter>();
574 }
575
576 resourceFilters.add((ResourceFilter)portletFilter);
577
578 _resourceFiltersMap.put(_portletId, resourceFilters);
579 }
580 }
581 }
582
583 protected void invoke(
584 LiferayPortletRequest portletRequest,
585 LiferayPortletResponse portletResponse, String lifecycle,
586 List<? extends PortletFilter> filters)
587 throws IOException, PortletException {
588
589 FilterChain filterChain = new FilterChainImpl(_portlet, filters);
590
591 if (_portletConfigImpl.isWARFile()) {
592 String path =
593 StringPool.SLASH + _portletConfigImpl.getPortletName() +
594 "/invoke";
595
596 RequestDispatcher requestDispatcher =
597 _portletContextImpl.getServletContext().getRequestDispatcher(
598 path);
599
600 HttpServletRequest request = portletRequest.getHttpServletRequest();
601 HttpServletResponse response =
602 portletResponse.getHttpServletResponse();
603
604 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
605 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
606 request.setAttribute(
607 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
608
609 try {
610
611
614 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
615 requestDispatcher.forward(request, response);
616 }
617 else {
618 requestDispatcher.include(request, response);
619 }
620 }
621 catch (ServletException se) {
622 Throwable cause = se.getRootCause();
623
624 if (cause instanceof PortletException) {
625 throw (PortletException)cause;
626 }
627
628 throw new PortletException(cause);
629 }
630 }
631 else {
632 PortletFilterUtil.doFilter(
633 portletRequest, portletResponse, lifecycle, filterChain);
634 }
635
636 Map<String, String[]> properties = portletResponse.getProperties();
637
638 if ((properties != null) && (properties.size() > 0)) {
639 if (_expCache != null) {
640 String[] expCache = properties.get(
641 RenderResponse.EXPIRATION_CACHE);
642
643 if ((expCache != null) && (expCache.length > 0) &&
644 (expCache[0] != null)) {
645
646 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
647 }
648 }
649 }
650 }
651
652 protected void invokeAction(
653 ActionRequest actionRequest, ActionResponse actionResponse)
654 throws IOException, PortletException {
655
656 LiferayPortletRequest portletRequest =
657 (LiferayPortletRequest)actionRequest;
658 LiferayPortletResponse portletResponse =
659 (LiferayPortletResponse)actionResponse;
660
661 List<ActionFilter> actionFilters =
662 _actionFiltersMap.get(_getPortletId(portletResponse));
663
664 invoke(
665 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
666 actionFilters);
667 }
668
669 protected void invokeEvent(
670 EventRequest eventRequest, EventResponse eventResponse)
671 throws IOException, PortletException {
672
673 LiferayPortletRequest portletRequest =
674 (LiferayPortletRequest)eventRequest;
675 LiferayPortletResponse portletResponse =
676 (LiferayPortletResponse)eventResponse;
677
678 String portletId = _getPortletId(portletResponse);
679
680 List<EventFilter> eventFilters = _eventFiltersMap.get(portletId);
681
682 invoke(
683 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
684 eventFilters);
685 }
686
687 protected String invokeRender(
688 RenderRequest renderRequest, RenderResponse renderResponse)
689 throws IOException, PortletException {
690
691 LiferayPortletRequest portletRequest =
692 (LiferayPortletRequest)renderRequest;
693 LiferayPortletResponse portletResponse =
694 (LiferayPortletResponse)renderResponse;
695
696 String portletId = _getPortletId(portletResponse);
697
698 List<RenderFilter> renderFilters = _renderFiltersMap.get(portletId);
699
700 invoke(
701 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
702 renderFilters);
703
704 RenderResponseImpl renderResponseImpl =
705 (RenderResponseImpl)renderResponse;
706
707 return renderResponseImpl.getTitle();
708 }
709
710 protected void invokeResource(
711 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
712 throws IOException, PortletException {
713
714 LiferayPortletRequest portletRequest =
715 (LiferayPortletRequest)resourceRequest;
716 LiferayPortletResponse portletResponse =
717 (LiferayPortletResponse)resourceResponse;
718
719 String portletId = _getPortletId(portletResponse);
720
721 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
722 portletId);
723
724 invoke(
725 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
726 resourceFilters);
727 }
728
729 protected void removePortletFilters() {
730 _actionFiltersMap.remove(_portletId);
731 _eventFiltersMap.remove(_portletId);
732 _renderFiltersMap.remove(_portletId);
733 _resourceFiltersMap.remove(_portletId);
734 }
735
736 private String _getPortletId(LiferayPortletResponse portletResponse) {
737 PortletResponseImpl portletResponseImpl =
738 (PortletResponseImpl)portletResponse;
739
740 com.liferay.portal.model.Portlet portlet =
741 portletResponseImpl.getPortlet();
742
743 return portlet.getPortletId();
744 }
745
746 private static Log _log = LogFactoryUtil.getLog(InvokerPortletImpl.class);
747
748 private com.liferay.portal.model.Portlet _portletModel;
749 private String _portletId;
750 private Portlet _portlet;
751 private PortletConfigImpl _portletConfigImpl;
752 private PortletContextImpl _portletContextImpl;
753 private Integer _expCache;
754 private boolean _destroyable;
755 private boolean _facesPortlet;
756 private boolean _strutsPortlet;
757 private boolean _strutsBridgePortlet;
758 private Map<String, List<ActionFilter>> _actionFiltersMap =
759 new HashMap<String, List<ActionFilter>>();
760 private Map<String, List<EventFilter>> _eventFiltersMap =
761 new HashMap<String, List<EventFilter>>();
762 private Map<String, List<RenderFilter>> _renderFiltersMap =
763 new HashMap<String, List<RenderFilter>>();
764 private Map<String, List<ResourceFilter>> _resourceFiltersMap =
765 new HashMap<String, List<ResourceFilter>>();
766
767 }