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