1 /**
2 * This file Copyright (c) 2010-2011 Magnolia International
3 * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4 *
5 *
6 * This file is dual-licensed under both the Magnolia
7 * Network Agreement and the GNU General Public License.
8 * You may elect to use one or the other of these licenses.
9 *
10 * This file is distributed in the hope that it will be
11 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14 * Redistribution, except as permitted by whichever of the GPL
15 * or MNA you select, is prohibited.
16 *
17 * 1. For the GPL license (GPL), you can redistribute and/or
18 * modify this file under the terms of the GNU General
19 * Public License, Version 3, as published by the Free Software
20 * Foundation. You should have received a copy of the GNU
21 * General Public License, Version 3 along with this program;
22 * if not, write to the Free Software Foundation, Inc., 51
23 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24 *
25 * 2. For the Magnolia Network Agreement (MNA), this file
26 * and the accompanying materials are made available under the
27 * terms of the MNA which accompanies this distribution, and
28 * is available at http://www.magnolia-cms.com/mna.html
29 *
30 * Any modifications to this file must keep this entire header
31 * intact.
32 *
33 */
34 package info.magnolia.module.blossom.web;
35
36 import java.io.IOException;
37 import javax.servlet.Servlet;
38 import javax.servlet.ServletConfig;
39 import javax.servlet.ServletException;
40 import javax.servlet.ServletRequest;
41 import javax.servlet.ServletResponse;
42 import javax.servlet.http.HttpServlet;
43
44 import info.magnolia.module.ModuleManager;
45 import info.magnolia.module.blossom.support.CustomServletConfig;
46
47 /**
48 * Proxy that postpones initialization of its target servlet while Magnolia is in update/install-mode. The servlet is
49 * initialized when it sees the first request after the update/installation phase is finished. It looks for an init
50 * parameter named 'servletClass' to find the class of the target servlet. Subclasses can override this behaviour. This
51 * is an alternative to running the servlet in the Magnolia filter chain. Any servlets configured in web.xml need to
52 * have a bypass configured on the Magnolia filter chain that matches its servlet mapping.
53 * <p/>
54 * Initialization of the target servlet will happen after all modules have started.
55 *
56 * @since 1.2
57 */
58 public class InstallationAwareServletProxy extends HttpServlet {
59
60 private static final String SERVLET_CLASS_PARAMETER = "servletClass";
61
62 private Servlet targetServlet;
63 private boolean initialized = false;
64 private final Object monitor = new Object();
65
66 @Override
67 public void init(ServletConfig config) throws ServletException {
68 super.init(config);
69 synchronized (monitor) {
70 if (canInitialize()) {
71 targetServlet = initTargetServlet();
72 initialized = true;
73 }
74 }
75 }
76
77 @Override
78 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
79 synchronized (monitor) {
80 if (!initialized) {
81 // Since the InstallFilter blocks all requests until the modules have started up we can safely init
82 // here. In fact this check is probably not necessary.
83 if (canInitialize()) {
84 targetServlet = initTargetServlet();
85 initialized = true;
86 } else {
87 return;
88 }
89 }
90 }
91 targetServlet.service(req, res);
92 }
93
94 @Override
95 public void destroy() {
96 synchronized (monitor) {
97 if (!initialized) {
98 return;
99 }
100 }
101 targetServlet.destroy();
102 }
103
104 protected Servlet initTargetServlet() throws ServletException {
105 ServletConfig config = getServletConfig();
106 Servlet servlet;
107 try {
108 servlet = (Servlet) Class.forName(config.getInitParameter(SERVLET_CLASS_PARAMETER)).newInstance();
109 } catch (ClassNotFoundException e) {
110 throw new ServletException(e);
111 } catch (InstantiationException e) {
112 throw new ServletException(e);
113 } catch (IllegalAccessException e) {
114 throw new ServletException(e);
115 }
116 CustomServletConfig customServletConfig = new CustomServletConfig(config);
117 customServletConfig.removeInitParameter(SERVLET_CLASS_PARAMETER);
118 servlet.init(customServletConfig);
119 return servlet;
120 }
121
122 protected boolean canInitialize() {
123 // This is the same criteria used by MgnlMainFilter when it decides if it should use the update/install -UI.
124 return !ModuleManager.Factory.getInstance().getStatus().needsUpdateOrInstall();
125 }
126 }