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 Thread currentThread = Thread.currentThread();
190
191 ClassLoader contextClassLoader =
192 currentThread.getContextClassLoader();
193
194 ClassLoader portletClassLoader = getPortletClassLoader();
195
196 try {
197 if (portletClassLoader != null) {
198 currentThread.setContextClassLoader(portletClassLoader);
199 }
200
201 _portlet.destroy();
202 }
203 finally {
204 if (portletClassLoader != null) {
205 currentThread.setContextClassLoader(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 Thread currentThread = Thread.currentThread();
240
241 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
242
243 ClassLoader portletClassLoader = getPortletClassLoader();
244
245 try {
246 if (portletClassLoader != null) {
247 currentThread.setContextClassLoader(portletClassLoader);
248 }
249
250 _portlet.init(portletConfig);
251 }
252 finally {
253 if (portletClassLoader != null) {
254 currentThread.setContextClassLoader(contextClassLoader);
255 }
256 }
257
258 _destroyable = true;
259 }
260
261 public boolean isDestroyable() {
262 return _destroyable;
263 }
264
265 public boolean isFacesPortlet() {
266 return _facesPortlet;
267 }
268
269 public boolean isStrutsBridgePortlet() {
270 return _strutsBridgePortlet;
271 }
272
273 public boolean isStrutsPortlet() {
274 return _strutsPortlet;
275 }
276
277 public void prepare(
278 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
279 PortletContext portletContext)
280 throws PortletException {
281
282 _portletModel = portletModel;
283 _portlet = portlet;
284 _portletContextImpl = (PortletContextImpl)portletContext;
285
286 if (_log.isDebugEnabled()) {
287 _log.debug(
288 "Create root cache wrapper for " +
289 _portletContextImpl.getPortlet().getPortletId());
290 }
291
292 if (ClassUtil.isSubclass(
293 _portlet.getClass(), PortletDeployer.JSF_MYFACES) ||
294 ClassUtil.isSubclass(
295 _portlet.getClass(), PortletDeployer.JSF_SUN)) {
296
297 _facesPortlet = true;
298 }
299
300 _strutsPortlet = ClassUtil.isSubclass(
301 portlet.getClass(), StrutsPortlet.class);
302 _strutsBridgePortlet = ClassUtil.isSubclass(
303 portlet.getClass(),
304 "org.apache.portals.bridges.struts.StrutsPortlet");
305 _expCache = portletModel.getExpCache();
306 setPortletFilters();
307 }
308
309 public void prepare(
310 com.liferay.portal.model.Portlet portletModel, Portlet portlet,
311 PortletConfig portletConfig, PortletContext portletContext,
312 boolean facesPortlet, boolean strutsPortlet,
313 boolean strutsBridgePortlet)
314 throws PortletException {
315
316
318 _portletModel = portletModel;
319 _portlet = portlet;
320 _portletContextImpl = (PortletContextImpl)portletContext;
321 _facesPortlet = facesPortlet;
322 _strutsPortlet = strutsPortlet;
323 _strutsBridgePortlet = strutsBridgePortlet;
324 _expCache = portletModel.getExpCache();
325 setPortletFilters();
326
327 if (_log.isDebugEnabled()) {
328 _log.debug(
329 "Create instance cache wrapper for " +
330 _portletContextImpl.getPortlet().getPortletId());
331 }
332
333
335 _portletConfigImpl = (PortletConfigImpl)portletConfig;
336
337 _portletId = _portletConfigImpl.getPortletId();
338 }
339
340 public void processAction(
341 ActionRequest actionRequest, ActionResponse actionResponse)
342 throws IOException {
343
344 StopWatch stopWatch = null;
345
346 if (_log.isDebugEnabled()) {
347 stopWatch = new StopWatch();
348
349 stopWatch.start();
350 }
351
352 try {
353 invokeAction(actionRequest, actionResponse);
354 }
355 catch (PortletException pe) {
356 actionRequest.setAttribute(
357 _portletId + PortletException.class.getName(), pe);
358 }
359
360 if (_log.isDebugEnabled()) {
361 _log.debug(
362 "processAction for " + _portletId + " takes " +
363 stopWatch.getTime() + " ms");
364 }
365 }
366
367 public void processEvent(
368 EventRequest eventRequest, EventResponse eventResponse)
369 throws IOException, PortletException {
370
371 StopWatch stopWatch = null;
372
373 if (_log.isDebugEnabled()) {
374 stopWatch = new StopWatch();
375
376 stopWatch.start();
377 }
378
379 invokeEvent(eventRequest, eventResponse);
380
381 if (_log.isDebugEnabled()) {
382 _log.debug(
383 "processEvent for " + _portletId + " takes " +
384 stopWatch.getTime() + " ms");
385 }
386 }
387
388 public void render(
389 RenderRequest renderRequest, RenderResponse renderResponse)
390 throws IOException, PortletException {
391
392 PortletException portletException =
393 (PortletException)renderRequest.getAttribute(
394 _portletId + PortletException.class.getName());
395
396 if (portletException != null) {
397 throw portletException;
398 }
399
400 StopWatch stopWatch = null;
401
402 if (_log.isDebugEnabled()) {
403 stopWatch = new StopWatch();
404
405 stopWatch.start();
406 }
407
408 String remoteUser = renderRequest.getRemoteUser();
409
410 if ((remoteUser == null) || (_expCache == null) ||
411 (_expCache.intValue() == 0)) {
412
413 invokeRender(renderRequest, renderResponse);
414 }
415 else {
416 RenderResponseImpl renderResponseImpl =
417 (RenderResponseImpl)renderResponse;
418
419 StringServletResponse stringResponse = (StringServletResponse)
420 renderResponseImpl.getHttpServletResponse();
421
422 PortletSession portletSession = renderRequest.getPortletSession();
423
424 long now = System.currentTimeMillis();
425
426 Layout layout = (Layout)renderRequest.getAttribute(WebKeys.LAYOUT);
427
428 Map<String, InvokerPortletResponse> sessionResponses =
429 getResponses(portletSession);
430
431 String sessionResponseId = encodeResponseKey(
432 layout.getPlid(), _portletId,
433 LanguageUtil.getLanguageId(renderRequest));
434
435 InvokerPortletResponse response = sessionResponses.get(
436 sessionResponseId);
437
438 if (response == null) {
439 String title = invokeRender(renderRequest, renderResponse);
440
441 response = new InvokerPortletResponse(
442 title, stringResponse.getString(),
443 now + Time.SECOND * _expCache.intValue());
444
445 sessionResponses.put(sessionResponseId, response);
446 }
447 else if ((response.getTime() < now) &&
448 (_expCache.intValue() > 0)) {
449
450 String title = invokeRender(renderRequest, renderResponse);
451
452 response.setTitle(title);
453 response.setContent(stringResponse.getString());
454 response.setTime(now + Time.SECOND * _expCache.intValue());
455 }
456 else {
457 renderResponseImpl.setTitle(response.getTitle());
458 stringResponse.getWriter().print(response.getContent());
459 }
460 }
461
462 Map<String, String[]> properties =
463 ((RenderResponseImpl)renderResponse).getProperties();
464
465 if (properties.containsKey("clear-request-parameters")) {
466 Map<String, String[]> renderParameters =
467 ((RenderRequestImpl)renderRequest).getRenderParameters();
468
469 renderParameters.clear();
470 }
471
472 if (_log.isDebugEnabled()) {
473 _log.debug(
474 "render for " + _portletId + " takes " + stopWatch.getTime() +
475 " ms");
476 }
477 }
478
479 public void serveResource(
480 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
481 throws IOException {
482
483 StopWatch stopWatch = null;
484
485 if (_log.isDebugEnabled()) {
486 stopWatch = new StopWatch();
487
488 stopWatch.start();
489 }
490
491 try {
492 invokeResource(resourceRequest, resourceResponse);
493 }
494 catch (PortletException pe) {
495 resourceRequest.setAttribute(
496 _portletId + PortletException.class.getName(), pe);
497 }
498
499 if (_log.isDebugEnabled()) {
500 _log.debug(
501 "serveResource for " + _portletId + " takes " +
502 stopWatch.getTime() + " ms");
503 }
504 }
505
506 public void setPortletFilters() throws PortletException {
507 _actionFilters.clear();
508 _eventFilters.clear();
509 _renderFilters.clear();
510 _resourceFilters.clear();
511
512 Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
513 _portletModel.getPortletFilters();
514
515 for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
516 portletFilters.entrySet()) {
517
518 com.liferay.portal.model.PortletFilter portletFilterModel =
519 entry.getValue();
520
521 PortletFilter portletFilter = PortletFilterFactory.create(
522 portletFilterModel, _portletContextImpl);
523
524 Set<String> lifecycles = portletFilterModel.getLifecycles();
525
526 if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
527 _actionFilters.add((ActionFilter)portletFilter);
528 }
529
530 if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
531 _eventFilters.add((EventFilter)portletFilter);
532 }
533
534 if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
535 _renderFilters.add((RenderFilter)portletFilter);
536 }
537
538 if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
539 _resourceFilters.add((ResourceFilter)portletFilter);
540 }
541 }
542 }
543
544 protected void invoke(
545 LiferayPortletRequest portletRequest,
546 LiferayPortletResponse portletResponse, String lifecycle,
547 List<? extends PortletFilter> filters)
548 throws IOException, PortletException {
549
550 FilterChain filterChain = new FilterChainImpl(_portlet, filters);
551
552 if (_portletConfigImpl.isWARFile()) {
553 String path =
554 StringPool.SLASH + _portletConfigImpl.getPortletName() +
555 "/invoke";
556
557 RequestDispatcher requestDispatcher =
558 _portletContextImpl.getServletContext().getRequestDispatcher(
559 path);
560
561 HttpServletRequest request = portletRequest.getHttpServletRequest();
562 HttpServletResponse response =
563 portletResponse.getHttpServletResponse();
564
565 request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
566 request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
567 request.setAttribute(
568 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
569
570 try {
571
572
575 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
576 requestDispatcher.forward(request, response);
577 }
578 else {
579 requestDispatcher.include(request, response);
580 }
581 }
582 catch (ServletException se) {
583 Throwable cause = se.getRootCause();
584
585 if (cause instanceof PortletException) {
586 throw (PortletException)cause;
587 }
588
589 throw new PortletException(cause);
590 }
591 }
592 else {
593 PortletFilterUtil.doFilter(
594 portletRequest, portletResponse, lifecycle, filterChain);
595 }
596
597 Map<String, String[]> properties = portletResponse.getProperties();
598
599 if ((properties != null) && (properties.size() > 0)) {
600 if (_expCache != null) {
601 String[] expCache = properties.get(
602 RenderResponse.EXPIRATION_CACHE);
603
604 if ((expCache != null) && (expCache.length > 0) &&
605 (expCache[0] != null)) {
606
607 _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
608 }
609 }
610 }
611 }
612
613 protected void invokeAction(
614 ActionRequest actionRequest, ActionResponse actionResponse)
615 throws IOException, PortletException {
616
617 LiferayPortletRequest portletRequest =
618 (LiferayPortletRequest)actionRequest;
619 LiferayPortletResponse portletResponse =
620 (LiferayPortletResponse)actionResponse;
621
622 invoke(
623 portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
624 _actionFilters);
625 }
626
627 protected void invokeEvent(
628 EventRequest eventRequest, EventResponse eventResponse)
629 throws IOException, PortletException {
630
631 LiferayPortletRequest portletRequest =
632 (LiferayPortletRequest)eventRequest;
633 LiferayPortletResponse portletResponse =
634 (LiferayPortletResponse)eventResponse;
635
636 invoke(
637 portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
638 _eventFilters);
639 }
640
641 protected String invokeRender(
642 RenderRequest renderRequest, RenderResponse renderResponse)
643 throws IOException, PortletException {
644
645 LiferayPortletRequest portletRequest =
646 (LiferayPortletRequest)renderRequest;
647 LiferayPortletResponse portletResponse =
648 (LiferayPortletResponse)renderResponse;
649
650 invoke(
651 portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
652 _renderFilters);
653
654 RenderResponseImpl renderResponseImpl =
655 (RenderResponseImpl)renderResponse;
656
657 return renderResponseImpl.getTitle();
658 }
659
660 protected void invokeResource(
661 ResourceRequest resourceRequest, ResourceResponse resourceResponse)
662 throws IOException, PortletException {
663
664 LiferayPortletRequest portletRequest =
665 (LiferayPortletRequest)resourceRequest;
666 LiferayPortletResponse portletResponse =
667 (LiferayPortletResponse)resourceResponse;
668
669 invoke(
670 portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
671 _resourceFilters);
672 }
673
674 private static Log _log = LogFactory.getLog(InvokerPortletImpl.class);
675
676 private com.liferay.portal.model.Portlet _portletModel;
677 private String _portletId;
678 private Portlet _portlet;
679 private PortletConfigImpl _portletConfigImpl;
680 private PortletContextImpl _portletContextImpl;
681 private Integer _expCache;
682 private boolean _destroyable;
683 private boolean _facesPortlet;
684 private boolean _strutsPortlet;
685 private boolean _strutsBridgePortlet;
686 private List<ActionFilter> _actionFilters = new ArrayList<ActionFilter>();
687 private List<EventFilter> _eventFilters = new ArrayList<EventFilter>();
688 private List<RenderFilter> _renderFilters = new ArrayList<RenderFilter>();
689 private List<ResourceFilter> _resourceFilters =
690 new ArrayList<ResourceFilter>();
691
692 }