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