1
22
23 package com.liferay.portlet;
24
25 import com.liferay.portal.kernel.language.LanguageUtil;
26 import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
27 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
28 import com.liferay.portal.kernel.portlet.PortletFilterUtil;
29 import com.liferay.portal.kernel.servlet.PortletServlet;
30 import com.liferay.portal.kernel.servlet.StringServletResponse;
31 import com.liferay.portal.kernel.util.ClassUtil;
32 import com.liferay.portal.kernel.util.GetterUtil;
33 import com.liferay.portal.kernel.util.JavaConstants;
34 import com.liferay.portal.kernel.util.StringPool;
35 import com.liferay.portal.kernel.util.Time;
36 import com.liferay.portal.model.Layout;
37 import com.liferay.portal.tools.PortletDeployer;
38 import com.liferay.portal.util.WebKeys;
39
40 import com.sun.portal.portletcontainer.appengine.filter.FilterChainImpl;
41
42 import java.io.IOException;
43
44 import java.util.ArrayList;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49
50 import javax.portlet.ActionRequest;
51 import javax.portlet.ActionResponse;
52 import javax.portlet.EventRequest;
53 import javax.portlet.EventResponse;
54 import javax.portlet.Portlet;
55 import javax.portlet.PortletConfig;
56 import javax.portlet.PortletContext;
57 import javax.portlet.PortletException;
58 import javax.portlet.PortletRequest;
59 import javax.portlet.PortletSession;
60 import javax.portlet.RenderRequest;
61 import javax.portlet.RenderResponse;
62 import javax.portlet.ResourceRequest;
63 import javax.portlet.ResourceResponse;
64 import javax.portlet.filter.ActionFilter;
65 import javax.portlet.filter.EventFilter;
66 import javax.portlet.filter.FilterChain;
67 import javax.portlet.filter.PortletFilter;
68 import javax.portlet.filter.RenderFilter;
69 import javax.portlet.filter.ResourceFilter;
70
71 import javax.servlet.RequestDispatcher;
72 import javax.servlet.ServletException;
73 import javax.servlet.http.HttpServletRequest;
74 import javax.servlet.http.HttpServletResponse;
75 import javax.servlet.http.HttpSession;
76
77 import org.apache.commons.lang.time.StopWatch;
78 import org.apache.commons.logging.Log;
79 import org.apache.commons.logging.LogFactory;
80
81
88 public class InvokerPortletImpl implements InvokerPortlet {
89
90 public static void clearResponse(
91 HttpSession session, long plid, String portletId, String languageId) {
92
93 String sesResponseId = encodeResponseKey(plid, portletId, languageId);
94
95 getResponses(session).remove(sesResponseId);
96 }
97
98 public static void clearResponses(HttpSession session) {
99 getResponses(session).clear();
100 }
101
102 public static void clearResponses(PortletSession session) {
103 getResponses(session).clear();
104 }
105
106 public static String encodeResponseKey(
107 long plid, String portletId, String languageId) {
108
109 StringBuilder sb = new StringBuilder();
110
111 sb.append(plid);
112 sb.append(StringPool.UNDERLINE);
113 sb.append(portletId);
114 sb.append(StringPool.UNDERLINE);
115 sb.append(languageId);
116
117 return sb.toString();
118 }
119
120 public static Map<String, InvokerPortletResponse> getResponses(
121 HttpSession session) {
122
123 Map<String, InvokerPortletResponse> responses =
124 (Map<String, InvokerPortletResponse>)session.getAttribute(
125 WebKeys.CACHE_PORTLET_RESPONSES);
126
127 if (responses == null) {
128 responses = new HashMap<String, InvokerPortletResponse>();
129
130 session.setAttribute(WebKeys.CACHE_PORTLET_RESPONSES, responses);
131 }
132
133 return responses;
134 }
135
136 public static Map<String, InvokerPortletResponse> getResponses(
137 PortletSession portletSession) {
138
139 return getResponses(
140 ((PortletSessionImpl)portletSession).getHttpSession());
141 }
142
143 public InvokerPortlet create(
144 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
145 PortletContext portletContext)
146 throws PortletException {
147
148 try {
149 InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
150
151 invokerPortlet.prepare(portletModel, portlet, portletContext);
152
153 return invokerPortlet;
154 }
155 catch (PortletException pe) {
156 throw pe;
157 }
158 catch (Exception e) {
159 throw new PortletException(e);
160 }
161 }
162
163 public InvokerPortlet create(
164 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
165 PortletConfig portletConfig, PortletContext portletContext,
166 boolean facesPortlet, boolean strutsPortlet,
167 boolean strutsBridgePortlet)
168 throws PortletException {
169
170 try {
171 InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
172
173 invokerPortlet.prepare(
174 portletModel, portlet, portletConfig, portletContext,
175 facesPortlet, strutsPortlet, strutsBridgePortlet);
176
177 return invokerPortlet;
178 }
179 catch (PortletException pe) {
180 throw pe;
181 }
182 catch (Exception e) {
183 throw new PortletException(e);
184 }
185 }
186
187 public void destroy() {
188 if (_destroyable) {
189 ClassLoader contextClassLoader =
190 Thread.currentThread().getContextClassLoader();
191
192 ClassLoader portletClassLoader = getPortletClassLoader();
193
194 try {
195 if (portletClassLoader != null) {
196 Thread.currentThread().setContextClassLoader(
197 portletClassLoader);
198 }
199
200 _portlet.destroy();
201 }
202 finally {
203 if (portletClassLoader != null) {
204 Thread.currentThread().setContextClassLoader(
205 contextClassLoader);
206 }
207 }
208 }
209
210 _destroyable = false;
211 }
212
213 public ClassLoader getPortletClassLoader() {
214 return (ClassLoader)_portletContextImpl.getAttribute(
215 PortletServlet.PORTLET_CLASS_LOADER);
216 }
217
218 public PortletConfigImpl getPortletConfig() {
219 return _portletConfigImpl;
220 }
221
222 public PortletContextImpl getPortletContext() {
223 return _portletContextImpl;
224 }
225
226 public Portlet getPortletInstance() {
227 return _portlet;
228 }
229
230 public Integer getExpCache() {
231 return _expCache;
232 }
233
234 public void init(PortletConfig portletConfig) throws PortletException {
235 _portletConfigImpl = (PortletConfigImpl)portletConfig;
236
237 _portletId = _portletConfigImpl.getPortletId();
238
239 ClassLoader contextClassLoader =
240 Thread.currentThread().getContextClassLoader();
241
242 ClassLoader portletClassLoader = getPortletClassLoader();
243
244 try {
245 if (portletClassLoader != null) {
246 Thread.currentThread().setContextClassLoader(
247 portletClassLoader);
248 }
249
250 _portlet.init(portletConfig);
251 }
252 finally {
253 if (portletClassLoader != null) {
254 Thread.currentThread().setContextClassLoader(
255 contextClassLoader);
256 }
257 }
258
259 _destroyable = true;
260 }
261
262 public boolean isDestroyable() {
263 return _destroyable;
264 }
265
266 public boolean isFacesPortlet() {
267 return _facesPortlet;
268 }
269
270 public boolean isStrutsBridgePortlet() {
271 return _strutsBridgePortlet;
272 }
273
274 public boolean isStrutsPortlet() {
275 return _strutsPortlet;
276 }
277
278 public void prepare(
279 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
280 PortletContext portletContext)
281 throws PortletException {
282
283 _portletModel = portletModel;
284 _portlet = portlet;
285 _portletContextImpl = (PortletContextImpl)portletContext;
286
287 if (_log.isDebugEnabled()) {
288 _log.debug(
289 "Create root cache wrapper for " +
290 _portletContextImpl.getPortlet().getPortletId());
291 }
292
293 if (ClassUtil.isSubclass(
294 _portlet.getClass(), PortletDeployer.JSF_MYFACES) ||
295 ClassUtil.isSubclass(
296 _portlet.getClass(), PortletDeployer.JSF_SUN)) {
297
298 _facesPortlet = true;
299 }
300
301 _strutsPortlet = ClassUtil.isSubclass(
302 portlet.getClass(), StrutsPortlet.class);
303 _strutsBridgePortlet = ClassUtil.isSubclass(
304 portlet.getClass(),
305 "org.apache.portals.bridges.struts.StrutsPortlet");
306 _expCache = portletModel.getExpCache();
307 setPortletFilters();
308 }
309
310 public void prepare(
311 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
312 PortletConfig portletConfig, PortletContext portletContext,
313 boolean facesPortlet, boolean strutsPortlet,
314 boolean strutsBridgePortlet)
315 throws PortletException {
316
317
319 _portletModel = portletModel;
320 _portlet = portlet;
321 _portletContextImpl = (PortletContextImpl)portletContext;
322 _facesPortlet = facesPortlet;
323 _strutsPortlet = strutsPortlet;
324 _strutsBridgePortlet = strutsBridgePortlet;
325 _expCache = portletModel.getExpCache();
326 setPortletFilters();
327
328 if (_log.isDebugEnabled()) {
329 _log.debug(
330 "Create instance cache wrapper for " +
331 _portletContextImpl.getPortlet().getPortletId());
332 }
333
334
336 _portletConfigImpl = (PortletConfigImpl)portletConfig;
337
338 _portletId = _portletConfigImpl.getPortletId();
339 }
340
341 public void processAction(
342 ActionRequest actionRequest, ActionResponse actionResponse)
343 throws IOException {
344
345 StopWatch stopWatch = null;
346
347 if (_log.isDebugEnabled()) {
348 stopWatch = new StopWatch();
349
350 stopWatch.start();
351 }
352
353 try {
354 invokeAction(actionRequest, actionResponse);
355 }
356 catch (PortletException pe) {
357 actionRequest.setAttribute(
358 _portletId + PortletException.class.getName(), pe);
359 }
360
361 if (_log.isDebugEnabled()) {
362 _log.debug(
363 "processAction for " + _portletId + " takes " +
364 stopWatch.getTime() + " ms");
365 }
366 }
367
368 public void processEvent(
369 EventRequest eventRequest, EventResponse eventResponse)
370 throws IOException, PortletException {
371
372 StopWatch stopWatch = null;
373
374 if (_log.isDebugEnabled()) {
375 stopWatch = new StopWatch();
376
377 stopWatch.start();
378 }
379
380 invokeEvent(eventRequest, eventResponse);
381
382 if (_log.isDebugEnabled()) {
383 _log.debug(
384 "processEvent for " + _portletId + " takes " +
385 stopWatch.getTime() + " ms");
386 }
387 }
388
389 public void render(
390 RenderRequest renderRequest, RenderResponse renderResponse)
391 throws IOException, PortletException {
392
393 PortletException portletException =
394 (PortletException)renderRequest.getAttribute(
395 _portletId + PortletException.class.getName());
396
397 if (portletException != null) {
398 throw portletException;
399 }
400
401 StopWatch stopWatch = null;
402
403 if (_log.isDebugEnabled()) {
404 stopWatch = new StopWatch();
405
406 stopWatch.start();
407 }
408
409 String remoteUser = renderRequest.getRemoteUser();
410
411 if ((remoteUser == null) || (_expCache == null) ||
412 (_expCache.intValue() == 0)) {
413
414 invokeRender(renderRequest, renderResponse);
415 }
416 else {
417 RenderResponseImpl renderResponseImpl =
418 (RenderResponseImpl)renderResponse;
419
420 StringServletResponse stringResponse = (StringServletResponse)
421 renderResponseImpl.getHttpServletResponse();
422
423 PortletSession portletSession = renderRequest.getPortletSession();
424
425 long now = System.currentTimeMillis();
426
427 Layout layout = (Layout)renderRequest.getAttribute(WebKeys.LAYOUT);
428
429 Map<String, InvokerPortletResponse> sessionResponses =
430 getResponses(portletSession);
431
432 String sessionResponseId = encodeResponseKey(
433 layout.getPlid(), _portletId,
434 LanguageUtil.getLanguageId(renderRequest));
435
436 InvokerPortletResponse response = sessionResponses.get(
437 sessionResponseId);
438
439 if (response == null) {
440 String title = invokeRender(renderRequest, renderResponse);
441
442 response = new InvokerPortletResponse(
443 title, stringResponse.getString(),
444 now + Time.SECOND * _expCache.intValue());
445
446 sessionResponses.put(sessionResponseId, response);
447 }
448 else if ((response.getTime() < now) &&
449 (_expCache.intValue() > 0)) {
450
451 String title = invokeRender(renderRequest, renderResponse);
452
453 response.setTitle(title);
454 response.setContent(stringResponse.getString());
455 response.setTime(now + Time.SECOND * _expCache.intValue());
456 }
457 else {
458 renderResponseImpl.setTitle(response.getTitle());
459 stringResponse.getWriter().print(response.getContent());
460 }
461 }
462
463 Map<String, String[]> properties =
464 ((RenderResponseImpl)renderResponse).getProperties();
465
466 if (properties.containsKey("clear-request-parameters")) {
467 Map<String, String[]> renderParameters =
468 ((RenderRequestImpl)renderRequest).getRenderParameters();
469
470 renderParameters.clear();
471 }
472
473 if (_log.isDebugEnabled()) {
474 _log.debug(
475 "render for " + _portletId + " takes " + stopWatch.getTime() +
476 " ms");
477 }
478 }
479
480 public void serveResource(
481 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
482 throws IOException {
483
484 StopWatch stopWatch = null;
485
486 if (_log.isDebugEnabled()) {
487 stopWatch = new StopWatch();
488
489 stopWatch.start();
490 }
491
492 try {
493 invokeResource(resourceRequest, resourceResponse);
494 }
495 catch (PortletException pe) {
496 resourceRequest.setAttribute(
497 _portletId + PortletException.class.getName(), pe);
498 }
499
500 if (_log.isDebugEnabled()) {
501 _log.debug(
502 "serveResource for " + _portletId + " takes " +
503 stopWatch.getTime() + " ms");
504 }
505 }
506
507 public void setPortletFilters() throws PortletException {
508 Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
509 _portletModel.getPortletFilters();
510
511 for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
512 portletFilters.entrySet()) {
513
514 com.liferay.portal.model.PortletFilter portletFilterModel =
515 entry.getValue();
516
517 PortletFilter portletFilter = PortletFilterFactory.create(
518 portletFilterModel, _portletContextImpl);
519
520 Set<String> lifecycles = portletFilterModel.getLifecycles();
521
522 if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
523 _actionFilters.add((ActionFilter)portletFilter);
524 }
525
526 if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
527 _eventFilters.add((EventFilter)portletFilter);
528 }
529
530 if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
531 _renderFilters.add((RenderFilter)portletFilter);
532 }
533
534 if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
535 _resourceFilters.add((ResourceFilter)portletFilter);
536 }
537 }
538 }
539
540 protected void invoke(
541 LiferayPortletRequest portletRequest,
542 LiferayPortletResponse portletResponse, String lifecycle,
543 List<? extends PortletFilter> filters)
544 throws IOException, PortletException {
545
546 FilterChain filterChain = new FilterChainImpl(_portlet, filters);
547
548 if (_portletConfigImpl.isWARFile()) {
549 String path =
550 StringPool.SLASH + _portletConfigImpl.getPortletName() +
551 "/invoke";
552
553 RequestDispatcher requestDispatcher =
554 _portletContextImpl.getServletContext().getRequestDispatcher(
555 path);
556
557 HttpServletRequest request = portletRequest.getHttpServletRequest();
558 HttpServletResponse response =
559 portletResponse.getHttpServletResponse();
560
561 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
562 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
563 request.setAttribute(
564 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
565
566 try {
567
568
571 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
572 requestDispatcher.forward(request, response);
573 }
574 else {
575 requestDispatcher.include(request, response);
576 }
577 }
578 catch (ServletException se) {
579 Throwable cause = se.getRootCause();
580
581 if (cause instanceof PortletException) {
582 throw (PortletException)cause;
583 }
584
585 throw new PortletException(cause);
586 }
587 }
588 else {
589 PortletFilterUtil.doFilter(
590 portletRequest, portletResponse, lifecycle, filterChain);
591 }
592
593 Map<String, String[]> properties = portletResponse.getProperties();
594
595 if ((properties != null) && (properties.size() > 0)) {
596 if (_expCache != null) {
597 String[] expCache = properties.get(
598 RenderResponse.EXPIRATION_CACHE);
599
600 if ((expCache != null) && (expCache.length > 0) &&
601 (expCache[0] != null)) {
602
603 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
604 }
605 }
606 }
607 }
608
609 protected void invokeAction(
610 ActionRequest actionRequest, ActionResponse actionResponse)
611 throws IOException, PortletException {
612
613 LiferayPortletRequest portletRequest =
614 (LiferayPortletRequest)actionRequest;
615 LiferayPortletResponse portletResponse =
616 (LiferayPortletResponse)actionResponse;
617
618 invoke(
619 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
620 _actionFilters);
621 }
622
623 protected void invokeEvent(
624 EventRequest eventRequest, EventResponse eventResponse)
625 throws IOException, PortletException {
626
627 LiferayPortletRequest portletRequest =
628 (LiferayPortletRequest)eventRequest;
629 LiferayPortletResponse portletResponse =
630 (LiferayPortletResponse)eventResponse;
631
632 invoke(
633 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
634 _eventFilters);
635 }
636
637 protected String invokeRender(
638 RenderRequest renderRequest, RenderResponse renderResponse)
639 throws IOException, PortletException {
640
641 LiferayPortletRequest portletRequest =
642 (LiferayPortletRequest)renderRequest;
643 LiferayPortletResponse portletResponse =
644 (LiferayPortletResponse)renderResponse;
645
646 invoke(
647 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
648 _renderFilters);
649
650 RenderResponseImpl renderResponseImpl =
651 (RenderResponseImpl)renderResponse;
652
653 return renderResponseImpl.getTitle();
654 }
655
656 protected void invokeResource(
657 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
658 throws IOException, PortletException {
659
660 LiferayPortletRequest portletRequest =
661 (LiferayPortletRequest)resourceRequest;
662 LiferayPortletResponse portletResponse =
663 (LiferayPortletResponse)resourceResponse;
664
665 invoke(
666 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
667 _resourceFilters);
668 }
669
670 private static Log _log = LogFactory.getLog(InvokerPortletImpl.class);
671
672 private com.liferay.portal.model.Portlet _portletModel;
673 private String _portletId;
674 private Portlet _portlet;
675 private PortletConfigImpl _portletConfigImpl;
676 private PortletContextImpl _portletContextImpl;
677 private Integer _expCache;
678 private boolean _destroyable;
679 private boolean _facesPortlet;
680 private boolean _strutsPortlet;
681 private boolean _strutsBridgePortlet;
682 private List<ActionFilter> _actionFilters = new ArrayList<ActionFilter>();
683 private List<EventFilter> _eventFilters = new ArrayList<EventFilter>();
684 private List<RenderFilter> _renderFilters = new ArrayList<RenderFilter>();
685 private List<ResourceFilter> _resourceFilters =
686 new ArrayList<ResourceFilter>();
687
688 }