001    /*
002     * Copyright (c) 2011, Cloudera, Inc. All Rights Reserved.
003     *
004     * Cloudera, Inc. licenses this file to you under the Apache License,
005     * Version 2.0 (the "License"). You may not use this file except in
006     * compliance with the License. You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
011     * CONDITIONS OF ANY KIND, either express or implied. See the License for
012     * the specific language governing permissions and limitations under the
013     * License.
014     */
015    package com.cloudera.lib.servlet;
016    
017    import com.cloudera.lib.server.Server;
018    import com.cloudera.lib.server.ServerException;
019    import com.cloudera.lib.util.XConfiguration;
020    
021    import javax.servlet.ServletContextEvent;
022    import javax.servlet.ServletContextListener;
023    import java.text.MessageFormat;
024    
025    /**
026     * {@link Server} subclass that implements <code>ServletContextListener</code>
027     * and uses its lifecycle to start and stop the server.
028     *
029     */
030    public abstract class ServerWebApp extends Server implements ServletContextListener {
031    
032      private static final String HOME_DIR = ".home.dir";
033      private static final String CONFIG_DIR = ".config.dir";
034      private static final String LOG_DIR = ".log.dir";
035      private static final String TEMP_DIR = ".temp.dir";
036    
037      private static ThreadLocal<String> HOME_DIR_TL = new ThreadLocal<String>();
038    
039      /**
040       * Method for testing purposes.
041       */
042      public static void setHomeDirForCurrentThread(String homeDir) {
043        HOME_DIR_TL.set(homeDir);
044      }
045    
046      /**
047       * Constructor for testing purposes.
048       */
049      protected ServerWebApp(String name, String homeDir, String configDir, String logDir, String tempDir,
050                             XConfiguration config) {
051        super(name, homeDir, configDir, logDir, tempDir, config);
052      }
053    
054      /**
055       * Constructor for testing purposes.
056       */
057      protected ServerWebApp(String name, String homeDir, XConfiguration config) {
058        super(name, homeDir, config);
059      }
060    
061      /**
062       * Constructor. Subclasses must have a default constructor specifying
063       * the server name.
064       * <p/>
065       * The server name is used to resolve the Java System properties that define
066       * the server home, config, log and temp directories.
067       * <p/>
068       * The home directory is looked in the Java System property
069       * <code>#SERVER_NAME#.home.dir</code>.
070       * <p/>
071       * The config directory is looked in the Java System property
072       * <code>#SERVER_NAME#.config.dir</code>, if not defined it resolves to
073       * the <code>#SERVER_HOME_DIR#/conf</code> directory.
074       * <p/>
075       * The log directory is looked in the Java System property
076       * <code>#SERVER_NAME#.log.dir</code>, if not defined it resolves to
077       * the <code>#SERVER_HOME_DIR#/log</code> directory.
078       * <p/>
079       * The temp directory is looked in the Java System property
080       * <code>#SERVER_NAME#.temp.dir</code>, if not defined it resolves to
081       * the <code>#SERVER_HOME_DIR#/temp</code> directory.
082       *
083       * @param name server name.
084       */
085      public ServerWebApp(String name) {
086        super(name, getHomeDir(name),
087              getDir(name, CONFIG_DIR, getHomeDir(name) + "/conf"),
088              getDir(name, LOG_DIR, getHomeDir(name) + "/log"),
089              getDir(name, TEMP_DIR, getHomeDir(name) + "/temp"), null);
090      }
091    
092      /**
093       * Returns the server home directory.
094       * <p/>
095       * It is looked up in the Java System property
096       * <code>#SERVER_NAME#.home.dir</code>.
097       *
098       * @param name the server home directory.
099       * @return the server home directory.
100       */
101      static String getHomeDir(String name) {
102        String homeDir = HOME_DIR_TL.get();
103        if (homeDir == null) {
104          String sysProp = name + HOME_DIR;
105          homeDir = System.getProperty(sysProp);
106          if (homeDir == null) {
107            throw new IllegalArgumentException(MessageFormat.format("System property [{0}] not defined", sysProp));
108          }
109        }
110        return homeDir;
111      }
112    
113      /**
114       * Convenience method that looks for Java System property defining a
115       * diretory and if not present defaults to the specified directory.
116       *
117       * @param name server name, used as prefix of the Java System property.
118       * @param dirType dir type, use as postfix of the Java System property.
119       * @param defaultDir the default directory to return if the Java System
120       * property <code>name + dirType</code> is not defined.
121       * @return the directory defined in the Java System property or the
122       * the default directory if the Java System property is not defined.
123       */
124      static String getDir(String name, String dirType, String defaultDir) {
125        String sysProp = name + dirType;
126        return System.getProperty(sysProp, defaultDir);
127      }
128    
129      /**
130       * Initializes the <code>ServletContextListener</code> which initializes
131       * the Server.
132       *
133       * @param event servelt context event.
134       */
135      public void contextInitialized(ServletContextEvent event) {
136        try {
137          init();
138        }
139        catch (ServerException ex) {
140          event.getServletContext().log("ERROR: " + ex.getMessage());
141          throw new RuntimeException(ex);
142        }
143      }
144    
145      /**
146       * Destroys the <code>ServletContextListener</code> which destroys
147       * the Server.
148       *
149       * @param event servelt context event.
150       */
151      public void contextDestroyed(ServletContextEvent event) {
152        destroy();
153      }
154    
155    }