1   /**
2    * Copyright (c) 2000-2008 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.EventsProcessor;
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.plugin.PluginPackage;
33  import com.liferay.portal.kernel.pop.MessageListener;
34  import com.liferay.portal.kernel.servlet.HttpHeaders;
35  import com.liferay.portal.kernel.servlet.PortletSessionTracker;
36  import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
37  import com.liferay.portal.kernel.util.ContentTypes;
38  import com.liferay.portal.kernel.util.GetterUtil;
39  import com.liferay.portal.kernel.util.HttpUtil;
40  import com.liferay.portal.kernel.util.InstancePool;
41  import com.liferay.portal.kernel.util.ParamUtil;
42  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
43  import com.liferay.portal.kernel.util.PortalInitableUtil;
44  import com.liferay.portal.kernel.util.ReleaseInfo;
45  import com.liferay.portal.kernel.util.StringPool;
46  import com.liferay.portal.kernel.util.Validator;
47  import com.liferay.portal.kernel.xml.Document;
48  import com.liferay.portal.kernel.xml.DocumentException;
49  import com.liferay.portal.kernel.xml.Element;
50  import com.liferay.portal.kernel.xml.SAXReaderUtil;
51  import com.liferay.portal.lastmodified.LastModifiedAction;
52  import com.liferay.portal.model.Company;
53  import com.liferay.portal.model.Portlet;
54  import com.liferay.portal.model.PortletApp;
55  import com.liferay.portal.model.PortletFilter;
56  import com.liferay.portal.model.PortletURLListener;
57  import com.liferay.portal.model.User;
58  import com.liferay.portal.pop.POPServerUtil;
59  import com.liferay.portal.security.auth.CompanyThreadLocal;
60  import com.liferay.portal.security.auth.PrincipalThreadLocal;
61  import com.liferay.portal.service.CompanyLocalServiceUtil;
62  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
63  import com.liferay.portal.service.PortletLocalServiceUtil;
64  import com.liferay.portal.service.ThemeLocalServiceUtil;
65  import com.liferay.portal.service.UserLocalServiceUtil;
66  import com.liferay.portal.struts.PortletRequestProcessor;
67  import com.liferay.portal.struts.StrutsUtil;
68  import com.liferay.portal.util.ContentUtil;
69  import com.liferay.portal.util.Portal;
70  import com.liferay.portal.util.PortalInstances;
71  import com.liferay.portal.util.PortalUtil;
72  import com.liferay.portal.util.PropsKeys;
73  import com.liferay.portal.util.PropsUtil;
74  import com.liferay.portal.util.PropsValues;
75  import com.liferay.portal.util.ShutdownUtil;
76  import com.liferay.portal.util.WebKeys;
77  import com.liferay.portal.velocity.VelocityContextPool;
78  import com.liferay.portlet.PortletConfigFactory;
79  import com.liferay.portlet.PortletFilterFactory;
80  import com.liferay.portlet.PortletInstanceFactory;
81  import com.liferay.portlet.PortletURLListenerFactory;
82  import com.liferay.portlet.social.model.SocialActivityInterpreter;
83  import com.liferay.portlet.social.model.SocialRequestInterpreter;
84  import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
85  import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
86  import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
87  import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
88  import com.liferay.util.servlet.DynamicServletRequest;
89  import com.liferay.util.servlet.EncryptedServletRequest;
90  
91  import java.io.IOException;
92  
93  import java.util.HashSet;
94  import java.util.Iterator;
95  import java.util.List;
96  import java.util.Set;
97  
98  import javax.portlet.PortletConfig;
99  import javax.portlet.PortletContext;
100 import javax.portlet.PortletException;
101 
102 import javax.servlet.ServletContext;
103 import javax.servlet.ServletException;
104 import javax.servlet.http.HttpServletRequest;
105 import javax.servlet.http.HttpServletResponse;
106 import javax.servlet.http.HttpSession;
107 import javax.servlet.jsp.PageContext;
108 
109 import org.apache.commons.logging.Log;
110 import org.apache.commons.logging.LogFactory;
111 import org.apache.struts.Globals;
112 import org.apache.struts.action.ActionMapping;
113 import org.apache.struts.action.ActionServlet;
114 import org.apache.struts.action.RequestProcessor;
115 import org.apache.struts.config.ControllerConfig;
116 import org.apache.struts.config.ModuleConfig;
117 import org.apache.struts.tiles.TilesUtilImpl;
118 
119 /**
120  * <a href="MainServlet.java.html"><b><i>View Source</i></b></a>
121  *
122  * @author Brian Wing Shun Chan
123  * @author Jorge Ferrer
124  * @author Brian Myunghun Kim
125  *
126  */
127 public class MainServlet extends ActionServlet {
128 
129     public void init() throws ServletException {
130 
131         // Initialize
132 
133         if (_log.isDebugEnabled()) {
134             _log.debug("Initialize");
135         }
136 
137         super.init();
138 
139         // Startup events
140 
141         if (_log.isDebugEnabled()) {
142             _log.debug("Process startup events");
143         }
144 
145         try {
146             StartupAction startupAction = new StartupAction();
147 
148             startupAction.run(null);
149         }
150         catch (RuntimeException re) {
151             ShutdownUtil.shutdown(0);
152 
153             throw new ServletException(re);
154         }
155         catch (ActionException ae) {
156             _log.error(ae, ae);
157         }
158 
159         // Velocity
160 
161         String contextPath = PortalUtil.getPathContext();
162 
163         ServletContext servletContext = getServletContext();
164 
165         VelocityContextPool.put(contextPath, servletContext);
166 
167         // Plugin package
168 
169         if (_log.isDebugEnabled()) {
170             _log.debug("Initialize plugin package");
171         }
172 
173         PluginPackage pluginPackage = null;
174 
175         try {
176             pluginPackage =
177                 PluginPackageHotDeployListener.readPluginPackage(
178                     servletContext);
179         }
180         catch (Exception e) {
181             _log.error(e, e);
182         }
183 
184         // Portlets
185 
186         if (_log.isDebugEnabled()) {
187             _log.debug("Initialize portlets");
188         }
189 
190         List<Portlet> portlets = null;
191 
192         try {
193             String[] xmls = new String[] {
194                 HttpUtil.URLtoString(servletContext.getResource(
195                     "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
196                 HttpUtil.URLtoString(servletContext.getResource(
197                     "/WEB-INF/portlet-ext.xml")),
198                 HttpUtil.URLtoString(servletContext.getResource(
199                     "/WEB-INF/liferay-portlet.xml")),
200                 HttpUtil.URLtoString(servletContext.getResource(
201                     "/WEB-INF/liferay-portlet-ext.xml")),
202                 HttpUtil.URLtoString(servletContext.getResource(
203                     "/WEB-INF/web.xml"))
204             };
205 
206             PortletLocalServiceUtil.initEAR(xmls, pluginPackage);
207 
208             portlets = PortletLocalServiceUtil.getPortlets();
209 
210             for (int i = 0; i < portlets.size(); i++) {
211                 Portlet portlet = portlets.get(i);
212 
213                 if (i == 0) {
214                     initPortletApp(portlet, servletContext);
215                 }
216 
217                 PortletInstanceFactory.create(portlet, servletContext);
218             }
219         }
220         catch (Exception e) {
221             _log.error(e, e);
222         }
223 
224         // Layout templates
225 
226         if (_log.isDebugEnabled()) {
227             _log.debug("Initialize layout templates");
228         }
229 
230         try {
231             String[] xmls = new String[] {
232                 HttpUtil.URLtoString(servletContext.getResource(
233                     "/WEB-INF/liferay-layout-templates.xml")),
234                 HttpUtil.URLtoString(servletContext.getResource(
235                     "/WEB-INF/liferay-layout-templates-ext.xml"))
236             };
237 
238             LayoutTemplateLocalServiceUtil.init(
239                 servletContext, xmls, pluginPackage);
240         }
241         catch (Exception e) {
242             _log.error(e, e);
243         }
244 
245         // Look and feel
246 
247         if (_log.isDebugEnabled()) {
248             _log.debug("Initialize look and feel");
249         }
250 
251         try {
252             String[] xmls = new String[] {
253                 HttpUtil.URLtoString(servletContext.getResource(
254                     "/WEB-INF/liferay-look-and-feel.xml")),
255                 HttpUtil.URLtoString(servletContext.getResource(
256                     "/WEB-INF/liferay-look-and-feel-ext.xml"))
257             };
258 
259             ThemeLocalServiceUtil.init(
260                 servletContext, null, true, xmls, pluginPackage);
261         }
262         catch (Exception e) {
263             _log.error(e, e);
264         }
265 
266         // Scheduler
267 
268         if (_log.isDebugEnabled()) {
269             _log.debug("Scheduler");
270         }
271 
272         try {
273             if (PropsValues.SCHEDULER_ENABLED) {
274                 for (String className : PropsValues.SCHEDULER_CLASSES) {
275                     Scheduler scheduler = (Scheduler)InstancePool.get(
276                         className);
277 
278                     scheduler.schedule();
279                 }
280 
281                 Iterator<Portlet> itr = portlets.iterator();
282 
283                 while (itr.hasNext()) {
284                     Portlet portlet = itr.next();
285 
286                     String className = portlet.getSchedulerClass();
287 
288                     if (portlet.isActive() && Validator.isNotNull(className)) {
289                         Scheduler scheduler = (Scheduler)InstancePool.get(
290                             className);
291 
292                         scheduler.schedule();
293                     }
294                 }
295             }
296         }
297         catch (Exception e) {
298             _log.error(e, e);
299         }
300 
301         // POP message listener
302 
303         if (_log.isDebugEnabled()) {
304             _log.debug("POP message listener");
305         }
306 
307         try {
308             Iterator<Portlet> itr = portlets.iterator();
309 
310             while (itr.hasNext()) {
311                 Portlet portlet = itr.next();
312 
313                 MessageListener popMessageListener =
314                     portlet.getPopMessageListenerInstance();
315 
316                 if (portlet.isActive() && (popMessageListener != null)) {
317                     POPServerUtil.addListener(popMessageListener);
318                 }
319             }
320         }
321         catch (Exception e) {
322             _log.error(e, e);
323         }
324 
325         // Social activity interpreter
326 
327         if (_log.isDebugEnabled()) {
328             _log.debug("Social activity interpreter");
329         }
330 
331         try {
332             Iterator<Portlet> itr = portlets.iterator();
333 
334             while (itr.hasNext()) {
335                 Portlet portlet = itr.next();
336 
337                 SocialActivityInterpreter socialActivityInterpreter =
338                     portlet.getSocialActivityInterpreterInstance();
339 
340                 if (portlet.isActive() && (socialActivityInterpreter != null)) {
341                     socialActivityInterpreter =
342                         new SocialActivityInterpreterImpl(
343                             portlet.getPortletId(), socialActivityInterpreter);
344 
345                     SocialActivityInterpreterLocalServiceUtil.
346                         addActivityInterpreter(socialActivityInterpreter);
347                 }
348             }
349         }
350         catch (Exception e) {
351             _log.error(e, e);
352         }
353 
354         // Social request interpreter
355 
356         if (_log.isDebugEnabled()) {
357             _log.debug("Social request interpreter");
358         }
359 
360         try {
361             Iterator<Portlet> itr = portlets.iterator();
362 
363             while (itr.hasNext()) {
364                 Portlet portlet = itr.next();
365 
366                 SocialRequestInterpreter socialRequestInterpreter =
367                     portlet.getSocialRequestInterpreterInstance();
368 
369                 if (portlet.isActive() && (socialRequestInterpreter != null)) {
370                     socialRequestInterpreter = new SocialRequestInterpreterImpl(
371                         portlet.getPortletId(), socialRequestInterpreter);
372 
373                     SocialRequestInterpreterLocalServiceUtil.
374                         addRequestInterpreter(socialRequestInterpreter);
375                 }
376             }
377         }
378         catch (Exception e) {
379             _log.error(e, e);
380         }
381 
382         // Check web settings
383 
384         if (_log.isDebugEnabled()) {
385             _log.debug("Check web settings");
386         }
387 
388         try {
389             String xml = HttpUtil.URLtoString(
390                 servletContext.getResource("/WEB-INF/web.xml"));
391 
392             checkWebSettings(xml);
393         }
394         catch (Exception e) {
395             _log.error(e, e);
396         }
397 
398         // Last modified paths
399 
400         if (_log.isDebugEnabled()) {
401             _log.debug("Last modified paths");
402         }
403 
404         if (_lastModifiedPaths == null) {
405             _lastModifiedPaths = new HashSet<String>();
406 
407             for (String lastModifiedPath : PropsValues.LAST_MODIFIED_PATHS) {
408                 _lastModifiedPaths.add(lastModifiedPath);
409             }
410         }
411 
412         // Global startup events
413 
414         if (_log.isDebugEnabled()) {
415             _log.debug("Process global startup events");
416         }
417 
418         try {
419             EventsProcessor.process(
420                 PropsKeys.GLOBAL_STARTUP_EVENTS,
421                 PropsValues.GLOBAL_STARTUP_EVENTS);
422         }
423         catch (Exception e) {
424             _log.error(e, e);
425         }
426 
427         // Companies
428 
429         String[] webIds = PortalInstances.getWebIds();
430 
431         for (int i = 0; i < webIds.length; i++) {
432             PortalInstances.initCompany(servletContext, webIds[i]);
433         }
434 
435         // See LEP-2885. Don't flush hot deploy events until after the portal
436         // has initialized.
437 
438         PortalInitableUtil.flushInitables();
439         HotDeployUtil.flushEvents();
440     }
441 
442     public void callParentService(
443             HttpServletRequest request, HttpServletResponse response)
444         throws IOException, ServletException {
445 
446         super.service(request, response);
447     }
448 
449     public void service(
450             HttpServletRequest request, HttpServletResponse response)
451         throws IOException, ServletException {
452 
453         if (_log.isDebugEnabled()) {
454             _log.debug("Process service request");
455         }
456 
457         if (ShutdownUtil.isShutdown()) {
458             response.setContentType(ContentTypes.TEXT_HTML_UTF8);
459 
460             String html = ContentUtil.get(
461                 "com/liferay/portal/dependencies/shutdown.html");
462 
463             response.getOutputStream().print(html);
464 
465             return;
466         }
467 
468         HttpSession session = request.getSession();
469 
470         // Company id
471 
472         long companyId = PortalInstances.getCompanyId(request);
473 
474         //CompanyThreadLocal.setCompanyId(companyId);
475 
476         // Portal port
477 
478         PortalUtil.setPortalPort(request);
479 
480         // CTX
481 
482         ServletContext servletContext = getServletContext();
483 
484         request.setAttribute(WebKeys.CTX, servletContext);
485 
486         // Struts module config
487 
488         ModuleConfig moduleConfig = getModuleConfig(request);
489 
490         // Last modified check
491 
492         if (PropsValues.LAST_MODIFIED_CHECK) {
493             String path = request.getPathInfo();
494 
495             if ((path != null) && _lastModifiedPaths.contains(path)) {
496                 ActionMapping mapping =
497                     (ActionMapping)moduleConfig.findActionConfig(path);
498 
499                 LastModifiedAction lastModifiedAction =
500                     (LastModifiedAction)InstancePool.get(mapping.getType());
501 
502                 String lmKey = lastModifiedAction.getLastModifiedKey(request);
503 
504                 if (lmKey != null) {
505                     long ifModifiedSince =
506                         request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
507 
508                     if (ifModifiedSince <= 0) {
509                         lastModifiedAction.setLastModifiedValue(lmKey, lmKey);
510                     }
511                     else {
512                         String lmValue =
513                             lastModifiedAction.getLastModifiedValue(lmKey);
514 
515                         if (lmValue != null) {
516                             response.setStatus(
517                                 HttpServletResponse.SC_NOT_MODIFIED);
518 
519                             return;
520                         }
521                         else {
522                             lastModifiedAction.setLastModifiedValue(
523                                 lmKey, lmKey);
524                         }
525                     }
526                 }
527             }
528         }
529 
530         // Portlet session tracker
531 
532         if (session.getAttribute(WebKeys.PORTLET_SESSION_TRACKER) == null ) {
533             session.setAttribute(
534                 WebKeys.PORTLET_SESSION_TRACKER,
535                 PortletSessionTracker.getInstance());
536         }
537 
538         // Portlet Request Processor
539 
540         PortletRequestProcessor portletReqProcessor =
541             (PortletRequestProcessor)servletContext.getAttribute(
542                 WebKeys.PORTLET_STRUTS_PROCESSOR);
543 
544         if (portletReqProcessor == null) {
545             portletReqProcessor =
546                 PortletRequestProcessor.getInstance(this, moduleConfig);
547 
548             servletContext.setAttribute(
549                 WebKeys.PORTLET_STRUTS_PROCESSOR, portletReqProcessor);
550         }
551 
552         // Tiles definitions factory
553 
554         if (servletContext.getAttribute(
555                 TilesUtilImpl.DEFINITIONS_FACTORY) == null) {
556 
557             servletContext.setAttribute(
558                 TilesUtilImpl.DEFINITIONS_FACTORY,
559                 servletContext.getAttribute(TilesUtilImpl.DEFINITIONS_FACTORY));
560         }
561 
562         Object applicationAssociate = servletContext.getAttribute(
563             WebKeys.ASSOCIATE_KEY);
564 
565         if (servletContext.getAttribute(WebKeys.ASSOCIATE_KEY) == null) {
566             servletContext.setAttribute(
567                 WebKeys.ASSOCIATE_KEY, applicationAssociate);
568         }
569 
570         // Encrypt request
571 
572         if (ParamUtil.get(request, WebKeys.ENCRYPT, false)) {
573             try {
574                 Company company = CompanyLocalServiceUtil.getCompanyById(
575                     companyId);
576 
577                 request = new EncryptedServletRequest(
578                     request, company.getKeyObj());
579             }
580             catch (Exception e) {
581             }
582         }
583 
584         // Current URL
585 
586         PortalUtil.getCurrentURL(request);
587 
588         // Login
589 
590         long userId = PortalUtil.getUserId(request);
591         String remoteUser = request.getRemoteUser();
592 
593         // Is JAAS enabled?
594 
595         if (!PropsValues.PORTAL_JAAS_ENABLE) {
596             String jRemoteUser = (String)session.getAttribute("j_remoteuser");
597 
598             if (jRemoteUser != null) {
599                 remoteUser = jRemoteUser;
600 
601                 session.removeAttribute("j_remoteuser");
602             }
603         }
604 
605         if ((userId > 0) && (remoteUser == null)) {
606             remoteUser = String.valueOf(userId);
607         }
608 
609         // WebSphere will not return the remote user unless you are
610         // authenticated AND accessing a protected path. Other servers will
611         // return the remote user for all threads associated with an
612         // authenticated user. We use ProtectedServletRequest to ensure we get
613         // similar behavior across all servers.
614 
615         request = new ProtectedServletRequest(request, remoteUser);
616 
617         if ((userId > 0) || (remoteUser != null)) {
618 
619             // Set the principal associated with this thread
620 
621             String name = String.valueOf(userId);
622 
623             if (remoteUser != null) {
624                 name = remoteUser;
625             }
626 
627             PrincipalThreadLocal.setName(name);
628         }
629 
630         if ((userId <= 0) && (remoteUser != null)) {
631             try {
632 
633                 // User id
634 
635                 userId = GetterUtil.getLong(remoteUser);
636 
637                 // Pre login events
638 
639                 EventsProcessor.process(
640                     PropsKeys.LOGIN_EVENTS_PRE, PropsValues.LOGIN_EVENTS_PRE,
641                     request, response);
642 
643                 // User
644 
645                 User user = UserLocalServiceUtil.getUserById(userId);
646 
647                 if (PropsValues.USERS_UPDATE_LAST_LOGIN) {
648                     UserLocalServiceUtil.updateLastLogin(
649                         userId, request.getRemoteAddr());
650                 }
651 
652                 // User id
653 
654                 session.setAttribute(WebKeys.USER_ID, new Long(userId));
655 
656                 // User locale
657 
658                 session.setAttribute(Globals.LOCALE_KEY, user.getLocale());
659 
660                 // Post login events
661 
662                 EventsProcessor.process(
663                     PropsKeys.LOGIN_EVENTS_POST, PropsValues.LOGIN_EVENTS_POST,
664                     request, response);
665             }
666             catch (Exception e) {
667                 _log.error(e, e);
668             }
669         }
670 
671         // Pre service events
672 
673         try {
674             EventsProcessor.process(
675                 PropsKeys.SERVLET_SERVICE_EVENTS_PRE,
676                 PropsValues.SERVLET_SERVICE_EVENTS_PRE, request, response);
677         }
678         catch (Exception e) {
679             Throwable cause = e.getCause();
680 
681             if (cause instanceof NoSuchLayoutException) {
682                 DynamicServletRequest dynamicRequest =
683                     new DynamicServletRequest(request);
684 
685                 // Reset p_l_id or there will be an infinite loop
686 
687                 dynamicRequest.setParameter("p_l_id", StringPool.BLANK);
688 
689                 PortalUtil.sendError(
690                     HttpServletResponse.SC_NOT_FOUND,
691                     (NoSuchLayoutException)cause, dynamicRequest, response);
692 
693                 return;
694             }
695 
696             _log.error(e, e);
697 
698             request.setAttribute(PageContext.EXCEPTION, e);
699 
700             StrutsUtil.forward(
701                 PropsValues.SERVLET_SERVICE_EVENTS_PRE_ERROR_PAGE,
702                 servletContext, request, response);
703 
704             return;
705         }
706 
707         try {
708 
709             // Struts service
710 
711             callParentService(request, response);
712         }
713         finally {
714 
715             // Post service events
716 
717             try {
718                 EventsProcessor.process(
719                     PropsKeys.SERVLET_SERVICE_EVENTS_POST,
720                     PropsValues.SERVLET_SERVICE_EVENTS_POST, request, response);
721             }
722             catch (Exception e) {
723                 _log.error(e, e);
724             }
725 
726             response.addHeader(
727                 _LIFERAY_PORTAL_REQUEST_HEADER, ReleaseInfo.getReleaseInfo());
728 
729             // Clear the company id associated with this thread
730 
731             CompanyThreadLocal.setCompanyId(0);
732 
733             // Clear the principal associated with this thread
734 
735             PrincipalThreadLocal.setName(null);
736         }
737     }
738 
739     public void destroy() {
740         List<Portlet> portlets = PortletLocalServiceUtil.getPortlets();
741 
742         // Scheduler
743 
744         if (_log.isDebugEnabled()) {
745             _log.debug("Scheduler");
746         }
747 
748         try {
749             if (PropsValues.SCHEDULER_ENABLED) {
750                 for (String className : PropsValues.SCHEDULER_CLASSES) {
751                     Scheduler scheduler = (Scheduler)InstancePool.get(
752                         className);
753 
754                     scheduler.unschedule();
755                 }
756 
757                 Iterator<Portlet> itr = portlets.iterator();
758 
759                 while (itr.hasNext()) {
760                     Portlet portlet = itr.next();
761 
762                     String className = portlet.getSchedulerClass();
763 
764                     if (portlet.isActive() && Validator.isNotNull(className)) {
765                         Scheduler scheduler = (Scheduler)InstancePool.get(
766                             className);
767 
768                         scheduler.unschedule();
769                     }
770                 }
771             }
772         }
773         catch (Exception e) {
774             _log.error(e, e);
775         }
776 
777         // Portlets
778 
779         try {
780             Iterator<Portlet> itr = portlets.iterator();
781 
782             while (itr.hasNext()) {
783                 Portlet portlet = itr.next();
784 
785                 PortletInstanceFactory.destroy(portlet);
786             }
787         }
788         catch (Exception e) {
789             _log.error(e, e);
790         }
791 
792         // Companies
793 
794         long[] companyIds = PortalInstances.getCompanyIds();
795 
796         for (int i = 0; i < companyIds.length; i++) {
797             destroyCompany(companyIds[i]);
798         }
799 
800         // Global shutdown events
801 
802         if (_log.isDebugEnabled()) {
803             _log.debug("Process global shutdown events");
804         }
805 
806         try {
807             EventsProcessor.process(
808                 PropsKeys.GLOBAL_SHUTDOWN_EVENTS,
809                 PropsValues.GLOBAL_SHUTDOWN_EVENTS);
810         }
811         catch (Exception e) {
812             _log.error(e, e);
813         }
814 
815         super.destroy();
816     }
817 
818     protected void checkWebSettings(String xml) throws DocumentException {
819         Document doc = SAXReaderUtil.read(xml);
820 
821         Element root = doc.getRootElement();
822 
823         int timeout = PropsValues.SESSION_TIMEOUT;
824 
825         Element sessionConfig = root.element("session-config");
826 
827         if (sessionConfig != null) {
828             String sessionTimeout = sessionConfig.elementText(
829                 "session-timeout");
830 
831             timeout = GetterUtil.getInteger(sessionTimeout, timeout);
832         }
833 
834         PropsUtil.set(PropsKeys.SESSION_TIMEOUT, String.valueOf(timeout));
835 
836         PropsValues.SESSION_TIMEOUT = timeout;
837 
838         I18nServlet.setLanguageIds(root);
839     }
840 
841     protected void destroyCompany(long companyId) {
842         if (_log.isDebugEnabled()) {
843             _log.debug("Process shutdown events");
844         }
845 
846         try {
847             EventsProcessor.process(
848                 PropsKeys.APPLICATION_SHUTDOWN_EVENTS,
849                 PropsValues.APPLICATION_SHUTDOWN_EVENTS,
850                 new String[] {String.valueOf(companyId)});
851         }
852         catch (Exception e) {
853             _log.error(e, e);
854         }
855     }
856 
857     protected synchronized RequestProcessor getRequestProcessor(
858             ModuleConfig moduleConfig)
859         throws ServletException {
860 
861         ServletContext servletContext = getServletContext();
862 
863         String key = Globals.REQUEST_PROCESSOR_KEY + moduleConfig.getPrefix();
864 
865         RequestProcessor processor =
866             (RequestProcessor)servletContext.getAttribute(key);
867 
868         if (processor == null) {
869             ControllerConfig controllerConfig =
870                 moduleConfig.getControllerConfig();
871 
872             String processorClass = controllerConfig.getProcessorClass();
873 
874             ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
875 
876             try {
877                 processor = (RequestProcessor)classLoader.loadClass(
878                     processorClass).newInstance();
879             }
880             catch (Exception e) {
881                 throw new ServletException(e);
882             }
883 
884             processor.init(this, moduleConfig);
885 
886             servletContext.setAttribute(key, processor);
887         }
888 
889         return processor;
890     }
891 
892     protected void initPortletApp(
893             Portlet portlet, ServletContext servletContext)
894         throws PortletException {
895 
896         PortletApp portletApp = portlet.getPortletApp();
897 
898         PortletConfig portletConfig = PortletConfigFactory.create(
899             portlet, servletContext);
900 
901         PortletContext portletContext = portletConfig.getPortletContext();
902 
903         Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
904 
905         for (PortletFilter portletFilter : portletFilters) {
906             PortletFilterFactory.create(portletFilter, portletContext);
907         }
908 
909         Set<PortletURLListener> portletURLListeners =
910             portletApp.getPortletURLListeners();
911 
912         for (PortletURLListener portletURLListener : portletURLListeners) {
913             PortletURLListenerFactory.create(portletURLListener);
914         }
915     }
916 
917     private static final String _LIFERAY_PORTAL_REQUEST_HEADER =
918         "Liferay-Portal";
919 
920     private static Log _log = LogFactory.getLog(MainServlet.class);
921 
922     private Set<String> _lastModifiedPaths;
923 
924 }