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