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