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