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