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