View Javadoc

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 }