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