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