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