http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java deleted file mode 100644 index 726595b..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java +++ /dev/null @@ -1,1380 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.http; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.PrintStream; -import java.net.BindException; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.HadoopIllegalArgumentException; -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.yetus.audience.InterfaceStability; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CommonConfigurationKeys; -import org.apache.hadoop.hbase.HBaseInterfaceAudience; -import org.apache.hadoop.hbase.http.conf.ConfServlet; -import org.apache.hadoop.hbase.http.jmx.JMXJsonServlet; -import org.apache.hadoop.hbase.http.log.LogLevel; -import org.apache.hadoop.hbase.util.Threads; -import org.apache.hadoop.hbase.util.ReflectionUtils; -import org.apache.hadoop.security.SecurityUtil; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.authentication.server.AuthenticationFilter; -import org.apache.hadoop.security.authorize.AccessControlList; -import org.apache.hadoop.util.Shell; - -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SecureRequestCustomizer; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.HandlerCollection; -import org.eclipse.jetty.server.RequestLog; -import org.eclipse.jetty.server.handler.RequestLogHandler; -import org.eclipse.jetty.servlet.FilterMapping; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.MultiException; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.webapp.WebAppContext; - -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; - -import org.apache.hadoop.hbase.shaded.com.google.common.base.Preconditions; -import org.apache.hadoop.hbase.shaded.com.google.common.collect.Lists; - -/** - * Create a Jetty embedded server to answer http requests. The primary goal - * is to serve up status information for the server. - * There are three contexts: - * "/logs/" -> points to the log directory - * "/static/" -> points to common static files (src/webapps/static) - * "/" -> the jsp server code from (src/webapps/<name>) - */ [email protected] [email protected] -public class HttpServer implements FilterContainer { - private static final Log LOG = LogFactory.getLog(HttpServer.class); - private static final String EMPTY_STRING = ""; - - private static final int DEFAULT_MAX_HEADER_SIZE = 64 * 1024; // 64K - - static final String FILTER_INITIALIZERS_PROPERTY - = "hbase.http.filter.initializers"; - static final String HTTP_MAX_THREADS = "hbase.http.max.threads"; - - public static final String HTTP_UI_AUTHENTICATION = "hbase.security.authentication.ui"; - static final String HTTP_AUTHENTICATION_PREFIX = "hbase.security.authentication."; - static final String HTTP_SPNEGO_AUTHENTICATION_PREFIX = HTTP_AUTHENTICATION_PREFIX - + "spnego."; - static final String HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_SUFFIX = "kerberos.principal"; - public static final String HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_KEY = - HTTP_SPNEGO_AUTHENTICATION_PREFIX + HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_SUFFIX; - static final String HTTP_SPNEGO_AUTHENTICATION_KEYTAB_SUFFIX = "kerberos.keytab"; - public static final String HTTP_SPNEGO_AUTHENTICATION_KEYTAB_KEY = - HTTP_SPNEGO_AUTHENTICATION_PREFIX + HTTP_SPNEGO_AUTHENTICATION_KEYTAB_SUFFIX; - static final String HTTP_SPNEGO_AUTHENTICATION_KRB_NAME_SUFFIX = "kerberos.name.rules"; - public static final String HTTP_SPNEGO_AUTHENTICATION_KRB_NAME_KEY = - HTTP_SPNEGO_AUTHENTICATION_PREFIX + HTTP_SPNEGO_AUTHENTICATION_KRB_NAME_SUFFIX; - static final String HTTP_AUTHENTICATION_SIGNATURE_SECRET_FILE_SUFFIX = - "signature.secret.file"; - public static final String HTTP_AUTHENTICATION_SIGNATURE_SECRET_FILE_KEY = - HTTP_AUTHENTICATION_PREFIX + HTTP_AUTHENTICATION_SIGNATURE_SECRET_FILE_SUFFIX; - - // The ServletContext attribute where the daemon Configuration - // gets stored. - public static final String CONF_CONTEXT_ATTRIBUTE = "hbase.conf"; - public static final String ADMINS_ACL = "admins.acl"; - public static final String BIND_ADDRESS = "bind.address"; - public static final String SPNEGO_FILTER = "SpnegoFilter"; - public static final String NO_CACHE_FILTER = "NoCacheFilter"; - public static final String APP_DIR = "webapps"; - - private final AccessControlList adminsAcl; - - protected final Server webServer; - protected String appDir; - protected String logDir; - - private static class ListenerInfo { - /** - * Boolean flag to determine whether the HTTP server should clean up the - * listener in stop(). - */ - private final boolean isManaged; - private final ServerConnector listener; - private ListenerInfo(boolean isManaged, ServerConnector listener) { - this.isManaged = isManaged; - this.listener = listener; - } - } - - private final List<ListenerInfo> listeners = Lists.newArrayList(); - - protected final WebAppContext webAppContext; - protected final boolean findPort; - protected final Map<ServletContextHandler, Boolean> defaultContexts = new HashMap<>(); - protected final List<String> filterNames = new ArrayList<>(); - static final String STATE_DESCRIPTION_ALIVE = " - alive"; - static final String STATE_DESCRIPTION_NOT_LIVE = " - not live"; - - /** - * Class to construct instances of HTTP server with specific options. - */ - public static class Builder { - private ArrayList<URI> endpoints = Lists.newArrayList(); - private Configuration conf; - private String[] pathSpecs; - private AccessControlList adminsAcl; - private boolean securityEnabled = false; - private String usernameConfKey; - private String keytabConfKey; - private boolean needsClientAuth; - - private String hostName; - private String appDir = APP_DIR; - private String logDir; - private boolean findPort; - - private String trustStore; - private String trustStorePassword; - private String trustStoreType; - - private String keyStore; - private String keyStorePassword; - private String keyStoreType; - - // The -keypass option in keytool - private String keyPassword; - - private String kerberosNameRulesKey; - private String signatureSecretFileKey; - - @Deprecated - private String name; - @Deprecated - private String bindAddress; - @Deprecated - private int port = -1; - - /** - * Add an endpoint that the HTTP server should listen to. - * - * @param endpoint - * the endpoint of that the HTTP server should listen to. The - * scheme specifies the protocol (i.e. HTTP / HTTPS), the host - * specifies the binding address, and the port specifies the - * listening port. Unspecified or zero port means that the server - * can listen to any port. - */ - public Builder addEndpoint(URI endpoint) { - endpoints.add(endpoint); - return this; - } - - /** - * Set the hostname of the http server. The host name is used to resolve the - * _HOST field in Kerberos principals. The hostname of the first listener - * will be used if the name is unspecified. - */ - public Builder hostName(String hostName) { - this.hostName = hostName; - return this; - } - - public Builder trustStore(String location, String password, String type) { - this.trustStore = location; - this.trustStorePassword = password; - this.trustStoreType = type; - return this; - } - - public Builder keyStore(String location, String password, String type) { - this.keyStore = location; - this.keyStorePassword = password; - this.keyStoreType = type; - return this; - } - - public Builder keyPassword(String password) { - this.keyPassword = password; - return this; - } - - /** - * Specify whether the server should authorize the client in SSL - * connections. - */ - public Builder needsClientAuth(boolean value) { - this.needsClientAuth = value; - return this; - } - - /** - * Use setAppDir() instead. - */ - @Deprecated - public Builder setName(String name){ - this.name = name; - return this; - } - - /** - * Use addEndpoint() instead. - */ - @Deprecated - public Builder setBindAddress(String bindAddress){ - this.bindAddress = bindAddress; - return this; - } - - /** - * Use addEndpoint() instead. - */ - @Deprecated - public Builder setPort(int port) { - this.port = port; - return this; - } - - public Builder setFindPort(boolean findPort) { - this.findPort = findPort; - return this; - } - - public Builder setConf(Configuration conf) { - this.conf = conf; - return this; - } - - public Builder setPathSpec(String[] pathSpec) { - this.pathSpecs = pathSpec; - return this; - } - - public Builder setACL(AccessControlList acl) { - this.adminsAcl = acl; - return this; - } - - public Builder setSecurityEnabled(boolean securityEnabled) { - this.securityEnabled = securityEnabled; - return this; - } - - public Builder setUsernameConfKey(String usernameConfKey) { - this.usernameConfKey = usernameConfKey; - return this; - } - - public Builder setKeytabConfKey(String keytabConfKey) { - this.keytabConfKey = keytabConfKey; - return this; - } - - public Builder setKerberosNameRulesKey(String kerberosNameRulesKey) { - this.kerberosNameRulesKey = kerberosNameRulesKey; - return this; - } - - public Builder setSignatureSecretFileKey(String signatureSecretFileKey) { - this.signatureSecretFileKey = signatureSecretFileKey; - return this; - } - - public Builder setAppDir(String appDir) { - this.appDir = appDir; - return this; - } - - public Builder setLogDir(String logDir) { - this.logDir = logDir; - return this; - } - - public HttpServer build() throws IOException { - - // Do we still need to assert this non null name if it is deprecated? - if (this.name == null) { - throw new HadoopIllegalArgumentException("name is not set"); - } - - // Make the behavior compatible with deprecated interfaces - if (bindAddress != null && port != -1) { - try { - endpoints.add(0, new URI("http", "", bindAddress, port, "", "", "")); - } catch (URISyntaxException e) { - throw new HadoopIllegalArgumentException("Invalid endpoint: "+ e); } - } - - if (endpoints.isEmpty()) { - throw new HadoopIllegalArgumentException("No endpoints specified"); - } - - if (hostName == null) { - hostName = endpoints.get(0).getHost(); - } - - if (this.conf == null) { - conf = new Configuration(); - } - - HttpServer server = new HttpServer(this); - - if (this.securityEnabled) { - server.initSpnego(conf, hostName, usernameConfKey, keytabConfKey, kerberosNameRulesKey, - signatureSecretFileKey); - } - - for (URI ep : endpoints) { - ServerConnector listener = null; - String scheme = ep.getScheme(); - HttpConfiguration httpConfig = new HttpConfiguration(); - httpConfig.setSecureScheme("https"); - httpConfig.setHeaderCacheSize(DEFAULT_MAX_HEADER_SIZE); - httpConfig.setResponseHeaderSize(DEFAULT_MAX_HEADER_SIZE); - httpConfig.setRequestHeaderSize(DEFAULT_MAX_HEADER_SIZE); - - if ("http".equals(scheme)) { - listener = new ServerConnector(server.webServer, new HttpConnectionFactory(httpConfig)); - } else if ("https".equals(scheme)) { - HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); - httpsConfig.addCustomizer(new SecureRequestCustomizer()); - SslContextFactory sslCtxFactory = new SslContextFactory(); - sslCtxFactory.setNeedClientAuth(needsClientAuth); - sslCtxFactory.setKeyManagerPassword(keyPassword); - - if (keyStore != null) { - sslCtxFactory.setKeyStorePath(keyStore); - sslCtxFactory.setKeyStoreType(keyStoreType); - sslCtxFactory.setKeyStorePassword(keyStorePassword); - } - - if (trustStore != null) { - sslCtxFactory.setTrustStorePath(trustStore); - sslCtxFactory.setTrustStoreType(trustStoreType); - sslCtxFactory.setTrustStorePassword(trustStorePassword); - - } - listener = new ServerConnector(server.webServer, new SslConnectionFactory(sslCtxFactory, - HttpVersion.HTTP_1_1.toString()), new HttpConnectionFactory(httpsConfig)); - } else { - throw new HadoopIllegalArgumentException( - "unknown scheme for endpoint:" + ep); - } - - // default settings for connector - listener.setAcceptQueueSize(128); - if (Shell.WINDOWS) { - // result of setting the SO_REUSEADDR flag is different on Windows - // http://msdn.microsoft.com/en-us/library/ms740621(v=vs.85).aspx - // without this 2 NN's can start on the same machine and listen on - // the same port with indeterminate routing of incoming requests to them - listener.setReuseAddress(false); - } - - listener.setHost(ep.getHost()); - listener.setPort(ep.getPort() == -1 ? 0 : ep.getPort()); - server.addManagedListener(listener); - } - - server.loadListeners(); - return server; - - } - - } - - /** Same as this(name, bindAddress, port, findPort, null); */ - @Deprecated - public HttpServer(String name, String bindAddress, int port, boolean findPort - ) throws IOException { - this(name, bindAddress, port, findPort, new Configuration()); - } - - /** - * Create a status server on the given port. Allows you to specify the - * path specifications that this server will be serving so that they will be - * added to the filters properly. - * - * @param name The name of the server - * @param bindAddress The address for this server - * @param port The port to use on the server - * @param findPort whether the server should start at the given port and - * increment by 1 until it finds a free port. - * @param conf Configuration - * @param pathSpecs Path specifications that this httpserver will be serving. - * These will be added to any filters. - */ - @Deprecated - public HttpServer(String name, String bindAddress, int port, - boolean findPort, Configuration conf, String[] pathSpecs) throws IOException { - this(name, bindAddress, port, findPort, conf, null, pathSpecs); - } - - /** - * Create a status server on the given port. - * The jsp scripts are taken from src/webapps/<name>. - * @param name The name of the server - * @param port The port to use on the server - * @param findPort whether the server should start at the given port and - * increment by 1 until it finds a free port. - * @param conf Configuration - */ - @Deprecated - public HttpServer(String name, String bindAddress, int port, - boolean findPort, Configuration conf) throws IOException { - this(name, bindAddress, port, findPort, conf, null, null); - } - - @Deprecated - public HttpServer(String name, String bindAddress, int port, - boolean findPort, Configuration conf, AccessControlList adminsAcl) - throws IOException { - this(name, bindAddress, port, findPort, conf, adminsAcl, null); - } - - /** - * Create a status server on the given port. - * The jsp scripts are taken from src/webapps/<name>. - * @param name The name of the server - * @param bindAddress The address for this server - * @param port The port to use on the server - * @param findPort whether the server should start at the given port and - * increment by 1 until it finds a free port. - * @param conf Configuration - * @param adminsAcl {@link AccessControlList} of the admins - * @param pathSpecs Path specifications that this httpserver will be serving. - * These will be added to any filters. - */ - @Deprecated - public HttpServer(String name, String bindAddress, int port, - boolean findPort, Configuration conf, AccessControlList adminsAcl, - String[] pathSpecs) throws IOException { - this(new Builder().setName(name) - .addEndpoint(URI.create("http://" + bindAddress + ":" + port)) - .setFindPort(findPort).setConf(conf).setACL(adminsAcl) - .setPathSpec(pathSpecs)); - } - - private HttpServer(final Builder b) throws IOException { - this.appDir = b.appDir; - this.logDir = b.logDir; - final String appDir = getWebAppsPath(b.name); - - - int maxThreads = b.conf.getInt(HTTP_MAX_THREADS, 16); - // If HTTP_MAX_THREADS is less than or equal to 0, QueueThreadPool() will use the - // default value (currently 200). - QueuedThreadPool threadPool = maxThreads <= 0 ? new QueuedThreadPool() - : new QueuedThreadPool(maxThreads); - threadPool.setDaemon(true); - this.webServer = new Server(threadPool); - - this.adminsAcl = b.adminsAcl; - this.webAppContext = createWebAppContext(b.name, b.conf, adminsAcl, appDir); - this.findPort = b.findPort; - initializeWebServer(b.name, b.hostName, b.conf, b.pathSpecs); - } - - private void initializeWebServer(String name, String hostName, - Configuration conf, String[] pathSpecs) - throws FileNotFoundException, IOException { - - Preconditions.checkNotNull(webAppContext); - - HandlerCollection handlerCollection = new HandlerCollection(); - - ContextHandlerCollection contexts = new ContextHandlerCollection(); - RequestLog requestLog = HttpRequestLog.getRequestLog(name); - - if (requestLog != null) { - RequestLogHandler requestLogHandler = new RequestLogHandler(); - requestLogHandler.setRequestLog(requestLog); - handlerCollection.addHandler(requestLogHandler); - } - - final String appDir = getWebAppsPath(name); - - handlerCollection.addHandler(contexts); - handlerCollection.addHandler(webAppContext); - - webServer.setHandler(handlerCollection); - - addDefaultApps(contexts, appDir, conf); - - addGlobalFilter("safety", QuotingInputFilter.class.getName(), null); - Map<String, String> params = new HashMap<>(); - params.put("xframeoptions", conf.get("hbase.http.filter.xframeoptions.mode", "DENY")); - addGlobalFilter("clickjackingprevention", - ClickjackingPreventionFilter.class.getName(), params); - final FilterInitializer[] initializers = getFilterInitializers(conf); - if (initializers != null) { - conf = new Configuration(conf); - conf.set(BIND_ADDRESS, hostName); - for (FilterInitializer c : initializers) { - c.initFilter(this, conf); - } - } - - addDefaultServlets(); - - if (pathSpecs != null) { - for (String path : pathSpecs) { - LOG.info("adding path spec: " + path); - addFilterPathMapping(path, webAppContext); - } - } - } - - private void addManagedListener(ServerConnector connector) { - listeners.add(new ListenerInfo(true, connector)); - } - - private static WebAppContext createWebAppContext(String name, - Configuration conf, AccessControlList adminsAcl, final String appDir) { - WebAppContext ctx = new WebAppContext(); - ctx.setDisplayName(name); - ctx.setContextPath("/"); - ctx.setWar(appDir + "/" + name); - ctx.getServletContext().setAttribute(CONF_CONTEXT_ATTRIBUTE, conf); - ctx.getServletContext().setAttribute(ADMINS_ACL, adminsAcl); - addNoCacheFilter(ctx); - return ctx; - } - - private static void addNoCacheFilter(WebAppContext ctxt) { - defineFilter(ctxt, NO_CACHE_FILTER, NoCacheFilter.class.getName(), - Collections.<String, String> emptyMap(), new String[] { "/*" }); - } - - /** Get an array of FilterConfiguration specified in the conf */ - private static FilterInitializer[] getFilterInitializers(Configuration conf) { - if (conf == null) { - return null; - } - - Class<?>[] classes = conf.getClasses(FILTER_INITIALIZERS_PROPERTY); - if (classes == null) { - return null; - } - - FilterInitializer[] initializers = new FilterInitializer[classes.length]; - for(int i = 0; i < classes.length; i++) { - initializers[i] = (FilterInitializer)ReflectionUtils.newInstance(classes[i]); - } - return initializers; - } - - /** - * Add default apps. - * @param appDir The application directory - * @throws IOException - */ - protected void addDefaultApps(ContextHandlerCollection parent, - final String appDir, Configuration conf) throws IOException { - // set up the context for "/logs/" if "hadoop.log.dir" property is defined. - String logDir = this.logDir; - if (logDir == null) { - logDir = System.getProperty("hadoop.log.dir"); - } - if (logDir != null) { - ServletContextHandler logContext = new ServletContextHandler(parent, "/logs"); - logContext.addServlet(AdminAuthorizedServlet.class, "/*"); - logContext.setResourceBase(logDir); - - if (conf.getBoolean( - ServerConfigurationKeys.HBASE_JETTY_LOGS_SERVE_ALIASES, - ServerConfigurationKeys.DEFAULT_HBASE_JETTY_LOGS_SERVE_ALIASES)) { - Map<String, String> params = logContext.getInitParams(); - params.put( - "org.mortbay.jetty.servlet.Default.aliases", "true"); - } - logContext.setDisplayName("logs"); - setContextAttributes(logContext, conf); - addNoCacheFilter(webAppContext); - defaultContexts.put(logContext, true); - } - // set up the context for "/static/*" - ServletContextHandler staticContext = new ServletContextHandler(parent, "/static"); - staticContext.setResourceBase(appDir + "/static"); - staticContext.addServlet(DefaultServlet.class, "/*"); - staticContext.setDisplayName("static"); - setContextAttributes(staticContext, conf); - defaultContexts.put(staticContext, true); - } - - private void setContextAttributes(ServletContextHandler context, Configuration conf) { - context.getServletContext().setAttribute(CONF_CONTEXT_ATTRIBUTE, conf); - context.getServletContext().setAttribute(ADMINS_ACL, adminsAcl); - } - - /** - * Add default servlets. - */ - protected void addDefaultServlets() { - // set up default servlets - addServlet("stacks", "/stacks", StackServlet.class); - addServlet("logLevel", "/logLevel", LogLevel.Servlet.class); - - // Hadoop3 has moved completely to metrics2, and dropped support for Metrics v1's - // MetricsServlet (see HADOOP-12504). We'll using reflection to load if against hadoop2. - // Remove when we drop support for hbase on hadoop2.x. - try { - Class clz = Class.forName("org.apache.hadoop.metrics.MetricsServlet"); - addServlet("metrics", "/metrics", clz); - } catch (Exception e) { - // do nothing - } - - addServlet("jmx", "/jmx", JMXJsonServlet.class); - addServlet("conf", "/conf", ConfServlet.class); - } - - /** - * Set a value in the webapp context. These values are available to the jsp - * pages as "application.getAttribute(name)". - * @param name The name of the attribute - * @param value The value of the attribute - */ - public void setAttribute(String name, Object value) { - webAppContext.setAttribute(name, value); - } - - /** - * Add a Jersey resource package. - * @param packageName The Java package name containing the Jersey resource. - * @param pathSpec The path spec for the servlet - */ - public void addJerseyResourcePackage(final String packageName, - final String pathSpec) { - LOG.info("addJerseyResourcePackage: packageName=" + packageName - + ", pathSpec=" + pathSpec); - - ResourceConfig application = new ResourceConfig().packages(packageName); - final ServletHolder sh = new ServletHolder(new ServletContainer(application)); - webAppContext.addServlet(sh, pathSpec); - } - - /** - * Add a servlet in the server. - * @param name The name of the servlet (can be passed as null) - * @param pathSpec The path spec for the servlet - * @param clazz The servlet class - */ - public void addServlet(String name, String pathSpec, - Class<? extends HttpServlet> clazz) { - addInternalServlet(name, pathSpec, clazz, false); - addFilterPathMapping(pathSpec, webAppContext); - } - - /** - * Add an internal servlet in the server. - * Note: This method is to be used for adding servlets that facilitate - * internal communication and not for user facing functionality. For - * servlets added using this method, filters are not enabled. - * - * @param name The name of the servlet (can be passed as null) - * @param pathSpec The path spec for the servlet - * @param clazz The servlet class - */ - public void addInternalServlet(String name, String pathSpec, - Class<? extends HttpServlet> clazz) { - addInternalServlet(name, pathSpec, clazz, false); - } - - /** - * Add an internal servlet in the server, specifying whether or not to - * protect with Kerberos authentication. - * Note: This method is to be used for adding servlets that facilitate - * internal communication and not for user facing functionality. For - + * servlets added using this method, filters (except internal Kerberos - * filters) are not enabled. - * - * @param name The name of the servlet (can be passed as null) - * @param pathSpec The path spec for the servlet - * @param clazz The servlet class - * @param requireAuth Require Kerberos authenticate to access servlet - */ - public void addInternalServlet(String name, String pathSpec, - Class<? extends HttpServlet> clazz, boolean requireAuth) { - ServletHolder holder = new ServletHolder(clazz); - if (name != null) { - holder.setName(name); - } - webAppContext.addServlet(holder, pathSpec); - - if(requireAuth && UserGroupInformation.isSecurityEnabled()) { - LOG.info("Adding Kerberos (SPNEGO) filter to " + name); - ServletHandler handler = webAppContext.getServletHandler(); - FilterMapping fmap = new FilterMapping(); - fmap.setPathSpec(pathSpec); - fmap.setFilterName(SPNEGO_FILTER); - fmap.setDispatches(FilterMapping.ALL); - handler.addFilterMapping(fmap); - } - } - - @Override - public void addFilter(String name, String classname, - Map<String, String> parameters) { - - final String[] USER_FACING_URLS = { "*.html", "*.jsp" }; - defineFilter(webAppContext, name, classname, parameters, USER_FACING_URLS); - LOG.info("Added filter " + name + " (class=" + classname - + ") to context " + webAppContext.getDisplayName()); - final String[] ALL_URLS = { "/*" }; - for (Map.Entry<ServletContextHandler, Boolean> e : defaultContexts.entrySet()) { - if (e.getValue()) { - ServletContextHandler handler = e.getKey(); - defineFilter(handler, name, classname, parameters, ALL_URLS); - LOG.info("Added filter " + name + " (class=" + classname - + ") to context " + handler.getDisplayName()); - } - } - filterNames.add(name); - } - - @Override - public void addGlobalFilter(String name, String classname, - Map<String, String> parameters) { - final String[] ALL_URLS = { "/*" }; - defineFilter(webAppContext, name, classname, parameters, ALL_URLS); - for (ServletContextHandler ctx : defaultContexts.keySet()) { - defineFilter(ctx, name, classname, parameters, ALL_URLS); - } - LOG.info("Added global filter '" + name + "' (class=" + classname + ")"); - } - - /** - * Define a filter for a context and set up default url mappings. - */ - public static void defineFilter(ServletContextHandler handler, String name, - String classname, Map<String,String> parameters, String[] urls) { - - FilterHolder holder = new FilterHolder(); - holder.setName(name); - holder.setClassName(classname); - if (parameters != null) { - holder.setInitParameters(parameters); - } - FilterMapping fmap = new FilterMapping(); - fmap.setPathSpecs(urls); - fmap.setDispatches(FilterMapping.ALL); - fmap.setFilterName(name); - handler.getServletHandler().addFilter(holder, fmap); - } - - /** - * Add the path spec to the filter path mapping. - * @param pathSpec The path spec - * @param webAppCtx The WebApplicationContext to add to - */ - protected void addFilterPathMapping(String pathSpec, - WebAppContext webAppCtx) { - for(String name : filterNames) { - FilterMapping fmap = new FilterMapping(); - fmap.setPathSpec(pathSpec); - fmap.setFilterName(name); - fmap.setDispatches(FilterMapping.ALL); - webAppCtx.getServletHandler().addFilterMapping(fmap); - } - } - - /** - * Get the value in the webapp context. - * @param name The name of the attribute - * @return The value of the attribute - */ - public Object getAttribute(String name) { - return webAppContext.getAttribute(name); - } - - public WebAppContext getWebAppContext(){ - return this.webAppContext; - } - - public String getWebAppsPath(String appName) throws FileNotFoundException { - return getWebAppsPath(this.appDir, appName); - } - - /** - * Get the pathname to the webapps files. - * @param appName eg "secondary" or "datanode" - * @return the pathname as a URL - * @throws FileNotFoundException if 'webapps' directory cannot be found on CLASSPATH. - */ - protected String getWebAppsPath(String webapps, String appName) throws FileNotFoundException { - URL url = getClass().getClassLoader().getResource(webapps + "/" + appName); - if (url == null) - throw new FileNotFoundException(webapps + "/" + appName - + " not found in CLASSPATH"); - String urlString = url.toString(); - return urlString.substring(0, urlString.lastIndexOf('/')); - } - - /** - * Get the port that the server is on - * @return the port - */ - @Deprecated - public int getPort() { - return ((ServerConnector)webServer.getConnectors()[0]).getLocalPort(); - } - - /** - * Get the address that corresponds to a particular connector. - * - * @return the corresponding address for the connector, or null if there's no - * such connector or the connector is not bounded. - */ - public InetSocketAddress getConnectorAddress(int index) { - Preconditions.checkArgument(index >= 0); - if (index > webServer.getConnectors().length) - return null; - - ServerConnector c = (ServerConnector)webServer.getConnectors()[index]; - if (c.getLocalPort() == -1 || c.getLocalPort() == -2) { - // -1 if the connector has not been opened - // -2 if it has been closed - return null; - } - - return new InetSocketAddress(c.getHost(), c.getLocalPort()); - } - - /** - * Set the min, max number of worker threads (simultaneous connections). - */ - public void setThreads(int min, int max) { - QueuedThreadPool pool = (QueuedThreadPool) webServer.getThreadPool(); - pool.setMinThreads(min); - pool.setMaxThreads(max); - } - - private void initSpnego(Configuration conf, String hostName, - String usernameConfKey, String keytabConfKey, String kerberosNameRuleKey, - String signatureSecretKeyFileKey) throws IOException { - Map<String, String> params = new HashMap<>(); - String principalInConf = getOrEmptyString(conf, usernameConfKey); - if (!principalInConf.isEmpty()) { - params.put(HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_SUFFIX, SecurityUtil.getServerPrincipal( - principalInConf, hostName)); - } - String httpKeytab = getOrEmptyString(conf, keytabConfKey); - if (!httpKeytab.isEmpty()) { - params.put(HTTP_SPNEGO_AUTHENTICATION_KEYTAB_SUFFIX, httpKeytab); - } - String kerberosNameRule = getOrEmptyString(conf, kerberosNameRuleKey); - if (!kerberosNameRule.isEmpty()) { - params.put(HTTP_SPNEGO_AUTHENTICATION_KRB_NAME_SUFFIX, kerberosNameRule); - } - String signatureSecretKeyFile = getOrEmptyString(conf, signatureSecretKeyFileKey); - if (!signatureSecretKeyFile.isEmpty()) { - params.put(HTTP_AUTHENTICATION_SIGNATURE_SECRET_FILE_SUFFIX, - signatureSecretKeyFile); - } - params.put(AuthenticationFilter.AUTH_TYPE, "kerberos"); - - // Verify that the required options were provided - if (isMissing(params.get(HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_SUFFIX)) || - isMissing(params.get(HTTP_SPNEGO_AUTHENTICATION_KEYTAB_SUFFIX))) { - throw new IllegalArgumentException(usernameConfKey + " and " - + keytabConfKey + " are both required in the configuration " - + "to enable SPNEGO/Kerberos authentication for the Web UI"); - } - - addGlobalFilter(SPNEGO_FILTER, AuthenticationFilter.class.getName(), params); - } - - /** - * Returns true if the argument is non-null and not whitespace - */ - private boolean isMissing(String value) { - if (null == value) { - return true; - } - return value.trim().isEmpty(); - } - - /** - * Extracts the value for the given key from the configuration of returns a string of - * zero length. - */ - private String getOrEmptyString(Configuration conf, String key) { - if (null == key) { - return EMPTY_STRING; - } - final String value = conf.get(key.trim()); - return null == value ? EMPTY_STRING : value; - } - - /** - * Start the server. Does not wait for the server to start. - */ - public void start() throws IOException { - try { - try { - openListeners(); - webServer.start(); - } catch (IOException ex) { - LOG.info("HttpServer.start() threw a non Bind IOException", ex); - throw ex; - } catch (MultiException ex) { - LOG.info("HttpServer.start() threw a MultiException", ex); - throw ex; - } - // Make sure there is no handler failures. - Handler[] handlers = webServer.getHandlers(); - for (int i = 0; i < handlers.length; i++) { - if (handlers[i].isFailed()) { - throw new IOException( - "Problem in starting http server. Server handlers failed"); - } - } - // Make sure there are no errors initializing the context. - Throwable unavailableException = webAppContext.getUnavailableException(); - if (unavailableException != null) { - // Have to stop the webserver, or else its non-daemon threads - // will hang forever. - webServer.stop(); - throw new IOException("Unable to initialize WebAppContext", - unavailableException); - } - } catch (IOException e) { - throw e; - } catch (InterruptedException e) { - throw (IOException) new InterruptedIOException( - "Interrupted while starting HTTP server").initCause(e); - } catch (Exception e) { - throw new IOException("Problem starting http server", e); - } - } - - private void loadListeners() { - for (ListenerInfo li : listeners) { - webServer.addConnector(li.listener); - } - } - - /** - * Open the main listener for the server - * @throws Exception - */ - void openListeners() throws Exception { - for (ListenerInfo li : listeners) { - ServerConnector listener = li.listener; - if (!li.isManaged || (li.listener.getLocalPort() != -1 && li.listener.getLocalPort() != -2)) { - // This listener is either started externally, or has not been opened, or has been closed - continue; - } - int port = listener.getPort(); - while (true) { - // jetty has a bug where you can't reopen a listener that previously - // failed to open w/o issuing a close first, even if the port is changed - try { - listener.close(); - listener.open(); - LOG.info("Jetty bound to port " + listener.getLocalPort()); - break; - } catch (BindException ex) { - if (port == 0 || !findPort) { - BindException be = new BindException("Port in use: " - + listener.getHost() + ":" + listener.getPort()); - be.initCause(ex); - throw be; - } - } - // try the next port number - listener.setPort(++port); - Thread.sleep(100); - } - } - } - - /** - * stop the server - */ - public void stop() throws Exception { - MultiException exception = null; - for (ListenerInfo li : listeners) { - if (!li.isManaged) { - continue; - } - - try { - li.listener.close(); - } catch (Exception e) { - LOG.error( - "Error while stopping listener for webapp" - + webAppContext.getDisplayName(), e); - exception = addMultiException(exception, e); - } - } - - try { - // clear & stop webAppContext attributes to avoid memory leaks. - webAppContext.clearAttributes(); - webAppContext.stop(); - } catch (Exception e) { - LOG.error("Error while stopping web app context for webapp " - + webAppContext.getDisplayName(), e); - exception = addMultiException(exception, e); - } - - try { - webServer.stop(); - } catch (Exception e) { - LOG.error("Error while stopping web server for webapp " - + webAppContext.getDisplayName(), e); - exception = addMultiException(exception, e); - } - - if (exception != null) { - exception.ifExceptionThrow(); - } - - } - - private MultiException addMultiException(MultiException exception, Exception e) { - if(exception == null){ - exception = new MultiException(); - } - exception.add(e); - return exception; - } - - public void join() throws InterruptedException { - webServer.join(); - } - - /** - * Test for the availability of the web server - * @return true if the web server is started, false otherwise - */ - public boolean isAlive() { - return webServer != null && webServer.isStarted(); - } - - /** - * Return the host and port of the HttpServer, if live - * @return the classname and any HTTP URL - */ - @Override - public String toString() { - if (listeners.isEmpty()) { - return "Inactive HttpServer"; - } else { - StringBuilder sb = new StringBuilder("HttpServer (") - .append(isAlive() ? STATE_DESCRIPTION_ALIVE : STATE_DESCRIPTION_NOT_LIVE).append("), listening at:"); - for (ListenerInfo li : listeners) { - ServerConnector l = li.listener; - sb.append(l.getHost()).append(":").append(l.getPort()).append("/,"); - } - return sb.toString(); - } - } - - /** - * Checks the user has privileges to access to instrumentation servlets. - * <p> - * If <code>hadoop.security.instrumentation.requires.admin</code> is set to FALSE - * (default value) it always returns TRUE. - * </p><p> - * If <code>hadoop.security.instrumentation.requires.admin</code> is set to TRUE - * it will check that if the current user is in the admin ACLS. If the user is - * in the admin ACLs it returns TRUE, otherwise it returns FALSE. - * </p> - * - * @param servletContext the servlet context. - * @param request the servlet request. - * @param response the servlet response. - * @return TRUE/FALSE based on the logic decribed above. - */ - public static boolean isInstrumentationAccessAllowed( - ServletContext servletContext, HttpServletRequest request, - HttpServletResponse response) throws IOException { - Configuration conf = - (Configuration) servletContext.getAttribute(CONF_CONTEXT_ATTRIBUTE); - - boolean access = true; - boolean adminAccess = conf.getBoolean( - CommonConfigurationKeys.HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN, - false); - if (adminAccess) { - access = hasAdministratorAccess(servletContext, request, response); - } - return access; - } - - /** - * Does the user sending the HttpServletRequest has the administrator ACLs? If - * it isn't the case, response will be modified to send an error to the user. - * - * @param servletContext - * @param request - * @param response used to send the error response if user does not have admin access. - * @return true if admin-authorized, false otherwise - * @throws IOException - */ - public static boolean hasAdministratorAccess( - ServletContext servletContext, HttpServletRequest request, - HttpServletResponse response) throws IOException { - Configuration conf = - (Configuration) servletContext.getAttribute(CONF_CONTEXT_ATTRIBUTE); - // If there is no authorization, anybody has administrator access. - if (!conf.getBoolean( - CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, false)) { - return true; - } - - String remoteUser = request.getRemoteUser(); - if (remoteUser == null) { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, - "Unauthenticated users are not " + - "authorized to access this page."); - return false; - } - - if (servletContext.getAttribute(ADMINS_ACL) != null && - !userHasAdministratorAccess(servletContext, remoteUser)) { - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "User " - + remoteUser + " is unauthorized to access this page."); - return false; - } - - return true; - } - - /** - * Get the admin ACLs from the given ServletContext and check if the given - * user is in the ACL. - * - * @param servletContext the context containing the admin ACL. - * @param remoteUser the remote user to check for. - * @return true if the user is present in the ACL, false if no ACL is set or - * the user is not present - */ - public static boolean userHasAdministratorAccess(ServletContext servletContext, - String remoteUser) { - AccessControlList adminsAcl = (AccessControlList) servletContext - .getAttribute(ADMINS_ACL); - UserGroupInformation remoteUserUGI = - UserGroupInformation.createRemoteUser(remoteUser); - return adminsAcl != null && adminsAcl.isUserAllowed(remoteUserUGI); - } - - /** - * A very simple servlet to serve up a text representation of the current - * stack traces. It both returns the stacks to the caller and logs them. - * Currently the stack traces are done sequentially rather than exactly the - * same data. - */ - public static class StackServlet extends HttpServlet { - private static final long serialVersionUID = -6284183679759467039L; - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), - request, response)) { - return; - } - response.setContentType("text/plain; charset=UTF-8"); - try (PrintStream out = new PrintStream( - response.getOutputStream(), false, "UTF-8")) { - Threads.printThreadInfo(out, ""); - out.flush(); - } - ReflectionUtils.logThreadInfo(LOG, "jsp requested", 1); - } - } - - /** - * A Servlet input filter that quotes all HTML active characters in the - * parameter names and values. The goal is to quote the characters to make - * all of the servlets resistant to cross-site scripting attacks. - */ - @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) - public static class QuotingInputFilter implements Filter { - private FilterConfig config; - - public static class RequestQuoter extends HttpServletRequestWrapper { - private final HttpServletRequest rawRequest; - public RequestQuoter(HttpServletRequest rawRequest) { - super(rawRequest); - this.rawRequest = rawRequest; - } - - /** - * Return the set of parameter names, quoting each name. - */ - @Override - public Enumeration<String> getParameterNames() { - return new Enumeration<String>() { - private Enumeration<String> rawIterator = - rawRequest.getParameterNames(); - @Override - public boolean hasMoreElements() { - return rawIterator.hasMoreElements(); - } - - @Override - public String nextElement() { - return HtmlQuoting.quoteHtmlChars(rawIterator.nextElement()); - } - }; - } - - /** - * Unquote the name and quote the value. - */ - @Override - public String getParameter(String name) { - return HtmlQuoting.quoteHtmlChars(rawRequest.getParameter - (HtmlQuoting.unquoteHtmlChars(name))); - } - - @Override - public String[] getParameterValues(String name) { - String unquoteName = HtmlQuoting.unquoteHtmlChars(name); - String[] unquoteValue = rawRequest.getParameterValues(unquoteName); - if (unquoteValue == null) { - return null; - } - String[] result = new String[unquoteValue.length]; - for(int i=0; i < result.length; ++i) { - result[i] = HtmlQuoting.quoteHtmlChars(unquoteValue[i]); - } - return result; - } - - @Override - public Map<String, String[]> getParameterMap() { - Map<String, String[]> result = new HashMap<>(); - Map<String, String[]> raw = rawRequest.getParameterMap(); - for (Map.Entry<String,String[]> item: raw.entrySet()) { - String[] rawValue = item.getValue(); - String[] cookedValue = new String[rawValue.length]; - for(int i=0; i< rawValue.length; ++i) { - cookedValue[i] = HtmlQuoting.quoteHtmlChars(rawValue[i]); - } - result.put(HtmlQuoting.quoteHtmlChars(item.getKey()), cookedValue); - } - return result; - } - - /** - * Quote the url so that users specifying the HOST HTTP header - * can't inject attacks. - */ - @Override - public StringBuffer getRequestURL(){ - String url = rawRequest.getRequestURL().toString(); - return new StringBuffer(HtmlQuoting.quoteHtmlChars(url)); - } - - /** - * Quote the server name so that users specifying the HOST HTTP header - * can't inject attacks. - */ - @Override - public String getServerName() { - return HtmlQuoting.quoteHtmlChars(rawRequest.getServerName()); - } - } - - @Override - public void init(FilterConfig config) throws ServletException { - this.config = config; - } - - @Override - public void destroy() { - } - - @Override - public void doFilter(ServletRequest request, - ServletResponse response, - FilterChain chain - ) throws IOException, ServletException { - HttpServletRequestWrapper quoted = - new RequestQuoter((HttpServletRequest) request); - HttpServletResponse httpResponse = (HttpServletResponse) response; - - String mime = inferMimeType(request); - if (mime == null) { - httpResponse.setContentType("text/plain; charset=utf-8"); - } else if (mime.startsWith("text/html")) { - // HTML with unspecified encoding, we want to - // force HTML with utf-8 encoding - // This is to avoid the following security issue: - // http://openmya.hacker.jp/hasegawa/security/utf7cs.html - httpResponse.setContentType("text/html; charset=utf-8"); - } else if (mime.startsWith("application/xml")) { - httpResponse.setContentType("text/xml; charset=utf-8"); - } - chain.doFilter(quoted, httpResponse); - } - - /** - * Infer the mime type for the response based on the extension of the request - * URI. Returns null if unknown. - */ - private String inferMimeType(ServletRequest request) { - String path = ((HttpServletRequest)request).getRequestURI(); - ServletContext context = config.getServletContext(); - return context.getMimeType(path); - } - } -}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java deleted file mode 100644 index b5f4183..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hbase.http; - -import java.io.IOException; -import java.net.URI; - -import javax.servlet.http.HttpServlet; - -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; - -/** - * Create a Jetty embedded server to answer http requests. The primary goal - * is to serve up status information for the server. - * There are three contexts: - * "/stacks/" -> points to stack trace - * "/static/" -> points to common static files (src/hbase-webapps/static) - * "/" -> the jsp server code from (src/hbase-webapps/<name>) - */ [email protected] -public class InfoServer { - - private static final String HBASE_APP_DIR = "hbase-webapps"; - private final org.apache.hadoop.hbase.http.HttpServer httpServer; - - /** - * Create a status server on the given port. - * The jsp scripts are taken from src/hbase-webapps/<code>name</code>. - * @param name The name of the server - * @param bindAddress address to bind to - * @param port The port to use on the server - * @param findPort whether the server should start at the given port and - * increment by 1 until it finds a free port. - * @throws IOException e - */ - public InfoServer(String name, String bindAddress, int port, boolean findPort, - final Configuration c) - throws IOException { - HttpConfig httpConfig = new HttpConfig(c); - HttpServer.Builder builder = - new org.apache.hadoop.hbase.http.HttpServer.Builder(); - - builder.setName(name).addEndpoint(URI.create(httpConfig.getSchemePrefix() + - bindAddress + ":" + - port)).setAppDir(HBASE_APP_DIR).setFindPort(findPort).setConf(c); - String logDir = System.getProperty("hbase.log.dir"); - if (logDir != null) { - builder.setLogDir(logDir); - } - if (httpConfig.isSecure()) { - builder.keyPassword(HBaseConfiguration.getPassword(c, "ssl.server.keystore.keypassword", null)) - .keyStore(c.get("ssl.server.keystore.location"), - HBaseConfiguration.getPassword(c,"ssl.server.keystore.password", null), - c.get("ssl.server.keystore.type", "jks")) - .trustStore(c.get("ssl.server.truststore.location"), - HBaseConfiguration.getPassword(c, "ssl.server.truststore.password", null), - c.get("ssl.server.truststore.type", "jks")); - } - // Enable SPNEGO authentication - if ("kerberos".equalsIgnoreCase(c.get(HttpServer.HTTP_UI_AUTHENTICATION, null))) { - builder.setUsernameConfKey(HttpServer.HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_KEY) - .setKeytabConfKey(HttpServer.HTTP_SPNEGO_AUTHENTICATION_KEYTAB_KEY) - .setKerberosNameRulesKey(HttpServer.HTTP_SPNEGO_AUTHENTICATION_KRB_NAME_KEY) - .setSignatureSecretFileKey( - HttpServer.HTTP_AUTHENTICATION_SIGNATURE_SECRET_FILE_KEY) - .setSecurityEnabled(true); - } - this.httpServer = builder.build(); - } - - public void addServlet(String name, String pathSpec, - Class<? extends HttpServlet> clazz) { - this.httpServer.addServlet(name, pathSpec, clazz); - } - - public void setAttribute(String name, Object value) { - this.httpServer.setAttribute(name, value); - } - - public void start() throws IOException { - this.httpServer.start(); - } - - @Deprecated - public int getPort() { - return this.httpServer.getPort(); - } - - public void stop() throws Exception { - this.httpServer.stop(); - } - -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java deleted file mode 100644 index a1daf15..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.http; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.hadoop.hbase.HBaseInterfaceAudience; - [email protected](HBaseInterfaceAudience.CONFIG) -public class NoCacheFilter implements Filter { - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - public void doFilter(ServletRequest req, ServletResponse res, - FilterChain chain) - throws IOException, ServletException { - HttpServletResponse httpRes = (HttpServletResponse) res; - httpRes.setHeader("Cache-Control", "no-cache"); - long now = System.currentTimeMillis(); - httpRes.addDateHeader("Expires", now); - httpRes.addDateHeader("Date", now); - httpRes.addHeader("Pragma", "no-cache"); - chain.doFilter(req, res); - } - - @Override - public void destroy() { - } - -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ServerConfigurationKeys.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ServerConfigurationKeys.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ServerConfigurationKeys.java deleted file mode 100644 index 4ae4a2f..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ServerConfigurationKeys.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.http; - -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.yetus.audience.InterfaceStability; - -/** - * This interface contains constants for configuration keys used - * in the hbase http server code. - */ [email protected] [email protected] -public interface ServerConfigurationKeys { - - /** Enable/Disable ssl for http server */ - public static final String HBASE_SSL_ENABLED_KEY = "hbase.ssl.enabled"; - - public static final boolean HBASE_SSL_ENABLED_DEFAULT = false; - - /** Enable/Disable aliases serving from jetty */ - public static final String HBASE_JETTY_LOGS_SERVE_ALIASES = - "hbase.jetty.logs.serve.aliases"; - - public static final boolean DEFAULT_HBASE_JETTY_LOGS_SERVE_ALIASES = - true; - - public static final String HBASE_HTTP_STATIC_USER = "hbase.http.staticuser.user"; - - public static final String DEFAULT_HBASE_HTTP_STATIC_USER = "dr.stack"; - -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java deleted file mode 100644 index d9aa7b6..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.http.conf; - -import java.io.IOException; -import java.io.Writer; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.yetus.audience.InterfaceStability; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.http.HttpServer; - -/** - * A servlet to print out the running configuration data. - */ [email protected]({"HBase"}) [email protected] -public class ConfServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - - private static final String FORMAT_JSON = "json"; - private static final String FORMAT_XML = "xml"; - private static final String FORMAT_PARAM = "format"; - - /** - * Return the Configuration of the daemon hosting this servlet. - * This is populated when the HttpServer starts. - */ - private Configuration getConfFromContext() { - Configuration conf = (Configuration)getServletContext().getAttribute( - HttpServer.CONF_CONTEXT_ATTRIBUTE); - assert conf != null; - return conf; - } - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), - request, response)) { - return; - } - - String format = request.getParameter(FORMAT_PARAM); - if (null == format) { - format = FORMAT_XML; - } - - if (FORMAT_XML.equals(format)) { - response.setContentType("text/xml; charset=utf-8"); - } else if (FORMAT_JSON.equals(format)) { - response.setContentType("application/json; charset=utf-8"); - } - - Writer out = response.getWriter(); - try { - writeResponse(getConfFromContext(), out, format); - } catch (BadFormatException bfe) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, bfe.getMessage()); - } - out.close(); - } - - /** - * Guts of the servlet - extracted for easy testing. - */ - static void writeResponse(Configuration conf, Writer out, String format) - throws IOException, BadFormatException { - if (FORMAT_JSON.equals(format)) { - Configuration.dumpConfiguration(conf, out); - } else if (FORMAT_XML.equals(format)) { - conf.writeXml(out); - } else { - throw new BadFormatException("Bad format: " + format); - } - } - - public static class BadFormatException extends Exception { - private static final long serialVersionUID = 1L; - - public BadFormatException(String msg) { - super(msg); - } - } - -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java deleted file mode 100644 index 3abad3a..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.hadoop.hbase.http.jmx; - -import java.io.IOException; -import java.io.PrintWriter; -import java.lang.management.ManagementFactory; - -import javax.management.MBeanServer; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.hbase.http.HttpServer; -import org.apache.hadoop.hbase.util.JSONBean; - -/* - * This servlet is based off of the JMXProxyServlet from Tomcat 7.0.14. It has - * been rewritten to be read only and to output in a JSON format so it is not - * really that close to the original. - */ -/** - * Provides Read only web access to JMX. - * <p> - * This servlet generally will be placed under the /jmx URL for each - * HttpServer. It provides read only - * access to JMX metrics. The optional <code>qry</code> parameter - * may be used to query only a subset of the JMX Beans. This query - * functionality is provided through the - * {@link MBeanServer#queryNames(ObjectName, javax.management.QueryExp)} - * method. - * </p> - * <p> - * For example <code>http://.../jmx?qry=Hadoop:*</code> will return - * all hadoop metrics exposed through JMX. - * </p> - * <p> - * The optional <code>get</code> parameter is used to query an specific - * attribute of a JMX bean. The format of the URL is - * <code>http://.../jmx?get=MXBeanName::AttributeName</code> - * </p> - * <p> - * For example - * <code> - * http://../jmx?get=Hadoop:service=NameNode,name=NameNodeInfo::ClusterId - * </code> will return the cluster id of the namenode mxbean. - * </p> - * <p> - * If the <code>qry</code> or the <code>get</code> parameter is not formatted - * correctly then a 400 BAD REQUEST http response code will be returned. - * </p> - * <p> - * If a resouce such as a mbean or attribute can not be found, - * a 404 SC_NOT_FOUND http response code will be returned. - * </p> - * <p> - * The return format is JSON and in the form - * </p> - * <pre><code> - * { - * "beans" : [ - * { - * "name":"bean-name" - * ... - * } - * ] - * } - * </code></pre> - * <p> - * The servlet attempts to convert the the JMXBeans into JSON. Each - * bean's attributes will be converted to a JSON object member. - * - * If the attribute is a boolean, a number, a string, or an array - * it will be converted to the JSON equivalent. - * - * If the value is a {@link CompositeData} then it will be converted - * to a JSON object with the keys as the name of the JSON member and - * the value is converted following these same rules. - * - * If the value is a {@link TabularData} then it will be converted - * to an array of the {@link CompositeData} elements that it contains. - * - * All other objects will be converted to a string and output as such. - * - * The bean's name and modelerType will be returned for all beans. - * - * Optional paramater "callback" should be used to deliver JSONP response. - * </p> - * - */ -public class JMXJsonServlet extends HttpServlet { - private static final Log LOG = LogFactory.getLog(JMXJsonServlet.class); - - private static final long serialVersionUID = 1L; - - private static final String CALLBACK_PARAM = "callback"; - /** - * If query string includes 'description', then we will emit bean and attribute descriptions to - * output IFF they are not null and IFF the description is not the same as the attribute name: - * i.e. specify an URL like so: /jmx?description=true - */ - private static final String INCLUDE_DESCRIPTION = "description"; - - /** - * MBean server. - */ - protected transient MBeanServer mBeanServer; - - protected transient JSONBean jsonBeanWriter; - - /** - * Initialize this servlet. - */ - @Override - public void init() throws ServletException { - // Retrieve the MBean server - mBeanServer = ManagementFactory.getPlatformMBeanServer(); - this.jsonBeanWriter = new JSONBean(); - } - - /** - * Process a GET request for the specified resource. - * - * @param request - * The servlet request we are processing - * @param response - * The servlet response we are creating - */ - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - try { - if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) { - return; - } - String jsonpcb = null; - PrintWriter writer = null; - JSONBean.Writer beanWriter = null; - try { - jsonpcb = checkCallbackName(request.getParameter(CALLBACK_PARAM)); - writer = response.getWriter(); - beanWriter = this.jsonBeanWriter.open(writer); - - // "callback" parameter implies JSONP outpout - if (jsonpcb != null) { - response.setContentType("application/javascript; charset=utf8"); - writer.write(jsonpcb + "("); - } else { - response.setContentType("application/json; charset=utf8"); - } - // Should we output description on each attribute and bean? - String tmpStr = request.getParameter(INCLUDE_DESCRIPTION); - boolean description = tmpStr != null && tmpStr.length() > 0; - - // query per mbean attribute - String getmethod = request.getParameter("get"); - if (getmethod != null) { - String[] splitStrings = getmethod.split("\\:\\:"); - if (splitStrings.length != 2) { - beanWriter.write("result", "ERROR"); - beanWriter.write("message", "query format is not as expected."); - beanWriter.flush(); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - return; - } - if (beanWriter.write(this.mBeanServer, new ObjectName(splitStrings[0]), - splitStrings[1], description) != 0) { - beanWriter.flush(); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - } - return; - } - - // query per mbean - String qry = request.getParameter("qry"); - if (qry == null) { - qry = "*:*"; - } - if (beanWriter.write(this.mBeanServer, new ObjectName(qry), null, description) != 0) { - beanWriter.flush(); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - } - } finally { - if (beanWriter != null) beanWriter.close(); - if (jsonpcb != null) { - writer.write(");"); - } - if (writer != null) { - writer.close(); - } - } - } catch (IOException e) { - LOG.error("Caught an exception while processing JMX request", e); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } catch (MalformedObjectNameException e) { - LOG.error("Caught an exception while processing JMX request", e); - response.sendError(HttpServletResponse.SC_BAD_REQUEST); - } - } - - /** - * Verifies that the callback property, if provided, is purely alphanumeric. - * This prevents a malicious callback name (that is javascript code) from being - * returned by the UI to an unsuspecting user. - * - * @param callbackName The callback name, can be null. - * @return The callback name - * @throws IOException If the name is disallowed. - */ - private String checkCallbackName(String callbackName) throws IOException { - if (null == callbackName) { - return null; - } - if (callbackName.matches("[A-Za-z0-9_]+")) { - return callbackName; - } - throw new IOException("'callback' must be alphanumeric"); - } -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/package-info.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/package-info.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/package-info.java deleted file mode 100644 index 324cc2d..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/jmx/package-info.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This package provides access to JMX primarily through the - * {@link org.apache.hadoop.hbase.http.jmx.JMXJsonServlet} class. - * <p> - * Copied from hadoop source code.<br> - * See https://issues.apache.org/jira/browse/HADOOP-10232 to know why. - * </p> - */ -package org.apache.hadoop.hbase.http.jmx; http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/StaticUserWebFilter.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/StaticUserWebFilter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/StaticUserWebFilter.java deleted file mode 100644 index bce3a07..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/StaticUserWebFilter.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.http.lib; - -import java.io.IOException; -import java.security.Principal; -import java.util.HashMap; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.HBaseInterfaceAudience; -import org.apache.hadoop.hbase.http.FilterContainer; -import org.apache.hadoop.hbase.http.FilterInitializer; - -import javax.servlet.Filter; - -import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.HBASE_HTTP_STATIC_USER; -import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.DEFAULT_HBASE_HTTP_STATIC_USER; - -/** - * Provides a servlet filter that pretends to authenticate a fake user (Dr.Who) - * so that the web UI is usable for a secure cluster without authentication. - */ [email protected](HBaseInterfaceAudience.CONFIG) -public class StaticUserWebFilter extends FilterInitializer { - static final String DEPRECATED_UGI_KEY = "dfs.web.ugi"; - - private static final Log LOG = LogFactory.getLog(StaticUserWebFilter.class); - - static class User implements Principal { - private final String name; - public User(String name) { - this.name = name; - } - @Override - public String getName() { - return name; - } - @Override - public int hashCode() { - return name.hashCode(); - } - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } else if (other == null || other.getClass() != getClass()) { - return false; - } - return ((User) other).name.equals(name); - } - @Override - public String toString() { - return name; - } - } - - @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) - public static class StaticUserFilter implements Filter { - private User user; - private String username; - - @Override - public void destroy() { - // NOTHING - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain - ) throws IOException, ServletException { - HttpServletRequest httpRequest = (HttpServletRequest) request; - // if the user is already authenticated, don't override it - if (httpRequest.getRemoteUser() != null) { - chain.doFilter(request, response); - } else { - HttpServletRequestWrapper wrapper = - new HttpServletRequestWrapper(httpRequest) { - @Override - public Principal getUserPrincipal() { - return user; - } - @Override - public String getRemoteUser() { - return username; - } - }; - chain.doFilter(wrapper, response); - } - } - - @Override - public void init(FilterConfig conf) throws ServletException { - this.username = conf.getInitParameter(HBASE_HTTP_STATIC_USER); - this.user = new User(username); - } - - } - - @Override - public void initFilter(FilterContainer container, Configuration conf) { - HashMap<String, String> options = new HashMap<>(); - - String username = getUsernameFromConf(conf); - options.put(HBASE_HTTP_STATIC_USER, username); - - container.addFilter("static_user_filter", - StaticUserFilter.class.getName(), - options); - } - - /** - * Retrieve the static username from the configuration. - */ - static String getUsernameFromConf(Configuration conf) { - String oldStyleUgi = conf.get(DEPRECATED_UGI_KEY); - if (oldStyleUgi != null) { - // We can't use the normal configuration deprecation mechanism here - // since we need to split out the username from the configured UGI. - LOG.warn(DEPRECATED_UGI_KEY + " should not be used. Instead, use " + - HBASE_HTTP_STATIC_USER + "."); - String[] parts = oldStyleUgi.split(","); - return parts[0]; - } else { - return conf.get(HBASE_HTTP_STATIC_USER, - DEFAULT_HBASE_HTTP_STATIC_USER); - } - } - -} http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/package-info.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/package-info.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/package-info.java deleted file mode 100644 index 7bb9a0f..0000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/lib/package-info.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * <p> - * This package provides user-selectable (via configuration) classes that add - * functionality to the web UI. They are configured as a list of classes in the - * configuration parameter <b>hadoop.http.filter.initializers</b>. - * </p> - * <ul> - * <li> <b>StaticUserWebFilter</b> - An authorization plugin that makes all - * users a static configured user. - * </ul> - * <p> - * Copied from hadoop source code.<br> - * See https://issues.apache.org/jira/browse/HADOOP-10232 to know why - * </p> - */ [email protected]({"HBase"}) [email protected] -package org.apache.hadoop.hbase.http.lib; - -import org.apache.yetus.audience.InterfaceAudience; -import org.apache.yetus.audience.InterfaceStability;
