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