1
22
23 package com.liferay.portal.servlet;
24
25 import com.liferay.portal.deploy.hot.PluginPackageHotDeployListener;
26 import com.liferay.portal.events.EventsProcessor;
27 import com.liferay.portal.events.StartupAction;
28 import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
29 import com.liferay.portal.kernel.events.ActionException;
30 import com.liferay.portal.kernel.job.Scheduler;
31 import com.liferay.portal.kernel.plugin.PluginPackage;
32 import com.liferay.portal.kernel.pop.MessageListener;
33 import com.liferay.portal.kernel.servlet.HttpHeaders;
34 import com.liferay.portal.kernel.servlet.PortletSessionTracker;
35 import com.liferay.portal.kernel.servlet.ProtectedServletRequest;
36 import com.liferay.portal.kernel.util.ContentTypes;
37 import com.liferay.portal.kernel.util.GetterUtil;
38 import com.liferay.portal.kernel.util.HttpUtil;
39 import com.liferay.portal.kernel.util.InstancePool;
40 import com.liferay.portal.kernel.util.ParamUtil;
41 import com.liferay.portal.kernel.util.PortalInitableUtil;
42 import com.liferay.portal.kernel.util.ReleaseInfo;
43 import com.liferay.portal.kernel.util.Validator;
44 import com.liferay.portal.lastmodified.LastModifiedAction;
45 import com.liferay.portal.model.Company;
46 import com.liferay.portal.model.Portlet;
47 import com.liferay.portal.model.PortletApp;
48 import com.liferay.portal.model.PortletFilter;
49 import com.liferay.portal.model.PortletURLListener;
50 import com.liferay.portal.model.User;
51 import com.liferay.portal.pop.POPServerUtil;
52 import com.liferay.portal.security.auth.CompanyThreadLocal;
53 import com.liferay.portal.security.auth.PrincipalThreadLocal;
54 import com.liferay.portal.service.CompanyLocalServiceUtil;
55 import com.liferay.portal.service.PortletLocalServiceUtil;
56 import com.liferay.portal.service.UserLocalServiceUtil;
57 import com.liferay.portal.service.impl.LayoutTemplateLocalUtil;
58 import com.liferay.portal.service.impl.ThemeLocalUtil;
59 import com.liferay.portal.struts.PortletRequestProcessor;
60 import com.liferay.portal.struts.StrutsUtil;
61 import com.liferay.portal.util.ContentUtil;
62 import com.liferay.portal.util.DocumentUtil;
63 import com.liferay.portal.util.InitUtil;
64 import com.liferay.portal.util.Portal;
65 import com.liferay.portal.util.PortalInstances;
66 import com.liferay.portal.util.PortalUtil;
67 import com.liferay.portal.util.PropsUtil;
68 import com.liferay.portal.util.PropsValues;
69 import com.liferay.portal.util.ShutdownUtil;
70 import com.liferay.portal.util.WebKeys;
71 import com.liferay.portal.velocity.VelocityContextPool;
72 import com.liferay.portlet.PortletConfigFactory;
73 import com.liferay.portlet.PortletFilterFactory;
74 import com.liferay.portlet.PortletInstanceFactory;
75 import com.liferay.portlet.PortletURLListenerFactory;
76 import com.liferay.portlet.social.model.SocialActivityInterpreter;
77 import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
78 import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
79 import com.liferay.util.servlet.EncryptedServletRequest;
80
81 import java.io.IOException;
82
83 import java.util.HashSet;
84 import java.util.Iterator;
85 import java.util.List;
86 import java.util.Set;
87
88 import javax.portlet.PortletConfig;
89 import javax.portlet.PortletContext;
90 import javax.portlet.PortletException;
91
92 import javax.servlet.ServletContext;
93 import javax.servlet.ServletException;
94 import javax.servlet.http.HttpServletRequest;
95 import javax.servlet.http.HttpServletResponse;
96 import javax.servlet.http.HttpSession;
97 import javax.servlet.jsp.PageContext;
98
99 import org.apache.commons.logging.Log;
100 import org.apache.commons.logging.LogFactory;
101 import org.apache.struts.Globals;
102 import org.apache.struts.action.ActionMapping;
103 import org.apache.struts.action.ActionServlet;
104 import org.apache.struts.config.ModuleConfig;
105 import org.apache.struts.tiles.TilesUtilImpl;
106
107 import org.dom4j.Document;
108 import org.dom4j.DocumentException;
109 import org.dom4j.Element;
110
111
119 public class MainServlet extends ActionServlet {
120
121 static {
122 InitUtil.init();
123 }
124
125 public void init() throws ServletException {
126
127
129 if (_log.isDebugEnabled()) {
130 _log.debug("Initialize");
131 }
132
133 super.init();
134
135
137 if (_log.isDebugEnabled()) {
138 _log.debug("Process startup events");
139 }
140
141 try {
142 EventsProcessor.process(
143 new String[] {
144 StartupAction.class.getName()
145 },
146 true);
147 }
148 catch (RuntimeException re) {
149 ShutdownUtil.shutdown(0);
150
151 throw new ServletException(re);
152 }
153 catch (ActionException ae) {
154 _log.error(ae, ae);
155 }
156
157
159 String contextPath = PortalUtil.getPathContext();
160
161 ServletContext ctx = getServletContext();
162
163 VelocityContextPool.put(contextPath, ctx);
164
165
167 if (_log.isDebugEnabled()) {
168 _log.debug("Initialize plugin package");
169 }
170
171 PluginPackage pluginPackage = null;
172
173 try {
174 pluginPackage =
175 PluginPackageHotDeployListener.readPluginPackage(ctx);
176 }
177 catch (Exception e) {
178 _log.error(e, e);
179 }
180
181
183 if (_log.isDebugEnabled()) {
184 _log.debug("Initialize portlets");
185 }
186
187 List<Portlet> portlets = null;
188
189 try {
190 String[] xmls = new String[] {
191 HttpUtil.URLtoString(ctx.getResource(
192 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
193 HttpUtil.URLtoString(ctx.getResource(
194 "/WEB-INF/portlet-ext.xml")),
195 HttpUtil.URLtoString(ctx.getResource(
196 "/WEB-INF/liferay-portlet.xml")),
197 HttpUtil.URLtoString(ctx.getResource(
198 "/WEB-INF/liferay-portlet-ext.xml")),
199 HttpUtil.URLtoString(ctx.getResource("/WEB-INF/web.xml"))
200 };
201
202 PortletLocalServiceUtil.initEAR(xmls, pluginPackage);
203
204 portlets = PortletLocalServiceUtil.getPortlets();
205
206 for (int i = 0; i < portlets.size(); i++) {
207 Portlet portlet = portlets.get(i);
208
209 if (i == 0) {
210 initPortletApp(portlet, ctx);
211 }
212
213 PortletInstanceFactory.create(portlet, ctx);
214 }
215 }
216 catch (Exception e) {
217 _log.error(e, e);
218 }
219
220
222 if (_log.isDebugEnabled()) {
223 _log.debug("Initialize layout templates");
224 }
225
226 try {
227 String[] xmls = new String[] {
228 HttpUtil.URLtoString(ctx.getResource(
229 "/WEB-INF/liferay-layout-templates.xml")),
230 HttpUtil.URLtoString(ctx.getResource(
231 "/WEB-INF/liferay-layout-templates-ext.xml"))
232 };
233
234 LayoutTemplateLocalUtil.init(ctx, xmls, pluginPackage);
235 }
236 catch (Exception e) {
237 _log.error(e, e);
238 }
239
240
242 if (_log.isDebugEnabled()) {
243 _log.debug("Initialize look and feel");
244 }
245
246 try {
247 String[] xmls = new String[] {
248 HttpUtil.URLtoString(ctx.getResource(
249 "/WEB-INF/liferay-look-and-feel.xml")),
250 HttpUtil.URLtoString(ctx.getResource(
251 "/WEB-INF/liferay-look-and-feel-ext.xml"))
252 };
253
254 ThemeLocalUtil.init(ctx, null, true, xmls, pluginPackage);
255 }
256 catch (Exception e) {
257 _log.error(e, e);
258 }
259
260
262 if (_log.isDebugEnabled()) {
263 _log.debug("Scheduler");
264 }
265
266 try {
267 if (GetterUtil.getBoolean(PropsUtil.get(
268 PropsUtil.SCHEDULER_ENABLED))) {
269
270 Iterator<Portlet> itr = portlets.iterator();
271
272 while (itr.hasNext()) {
273 Portlet portlet = itr.next();
274
275 String className = portlet.getSchedulerClass();
276
277 if (portlet.isActive() && Validator.isNotNull(className)) {
278 Scheduler scheduler = (Scheduler)InstancePool.get(
279 className);
280
281 scheduler.schedule();
282 }
283 }
284 }
285 }
286 catch (Exception e) {
287 _log.error(e, e);
288 }
289
290
292 if (_log.isDebugEnabled()) {
293 _log.debug("POP message listener");
294 }
295
296 try {
297 Iterator<Portlet> itr = portlets.iterator();
298
299 while (itr.hasNext()) {
300 Portlet portlet = itr.next();
301
302 MessageListener popMessageListener =
303 portlet.getPopMessageListenerInstance();
304
305 if (portlet.isActive() && (popMessageListener != null)) {
306 POPServerUtil.addListener(popMessageListener);
307 }
308 }
309 }
310 catch (Exception e) {
311 _log.error(e, e);
312 }
313
314
316 if (_log.isDebugEnabled()) {
317 _log.debug("Social activity interpreter");
318 }
319
320 try {
321 Iterator<Portlet> itr = portlets.iterator();
322
323 while (itr.hasNext()) {
324 Portlet portlet = itr.next();
325
326 SocialActivityInterpreter socialActivityInterpreter =
327 portlet.getSocialActivityInterpreterInstance();
328
329 if (portlet.isActive() && (socialActivityInterpreter != null)) {
330 socialActivityInterpreter =
331 new SocialActivityInterpreterImpl(
332 socialActivityInterpreter);
333
334 SocialActivityInterpreterLocalServiceUtil.
335 addActivityInterpreter(socialActivityInterpreter);
336 }
337 }
338 }
339 catch (Exception e) {
340 _log.error(e, e);
341 }
342
343
345 if (_log.isDebugEnabled()) {
346 _log.debug("Check web settings");
347 }
348
349 try {
350 String xml = HttpUtil.URLtoString(
351 ctx.getResource("/WEB-INF/web.xml"));
352
353 checkWebSettings(xml);
354 }
355 catch (Exception e) {
356 _log.error(e, e);
357 }
358
359
361 if (_log.isDebugEnabled()) {
362 _log.debug("Last modified paths");
363 }
364
365 if (_lastModifiedPaths == null) {
366 _lastModifiedPaths = new HashSet<String>();
367
368 String[] pathsArray = PropsUtil.getArray(
369 PropsUtil.LAST_MODIFIED_PATHS);
370
371 for (int i = 0; i < pathsArray.length; i++) {
372 _lastModifiedPaths.add(pathsArray[i]);
373 }
374 }
375
376
378 if (_log.isDebugEnabled()) {
379 _log.debug("Process global startup events");
380 }
381
382 try {
383 EventsProcessor.process(PropsUtil.getArray(
384 PropsUtil.GLOBAL_STARTUP_EVENTS), true);
385 }
386 catch (Exception e) {
387 _log.error(e, e);
388 }
389
390
392 String[] webIds = PortalInstances.getWebIds();
393
394 for (int i = 0; i < webIds.length; i++) {
395 PortalInstances.initCompany(ctx, webIds[i]);
396 }
397
398
401 PortalInitableUtil.flushInitables();
402 HotDeployUtil.flushEvents();
403 }
404
405 public void callParentService(
406 HttpServletRequest req, HttpServletResponse res)
407 throws IOException, ServletException {
408
409 super.service(req, res);
410 }
411
412 public void service(HttpServletRequest req, HttpServletResponse res)
413 throws IOException, ServletException {
414
415 if (_log.isDebugEnabled()) {
416 _log.debug("Process service request");
417 }
418
419 if (ShutdownUtil.isShutdown()) {
420 res.setContentType(ContentTypes.TEXT_HTML_UTF8);
421
422 String html = ContentUtil.get(
423 "com/liferay/portal/dependencies/shutdown.html");
424
425 res.getOutputStream().print(html);
426
427 return;
428 }
429
430 HttpSession ses = req.getSession();
431
432
434 long companyId = PortalInstances.getCompanyId(req);
435
436
438
440 ServletContext ctx = getServletContext();
441
442 req.setAttribute(WebKeys.CTX, ctx);
443
444
446 ModuleConfig moduleConfig = getModuleConfig(req);
447
448
450 if (PropsValues.LAST_MODIFIED_CHECK) {
451 String path = req.getPathInfo();
452
453 if ((path != null) && _lastModifiedPaths.contains(path)) {
454 ActionMapping mapping =
455 (ActionMapping)moduleConfig.findActionConfig(path);
456
457 LastModifiedAction lastModifiedAction =
458 (LastModifiedAction)InstancePool.get(mapping.getType());
459
460 String lmKey = lastModifiedAction.getLastModifiedKey(req);
461
462 if (lmKey != null) {
463 long ifModifiedSince =
464 req.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
465
466 if (ifModifiedSince <= 0) {
467 lastModifiedAction.setLastModifiedValue(lmKey, lmKey);
468 }
469 else {
470 String lmValue =
471 lastModifiedAction.getLastModifiedValue(lmKey);
472
473 if (lmValue != null) {
474 res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
475
476 return;
477 }
478 else {
479 lastModifiedAction.setLastModifiedValue(
480 lmKey, lmKey);
481 }
482 }
483 }
484 }
485 }
486
487
489 if (ses.getAttribute(WebKeys.PORTLET_SESSION_TRACKER) == null ) {
490 ses.setAttribute(
491 WebKeys.PORTLET_SESSION_TRACKER,
492 PortletSessionTracker.getInstance());
493 }
494
495
497 PortletRequestProcessor portletReqProcessor =
498 (PortletRequestProcessor)ctx.getAttribute(
499 WebKeys.PORTLET_STRUTS_PROCESSOR);
500
501 if (portletReqProcessor == null) {
502 portletReqProcessor =
503 PortletRequestProcessor.getInstance(this, moduleConfig);
504
505 ctx.setAttribute(
506 WebKeys.PORTLET_STRUTS_PROCESSOR, portletReqProcessor);
507 }
508
509
511 if (ctx.getAttribute(TilesUtilImpl.DEFINITIONS_FACTORY) == null) {
512 ctx.setAttribute(
513 TilesUtilImpl.DEFINITIONS_FACTORY,
514 ctx.getAttribute(TilesUtilImpl.DEFINITIONS_FACTORY));
515 }
516
517 Object applicationAssociate = ctx.getAttribute(WebKeys.ASSOCIATE_KEY);
518
519 if (ctx.getAttribute(WebKeys.ASSOCIATE_KEY) == null) {
520 ctx.setAttribute(WebKeys.ASSOCIATE_KEY, applicationAssociate);
521 }
522
523
525 if (ParamUtil.get(req, WebKeys.ENCRYPT, false)) {
526 try {
527 Company company = CompanyLocalServiceUtil.getCompanyById(
528 companyId);
529
530 req = new EncryptedServletRequest(req, company.getKeyObj());
531 }
532 catch (Exception e) {
533 }
534 }
535
536
538 PortalUtil.getCurrentURL(req);
539
540
542 long userId = PortalUtil.getUserId(req);
543 String remoteUser = req.getRemoteUser();
544
545
547 if (!PropsValues.PORTAL_JAAS_ENABLE) {
548 String jRemoteUser = (String)ses.getAttribute("j_remoteuser");
549
550 if (jRemoteUser != null) {
551 remoteUser = jRemoteUser;
552
553 ses.removeAttribute("j_remoteuser");
554 }
555 }
556
557 if ((userId > 0) && (remoteUser == null)) {
558 remoteUser = String.valueOf(userId);
559 }
560
561
567 req = new ProtectedServletRequest(req, remoteUser);
568
569 if ((userId > 0) || (remoteUser != null)) {
570
571
573 String name = String.valueOf(userId);
574
575 if (remoteUser != null) {
576 name = remoteUser;
577 }
578
579 PrincipalThreadLocal.setName(name);
580 }
581
582 if ((userId <= 0) && (remoteUser != null)) {
583 try {
584
585
587 userId = GetterUtil.getLong(remoteUser);
588
589
591 EventsProcessor.process(PropsValues.LOGIN_EVENTS_PRE, req, res);
592
593
595 User user = UserLocalServiceUtil.getUserById(userId);
596
597 UserLocalServiceUtil.updateLastLogin(
598 userId, req.getRemoteAddr());
599
600
602 ses.setAttribute(WebKeys.USER_ID, new Long(userId));
603
604
606 ses.setAttribute(Globals.LOCALE_KEY, user.getLocale());
607
608
610 EventsProcessor.process(
611 PropsValues.LOGIN_EVENTS_POST, req, res);
612 }
613 catch (Exception e) {
614 _log.error(e, e);
615 }
616 }
617
618
620 try {
621 EventsProcessor.process(
622 PropsValues.SERVLET_SERVICE_EVENTS_PRE, req, res);
623 }
624 catch (Exception e) {
625 _log.error(e, e);
626
627 req.setAttribute(PageContext.EXCEPTION, e);
628
629 StrutsUtil.forward(
630 PropsValues.SERVLET_SERVICE_EVENTS_PRE_ERROR_PAGE, ctx, req,
631 res);
632 }
633
634 try {
635
636
638 callParentService(req, res);
639 }
640 finally {
641
642
644 try {
645 EventsProcessor.process(
646 PropsValues.SERVLET_SERVICE_EVENTS_POST, req, res);
647 }
648 catch (Exception e) {
649 _log.error(e, e);
650 }
651
652 res.addHeader(
653 _LIFERAY_PORTAL_REQUEST_HEADER, ReleaseInfo.getReleaseInfo());
654
655
657 CompanyThreadLocal.setCompanyId(0);
658
659
661 PrincipalThreadLocal.setName(null);
662 }
663 }
664
665 public void destroy() {
666 try {
667 Iterator<Portlet> itr =
668 PortletLocalServiceUtil.getPortlets().iterator();
669
670 while (itr.hasNext()) {
671 Portlet portlet = itr.next();
672
673 PortletInstanceFactory.destroy(portlet);
674 }
675 }
676 catch (Exception e) {
677 _log.error(e, e);
678 }
679
680 long[] companyIds = PortalInstances.getCompanyIds();
681
682 for (int i = 0; i < companyIds.length; i++) {
683 destroyCompany(companyIds[i]);
684 }
685
686 try {
687 EventsProcessor.process(PropsUtil.getArray(
688 PropsUtil.GLOBAL_SHUTDOWN_EVENTS), true);
689 }
690 catch (Exception e) {
691 _log.error(e, e);
692 }
693
694 super.destroy();
695 }
696
697 protected void checkWebSettings(String xml) throws DocumentException {
698 Document doc = DocumentUtil.readDocumentFromXML(xml);
699
700 Element root = doc.getRootElement();
701
702 int timeout = PropsValues.SESSION_TIMEOUT;
703
704 Element sessionConfig = root.element("session-config");
705
706 if (sessionConfig != null) {
707 String sessionTimeout =
708 sessionConfig.elementText("session-timeout");
709
710 timeout = GetterUtil.getInteger(sessionTimeout, timeout);
711 }
712
713 PropsUtil.set(PropsUtil.SESSION_TIMEOUT, String.valueOf(timeout));
714
715 PropsValues.SESSION_TIMEOUT = timeout;
716 }
717
718 protected void destroyCompany(long companyId) {
719 if (_log.isDebugEnabled()) {
720 _log.debug("Process shutdown events");
721 }
722
723 try {
724 EventsProcessor.process(PropsUtil.getArray(
725 PropsUtil.APPLICATION_SHUTDOWN_EVENTS),
726 new String[] {String.valueOf(companyId)});
727 }
728 catch (Exception e) {
729 _log.error(e, e);
730 }
731 }
732
733 protected void initPortletApp(Portlet portlet, ServletContext ctx)
734 throws PortletException {
735
736 PortletApp portletApp = portlet.getPortletApp();
737
738 PortletConfig portletConfig = PortletConfigFactory.create(
739 portlet, ctx);
740
741 PortletContext portletCtx = portletConfig.getPortletContext();
742
743 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
744
745 for (PortletFilter portletFilter : portletFilters) {
746 PortletFilterFactory.create(portletFilter, portletCtx);
747 }
748
749 Set<PortletURLListener> portletURLListeners =
750 portletApp.getPortletURLListeners();
751
752 for (PortletURLListener portletURLListener : portletURLListeners) {
753 PortletURLListenerFactory.create(portletURLListener);
754 }
755 }
756
757 private static final String _LIFERAY_PORTAL_REQUEST_HEADER =
758 "Liferay-Portal";
759
760 private static Log _log = LogFactory.getLog(MainServlet.class);
761
762 private Set<String> _lastModifiedPaths;
763
764 }