1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portlet;
21  
22  import com.liferay.portal.kernel.language.LanguageUtil;
23  import com.liferay.portal.kernel.log.Log;
24  import com.liferay.portal.kernel.log.LogFactoryUtil;
25  import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
26  import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
27  import com.liferay.portal.kernel.portlet.PortletFilterUtil;
28  import com.liferay.portal.kernel.servlet.PortletServlet;
29  import com.liferay.portal.kernel.servlet.StringServletResponse;
30  import com.liferay.portal.kernel.util.ClassUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.JavaConstants;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.Time;
35  import com.liferay.portal.model.Layout;
36  import com.liferay.portal.tools.PortletDeployer;
37  import com.liferay.portal.util.WebKeys;
38  
39  import com.sun.portal.portletcontainer.appengine.filter.FilterChainImpl;
40  
41  import java.io.IOException;
42  
43  import java.util.ArrayList;
44  import java.util.HashMap;
45  import java.util.List;
46  import java.util.Map;
47  import java.util.Set;
48  
49  import javax.portlet.ActionRequest;
50  import javax.portlet.ActionResponse;
51  import javax.portlet.EventRequest;
52  import javax.portlet.EventResponse;
53  import javax.portlet.Portlet;
54  import javax.portlet.PortletConfig;
55  import javax.portlet.PortletContext;
56  import javax.portlet.PortletException;
57  import javax.portlet.PortletRequest;
58  import javax.portlet.PortletSession;
59  import javax.portlet.RenderRequest;
60  import javax.portlet.RenderResponse;
61  import javax.portlet.ResourceRequest;
62  import javax.portlet.ResourceResponse;
63  import javax.portlet.filter.ActionFilter;
64  import javax.portlet.filter.EventFilter;
65  import javax.portlet.filter.FilterChain;
66  import javax.portlet.filter.PortletFilter;
67  import javax.portlet.filter.RenderFilter;
68  import javax.portlet.filter.ResourceFilter;
69  
70  import javax.servlet.RequestDispatcher;
71  import javax.servlet.ServletException;
72  import javax.servlet.http.HttpServletRequest;
73  import javax.servlet.http.HttpServletResponse;
74  import javax.servlet.http.HttpSession;
75  
76  import org.apache.commons.lang.time.StopWatch;
77  
78  /**
79   * <a href="InvokerPortletImpl.java.html"><b><i>View Source</i></b></a>
80   *
81   * @author Brian Wing Shun Chan
82   * @author Brian Myunghun Kim
83   *
84   */
85  public class InvokerPortletImpl implements InvokerPortlet {
86  
87      public static void clearResponse(
88          HttpSession session, long plid, String portletId, String languageId) {
89  
90          String sesResponseId = encodeResponseKey(plid, portletId, languageId);
91  
92          getResponses(session).remove(sesResponseId);
93      }
94  
95      public static void clearResponses(HttpSession session) {
96          getResponses(session).clear();
97      }
98  
99      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         StringBuilder sb = new StringBuilder();
107 
108         sb.append(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 HashMap<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 InvokerPortlet create(
141             com.liferay.portal.model.Portlet portletModel, Portlet portlet,
142             PortletContext portletContext)
143         throws PortletException {
144 
145         try {
146             InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
147 
148             invokerPortlet.prepare(portletModel, portlet, portletContext);
149 
150             return invokerPortlet;
151         }
152         catch (PortletException pe) {
153             throw pe;
154         }
155         catch (Exception e) {
156             throw new PortletException(e);
157         }
158     }
159 
160     public InvokerPortlet create(
161             com.liferay.portal.model.Portlet portletModel, Portlet portlet,
162             PortletConfig portletConfig, PortletContext portletContext,
163             boolean facesPortlet, boolean strutsPortlet,
164             boolean strutsBridgePortlet)
165         throws PortletException {
166 
167         try {
168             InvokerPortlet invokerPortlet = (InvokerPortlet)clone();
169 
170             invokerPortlet.prepare(
171                 portletModel, portlet, portletConfig, portletContext,
172                 facesPortlet, strutsPortlet, strutsBridgePortlet);
173 
174             return invokerPortlet;
175         }
176         catch (PortletException pe) {
177             throw pe;
178         }
179         catch (Exception e) {
180             throw new PortletException(e);
181         }
182     }
183 
184     public void destroy() {
185         if (_destroyable) {
186             Thread currentThread = Thread.currentThread();
187 
188             ClassLoader contextClassLoader =
189                 currentThread.getContextClassLoader();
190 
191             ClassLoader portletClassLoader = getPortletClassLoader();
192 
193             try {
194                 if (portletClassLoader != null) {
195                     currentThread.setContextClassLoader(portletClassLoader);
196                 }
197 
198                 removePortletFilters();
199 
200                 _portlet.destroy();
201             }
202             finally {
203                 if (portletClassLoader != null) {
204                     currentThread.setContextClassLoader(contextClassLoader);
205                 }
206             }
207         }
208 
209         _destroyable = false;
210     }
211 
212     public ClassLoader getPortletClassLoader() {
213         return (ClassLoader)_portletContextImpl.getAttribute(
214             PortletServlet.PORTLET_CLASS_LOADER);
215     }
216 
217     public PortletConfigImpl getPortletConfig() {
218         return _portletConfigImpl;
219     }
220 
221     public PortletContextImpl getPortletContext() {
222         return _portletContextImpl;
223     }
224 
225     public Portlet getPortletInstance() {
226         return _portlet;
227     }
228 
229     public Integer getExpCache() {
230         return _expCache;
231     }
232 
233     public void init(PortletConfig portletConfig) throws PortletException {
234         _portletConfigImpl = (PortletConfigImpl)portletConfig;
235 
236         Thread currentThread = Thread.currentThread();
237 
238         ClassLoader contextClassLoader = currentThread.getContextClassLoader();
239 
240         ClassLoader portletClassLoader = getPortletClassLoader();
241 
242         try {
243             if (portletClassLoader != null) {
244                 currentThread.setContextClassLoader(portletClassLoader);
245             }
246 
247             _portlet.init(portletConfig);
248         }
249         finally {
250             if (portletClassLoader != null) {
251                 currentThread.setContextClassLoader(contextClassLoader);
252             }
253         }
254 
255         _destroyable = true;
256     }
257 
258     public boolean isDestroyable() {
259         return _destroyable;
260     }
261 
262     public boolean isFacesPortlet() {
263         return _facesPortlet;
264     }
265 
266     public boolean isStrutsBridgePortlet() {
267         return _strutsBridgePortlet;
268     }
269 
270     public boolean isStrutsPortlet() {
271         return _strutsPortlet;
272     }
273 
274     public void prepare(
275             com.liferay.portal.model.Portlet portletModel, Portlet portlet,
276             PortletContext portletContext)
277         throws PortletException {
278 
279         _portletModel = portletModel;
280         _portletId = _portletModel.getPortletId();
281         _portlet = portlet;
282         _portletContextImpl = (PortletContextImpl)portletContext;
283 
284         if (_log.isDebugEnabled()) {
285             _log.debug(
286                 "Create root cache wrapper for " +
287                     _portletContextImpl.getPortlet().getPortletId());
288         }
289 
290         if (ClassUtil.isSubclass(
291                 _portlet.getClass(), PortletDeployer.JSF_MYFACES) ||
292             ClassUtil.isSubclass(
293                 _portlet.getClass(), PortletDeployer.JSF_SUN)) {
294 
295             _facesPortlet = true;
296         }
297 
298         _strutsPortlet = ClassUtil.isSubclass(
299             portlet.getClass(), StrutsPortlet.class);
300         _strutsBridgePortlet = ClassUtil.isSubclass(
301             portlet.getClass(),
302             "org.apache.portals.bridges.struts.StrutsPortlet");
303         _expCache = portletModel.getExpCache();
304         setPortletFilters();
305     }
306 
307     public void prepare(
308             com.liferay.portal.model.Portlet portletModel, Portlet portlet,
309             PortletConfig portletConfig, PortletContext portletContext,
310             boolean facesPortlet, boolean strutsPortlet,
311             boolean strutsBridgePortlet)
312         throws PortletException {
313 
314         // From prepare
315 
316         _portletModel = portletModel;
317         _portlet = portlet;
318         _portletId = _portletModel.getPortletId();
319         _portletContextImpl = (PortletContextImpl)portletContext;
320         _facesPortlet = facesPortlet;
321         _strutsPortlet = strutsPortlet;
322         _strutsBridgePortlet = strutsBridgePortlet;
323         _expCache = portletModel.getExpCache();
324         setPortletFilters();
325 
326         if (_log.isDebugEnabled()) {
327             _log.debug(
328                 "Create instance cache wrapper for " +
329                     _portletContextImpl.getPortlet().getPortletId());
330         }
331 
332         // From init
333 
334         _portletConfigImpl = (PortletConfigImpl)portletConfig;
335     }
336 
337     public void processAction(
338             ActionRequest actionRequest, ActionResponse actionResponse)
339         throws IOException {
340 
341         StopWatch stopWatch = null;
342 
343         if (_log.isDebugEnabled()) {
344             stopWatch = new StopWatch();
345 
346             stopWatch.start();
347         }
348 
349         try {
350             invokeAction(actionRequest, actionResponse);
351         }
352         catch (PortletException pe) {
353             actionRequest.setAttribute(
354                 _portletId + PortletException.class.getName(), pe);
355         }
356 
357         if (_log.isDebugEnabled()) {
358             _log.debug(
359                 "processAction for " + _portletId + " takes " +
360                     stopWatch.getTime() + " ms");
361         }
362     }
363 
364     public void processEvent(
365             EventRequest eventRequest, EventResponse eventResponse)
366         throws IOException, PortletException {
367 
368         StopWatch stopWatch = null;
369 
370         if (_log.isDebugEnabled()) {
371             stopWatch = new StopWatch();
372 
373             stopWatch.start();
374         }
375 
376         invokeEvent(eventRequest, eventResponse);
377 
378         if (_log.isDebugEnabled()) {
379             _log.debug(
380                 "processEvent for " + _portletId + " takes " +
381                     stopWatch.getTime() + " ms");
382         }
383     }
384 
385     public void render(
386             RenderRequest renderRequest, RenderResponse renderResponse)
387         throws IOException, PortletException {
388 
389         PortletException portletException =
390             (PortletException)renderRequest.getAttribute(
391                 _portletId + PortletException.class.getName());
392 
393         if (portletException != null) {
394             throw portletException;
395         }
396 
397         StopWatch stopWatch = null;
398 
399         if (_log.isDebugEnabled()) {
400             stopWatch = new StopWatch();
401 
402             stopWatch.start();
403         }
404 
405         String remoteUser = renderRequest.getRemoteUser();
406 
407         if ((remoteUser == null) || (_expCache == null) ||
408             (_expCache.intValue() == 0)) {
409 
410             invokeRender(renderRequest, renderResponse);
411         }
412         else {
413             RenderResponseImpl renderResponseImpl =
414                 (RenderResponseImpl)renderResponse;
415 
416             StringServletResponse stringResponse = (StringServletResponse)
417                 renderResponseImpl.getHttpServletResponse();
418 
419             PortletSession portletSession = renderRequest.getPortletSession();
420 
421             long now = System.currentTimeMillis();
422 
423             Layout layout = (Layout)renderRequest.getAttribute(WebKeys.LAYOUT);
424 
425             Map<String, InvokerPortletResponse> sessionResponses =
426                 getResponses(portletSession);
427 
428             String sessionResponseId = encodeResponseKey(
429                 layout.getPlid(), _portletId,
430                 LanguageUtil.getLanguageId(renderRequest));
431 
432             InvokerPortletResponse response = sessionResponses.get(
433                 sessionResponseId);
434 
435             if (response == null) {
436                 String title = invokeRender(renderRequest, renderResponse);
437 
438                 response = new InvokerPortletResponse(
439                     title, stringResponse.getString(),
440                     now + Time.SECOND * _expCache.intValue());
441 
442                 sessionResponses.put(sessionResponseId, response);
443             }
444             else if ((response.getTime() < now) &&
445                      (_expCache.intValue() > 0)) {
446 
447                 String title = invokeRender(renderRequest, renderResponse);
448 
449                 response.setTitle(title);
450                 response.setContent(stringResponse.getString());
451                 response.setTime(now + Time.SECOND * _expCache.intValue());
452             }
453             else {
454                 renderResponseImpl.setTitle(response.getTitle());
455                 stringResponse.getWriter().print(response.getContent());
456             }
457         }
458 
459         Map<String, String[]> properties =
460             ((RenderResponseImpl)renderResponse).getProperties();
461 
462         if (properties.containsKey("clear-request-parameters")) {
463             Map<String, String[]> renderParameters =
464                 ((RenderRequestImpl)renderRequest).getRenderParameters();
465 
466             renderParameters.clear();
467         }
468 
469         if (_log.isDebugEnabled()) {
470             _log.debug(
471                 "render for " + _portletId + " takes " + stopWatch.getTime() +
472                     " ms");
473         }
474     }
475 
476     public void serveResource(
477             ResourceRequest resourceRequest, ResourceResponse resourceResponse)
478         throws IOException {
479 
480         StopWatch stopWatch = null;
481 
482         if (_log.isDebugEnabled()) {
483             stopWatch = new StopWatch();
484 
485             stopWatch.start();
486         }
487 
488         try {
489             invokeResource(resourceRequest, resourceResponse);
490         }
491         catch (PortletException pe) {
492             resourceRequest.setAttribute(
493                 _portletId + PortletException.class.getName(), pe);
494         }
495 
496         if (_log.isDebugEnabled()) {
497             _log.debug(
498                 "serveResource for " + _portletId + " takes " +
499                     stopWatch.getTime() + " ms");
500         }
501     }
502 
503     public void setPortletFilters() throws PortletException {
504         removePortletFilters();
505 
506         Map<String, com.liferay.portal.model.PortletFilter> portletFilters =
507             _portletModel.getPortletFilters();
508 
509         for (Map.Entry<String, com.liferay.portal.model.PortletFilter> entry :
510                 portletFilters.entrySet()) {
511 
512             com.liferay.portal.model.PortletFilter portletFilterModel =
513                 entry.getValue();
514 
515             PortletFilter portletFilter = PortletFilterFactory.create(
516                 portletFilterModel, _portletContextImpl);
517 
518             Set<String> lifecycles = portletFilterModel.getLifecycles();
519 
520             if (lifecycles.contains(PortletRequest.ACTION_PHASE)) {
521                 List<ActionFilter> actionFilters = _actionFiltersMap.get(
522                     _portletId);
523 
524                 if (actionFilters == null) {
525                     actionFilters = new ArrayList<ActionFilter>();
526                 }
527 
528                 actionFilters.add((ActionFilter)portletFilter);
529 
530                 _actionFiltersMap.put(_portletId, actionFilters);
531             }
532 
533             if (lifecycles.contains(PortletRequest.EVENT_PHASE)) {
534                 List<EventFilter> eventFilters = _eventFiltersMap.get(
535                     _portletId);
536 
537                 if (eventFilters == null) {
538                     eventFilters = new ArrayList<EventFilter>();
539                 }
540 
541                 eventFilters.add((EventFilter)portletFilter);
542 
543                 _eventFiltersMap.put(_portletId, eventFilters);
544             }
545 
546             if (lifecycles.contains(PortletRequest.RENDER_PHASE)) {
547                 List<RenderFilter> renderFilters = _renderFiltersMap.get(
548                     _portletId);
549 
550                 if (renderFilters == null) {
551                     renderFilters = new ArrayList<RenderFilter>();
552                 }
553 
554                 renderFilters.add((RenderFilter)portletFilter);
555 
556                 _renderFiltersMap.put(_portletId, renderFilters);
557             }
558 
559             if (lifecycles.contains(PortletRequest.RESOURCE_PHASE)) {
560                 List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
561                     _portletId);
562 
563                 if (resourceFilters == null) {
564                     resourceFilters = new ArrayList<ResourceFilter>();
565                 }
566 
567                 resourceFilters.add((ResourceFilter)portletFilter);
568 
569                 _resourceFiltersMap.put(_portletId, resourceFilters);
570             }
571         }
572     }
573 
574     protected void invoke(
575             LiferayPortletRequest portletRequest,
576             LiferayPortletResponse portletResponse, String lifecycle,
577             List<? extends PortletFilter> filters)
578         throws IOException, PortletException {
579 
580         FilterChain filterChain = new FilterChainImpl(_portlet, filters);
581 
582         if (_portletConfigImpl.isWARFile()) {
583             String path =
584                 StringPool.SLASH + _portletConfigImpl.getPortletName() +
585                     "/invoke";
586 
587             RequestDispatcher requestDispatcher =
588                 _portletContextImpl.getServletContext().getRequestDispatcher(
589                     path);
590 
591             HttpServletRequest request = portletRequest.getHttpServletRequest();
592             HttpServletResponse response =
593                 portletResponse.getHttpServletResponse();
594 
595             request.setAttribute(JavaConstants.JAVAX_PORTLET_PORTLET, _portlet);
596             request.setAttribute(PortletRequest.LIFECYCLE_PHASE, lifecycle);
597             request.setAttribute(
598                 PortletServlet.PORTLET_SERVLET_FILTER_CHAIN, filterChain);
599 
600             try {
601 
602                 // Resource phase must be a forward because includes do not
603                 // allow you to specify the content type or headers
604 
605                 if (lifecycle.equals(PortletRequest.RESOURCE_PHASE)) {
606                     requestDispatcher.forward(request, response);
607                 }
608                 else {
609                     requestDispatcher.include(request, response);
610                 }
611             }
612             catch (ServletException se) {
613                 Throwable cause = se.getRootCause();
614 
615                 if (cause instanceof PortletException) {
616                     throw (PortletException)cause;
617                 }
618 
619                 throw new PortletException(cause);
620             }
621         }
622         else {
623             PortletFilterUtil.doFilter(
624                 portletRequest, portletResponse, lifecycle, filterChain);
625         }
626 
627         Map<String, String[]> properties = portletResponse.getProperties();
628 
629         if ((properties != null) && (properties.size() > 0)) {
630             if (_expCache != null) {
631                 String[] expCache = properties.get(
632                     RenderResponse.EXPIRATION_CACHE);
633 
634                 if ((expCache != null) && (expCache.length > 0) &&
635                     (expCache[0] != null)) {
636 
637                     _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
638                 }
639             }
640         }
641     }
642 
643     protected void invokeAction(
644             ActionRequest actionRequest, ActionResponse actionResponse)
645         throws IOException, PortletException {
646 
647         LiferayPortletRequest portletRequest =
648             (LiferayPortletRequest)actionRequest;
649         LiferayPortletResponse portletResponse =
650             (LiferayPortletResponse)actionResponse;
651 
652         String portletId = _getPortletId(portletResponse);
653 
654         List<ActionFilter> actionFilters = _actionFiltersMap.get(portletId);
655 
656         invoke(
657             portletRequest, portletResponse, PortletRequest.ACTION_PHASE,
658             actionFilters);
659     }
660 
661     protected void invokeEvent(
662             EventRequest eventRequest, EventResponse eventResponse)
663         throws IOException, PortletException {
664 
665         LiferayPortletRequest portletRequest =
666             (LiferayPortletRequest)eventRequest;
667         LiferayPortletResponse portletResponse =
668             (LiferayPortletResponse)eventResponse;
669 
670         String portletId = _getPortletId(portletResponse);
671 
672         List<EventFilter> eventFilters = _eventFiltersMap.get(portletId);
673 
674         invoke(
675             portletRequest, portletResponse, PortletRequest.EVENT_PHASE,
676             eventFilters);
677     }
678 
679     protected String invokeRender(
680             RenderRequest renderRequest, RenderResponse renderResponse)
681         throws IOException, PortletException {
682 
683         LiferayPortletRequest portletRequest =
684             (LiferayPortletRequest)renderRequest;
685         LiferayPortletResponse portletResponse =
686             (LiferayPortletResponse)renderResponse;
687 
688         String portletId = _getPortletId(portletResponse);
689 
690         List<RenderFilter> renderFilters = _renderFiltersMap.get(portletId);
691 
692         invoke(
693             portletRequest, portletResponse, PortletRequest.RENDER_PHASE,
694             renderFilters);
695 
696         RenderResponseImpl renderResponseImpl =
697             (RenderResponseImpl)renderResponse;
698 
699         return renderResponseImpl.getTitle();
700     }
701 
702     protected void invokeResource(
703             ResourceRequest resourceRequest, ResourceResponse resourceResponse)
704         throws IOException, PortletException {
705 
706         LiferayPortletRequest portletRequest =
707             (LiferayPortletRequest)resourceRequest;
708         LiferayPortletResponse portletResponse =
709             (LiferayPortletResponse)resourceResponse;
710 
711         String portletId = _getPortletId(portletResponse);
712 
713         List<ResourceFilter> resourceFilters = _resourceFiltersMap.get(
714             portletId);
715 
716         invoke(
717             portletRequest, portletResponse, PortletRequest.RESOURCE_PHASE,
718             resourceFilters);
719     }
720 
721     protected void removePortletFilters() {
722         _actionFiltersMap.remove(_portletId);
723         _eventFiltersMap.remove(_portletId);
724         _renderFiltersMap.remove(_portletId);
725         _resourceFiltersMap.remove(_portletId);
726     }
727 
728     private String _getPortletId(LiferayPortletResponse portletResponse) {
729         PortletResponseImpl portletResponseImpl =
730             (PortletResponseImpl)portletResponse;
731 
732         com.liferay.portal.model.Portlet portlet =
733             portletResponseImpl.getPortlet();
734 
735         return portlet.getPortletId();
736     }
737 
738     private static Log _log = LogFactoryUtil.getLog(InvokerPortletImpl.class);
739 
740     private com.liferay.portal.model.Portlet _portletModel;
741     private String _portletId;
742     private Portlet _portlet;
743     private PortletConfigImpl _portletConfigImpl;
744     private PortletContextImpl _portletContextImpl;
745     private Integer _expCache;
746     private boolean _destroyable;
747     private boolean _facesPortlet;
748     private boolean _strutsPortlet;
749     private boolean _strutsBridgePortlet;
750     private Map<String, List<ActionFilter>> _actionFiltersMap =
751         new HashMap<String, List<ActionFilter>>();
752     private Map<String, List<EventFilter>> _eventFiltersMap =
753         new HashMap<String, List<EventFilter>>();
754     private Map<String, List<RenderFilter>> _renderFiltersMap =
755         new HashMap<String, List<RenderFilter>>();
756     private Map<String, List<ResourceFilter>> _resourceFiltersMap =
757         new HashMap<String, List<ResourceFilter>>();
758 
759 }