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