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.ClassUtil;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.JavaConstants;
030 import com.liferay.portal.kernel.util.MapUtil;
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.PortletConstants;
037 import com.liferay.portal.tools.deploy.PortletDeployer;
038 import com.liferay.portal.util.ClassLoaderUtil;
039 import com.liferay.portal.util.WebKeys;
040
041 import java.io.Closeable;
042 import java.io.IOException;
043 import java.io.PrintWriter;
044
045 import java.util.List;
046 import java.util.Map;
047 import java.util.concurrent.ConcurrentHashMap;
048
049 import javax.portlet.ActionRequest;
050 import javax.portlet.ActionResponse;
051 import javax.portlet.EventRequest;
052 import javax.portlet.EventResponse;
053 import javax.portlet.Portlet;
054 import javax.portlet.PortletConfig;
055 import javax.portlet.PortletContext;
056 import javax.portlet.PortletException;
057 import javax.portlet.PortletRequest;
058 import javax.portlet.PortletSession;
059 import javax.portlet.RenderRequest;
060 import javax.portlet.RenderResponse;
061 import javax.portlet.ResourceRequest;
062 import javax.portlet.ResourceResponse;
063 import javax.portlet.filter.ActionFilter;
064 import javax.portlet.filter.EventFilter;
065 import javax.portlet.filter.FilterChain;
066 import javax.portlet.filter.PortletFilter;
067 import javax.portlet.filter.RenderFilter;
068 import javax.portlet.filter.ResourceFilter;
069
070 import javax.servlet.RequestDispatcher;
071 import javax.servlet.ServletContext;
072 import javax.servlet.ServletException;
073 import javax.servlet.http.HttpServletRequest;
074 import javax.servlet.http.HttpServletResponse;
075 import javax.servlet.http.HttpSession;
076
077 import org.apache.commons.lang.time.StopWatch;
078
079
084 public class InvokerPortletImpl
085 implements InvokerFilterContainer, InvokerPortlet {
086
087 public static void clearResponse(
088 HttpSession session, long plid, String portletId, String languageId) {
089
090 String sesResponseId = encodeResponseKey(plid, portletId, languageId);
091
092 getResponses(session).remove(sesResponseId);
093 }
094
095 public static void clearResponses(HttpSession session) {
096 getResponses(session).clear();
097 }
098
099 public static void clearResponses(PortletSession session) {
100 getResponses(session).clear();
101 }
102
103 public static String encodeResponseKey(
104 long plid, String portletId, String languageId) {
105
106 StringBundler sb = new StringBundler(5);
107
108 sb.append(StringUtil.toHexString(plid));
109 sb.append(StringPool.UNDERLINE);
110 sb.append(portletId);
111 sb.append(StringPool.UNDERLINE);
112 sb.append(languageId);
113
114 return sb.toString();
115 }
116
117 public static Map<String, InvokerPortletResponse> getResponses(
118 HttpSession session) {
119
120 Map<String, InvokerPortletResponse> responses =
121 (Map<String, InvokerPortletResponse>)session.getAttribute(
122 WebKeys.CACHE_PORTLET_RESPONSES);
123
124 if (responses == null) {
125 responses = new ConcurrentHashMap<String, InvokerPortletResponse>();
126
127 session.setAttribute(WebKeys.CACHE_PORTLET_RESPONSES, responses);
128 }
129
130 return responses;
131 }
132
133 public static Map<String, InvokerPortletResponse> getResponses(
134 PortletSession portletSession) {
135
136 return getResponses(
137 ((PortletSessionImpl)portletSession).getHttpSession());
138 }
139
140 public InvokerPortletImpl(
141 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
142 PortletConfig portletConfig, PortletContext portletContext,
143 InvokerFilterContainer invokerFilterContainer, boolean checkAuthToken,
144 boolean facesPortlet, boolean strutsPortlet,
145 boolean strutsBridgePortlet) {
146
147 _initialize(
148 portletModel, portlet, portletConfig, portletContext,
149 invokerFilterContainer, checkAuthToken, facesPortlet, strutsPortlet,
150 strutsBridgePortlet);
151 }
152
153 public InvokerPortletImpl(
154 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
155 PortletContext portletContext,
156 InvokerFilterContainer invokerFilterContainer) {
157
158 Map<String, String> initParams = portletModel.getInitParams();
159
160 boolean checkAuthToken = GetterUtil.getBoolean(
161 initParams.get("check-auth-token"), true);
162
163 boolean facesPortlet = false;
164
165 if (ClassUtil.isSubclass(
166 portlet.getClass(), PortletDeployer.JSF_STANDARD)) {
167
168 facesPortlet = true;
169 }
170
171 boolean strutsPortlet = ClassUtil.isSubclass(
172 portlet.getClass(), StrutsPortlet.class);
173
174 boolean strutsBridgePortlet = ClassUtil.isSubclass(
175 portlet.getClass(),
176 "org.apache.portals.bridges.struts.StrutsPortlet");
177
178 _initialize(
179 portletModel, portlet, null, portletContext, invokerFilterContainer,
180 checkAuthToken, facesPortlet, strutsPortlet, strutsBridgePortlet);
181 }
182
183 @Override
184 public void destroy() {
185 if (PortletConstants.hasInstanceId(_portletModel.getPortletId())) {
186 if (_log.isWarnEnabled()) {
187 _log.warn("Destroying an instanced portlet is not allowed");
188 }
189
190 return;
191 }
192
193 ClassLoader contextClassLoader =
194 ClassLoaderUtil.getContextClassLoader();
195
196 ClassLoader portletClassLoader = getPortletClassLoader();
197
198 try {
199 if (portletClassLoader != null) {
200 ClassLoaderUtil.setContextClassLoader(portletClassLoader);
201 }
202
203 Closeable closeable = (Closeable)_invokerFilterContainer;
204
205 closeable.close();
206
207 _portlet.destroy();
208 }
209 catch (IOException ioe) {
210 _log.error(ioe, ioe);
211 }
212 finally {
213 if (portletClassLoader != null) {
214 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
215 }
216 }
217 }
218
219 @Override
220 public List<ActionFilter> getActionFilters() {
221 return _invokerFilterContainer.getActionFilters();
222 }
223
224 @Override
225 public List<EventFilter> getEventFilters() {
226 return _invokerFilterContainer.getEventFilters();
227 }
228
229 @Override
230 public Integer getExpCache() {
231 return _expCache;
232 }
233
234 @Override
235 public Portlet getPortlet() {
236 return _portlet;
237 }
238
239 @Override
240 public ClassLoader getPortletClassLoader() {
241 ServletContext servletContext =
242 _liferayPortletContext.getServletContext();
243
244 return servletContext.getClassLoader();
245 }
246
247 @Override
248 public PortletConfig getPortletConfig() {
249 return _liferayPortletConfig;
250 }
251
252 @Override
253 public PortletContext getPortletContext() {
254 return _liferayPortletContext;
255 }
256
257 @Override
258 public Portlet getPortletInstance() {
259 return _portlet;
260 }
261
262 @Override
263 public List<RenderFilter> getRenderFilters() {
264 return _invokerFilterContainer.getRenderFilters();
265 }
266
267 @Override
268 public List<ResourceFilter> getResourceFilters() {
269 return _invokerFilterContainer.getResourceFilters();
270 }
271
272 @Override
273 public void init(PortletConfig portletConfig) throws PortletException {
274 _liferayPortletConfig = (LiferayPortletConfig)portletConfig;
275
276 ClassLoader contextClassLoader =
277 ClassLoaderUtil.getContextClassLoader();
278
279 ClassLoader portletClassLoader = getPortletClassLoader();
280
281 try {
282 if (portletClassLoader != null) {
283 ClassLoaderUtil.setContextClassLoader(portletClassLoader);
284 }
285
286 _portlet.init(portletConfig);
287 }
288 finally {
289 if (portletClassLoader != null) {
290 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
291 }
292 }
293 }
294
295 @Override
296 public boolean isCheckAuthToken() {
297 return _checkAuthToken;
298 }
299
300 @Override
301 public boolean isFacesPortlet() {
302 return _facesPortlet;
303 }
304
305 @Override
306 public boolean isStrutsBridgePortlet() {
307 return _strutsBridgePortlet;
308 }
309
310 @Override
311 public boolean isStrutsPortlet() {
312 return _strutsPortlet;
313 }
314
315 @Override
316 public void processAction(
317 ActionRequest actionRequest, ActionResponse actionResponse)
318 throws IOException {
319
320 StopWatch stopWatch = new StopWatch();
321
322 stopWatch.start();
323
324 try {
325 invokeAction(actionRequest, actionResponse);
326 }
327 catch (PortletException pe) {
328 actionRequest.setAttribute(
329 _portletId + PortletException.class.getName(), pe);
330 }
331
332 if (_log.isDebugEnabled()) {
333 _log.debug(
334 "processAction for " + _portletId + " takes " +
335 stopWatch.getTime() + " ms");
336 }
337 }
338
339 @Override
340 public void processEvent(
341 EventRequest eventRequest, EventResponse eventResponse)
342 throws IOException, PortletException {
343
344 StopWatch stopWatch = new StopWatch();
345
346 stopWatch.start();
347
348 invokeEvent(eventRequest, eventResponse);
349
350 if (_log.isDebugEnabled()) {
351 _log.debug(
352 "processEvent for " + _portletId + " takes " +
353 stopWatch.getTime() + " ms");
354 }
355 }
356
357 @Override
358 public void render(
359 RenderRequest renderRequest, RenderResponse renderResponse)
360 throws IOException, PortletException {
361
362 PortletException portletException =
363 (PortletException)renderRequest.getAttribute(
364 _portletId + PortletException.class.getName());
365
366 if (portletException != null) {
367 throw portletException;
368 }
369
370 StopWatch stopWatch = new StopWatch();
371
372 stopWatch.start();
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 = new StopWatch();
454
455 stopWatch.start();
456
457 try {
458 invokeResource(resourceRequest, resourceResponse);
459 }
460 catch (PortletException pe) {
461 resourceRequest.setAttribute(
462 _portletId + PortletException.class.getName(), pe);
463 }
464
465 if (_log.isDebugEnabled()) {
466 _log.debug(
467 "serveResource for " + _portletId + " takes " +
468 stopWatch.getTime() + " ms");
469 }
470 }
471
472
475 @Deprecated
476 @Override
477 public void setPortletFilters() {
478 }
479
480 protected void invoke(
481 LiferayPortletRequest portletRequest,
482 LiferayPortletResponse portletResponse, String lifecycle,
483 List<? extends PortletFilter> filters)
484 throws IOException, PortletException {
485
486 FilterChain filterChain = new FilterChainImpl(_portlet, filters);
487
488 if (_liferayPortletConfig.isWARFile()) {
489 String invokerPortletName = _liferayPortletConfig.getInitParameter(
490 INIT_INVOKER_PORTLET_NAME);
491
492 if (invokerPortletName == null) {
493 invokerPortletName = _liferayPortletConfig.getPortletName();
494 }
495
496 String path = StringPool.SLASH + invokerPortletName + "/invoke";
497
498 ServletContext servletContext =
499 _liferayPortletContext.getServletContext();
500
501 RequestDispatcher requestDispatcher =
502 servletContext.getRequestDispatcher(path);
503
504 HttpServletRequest request = portletRequest.getHttpServletRequest();
505 HttpServletResponse response =
506 portletResponse.getHttpServletResponse();
507
508 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
509 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
510 request.setAttribute(
511 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
512
513 try {
514
515
516
517
518 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
519 requestDispatcher.forward(request, response);
520 }
521 else {
522 requestDispatcher.include(request, response);
523 }
524 }
525 catch (ServletException se) {
526 Throwable cause = se.getRootCause();
527
528 if (cause instanceof PortletException) {
529 throw (PortletException)cause;
530 }
531
532 throw new PortletException(cause);
533 }
534 }
535 else {
536 PortletFilterUtil.doFilter(
537 portletRequest, portletResponse, lifecycle, filterChain);
538 }
539
540 portletResponse.transferMarkupHeadElements();
541
542 Map<String, String[]> properties = portletResponse.getProperties();
543
544 if (MapUtil.isNotEmpty(properties)) {
545 if (_expCache != null) {
546 String[] expCache = properties.get(
547 RenderResponse.EXPIRATION_CACHE);
548
549 if ((expCache != null) && (expCache.length > 0) &&
550 (expCache[0] != null)) {
551
552 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
553 }
554 }
555 }
556 }
557
558 protected void invokeAction(
559 ActionRequest actionRequest, ActionResponse actionResponse)
560 throws IOException, PortletException {
561
562 LiferayPortletRequest portletRequest =
563 (LiferayPortletRequest)actionRequest;
564 LiferayPortletResponse portletResponse =
565 (LiferayPortletResponse)actionResponse;
566
567 invoke(
568 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
569 _invokerFilterContainer.getActionFilters());
570 }
571
572 protected void invokeEvent(
573 EventRequest eventRequest, EventResponse eventResponse)
574 throws IOException, PortletException {
575
576 LiferayPortletRequest portletRequest =
577 (LiferayPortletRequest)eventRequest;
578 LiferayPortletResponse portletResponse =
579 (LiferayPortletResponse)eventResponse;
580
581 invoke(
582 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
583 _invokerFilterContainer.getEventFilters());
584 }
585
586 protected String invokeRender(
587 RenderRequest renderRequest, RenderResponse renderResponse)
588 throws IOException, PortletException {
589
590 LiferayPortletRequest portletRequest =
591 (LiferayPortletRequest)renderRequest;
592 LiferayPortletResponse portletResponse =
593 (LiferayPortletResponse)renderResponse;
594
595 invoke(
596 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
597 _invokerFilterContainer.getRenderFilters());
598
599 RenderResponseImpl renderResponseImpl =
600 (RenderResponseImpl)renderResponse;
601
602 return renderResponseImpl.getTitle();
603 }
604
605 protected void invokeResource(
606 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
607 throws IOException, PortletException {
608
609 LiferayPortletRequest portletRequest =
610 (LiferayPortletRequest)resourceRequest;
611 LiferayPortletResponse portletResponse =
612 (LiferayPortletResponse)resourceResponse;
613
614 invoke(
615 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
616 _invokerFilterContainer.getResourceFilters());
617 }
618
619 private void _initialize(
620 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
621 PortletConfig portletConfig, PortletContext portletContext,
622 InvokerFilterContainer invokerFilterContainer, boolean checkAuthToken,
623 boolean facesPortlet, boolean strutsPortlet,
624 boolean strutsBridgePortlet) {
625
626 _portletModel = portletModel;
627 _portlet = portlet;
628 _liferayPortletConfig = (LiferayPortletConfig)portletConfig;
629 _portletId = _portletModel.getPortletId();
630 _liferayPortletContext = (LiferayPortletContext)portletContext;
631 _invokerFilterContainer = invokerFilterContainer;
632 _checkAuthToken = checkAuthToken;
633 _facesPortlet = facesPortlet;
634 _strutsPortlet = strutsPortlet;
635 _strutsBridgePortlet = strutsBridgePortlet;
636 _expCache = portletModel.getExpCache();
637
638 if (_log.isDebugEnabled()) {
639 _log.debug(
640 "Create instance cache wrapper for " +
641 _liferayPortletContext.getPortlet().getPortletId());
642 }
643 }
644
645 private static final Log _log = LogFactoryUtil.getLog(
646 InvokerPortletImpl.class);
647
648 private boolean _checkAuthToken;
649 private Integer _expCache;
650 private boolean _facesPortlet;
651 private InvokerFilterContainer _invokerFilterContainer;
652 private LiferayPortletConfig _liferayPortletConfig;
653 private LiferayPortletContext _liferayPortletContext;
654 private Portlet _portlet;
655 private String _portletId;
656 private com.liferay.portal.model.Portlet _portletModel;
657 private boolean _strutsBridgePortlet;
658 private boolean _strutsPortlet;
659
660 }