1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.servlet;
24  
25  import com.liferay.portal.NoSuchLayoutException;
26  import com.liferay.portal.deploy.hot.PluginPackageHotDeployListener;
27  import com.liferay.portal.events.EventsProcessorUtil;
28  import com.liferay.portal.events.StartupAction;
29  import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
30  import com.liferay.portal.kernel.events.ActionException;
31  import com.liferay.portal.kernel.job.Scheduler;
32  import com.liferay.portal.kernel.log.Log;
33  import com.liferay.portal.kernel.log.LogFactoryUtil;
34  import com.liferay.portal.kernel.plugin.PluginPackage;
35  import com.liferay.portal.kernel.poller.PollerProcessor;
36  import com.liferay.portal.kernel.pop.MessageListener;
37  import com.liferay.portal.kernel.servlet.PortletSessionTracker;
38  import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
39  import com.liferay.portal.kernel.util.ContentTypes;
40  import com.liferay.portal.kernel.util.GetterUtil;
41  import com.liferay.portal.kernel.util.HttpUtil;
42  import com.liferay.portal.kernel.util.InstancePool;
43  import com.liferay.portal.kernel.util.ParamUtil;
44  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
45  import com.liferay.portal.kernel.util.PortalInitableUtil;
46  import com.liferay.portal.kernel.util.ReleaseInfo;
47  import com.liferay.portal.kernel.util.StringPool;
48  import com.liferay.portal.kernel.util.Validator;
49  import com.liferay.portal.kernel.xml.Document;
50  import com.liferay.portal.kernel.xml.DocumentException;
51  import com.liferay.portal.kernel.xml.Element;
52  import com.liferay.portal.kernel.xml.SAXReaderUtil;
53  import com.liferay.portal.model.Company;
54  import com.liferay.portal.model.Layout;
55  import com.liferay.portal.model.Portlet;
56  import com.liferay.portal.model.PortletApp;
57  import com.liferay.portal.model.PortletFilter;
58  import com.liferay.portal.model.PortletURLListener;
59  import com.liferay.portal.model.User;
60  import com.liferay.portal.poller.PollerProcessorUtil;
61  import com.liferay.portal.pop.POPServerUtil;
62  import com.liferay.portal.security.auth.CompanyThreadLocal;
63  import com.liferay.portal.security.auth.PrincipalException;
64  import com.liferay.portal.security.auth.PrincipalThreadLocal;
65  import com.liferay.portal.security.permission.ResourceActionsUtil;
66  import com.liferay.portal.service.CompanyLocalServiceUtil;
67  import com.liferay.portal.service.LayoutLocalServiceUtil;
68  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
69  import com.liferay.portal.service.PortletLocalServiceUtil;
70  import com.liferay.portal.service.ResourceActionLocalServiceUtil;
71  import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
72  import com.liferay.portal.service.ThemeLocalServiceUtil;
73  import com.liferay.portal.service.UserLocalServiceUtil;
74  import com.liferay.portal.struts.PortletRequestProcessor;
75  import com.liferay.portal.struts.StrutsUtil;
76  import com.liferay.portal.util.ContentUtil;
77  import com.liferay.portal.util.MaintenanceUtil;
78  import com.liferay.portal.util.Portal;
79  import com.liferay.portal.util.PortalInstances;
80  import com.liferay.portal.util.PortalUtil;
81  import com.liferay.portal.util.PropsKeys;
82  import com.liferay.portal.util.PropsUtil;
83  import com.liferay.portal.util.PropsValues;
84  import com.liferay.portal.util.ShutdownUtil;
85  import com.liferay.portal.util.WebKeys;
86  import com.liferay.portal.velocity.VelocityContextPool;
87  import com.liferay.portlet.PortletConfigFactory;
88  import com.liferay.portlet.PortletFilterFactory;
89  import com.liferay.portlet.PortletInstanceFactory;
90  import com.liferay.portlet.PortletURLListenerFactory;
91  import com.liferay.portlet.social.model.SocialActivityInterpreter;
92  import com.liferay.portlet.social.model.SocialRequestInterpreter;
93  import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
94  import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
95  import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
96  import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
97  import com.liferay.util.servlet.DynamicServletRequest;
98  import com.liferay.util.servlet.EncryptedServletRequest;
99  
100 import java.io.IOException;
101 
102 import java.util.Iterator;
103 import java.util.List;
104 import java.util.Set;
105 
106 import javax.portlet.PortletConfig;
107 import javax.portlet.PortletContext;
108 import javax.portlet.PortletException;
109 
110 import javax.servlet.RequestDispatcher;
111 import javax.servlet.ServletContext;
112 import javax.servlet.ServletException;
113 import javax.servlet.http.HttpServletRequest;
114 import javax.servlet.http.HttpServletResponse;
115 import javax.servlet.http.HttpSession;
116 import javax.servlet.jsp.PageContext;
117 
118 import org.apache.struts.Globals;
119 import org.apache.struts.action.ActionServlet;
120 import org.apache.struts.action.RequestProcessor;
121 import org.apache.struts.config.ControllerConfig;
122 import org.apache.struts.config.ModuleConfig;
123 import org.apache.struts.tiles.TilesUtilImpl;
124 
125 /**
126  * <a href="MainServlet.java.html"><b><i>View Source</i></b></a>
127  *
128  * @author Brian Wing Shun Chan
129  * @author Jorge Ferrer
130  * @author Brian Myunghun Kim
131  *
132  */
133 public class MainServlet extends ActionServlet {
134 
135     public void init() throws ServletException {
136 
137         // Initialize
138 
139         if (_log.isDebugEnabled()) {
140             _log.debug("Initialize");
141         }
142 
143         super.init();
144 
145         // Startup events
146 
147         if (_log.isDebugEnabled()) {
148             _log.debug("Process startup events");
149         }
150 
151         try {
152             StartupAction startupAction = new StartupAction();
153 
154             startupAction.run(null);
155         }
156         catch (RuntimeException re) {
157             ShutdownUtil.shutdown(0);
158 
159             throw new ServletException(re);
160         }
161         catch (ActionException ae) {
162             _log.error(ae, ae);
163         }
164 
165         // Velocity
166 
167         String contextPath = PortalUtil.getPathContext();
168 
169         ServletContext servletContext = getServletContext();
170 
171         VelocityContextPool.put(contextPath, servletContext);
172 
173         // Plugin package
174 
175         if (_log.isDebugEnabled()) {
176             _log.debug("Initialize plugin package");
177         }
178 
179         PluginPackage pluginPackage = null;
180 
181         try {
182             pluginPackage =
183                 PluginPackageHotDeployListener.readPluginPackage(
184                     servletContext);
185         }
186         catch (Exception e) {
187             _log.error(e, e);
188         }
189 
190         // Portlets
191 
192         if (_log.isDebugEnabled()) {
193             _log.debug("Initialize portlets");
194         }
195 
196         List<Portlet> portlets = null;
197 
198         try {
199             String[] xmls = new String[] {
200                 HttpUtil.URLtoString(servletContext.getResource(
201                     "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
202                 HttpUtil.URLtoString(servletContext.getResource(
203                     "/WEB-INF/portlet-ext.xml")),
204                 HttpUtil.URLtoString(servletContext.getResource(
205                     "/WEB-INF/liferay-portlet.xml")),
206                 HttpUtil.URLtoString(servletContext.getResource(
207                     "/WEB-INF/liferay-portlet-ext.xml")),
208                 HttpUtil.URLtoString(servletContext.getResource(
209                     "/WEB-INF/web.xml"))
210             };
211 
212             PortletLocalServiceUtil.initEAR(
213                 servletContext, xmls, pluginPackage);
214 
215             portlets = PortletLocalServiceUtil.getPortlets();
216 
217             for (int i = 0; i < portlets.size(); i++) {
218                 Portlet portlet = portlets.get(i);
219 
220                 if (i == 0) {
221                     initPortletApp(portlet, servletContext);
222                 }
223 
224                 PortletInstanceFactory.create(portlet, servletContext);
225             }
226         }
227         catch (Exception e) {
228             _log.error(e, e);
229         }
230 
231         // Layout templates
232 
233         if (_log.isDebugEnabled()) {
234             _log.debug("Initialize layout templates");
235         }
236 
237         try {
238             String[] xmls = new String[] {
239                 HttpUtil.URLtoString(servletContext.getResource(
240                     "/WEB-INF/liferay-layout-templates.xml")),
241                 HttpUtil.URLtoString(servletContext.getResource(
242                     "/WEB-INF/liferay-layout-templates-ext.xml"))
243             };
244 
245             LayoutTemplateLocalServiceUtil.init(
246                 servletContext, xmls, pluginPackage);
247         }
248         catch (Exception e) {
249             _log.error(e, e);
250         }
251 
252         // Look and feel
253 
254         if (_log.isDebugEnabled()) {
255             _log.debug("Initialize look and feel");
256         }
257 
258         try {
259             String[] xmls = new String[] {
260                 HttpUtil.URLtoString(servletContext.getResource(
261                     "/WEB-INF/liferay-look-and-feel.xml")),
262                 HttpUtil.URLtoString(servletContext.getResource(
263                     "/WEB-INF/liferay-look-and-feel-ext.xml"))
264             };
265 
266             ThemeLocalServiceUtil.init(
267                 servletContext, null, true, xmls, pluginPackage);
268         }
269         catch (Exception e) {
270             _log.error(e, e);
271         }
272 
273         // Scheduler
274 
275         if (_log.isDebugEnabled()) {
276             _log.debug("Scheduler");
277         }
278 
279         try {
280             if (PropsValues.SCHEDULER_ENABLED) {
281                 for (String className : PropsValues.SCHEDULER_CLASSES) {
282                     Scheduler scheduler = (Scheduler)InstancePool.get(
283                         className);
284 
285                     scheduler.schedule();
286                 }
287 
288                 Iterator<Portlet> itr = portlets.iterator();
289 
290                 while (itr.hasNext()) {
291                     Portlet portlet = itr.next();
292 
293                     String className = portlet.getSchedulerClass();
294 
295                     if (portlet.isActive() && Validator.isNotNull(className)) {
296                         Scheduler scheduler = (Scheduler)InstancePool.get(
297                             className);
298 
299                         scheduler.schedule();
300                     }
301                 }
302             }
303         }
304         catch (Exception e) {
305             _log.error(e, e);
306         }
307 
308         // Poller processor
309 
310         if (_log.isDebugEnabled()) {
311             _log.debug("Poller processor");
312         }
313 
314         try {
315             Iterator<Portlet> itr = portlets.iterator();
316 
317             while (itr.hasNext()) {
318                 Portlet portlet = itr.next();
319 
320                 PollerProcessor pollerProcessor =
321                     portlet.getPollerProcessorInstance();
322 
323                 if (!portlet.isActive() || (pollerProcessor == null)) {
324                     continue;
325                 }
326 
327                 PollerProcessorUtil.addPollerProcessor(
328                     portlet.getPortletId(), pollerProcessor);
329             }
330         }
331         catch (Exception e) {
332             _log.error(e, e);
333         }
334 
335         // POP message listener
336 
337         if (_log.isDebugEnabled()) {
338             _log.debug("POP message listener");
339         }
340 
341         try {
342             Iterator<Portlet> itr = portlets.iterator();
343 
344             while (itr.hasNext()) {
345                 Portlet portlet = itr.next();
346 
347                 MessageListener popMessageListener =
348                     portlet.getPopMessageListenerInstance();
349 
350                 if (portlet.isActive() && (popMessageListener != null)) {
351                     POPServerUtil.addListener(popMessageListener);
352                 }
353             }
354         }
355         catch (Exception e) {
356             _log.error(e, e);
357         }
358 
359         // Social activity interpreter
360 
361         if (_log.isDebugEnabled()) {
362             _log.debug("Social activity interpreter");
363         }
364 
365         try {
366             Iterator<Portlet> itr = portlets.iterator();
367 
368             while (itr.hasNext()) {
369                 Portlet portlet = itr.next();
370 
371                 SocialActivityInterpreter socialActivityInterpreter =
372                     portlet.getSocialActivityInterpreterInstance();
373 
374                 if (portlet.isActive() && (socialActivityInterpreter != null)) {
375                     socialActivityInterpreter =
376                         new SocialActivityInterpreterImpl(
377                             portlet.getPortletId(), socialActivityInterpreter);
378 
379                     SocialActivityInterpreterLocalServiceUtil.
380                         addActivityInterpreter(socialActivityInterpreter);
381                 }
382             }
383         }
384         catch (Exception e) {
385             _log.error(e, e);
386         }
387 
388         // Social request interpreter
389 
390         if (_log.isDebugEnabled()) {
391             _log.debug("Social request interpreter");
392         }
393 
394         try {
395             Iterator<Portlet> itr = portlets.iterator();
396 
397             while (itr.hasNext()) {
398                 Portlet portlet = itr.next();
399 
400                 SocialRequestInterpreter socialRequestInterpreter =
401                     portlet.getSocialRequestInterpreterInstance();
402 
403                 if (portlet.isActive() && (socialRequestInterpreter != null)) {
404                     socialRequestInterpreter = new SocialRequestInterpreterImpl(
405                         portlet.getPortletId(), socialRequestInterpreter);
406 
407                     SocialRequestInterpreterLocalServiceUtil.
408                         addRequestInterpreter(socialRequestInterpreter);
409                 }
410             }
411         }
412         catch (Exception e) {
413             _log.error(e, e);
414         }
415 
416         // Check web settings
417 
418         if (_log.isDebugEnabled()) {
419             _log.debug("Check web settings");
420         }
421 
422         try {
423             String xml = HttpUtil.URLtoString(
424                 servletContext.getResource("/WEB-INF/web.xml"));
425 
426             checkWebSettings(xml);
427         }
428         catch (Exception e) {
429             _log.error(e, e);
430         }
431 
432         // Global startup events
433 
434         if (_log.isDebugEnabled()) {
435             _log.debug("Process global startup events");
436         }
437 
438         try {
439             EventsProcessorUtil.process(
440                 PropsKeys.GLOBAL_STARTUP_EVENTS,
441                 PropsValues.GLOBAL_STARTUP_EVENTS);
442         }
443         catch (Exception e) {
444             _log.error(e, e);
445         }
446 
447         // Resource actions
448 
449         if (_log.isDebugEnabled()) {
450             _log.debug("Initialize resource actions");
451         }
452 
453         try {
454             Iterator<Portlet> itr = portlets.iterator();
455 
456             while (itr.hasNext()) {
457                 Portlet portlet = itr.next();
458 
459                 List<String> portletActions =
460                     ResourceActionsUtil.getPortletResourceActions(
461                         portlet.getPortletId());
462 
463                 ResourceActionLocalServiceUtil.checkResourceActions(
464                     portlet.getPortletId(), portletActions);
465 
466                 List<String> modelNames =
467                     ResourceActionsUtil.getPortletModelResources(
468                         portlet.getPortletId());
469 
470                 for (String modelName : modelNames) {
471                     List<String> modelActions =
472                         ResourceActionsUtil.getModelResourceActions(modelName);
473 
474                     ResourceActionLocalServiceUtil.checkResourceActions(
475                         modelName, modelActions);
476                 }
477             }
478         }
479         catch (Exception e) {
480             _log.error(e, e);
481         }
482 
483         // Companies
484 
485         String[] webIds = PortalInstances.getWebIds();
486 
487         for (int i = 0; i < webIds.length; i++) {
488             PortalInstances.initCompany(servletContext, webIds[i]);
489         }
490 
491         // Resource codes
492 
493         if (_log.isDebugEnabled()) {
494             _log.debug("Initialize resource codes");
495         }
496 
497         try {
498             long[] companyIds = PortalInstances.getCompanyIds();
499 
500             Iterator<Portlet> itr = portlets.iterator();
501 
502             while (itr.hasNext()) {
503                 Portlet portlet = itr.next();
504 
505                 List<String> modelNames =
506                     ResourceActionsUtil.getPortletModelResources(
507                         portlet.getPortletId());
508 
509                 for (long companyId : companyIds) {
510                     ResourceCodeLocalServiceUtil.checkResourceCodes(
511                         companyId, portlet.getPortletId());
512 
513                     for (String modelName : modelNames) {
514                         ResourceCodeLocalServiceUtil.checkResourceCodes(
515                             companyId, modelName);
516                     }
517                 }
518             }
519         }
520         catch (Exception e) {
521             _log.error(e, e);
522         }
523 
524         // See LEP-2885. Don't flush hot deploy events until after the portal
525         // has initialized.
526 
527         PortalInitableUtil.flushInitables();
528         HotDeployUtil.flushPrematureEvents();
529     }
530 
531     public void callParentService(
532             HttpServletRequest request, HttpServletResponse response)
533         throws IOException, ServletException {
534 
535         super.service(request, response);
536     }
537 
538     public void service(
539             HttpServletRequest request, HttpServletResponse response)
540         throws IOException, ServletException {
541 
542         if (_log.isDebugEnabled()) {
543             _log.debug("Process service request");
544         }
545 
546         if (ShutdownUtil.isShutdown()) {
547             response.setContentType(ContentTypes.TEXT_HTML_UTF8);
548 
549             String html = ContentUtil.get(
550                 "com/liferay/portal/dependencies/shutdown.html");
551 
552             response.getOutputStream().print(html);
553 
554             return;
555         }
556 
557         if (MaintenanceUtil.isMaintaining()) {
558             RequestDispatcher requestDispatcher = request.getRequestDispatcher(
559                 "/html/portal/maintenance.jsp");
560 
561             requestDispatcher.include(request, response);
562 
563             return;
564         }
565 
566         HttpSession session = request.getSession();
567 
568         // Company id
569 
570         long companyId = PortalInstances.getCompanyId(request);
571 
572         //CompanyThreadLocal.setCompanyId(companyId);
573 
574         // Portal port
575 
576         PortalUtil.setPortalPort(request);
577 
578         // CTX
579 
580         ServletContext servletContext = getServletContext();
581 
582         request.setAttribute(WebKeys.CTX, servletContext);
583 
584         // Struts module config
585 
586         ModuleConfig moduleConfig = getModuleConfig(request);
587 
588         // Portlet session tracker
589 
590         if (session.getAttribute(WebKeys.PORTLET_SESSION_TRACKER) == null ) {
591             session.setAttribute(
592                 WebKeys.PORTLET_SESSION_TRACKER,
593                 PortletSessionTracker.getInstance());
594         }
595 
596         // Portlet Request Processor
597 
598         PortletRequestProcessor portletReqProcessor =
599             (PortletRequestProcessor)servletContext.getAttribute(
600                 WebKeys.PORTLET_STRUTS_PROCESSOR);
601 
602         if (portletReqProcessor == null) {
603             portletReqProcessor =
604                 PortletRequestProcessor.getInstance(this, moduleConfig);
605 
606             servletContext.setAttribute(
607                 WebKeys.PORTLET_STRUTS_PROCESSOR, portletReqProcessor);
608         }
609 
610         // Tiles definitions factory
611 
612         if (servletContext.getAttribute(
613                 TilesUtilImpl.DEFINITIONS_FACTORY) == null) {
614 
615             servletContext.setAttribute(
616                 TilesUtilImpl.DEFINITIONS_FACTORY,
617                 servletContext.getAttribute(TilesUtilImpl.DEFINITIONS_FACTORY));
618         }
619 
620         Object applicationAssociate = servletContext.getAttribute(
621             WebKeys.ASSOCIATE_KEY);
622 
623         if (servletContext.getAttribute(WebKeys.ASSOCIATE_KEY) == null) {
624             servletContext.setAttribute(
625                 WebKeys.ASSOCIATE_KEY, applicationAssociate);
626         }
627 
628         // Encrypt request
629 
630         if (ParamUtil.get(request, WebKeys.ENCRYPT, false)) {
631             try {
632                 Company company = CompanyLocalServiceUtil.getCompanyById(
633                     companyId);
634 
635                 request = new EncryptedServletRequest(
636                     request, company.getKeyObj());
637             }
638             catch (Exception e) {
639             }
640         }
641 
642         // Login
643 
644         long userId = PortalUtil.getUserId(request);
645         String remoteUser = request.getRemoteUser();
646 
647         // Is JAAS enabled?
648 
649         if (!PropsValues.PORTAL_JAAS_ENABLE) {
650             String jRemoteUser = (String)session.getAttribute("j_remoteuser");
651 
652             if (jRemoteUser != null) {
653                 remoteUser = jRemoteUser;
654 
655                 session.removeAttribute("j_remoteuser");
656             }
657         }
658 
659         if ((userId > 0) && (remoteUser == null)) {
660             remoteUser = String.valueOf(userId);
661         }
662 
663         // WebSphere will not return the remote user unless you are
664         // authenticated AND accessing a protected path. Other servers will
665         // return the remote user for all threads associated with an
666         // authenticated user. We use ProtectedServletRequest to ensure we get
667         // similar behavior across all servers.
668 
669         request = new ProtectedServletRequest(request, remoteUser);
670 
671         if ((userId > 0) || (remoteUser != null)) {
672 
673             // Set the principal associated with this thread
674 
675             String name = String.valueOf(userId);
676 
677             if (remoteUser != null) {
678                 name = remoteUser;
679             }
680 
681             PrincipalThreadLocal.setName(name);
682         }
683 
684         if ((userId <= 0) && (remoteUser != null)) {
685             try {
686 
687                 // User id
688 
689                 userId = GetterUtil.getLong(remoteUser);
690 
691                 // Pre login events
692 
693                 EventsProcessorUtil.process(
694                     PropsKeys.LOGIN_EVENTS_PRE, PropsValues.LOGIN_EVENTS_PRE,
695                     request, response);
696 
697                 // User
698 
699                 User user = UserLocalServiceUtil.getUserById(userId);
700 
701                 if (PropsValues.USERS_UPDATE_LAST_LOGIN) {
702                     UserLocalServiceUtil.updateLastLogin(
703                         userId, request.getRemoteAddr());
704                 }
705 
706                 // User id
707 
708                 session.setAttribute(WebKeys.USER_ID, new Long(userId));
709 
710                 // User locale
711 
712                 session.setAttribute(Globals.LOCALE_KEY, user.getLocale());
713 
714                 // Post login events
715 
716                 EventsProcessorUtil.process(
717                     PropsKeys.LOGIN_EVENTS_POST, PropsValues.LOGIN_EVENTS_POST,
718                     request, response);
719             }
720             catch (Exception e) {
721                 _log.error(e, e);
722             }
723         }
724 
725         // Pre service events
726 
727         try {
728             EventsProcessorUtil.process(
729                 PropsKeys.SERVLET_SERVICE_EVENTS_PRE,
730                 PropsValues.SERVLET_SERVICE_EVENTS_PRE, request, response);
731         }
732         catch (Exception e) {
733             Throwable cause = e.getCause();
734 
735             if (cause instanceof NoSuchLayoutException) {
736                 sendError(
737                     HttpServletResponse.SC_NOT_FOUND, cause, request, response);
738 
739                 return;
740             }
741             else if (cause instanceof PrincipalException) {
742                 processServicePrePrincipalException(
743                     cause, userId, request, response);
744 
745                 return;
746             }
747 
748             _log.error(e, e);
749 
750             request.setAttribute(PageContext.EXCEPTION, e);
751 
752             StrutsUtil.forward(
753                 PropsValues.SERVLET_SERVICE_EVENTS_PRE_ERROR_PAGE,
754                 servletContext, request, response);
755 
756             return;
757         }
758 
759         if (request.getAttribute(
760                 AbsoluteRedirectsResponse.class.getName()) != null) {
761 
762             return;
763         }
764 
765         if (request.getAttribute(WebKeys.THEME_DISPLAY) == null) {
766             return;
767         }
768 
769         try {
770 
771             // Struts service
772 
773             callParentService(request, response);
774         }
775         finally {
776 
777             // Post service events
778 
779             try {
780                 EventsProcessorUtil.process(
781                     PropsKeys.SERVLET_SERVICE_EVENTS_POST,
782                     PropsValues.SERVLET_SERVICE_EVENTS_POST, request, response);
783             }
784             catch (Exception e) {
785                 _log.error(e, e);
786             }
787 
788             response.addHeader(
789                 _LIFERAY_PORTAL_REQUEST_HEADER, ReleaseInfo.getReleaseInfo());
790 
791             // Clear the company id associated with this thread
792 
793             CompanyThreadLocal.setCompanyId(0);
794 
795             // Clear the principal associated with this thread
796 
797             PrincipalThreadLocal.setName(null);
798         }
799     }
800 
801     public void destroy() {
802         List<Portlet> portlets = PortletLocalServiceUtil.getPortlets();
803 
804         // Scheduler
805 
806         if (_log.isDebugEnabled()) {
807             _log.debug("Scheduler");
808         }
809 
810         try {
811             if (PropsValues.SCHEDULER_ENABLED) {
812                 for (String className : PropsValues.SCHEDULER_CLASSES) {
813                     Scheduler scheduler = (Scheduler)InstancePool.get(
814                         className);
815 
816                     scheduler.unschedule();
817                 }
818 
819                 Iterator<Portlet> itr = portlets.iterator();
820 
821                 while (itr.hasNext()) {
822                     Portlet portlet = itr.next();
823 
824                     String className = portlet.getSchedulerClass();
825 
826                     if (portlet.isActive() && Validator.isNotNull(className)) {
827                         Scheduler scheduler = (Scheduler)InstancePool.get(
828                             className);
829 
830                         scheduler.unschedule();
831                     }
832                 }
833             }
834         }
835         catch (Exception e) {
836             _log.error(e, e);
837         }
838 
839         // Portlets
840 
841         try {
842             Iterator<Portlet> itr = portlets.iterator();
843 
844             while (itr.hasNext()) {
845                 Portlet portlet = itr.next();
846 
847                 PortletInstanceFactory.destroy(portlet);
848             }
849         }
850         catch (Exception e) {
851             _log.error(e, e);
852         }
853 
854         // Companies
855 
856         long[] companyIds = PortalInstances.getCompanyIds();
857 
858         for (int i = 0; i < companyIds.length; i++) {
859             destroyCompany(companyIds[i]);
860         }
861 
862         // Global shutdown events
863 
864         if (_log.isDebugEnabled()) {
865             _log.debug("Process global shutdown events");
866         }
867 
868         try {
869             EventsProcessorUtil.process(
870                 PropsKeys.GLOBAL_SHUTDOWN_EVENTS,
871                 PropsValues.GLOBAL_SHUTDOWN_EVENTS);
872         }
873         catch (Exception e) {
874             _log.error(e, e);
875         }
876 
877         super.destroy();
878     }
879 
880     protected void checkWebSettings(String xml) throws DocumentException {
881         Document doc = SAXReaderUtil.read(xml);
882 
883         Element root = doc.getRootElement();
884 
885         int timeout = PropsValues.SESSION_TIMEOUT;
886 
887         Element sessionConfig = root.element("session-config");
888 
889         if (sessionConfig != null) {
890             String sessionTimeout = sessionConfig.elementText(
891                 "session-timeout");
892 
893             timeout = GetterUtil.getInteger(sessionTimeout, timeout);
894         }
895 
896         PropsUtil.set(PropsKeys.SESSION_TIMEOUT, String.valueOf(timeout));
897 
898         PropsValues.SESSION_TIMEOUT = timeout;
899 
900         I18nServlet.setLanguageIds(root);
901     }
902 
903     protected void destroyCompany(long companyId) {
904         if (_log.isDebugEnabled()) {
905             _log.debug("Process shutdown events");
906         }
907 
908         try {
909             EventsProcessorUtil.process(
910                 PropsKeys.APPLICATION_SHUTDOWN_EVENTS,
911                 PropsValues.APPLICATION_SHUTDOWN_EVENTS,
912                 new String[] {String.valueOf(companyId)});
913         }
914         catch (Exception e) {
915             _log.error(e, e);
916         }
917     }
918 
919     protected synchronized RequestProcessor getRequestProcessor(
920             ModuleConfig moduleConfig)
921         throws ServletException {
922 
923         ServletContext servletContext = getServletContext();
924 
925         String key = Globals.REQUEST_PROCESSOR_KEY + moduleConfig.getPrefix();
926 
927         RequestProcessor processor =
928             (RequestProcessor)servletContext.getAttribute(key);
929 
930         if (processor == null) {
931             ControllerConfig controllerConfig =
932                 moduleConfig.getControllerConfig();
933 
934             String processorClass = controllerConfig.getProcessorClass();
935 
936             ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
937 
938             try {
939                 processor = (RequestProcessor)classLoader.loadClass(
940                     processorClass).newInstance();
941             }
942             catch (Exception e) {
943                 throw new ServletException(e);
944             }
945 
946             processor.init(this, moduleConfig);
947 
948             servletContext.setAttribute(key, processor);
949         }
950 
951         return processor;
952     }
953 
954     protected void initPortletApp(
955             Portlet portlet, ServletContext servletContext)
956         throws PortletException {
957 
958         PortletApp portletApp = portlet.getPortletApp();
959 
960         PortletConfig portletConfig = PortletConfigFactory.create(
961             portlet, servletContext);
962 
963         PortletContext portletContext = portletConfig.getPortletContext();
964 
965         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
966 
967         for (PortletFilter portletFilter : portletFilters) {
968             PortletFilterFactory.create(portletFilter, portletContext);
969         }
970 
971         Set<PortletURLListener> portletURLListeners =
972             portletApp.getPortletURLListeners();
973 
974         for (PortletURLListener portletURLListener : portletURLListeners) {
975             PortletURLListenerFactory.create(portletURLListener);
976         }
977     }
978 
979     protected void processServicePrePrincipalException(
980             Throwable t, long userId, HttpServletRequest request,
981             HttpServletResponse response)
982         throws IOException, ServletException {
983 
984         if (userId > 0) {
985             sendError(
986                 HttpServletResponse.SC_UNAUTHORIZED, t, request, response);
987 
988             return;
989         }
990 
991         String redirect =
992             request.getContextPath() + Portal.PATH_MAIN + "/portal/login";
993 
994         String currentURL = PortalUtil.getCurrentURL(request);
995 
996         redirect = HttpUtil.addParameter(redirect, "redirect", currentURL);
997 
998         long plid = ParamUtil.getLong(request, "p_l_id");
999 
1000        if (plid > 0) {
1001            try {
1002                Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1003
1004                if (layout.isPrivateLayout()) {
1005                    plid = LayoutLocalServiceUtil.getDefaultPlid(
1006                        layout.getGroupId(), false);
1007                }
1008
1009                redirect = HttpUtil.addParameter(redirect, "p_l_id", plid);
1010            }
1011            catch (Exception e) {
1012            }
1013        }
1014
1015        response.sendRedirect(redirect);
1016    }
1017
1018    protected void sendError(
1019            int status, Throwable t, HttpServletRequest request,
1020            HttpServletResponse response)
1021        throws IOException, ServletException {
1022
1023        DynamicServletRequest dynamicRequest = new DynamicServletRequest(
1024            request);
1025
1026        // Reset p_l_id or there will be an infinite loop
1027
1028        dynamicRequest.setParameter("p_l_id", StringPool.BLANK);
1029
1030        PortalUtil.sendError(status, (Exception)t, dynamicRequest, response);
1031    }
1032
1033    private static final String _LIFERAY_PORTAL_REQUEST_HEADER =
1034        "Liferay-Portal";
1035
1036    private static Log _log = LogFactoryUtil.getLog(MainServlet.class);
1037
1038    private Set<String> _lastModifiedPaths;
1039
1040}