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