View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.util;
22  
23  import org.apache.hadoop.http.HttpServer;
24  import org.mortbay.jetty.handler.ContextHandlerCollection;
25  import org.mortbay.jetty.servlet.Context;
26  import org.mortbay.jetty.servlet.DefaultServlet;
27  
28  import java.io.IOException;
29  import java.net.URL;
30  import java.util.Map;
31  
32  /**
33   * Create a Jetty embedded server to answer http requests. The primary goal
34   * is to serve up status information for the server.
35   * There are three contexts:
36   *   "/stacks/" -> points to stack trace
37   *   "/static/" -> points to common static files (src/hbase-webapps/static)
38   *   "/" -> the jsp server code from (src/hbase-webapps/<name>)
39   */
40  public class InfoServer extends HttpServer {
41    /**
42     * Create a status server on the given port.
43     * The jsp scripts are taken from src/hbase-webapps/<code>name<code>.
44     * @param name The name of the server
45     * @param bindAddress address to bind to
46     * @param port The port to use on the server
47     * @param findPort whether the server should start at the given port and
48     * increment by 1 until it finds a free port.
49     * @throws IOException e
50     */
51    public InfoServer(String name, String bindAddress, int port, boolean findPort)
52    throws IOException {
53      super(name, bindAddress, port, findPort);
54      webServer.addHandler(new ContextHandlerCollection());
55    }
56  
57    protected void addDefaultApps(ContextHandlerCollection parent, String appDir)
58    throws IOException {
59      super.addDefaultApps(parent, appDir);
60      // Must be same as up in hadoop.
61      final String logsContextPath = "/logs";
62      // Now, put my logs in place of hadoops... disable old one first.
63      Context oldLogsContext = null;
64      for (Map.Entry<Context, Boolean> e : defaultContexts.entrySet()) {
65        if (e.getKey().getContextPath().equals(logsContextPath)) {
66          oldLogsContext = e.getKey();
67          break;
68        }
69      }
70      if (oldLogsContext != null) {
71        this.defaultContexts.put(oldLogsContext, Boolean.FALSE);
72      }
73      // Now do my logs.
74      // set up the context for "/logs/" if "hadoop.log.dir" property is defined.
75      String logDir = System.getProperty("hbase.log.dir");
76      if (logDir != null) {
77        Context logContext = new Context(parent, "/logs");
78        logContext.setResourceBase(logDir);
79        logContext.addServlet(DefaultServlet.class, "/");
80        defaultContexts.put(logContext, true);
81      }
82    }
83  
84    /**
85     * Get the pathname to the <code>path</code> files.
86     * @return the pathname as a URL
87     */
88    @Override
89    protected String getWebAppsPath() throws IOException {
90      // Hack: webapps is not a unique enough element to find in CLASSPATH
91      // We'll more than likely find the hadoop webapps dir.  So, instead
92      // look for the 'master' webapp in the webapps subdir.  That should
93      // get us the hbase context.  Presumption is that place where the
94      // master webapp resides is where we want this InfoServer picking up
95      // web applications.
96      final String master = "master";
97      String p = getWebAppDir(master);
98      // Now strip master + the separator off the end of our context
99      return p.substring(0, p.length() - (master.length() + 1/* The separator*/));
100   }
101 
102   private static String getWebAppsPath(final String path)
103   throws IOException {
104     URL url = InfoServer.class.getClassLoader().getResource(path);
105     if (url == null)
106       throw new IOException("hbase-webapps not found in CLASSPATH: " + path);
107     return url.toString();
108   }
109 
110   /**
111    * Get the path for this web app
112    * @param webappName web app
113    * @return path
114    * @throws IOException e
115    */
116   public static String getWebAppDir(final String webappName)
117   throws IOException {
118     String webappDir;
119     webappDir = getWebAppsPath("hbase-webapps/" + webappName);
120     return webappDir;
121   }
122 }