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