From 8823cb27178bc106b4dd8fbe27cb198eada691fc Mon Sep 17 00:00:00 2001
From: Jan Hentschel
Date: Wed, 7 Feb 2018 18:52:59 +0100
Subject: [PATCH] HBASE-19762 Fixed Checkstyle errors in hbase-http
---
.../hbase/checkstyle-suppressions.xml | 3 +
hbase-http/pom.xml | 7 +
.../http/ClickjackingPreventionFilter.java | 45 ++++---
.../apache/hadoop/hbase/http/HtmlQuoting.java | 58 +++++----
.../apache/hadoop/hbase/http/HttpConfig.java | 5 +-
.../hbase/http/HttpRequestLogAppender.java | 4 +-
.../apache/hadoop/hbase/http/HttpServer.java | 120 ++++++++++++------
.../apache/hadoop/hbase/http/InfoServer.java | 49 +++----
.../hadoop/hbase/http/NoCacheFilter.java | 8 +-
.../hadoop/hbase/http/conf/ConfServlet.java | 7 +-
.../hadoop/hbase/http/jmx/JMXJsonServlet.java | 6 +-
.../hadoop/hbase/http/log/LogLevel.java | 32 ++---
.../hbase/http/HttpServerFunctionalTest.java | 27 ++--
.../hadoop/hbase/http/TestGlobalFilter.java | 46 +++----
.../hadoop/hbase/http/TestHtmlQuoting.java | 7 +-
.../hadoop/hbase/http/TestHttpServer.java | 105 +++++++--------
.../hadoop/hbase/http/TestPathFilter.java | 43 +++----
.../hadoop/hbase/http/TestServletFilter.java | 40 +++---
.../hbase/http/TestSpnegoHttpServer.java | 59 +++++----
.../hadoop/hbase/http/log/TestLogLevel.java | 20 +--
.../hbase/http/resource/JerseyResource.java | 2 +-
.../hbase/http/ssl/KeyStoreTestUtil.java | 13 +-
22 files changed, 380 insertions(+), 326 deletions(-)
diff --git a/hbase-checkstyle/src/main/resources/hbase/checkstyle-suppressions.xml b/hbase-checkstyle/src/main/resources/hbase/checkstyle-suppressions.xml
index 9feb555877..903f83e375 100644
--- a/hbase-checkstyle/src/main/resources/hbase/checkstyle-suppressions.xml
+++ b/hbase-checkstyle/src/main/resources/hbase/checkstyle-suppressions.xml
@@ -38,4 +38,7 @@
+
+
+
diff --git a/hbase-http/pom.xml b/hbase-http/pom.xml
index 667b3f5887..a90cfd5f43 100644
--- a/hbase-http/pom.xml
+++ b/hbase-http/pom.xml
@@ -120,6 +120,13 @@
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ true
+
+
net.revelc.code
warbucks-maven-plugin
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
index 9944d29e64..7ce13012a4 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
@@ -17,6 +17,8 @@
*/
package org.apache.hadoop.hbase.http;
+import java.io.IOException;
+
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -24,32 +26,29 @@ 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;
+import org.apache.yetus.audience.InterfaceAudience;
+
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
public class ClickjackingPreventionFilter implements Filter {
-
- private FilterConfig filterConfig;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- this.filterConfig = filterConfig;
- }
-
- @Override
- public void doFilter(ServletRequest req, ServletResponse res,
- FilterChain chain)
- throws IOException, ServletException {
- HttpServletResponse httpRes = (HttpServletResponse) res;
- httpRes.addHeader("X-Frame-Options", filterConfig.getInitParameter("xframeoptions"));
- chain.doFilter(req, res);
- }
-
- @Override
- public void destroy() {
- }
-
+ private FilterConfig filterConfig;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletResponse httpRes = (HttpServletResponse) res;
+ httpRes.addHeader("X-Frame-Options", filterConfig.getInitParameter("xframeoptions"));
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void destroy() {
+ }
}
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
index e2eebb2519..38192f60b2 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -42,19 +42,19 @@ public final class HtmlQuoting {
*/
public static boolean needsQuoting(byte[] data, int off, int len) {
if (off+len > data.length) {
- throw new IllegalStateException("off+len=" + off+len + " should be lower"
- + " than data length=" + data.length);
+ throw new IllegalStateException("off+len=" + off+len + " should be lower"
+ + " than data length=" + data.length);
}
for(int i=off; i< off+len; ++i) {
switch(data[i]) {
- case '&':
- case '<':
- case '>':
- case '\'':
- case '"':
- return true;
- default:
- break;
+ case '&':
+ case '<':
+ case '>':
+ case '\'':
+ case '"':
+ return true;
+ default:
+ break;
}
}
return false;
@@ -81,16 +81,28 @@ public final class HtmlQuoting {
* @param off the index of the first byte to quote
* @param len the number of bytes to quote
*/
- public static void quoteHtmlChars(OutputStream output, byte[] buffer,
- int off, int len) throws IOException {
+ public static void quoteHtmlChars(OutputStream output, byte[] buffer, int off, int len)
+ throws IOException {
for(int i=off; i < off+len; i++) {
switch (buffer[i]) {
- case '&': output.write(ampBytes); break;
- case '<': output.write(ltBytes); break;
- case '>': output.write(gtBytes); break;
- case '\'': output.write(aposBytes); break;
- case '"': output.write(quotBytes); break;
- default: output.write(buffer, i, 1);
+ case '&':
+ output.write(ampBytes);
+ break;
+ case '<':
+ output.write(ltBytes);
+ break;
+ case '>':
+ output.write(gtBytes);
+ break;
+ case '\'':
+ output.write(aposBytes);
+ break;
+ case '"':
+ output.write(quotBytes);
+ break;
+ default:
+ output.write(buffer, i, 1);
+ break;
}
}
}
@@ -122,10 +134,8 @@ public final class HtmlQuoting {
* Return an output stream that quotes all of the output.
* @param out the stream to write the quoted output to
* @return a new stream that the application show write to
- * @throws IOException if the underlying output fails
*/
- public static OutputStream quoteOutputStream(final OutputStream out
- ) throws IOException {
+ public static OutputStream quoteOutputStream(final OutputStream out) {
return new OutputStream() {
private byte[] data = new byte[1];
@Override
@@ -200,9 +210,9 @@ public final class HtmlQuoting {
return buffer.toString();
}
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) {
if (args.length == 0) {
- throw new IllegalArgumentException("Please provide some arguments");
+ throw new IllegalArgumentException("Please provide some arguments");
}
for(String arg:args) {
System.out.println("Original: " + arg);
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
index b9dde238db..52c9133dcf 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
@@ -17,9 +17,10 @@
*/
package org.apache.hadoop.hbase.http;
+import org.apache.hadoop.conf.Configuration;
+
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.yetus.audience.InterfaceStability;
-import org.apache.hadoop.conf.Configuration;
/**
* Statics to get access to Http related configuration.
@@ -51,7 +52,7 @@ public class HttpConfig {
}
}
- public HttpConfig(final Configuration conf) {
+ public HttpConfig(final Configuration conf) {
boolean sslEnabled = conf.getBoolean(
ServerConfigurationKeys.HBASE_SSL_ENABLED_KEY,
ServerConfigurationKeys.HBASE_SSL_ENABLED_DEFAULT);
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
index b6ce3c1c23..9864c203f4 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -17,8 +17,8 @@
*/
package org.apache.hadoop.hbase.http;
-import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
import org.apache.yetus.audience.InterfaceAudience;
/**
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java
index af72ab8c1e..eced02f643 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/HttpServer.java
@@ -144,7 +144,7 @@ public class HttpServer implements FilterContainer {
protected String appDir;
protected String logDir;
- private static class ListenerInfo {
+ private static final class ListenerInfo {
/**
* Boolean flag to determine whether the HTTP server should clean up the
* listener in stop().
@@ -203,10 +203,22 @@ public class HttpServer implements FilterContainer {
private String kerberosNameRulesKey;
private String signatureSecretFileKey;
+ /**
+ * @see #setAppDir(String)
+ * @deprecated Since 0.99.0. Use builder pattern via {@link #setAppDir(String)} instead.
+ */
@Deprecated
private String name;
+ /**
+ * @see #addEndpoint(URI)
+ * @deprecated Since 0.99.0. Use builder pattern via {@link #addEndpoint(URI)} instead.
+ */
@Deprecated
private String bindAddress;
+ /**
+ * @see #addEndpoint(URI)
+ * @deprecated Since 0.99.0. Use builder pattern vai {@link #addEndpoint(URI)} instead.
+ */
@Deprecated
private int port = -1;
@@ -264,7 +276,8 @@ public class HttpServer implements FilterContainer {
}
/**
- * Use setAppDir() instead.
+ * @see #setAppDir(String)
+ * @deprecated Since 0.99.0. Use {@link #setAppDir(String)} instead.
*/
@Deprecated
public Builder setName(String name){
@@ -273,7 +286,8 @@ public class HttpServer implements FilterContainer {
}
/**
- * Use addEndpoint() instead.
+ * @see #addEndpoint(URI)
+ * @deprecated Since 0.99.0. Use {@link #addEndpoint(URI)} instead.
*/
@Deprecated
public Builder setBindAddress(String bindAddress){
@@ -282,7 +296,8 @@ public class HttpServer implements FilterContainer {
}
/**
- * Use addEndpoint() instead.
+ * @see #addEndpoint(URI)
+ * @deprecated Since 0.99.0. Use {@link #addEndpoint(URI)} instead.
*/
@Deprecated
public Builder setPort(int port) {
@@ -336,14 +351,14 @@ public class HttpServer implements FilterContainer {
}
public Builder setAppDir(String appDir) {
- this.appDir = appDir;
- return this;
- }
+ this.appDir = appDir;
+ return this;
+ }
public Builder setLogDir(String logDir) {
- this.logDir = logDir;
- return this;
- }
+ this.logDir = logDir;
+ return this;
+ }
public HttpServer build() throws IOException {
@@ -357,7 +372,8 @@ public class HttpServer implements FilterContainer {
try {
endpoints.add(0, new URI("http", "", bindAddress, port, "", "", ""));
} catch (URISyntaxException e) {
- throw new HadoopIllegalArgumentException("Invalid endpoint: "+ e); }
+ throw new HadoopIllegalArgumentException("Invalid endpoint: "+ e);
+ }
}
if (endpoints.isEmpty()) {
@@ -438,10 +454,13 @@ public class HttpServer implements FilterContainer {
}
- /** Same as this(name, bindAddress, port, findPort, null); */
+ /**
+ * @see #HttpServer(String, String, int, boolean, Configuration)
+ * @deprecated Since 0.99.0
+ */
@Deprecated
- public HttpServer(String name, String bindAddress, int port, boolean findPort
- ) throws IOException {
+ public HttpServer(String name, String bindAddress, int port, boolean findPort)
+ throws IOException {
this(name, bindAddress, port, findPort, new Configuration());
}
@@ -458,6 +477,7 @@ public class HttpServer implements FilterContainer {
* @param conf Configuration
* @param pathSpecs Path specifications that this httpserver will be serving.
* These will be added to any filters.
+ * @deprecated Since 0.99.0
*/
@Deprecated
public HttpServer(String name, String bindAddress, int port,
@@ -473,6 +493,7 @@ public class HttpServer implements FilterContainer {
* @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 Since 0.99.0
*/
@Deprecated
public HttpServer(String name, String bindAddress, int port,
@@ -480,6 +501,20 @@ public class HttpServer implements FilterContainer {
this(name, bindAddress, port, findPort, conf, null, null);
}
+ /**
+ * Creates a status server on the given port. The JSP scripts are taken
+ * from src/webapp<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 the configuration to use
+ * @param adminsAcl {@link AccessControlList} of the admins
+ * @throws IOException when creating the server fails
+ * @deprecated Since 0.99.0
+ */
@Deprecated
public HttpServer(String name, String bindAddress, int port,
boolean findPort, Configuration conf, AccessControlList adminsAcl)
@@ -499,6 +534,7 @@ public class HttpServer implements FilterContainer {
* @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 Since 0.99.0
*/
@Deprecated
public HttpServer(String name, String bindAddress, int port,
@@ -625,14 +661,13 @@ public class HttpServer implements FilterContainer {
/**
* Add default apps.
* @param appDir The application directory
- * @throws IOException
*/
protected void addDefaultApps(ContextHandlerCollection parent,
- final String appDir, Configuration conf) throws IOException {
+ final String appDir, Configuration conf) {
// 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");
+ logDir = System.getProperty("hadoop.log.dir");
}
if (logDir != null) {
ServletContextHandler logContext = new ServletContextHandler(parent, "/logs");
@@ -761,20 +796,18 @@ public class HttpServer implements FilterContainer {
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);
+ 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 parameters) {
-
+ public void addFilter(String name, String classname, Map parameters) {
final String[] USER_FACING_URLS = { "*.html", "*.jsp" };
defineFilter(webAppContext, name, classname, parameters, USER_FACING_URLS);
LOG.info("Added filter " + name + " (class=" + classname
@@ -792,8 +825,7 @@ public class HttpServer implements FilterContainer {
}
@Override
- public void addGlobalFilter(String name, String classname,
- Map parameters) {
+ public void addGlobalFilter(String name, String classname, Map parameters) {
final String[] ALL_URLS = { "/*" };
defineFilter(webAppContext, name, classname, parameters, ALL_URLS);
for (ServletContextHandler ctx : defaultContexts.keySet()) {
@@ -807,7 +839,6 @@ public class HttpServer implements FilterContainer {
*/
public static void defineFilter(ServletContextHandler handler, String name,
String classname, Map parameters, String[] urls) {
-
FilterHolder holder = new FilterHolder();
holder.setName(name);
holder.setClassName(classname);
@@ -851,7 +882,7 @@ public class HttpServer implements FilterContainer {
}
public String getWebAppsPath(String appName) throws FileNotFoundException {
- return getWebAppsPath(this.appDir, appName);
+ return getWebAppsPath(this.appDir, appName);
}
/**
@@ -862,9 +893,12 @@ public class HttpServer implements FilterContainer {
*/
protected String getWebAppsPath(String webapps, String appName) throws FileNotFoundException {
URL url = getClass().getClassLoader().getResource(webapps + "/" + appName);
- if (url == null)
+
+ if (url == null) {
throw new FileNotFoundException(webapps + "/" + appName
- + " not found in CLASSPATH");
+ + " not found in CLASSPATH");
+ }
+
String urlString = url.toString();
return urlString.substring(0, urlString.lastIndexOf('/'));
}
@@ -872,6 +906,7 @@ public class HttpServer implements FilterContainer {
/**
* Get the port that the server is on
* @return the port
+ * @deprecated Since 0.99.0
*/
@Deprecated
public int getPort() {
@@ -886,8 +921,10 @@ public class HttpServer implements FilterContainer {
*/
public InetSocketAddress getConnectorAddress(int index) {
Preconditions.checkArgument(index >= 0);
- if (index > webServer.getConnectors().length)
+
+ if (index > webServer.getConnectors().length) {
return null;
+ }
ServerConnector c = (ServerConnector)webServer.getConnectors()[index];
if (c.getLocalPort() == -1 || c.getLocalPort() == -2) {
@@ -1015,7 +1052,7 @@ public class HttpServer implements FilterContainer {
/**
* Open the main listener for the server
- * @throws Exception
+ * @throws Exception if the listener cannot be opened or the appropriate port is already in use
*/
@VisibleForTesting
void openListeners() throws Exception {
@@ -1123,7 +1160,8 @@ public class HttpServer implements FilterContainer {
return "Inactive HttpServer";
} else {
StringBuilder sb = new StringBuilder("HttpServer (")
- .append(isAlive() ? STATE_DESCRIPTION_ALIVE : STATE_DESCRIPTION_NOT_LIVE).append("), listening at:");
+ .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("/,");
@@ -1168,11 +1206,11 @@ public class HttpServer implements FilterContainer {
* 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 servletContext the {@link ServletContext} to use
+ * @param request the {@link HttpServletRequest} to check
* @param response used to send the error response if user does not have admin access.
* @return true if admin-authorized, false otherwise
- * @throws IOException
+ * @throws IOException if an unauthenticated or unauthorized user tries to access the page
*/
public static boolean hasAdministratorAccess(
ServletContext servletContext, HttpServletRequest request,
@@ -1288,8 +1326,8 @@ public class HttpServer implements FilterContainer {
*/
@Override
public String getParameter(String name) {
- return HtmlQuoting.quoteHtmlChars(rawRequest.getParameter
- (HtmlQuoting.unquoteHtmlChars(name)));
+ return HtmlQuoting.quoteHtmlChars(rawRequest.getParameter(
+ HtmlQuoting.unquoteHtmlChars(name)));
}
@Override
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java
index 5fd6514f91..6d62640c8b 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/InfoServer.java
@@ -1,4 +1,4 @@
-/**
+/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,7 +16,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.hadoop.hbase.http;
import java.io.IOException;
@@ -24,9 +23,9 @@ import java.net.URI;
import javax.servlet.http.HttpServlet;
+import org.apache.hadoop.conf.Configuration;
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
@@ -38,7 +37,6 @@ import org.apache.hadoop.conf.Configuration;
*/
@InterfaceAudience.Private
public class InfoServer {
-
private static final String HBASE_APP_DIR = "hbase-webapps";
private final org.apache.hadoop.hbase.http.HttpServer httpServer;
@@ -48,32 +46,32 @@ public class InfoServer {
* @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.
+ * @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 {
+ 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);
- }
+ 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"));
+ 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))) {
@@ -89,7 +87,7 @@ public class InfoServer {
public void addServlet(String name, String pathSpec,
Class extends HttpServlet> clazz) {
- this.httpServer.addServlet(name, pathSpec, clazz);
+ this.httpServer.addServlet(name, pathSpec, clazz);
}
public void setAttribute(String name, Object value) {
@@ -100,6 +98,10 @@ public class InfoServer {
this.httpServer.start();
}
+ /**
+ * @return the port of the info server
+ * @deprecated Since 0.99.0
+ */
@Deprecated
public int getPort() {
return this.httpServer.getPort();
@@ -108,5 +110,4 @@ public class InfoServer {
public void stop() throws Exception {
this.httpServer.stop();
}
-
}
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java
index a1daf1590a..a1d41732d4 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/NoCacheFilter.java
@@ -17,6 +17,8 @@
*/
package org.apache.hadoop.hbase.http;
+import java.io.IOException;
+
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -24,14 +26,13 @@ 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;
+import org.apache.yetus.audience.InterfaceAudience;
+
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
public class NoCacheFilter implements Filter {
-
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@@ -52,5 +53,4 @@ public class NoCacheFilter implements Filter {
@Override
public void destroy() {
}
-
}
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java
index d9aa7b60aa..05ca9a3abd 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/conf/ConfServlet.java
@@ -25,11 +25,12 @@ 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;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
/**
* A servlet to print out the running configuration data.
*/
@@ -56,7 +57,6 @@ public class ConfServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
-
if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(),
request, response)) {
return;
@@ -103,5 +103,4 @@ public class ConfServlet extends HttpServlet {
super(msg);
}
}
-
}
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
index b42c270a9b..c9a190054d 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/jmx/JMXJsonServlet.java
@@ -202,9 +202,11 @@ public class JMXJsonServlet extends HttpServlet {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
} finally {
- if (beanWriter != null) beanWriter.close();
+ if (beanWriter != null) {
+ beanWriter.close();
+ }
if (jsonpcb != null) {
- writer.write(");");
+ writer.write(");");
}
if (writer != null) {
writer.close();
diff --git a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/log/LogLevel.java b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/log/LogLevel.java
index aa223f3762..2e293450ea 100644
--- a/hbase-http/src/main/java/org/apache/hadoop/hbase/http/log/LogLevel.java
+++ b/hbase-http/src/main/java/org/apache/hadoop/hbase/http/log/LogLevel.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -23,6 +23,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
+import java.util.Objects;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -44,7 +45,7 @@ import org.slf4j.impl.Log4jLoggerAdapter;
*/
@InterfaceAudience.Private
public final class LogLevel {
- public static final String USAGES = "\nUsage: General options are:\n"
+ private static final String USAGES = "\nUsage: General options are:\n"
+ "\t[-getlevel ]\n"
+ "\t[-setlevel ]\n";
@@ -74,19 +75,16 @@ public final class LogLevel {
connection.connect();
try (InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(streamReader)) {
- for(String line; (line = bufferedReader.readLine()) != null; ) {
- if (line.startsWith(MARKER)) {
- System.out.println(TAG.matcher(line).replaceAll(""));
- }
- }
+ bufferedReader.lines().filter(Objects::nonNull).filter(line -> line.startsWith(MARKER))
+ .forEach(line -> System.out.println(TAG.matcher(line).replaceAll("")));
}
} catch (IOException ioe) {
System.err.println("" + ioe);
}
}
- static final String MARKER = "";
- static final Pattern TAG = Pattern.compile("<[^>]*>");
+ private static final String MARKER = "";
+ private static final Pattern TAG = Pattern.compile("<[^>]*>");
/**
* A servlet implementation
@@ -97,9 +95,8 @@ public final class LogLevel {
private static final long serialVersionUID = 1L;
@Override
- public void doGet(HttpServletRequest request, HttpServletResponse response
- ) throws ServletException, IOException {
-
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
// Do the authorization
if (!HttpServer.hasAdministratorAccess(getServletContext(), request,
response)) {
@@ -162,8 +159,7 @@ public final class LogLevel {
+ "Set the specified log level for the specified log name." + "\n" + "\n"
+ "\n" + "\n" + "\n" + "
\n" + "
\n";
- private static void process(org.apache.log4j.Logger log, String level,
- PrintWriter out) throws IOException {
+ private static void process(org.apache.log4j.Logger log, String level, PrintWriter out) {
if (level != null) {
if (!level.equals(org.apache.log4j.Level.toLevel(level).toString())) {
out.println(MARKER + "" + "Bad level :
" + level
@@ -179,14 +175,18 @@ public final class LogLevel {
}
private static void process(java.util.logging.Logger log, String level,
- PrintWriter out) throws IOException {
+ PrintWriter out) {
if (level != null) {
log.setLevel(java.util.logging.Level.parse(level));
out.println(MARKER + "Setting Level to " + level + " ...
");
}
java.util.logging.Level lev;
- for(; (lev = log.getLevel()) == null; log = log.getParent());
+
+ while ((lev = log.getLevel()) == null) {
+ log = log.getParent();
+ }
+
out.println(MARKER + "Effective level: " + lev + "
");
}
}
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/HttpServerFunctionalTest.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/HttpServerFunctionalTest.java
index 69972a2e12..b81826bd48 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/HttpServerFunctionalTest.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/HttpServerFunctionalTest.java
@@ -18,19 +18,19 @@
package org.apache.hadoop.hbase.http;
-import org.apache.hadoop.net.NetUtils;
-import org.apache.hadoop.security.authorize.AccessControlList;
-import org.junit.Assert;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.http.HttpServer.Builder;
-
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URI;
import java.net.URL;
-import java.net.MalformedURLException;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.http.HttpServer.Builder;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.authorize.AccessControlList;
+import org.junit.Assert;
/**
* This is a base class for functional tests of the {@link HttpServer}.
@@ -114,9 +114,9 @@ public class HttpServerFunctionalTest extends Assert {
File testWebappDir = new File(webapps +
File.separatorChar + TEST);
try {
- if (!testWebappDir.exists()) {
- fail("Test webapp dir " + testWebappDir.getCanonicalPath() + " missing");
- }
+ if (!testWebappDir.exists()) {
+ fail("Test webapp dir " + testWebappDir.getCanonicalPath() + " missing");
+ }
}
catch (IOException e) {
}
@@ -158,8 +158,8 @@ public class HttpServerFunctionalTest extends Assert {
return localServerBuilder(webapp).setFindPort(true).setConf(conf).build();
}
- public static HttpServer createServer(String webapp, Configuration conf, AccessControlList adminsAcl)
- throws IOException {
+ public static HttpServer createServer(String webapp, Configuration conf,
+ AccessControlList adminsAcl) throws IOException {
return localServerBuilder(webapp).setFindPort(true).setConf(conf).setACL(adminsAcl).build();
}
@@ -178,7 +178,8 @@ public class HttpServerFunctionalTest extends Assert {
*/
public static HttpServer createServer(String webapp, Configuration conf,
String[] pathSpecs) throws IOException {
- return localServerBuilder(webapp).setFindPort(true).setConf(conf).setPathSpec(pathSpecs).build();
+ return localServerBuilder(webapp).setFindPort(true).setConf(conf).setPathSpec(pathSpecs)
+ .build();
}
/**
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestGlobalFilter.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestGlobalFilter.java
index 81902901f8..dcad011afc 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestGlobalFilter.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestGlobalFilter.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -44,13 +44,12 @@ import org.slf4j.LoggerFactory;
@Category({MiscTests.class, SmallTests.class})
public class TestGlobalFilter extends HttpServerFunctionalTest {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestGlobalFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(HttpServer.class);
- static final Set RECORDS = new TreeSet<>();
+ private static final Set RECORDS = new TreeSet<>();
/** A very simple filter that records accessed uri's */
static public class RecordingFilter implements Filter {
@@ -67,10 +66,11 @@ public class TestGlobalFilter extends HttpServerFunctionalTest {
}
@Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- if (filterConfig == null)
- return;
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ if (filterConfig == null) {
+ return;
+ }
String uri = ((HttpServletRequest)request).getRequestURI();
LOG.info("filtering " + uri);
@@ -89,21 +89,21 @@ public class TestGlobalFilter extends HttpServerFunctionalTest {
}
}
-
- /** access a url, ignoring some IOException such as the page does not exist */
- static void access(String urlstring) throws IOException {
+ /**
+ * access a url, ignoring some IOException such as the page does not exist
+ */
+ private static void access(String urlstring) throws IOException {
LOG.warn("access " + urlstring);
URL url = new URL(urlstring);
URLConnection connection = url.openConnection();
connection.connect();
try {
- BufferedReader in = new BufferedReader(new InputStreamReader(
- connection.getInputStream()));
- try {
- for(; in.readLine() != null; );
- } finally {
- in.close();
+ try (BufferedReader in = new BufferedReader(
+ new InputStreamReader(connection.getInputStream()))) {
+ for (; in.readLine() != null; ) {
+ // Ignoring the content of the URLs. Only checking if something is there.
+ }
}
} catch(IOException ioe) {
LOG.warn("urlstring=" + urlstring, ioe);
@@ -131,15 +131,17 @@ public class TestGlobalFilter extends HttpServerFunctionalTest {
final String outURL = "/static/a.out";
final String logURL = "/logs/a.log";
- final String[] urls = {fsckURL, stacksURL, ajspURL, listPathsURL,
- dataURL, streamFile, rootURL, allURL, outURL, logURL};
+ final String[] urls = {
+ fsckURL, stacksURL, ajspURL, listPathsURL, dataURL, streamFile, rootURL, allURL,
+ outURL, logURL
+ };
//access the urls
final String prefix = "http://"
+ NetUtils.getHostPortString(http.getConnectorAddress(0));
try {
- for(int i = 0; i < urls.length; i++) {
- access(prefix + urls[i]);
+ for (String url : urls) {
+ access(prefix + url);
}
} finally {
http.stop();
@@ -148,8 +150,8 @@ public class TestGlobalFilter extends HttpServerFunctionalTest {
LOG.info("RECORDS = " + RECORDS);
//verify records
- for(int i = 0; i < urls.length; i++) {
- assertTrue(RECORDS.remove(urls[i]));
+ for (String url : urls) {
+ assertTrue(RECORDS.remove(url));
}
assertTrue(RECORDS.isEmpty());
}
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHtmlQuoting.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHtmlQuoting.java
index f47991d928..0f4c4d5d2a 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHtmlQuoting.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHtmlQuoting.java
@@ -17,7 +17,10 @@
*/
package org.apache.hadoop.hbase.http;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import javax.servlet.http.HttpServletRequest;
import org.apache.hadoop.hbase.HBaseClassTestRule;
@@ -30,7 +33,6 @@ import org.mockito.Mockito;
@Category({MiscTests.class, SmallTests.class})
public class TestHtmlQuoting {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestHtmlQuoting.class);
@@ -73,7 +75,6 @@ public class TestHtmlQuoting {
runRoundTrip(buffer.toString());
}
-
@Test
public void testRequestQuoting() throws Exception {
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHttpServer.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHttpServer.java
index 0f5b8a1a01..e92a17a7b8 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHttpServer.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestHttpServer.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -23,6 +23,7 @@ import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@@ -70,7 +71,6 @@ import org.slf4j.LoggerFactory;
@Category({MiscTests.class, SmallTests.class})
public class TestHttpServer extends HttpServerFunctionalTest {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestHttpServer.class);
@@ -84,9 +84,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
@SuppressWarnings("serial")
public static class EchoMapServlet extends HttpServlet {
@Override
- public void doGet(HttpServletRequest request,
- HttpServletResponse response
- ) throws ServletException, IOException {
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
Map params = request.getParameterMap();
SortedSet keys = new TreeSet<>(params.keySet());
@@ -110,9 +108,8 @@ public class TestHttpServer extends HttpServerFunctionalTest {
@SuppressWarnings("serial")
public static class EchoServlet extends HttpServlet {
@Override
- public void doGet(HttpServletRequest request,
- HttpServletResponse response
- ) throws ServletException, IOException {
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
PrintWriter out = response.getWriter();
SortedSet sortedKeys = new TreeSet<>();
Enumeration keys = request.getParameterNames();
@@ -132,9 +129,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
@SuppressWarnings("serial")
public static class LongHeaderServlet extends HttpServlet {
@Override
- public void doGet(HttpServletRequest request,
- HttpServletResponse response
- ) throws ServletException, IOException {
+ public void doGet(HttpServletRequest request, HttpServletResponse response) {
Assert.assertEquals(63 * 1024, request.getHeader("longheader").length());
response.setStatus(HttpServletResponse.SC_OK);
}
@@ -143,9 +138,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
@SuppressWarnings("serial")
public static class HtmlContentServlet extends HttpServlet {
@Override
- public void doGet(HttpServletRequest request,
- HttpServletResponse response
- ) throws ServletException, IOException {
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("hello world");
@@ -172,30 +165,30 @@ public class TestHttpServer extends HttpServerFunctionalTest {
server.stop();
}
- /** Test the maximum number of threads cannot be exceeded. */
- @Test public void testMaxThreads() throws Exception {
+ /**
+ * Test the maximum number of threads cannot be exceeded.
+ */
+ @Test
+ public void testMaxThreads() throws Exception {
int clientThreads = MAX_THREADS * 10;
Executor executor = Executors.newFixedThreadPool(clientThreads);
// Run many clients to make server reach its maximum number of threads
final CountDownLatch ready = new CountDownLatch(clientThreads);
final CountDownLatch start = new CountDownLatch(1);
for (int i = 0; i < clientThreads; i++) {
- executor.execute(new Runnable() {
- @Override
- public void run() {
- ready.countDown();
- try {
- start.await();
- assertEquals("a:b\nc:d\n",
- readOutput(new URL(baseUrl, "/echo?a=b&c=d")));
- int serverThreads = server.webServer.getThreadPool().getThreads();
- assertTrue("More threads are started than expected, Server Threads count: "
- + serverThreads, serverThreads <= MAX_THREADS);
- System.out.println("Number of threads = " + serverThreads +
- " which is less or equal than the max = " + MAX_THREADS);
- } catch (Exception e) {
- // do nothing
- }
+ executor.execute(() -> {
+ ready.countDown();
+ try {
+ start.await();
+ assertEquals("a:b\nc:d\n",
+ readOutput(new URL(baseUrl, "/echo?a=b&c=d")));
+ int serverThreads = server.webServer.getThreadPool().getThreads();
+ assertTrue("More threads are started than expected, Server Threads count: "
+ + serverThreads, serverThreads <= MAX_THREADS);
+ System.out.println("Number of threads = " + serverThreads +
+ " which is less or equal than the max = " + MAX_THREADS);
+ } catch (Exception e) {
+ // do nothing
}
});
}
@@ -300,7 +293,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
}
@Override
- public void init(FilterConfig arg0) throws ServletException { }
+ public void init(FilterConfig arg0) { }
}
/**
@@ -327,8 +320,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
* @return The HTTP response code
* @throws IOException if there is a problem communicating with the server
*/
- static int getHttpStatusCode(String urlstring, String userName)
- throws IOException {
+ private static int getHttpStatusCode(String urlstring, String userName) throws IOException {
URL url = new URL(urlstring + "?user.name=" + userName);
System.out.println("Accessing " + url + " as user " + userName);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
@@ -347,7 +339,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
}
@Override
- public List getGroups(String user) throws IOException {
+ public List getGroups(String user) {
return mapping.get(user);
}
}
@@ -356,12 +348,10 @@ public class TestHttpServer extends HttpServerFunctionalTest {
* Verify the access for /logs, /stacks, /conf, /logLevel and /metrics
* servlets, when authentication filters are set, but authorization is not
* enabled.
- * @throws Exception
*/
@Test
@Ignore
public void testDisabledAuthorizationOfDefaultServlets() throws Exception {
-
Configuration conf = new Configuration();
// Authorization is disabled by default
@@ -371,16 +361,15 @@ public class TestHttpServer extends HttpServerFunctionalTest {
MyGroupsProvider.class.getName());
Groups.getUserToGroupsMappingService(conf);
MyGroupsProvider.clearMapping();
- MyGroupsProvider.mapping.put("userA", Arrays.asList("groupA"));
- MyGroupsProvider.mapping.put("userB", Arrays.asList("groupB"));
+ MyGroupsProvider.mapping.put("userA", Collections.singletonList("groupA"));
+ MyGroupsProvider.mapping.put("userB", Collections.singletonList("groupB"));
HttpServer myServer = new HttpServer.Builder().setName("test")
.addEndpoint(new URI("http://localhost:0")).setFindPort(true).build();
myServer.setAttribute(HttpServer.CONF_CONTEXT_ATTRIBUTE, conf);
myServer.start();
String serverURL = "http://" + NetUtils.getHostPortString(myServer.getConnectorAddress(0)) + "/";
- for (String servlet : new String[] { "conf", "logs", "stacks",
- "logLevel", "metrics" }) {
+ for (String servlet : new String[] { "conf", "logs", "stacks", "logLevel", "metrics" }) {
for (String user : new String[] { "userA", "userB" }) {
assertEquals(HttpURLConnection.HTTP_OK, getHttpStatusCode(serverURL
+ servlet, user));
@@ -392,8 +381,6 @@ public class TestHttpServer extends HttpServerFunctionalTest {
/**
* Verify the administrator access for /logs, /stacks, /conf, /logLevel and
* /metrics servlets.
- *
- * @throws Exception
*/
@Test
@Ignore
@@ -410,11 +397,11 @@ public class TestHttpServer extends HttpServerFunctionalTest {
MyGroupsProvider.class.getName());
Groups.getUserToGroupsMappingService(conf);
MyGroupsProvider.clearMapping();
- MyGroupsProvider.mapping.put("userA", Arrays.asList("groupA"));
- MyGroupsProvider.mapping.put("userB", Arrays.asList("groupB"));
- MyGroupsProvider.mapping.put("userC", Arrays.asList("groupC"));
- MyGroupsProvider.mapping.put("userD", Arrays.asList("groupD"));
- MyGroupsProvider.mapping.put("userE", Arrays.asList("groupE"));
+ MyGroupsProvider.mapping.put("userA", Collections.singletonList("groupA"));
+ MyGroupsProvider.mapping.put("userB", Collections.singletonList("groupB"));
+ MyGroupsProvider.mapping.put("userC", Collections.singletonList("groupC"));
+ MyGroupsProvider.mapping.put("userD", Collections.singletonList("groupD"));
+ MyGroupsProvider.mapping.put("userE", Collections.singletonList("groupE"));
HttpServer myServer = new HttpServer.Builder().setName("test")
.addEndpoint(new URI("http://localhost:0")).setFindPort(true).setConf(conf)
@@ -424,8 +411,7 @@ public class TestHttpServer extends HttpServerFunctionalTest {
String serverURL = "http://"
+ NetUtils.getHostPortString(myServer.getConnectorAddress(0)) + "/";
- for (String servlet : new String[] { "conf", "logs", "stacks",
- "logLevel", "metrics" }) {
+ for (String servlet : new String[] { "conf", "logs", "stacks", "logLevel", "metrics" }) {
for (String user : new String[] { "userA", "userB", "userC", "userD" }) {
assertEquals(HttpURLConnection.HTTP_OK, getHttpStatusCode(serverURL
+ servlet, user));
@@ -437,17 +423,17 @@ public class TestHttpServer extends HttpServerFunctionalTest {
}
@Test
- public void testRequestQuoterWithNull() throws Exception {
+ public void testRequestQuoterWithNull() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.doReturn(null).when(request).getParameterValues("dummy");
RequestQuoter requestQuoter = new RequestQuoter(request);
String[] parameterValues = requestQuoter.getParameterValues("dummy");
- Assert.assertEquals("It should return null "
- + "when there are no values for the parameter", null, parameterValues);
+ Assert.assertNull("It should return null "
+ + "when there are no values for the parameter", parameterValues);
}
@Test
- public void testRequestQuoterWithNotNull() throws Exception {
+ public void testRequestQuoterWithNotNull() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
String[] values = new String[] { "abc", "def" };
Mockito.doReturn(values).when(request).getParameterValues("dummy");
@@ -490,7 +476,8 @@ public class TestHttpServer extends HttpServerFunctionalTest {
response = Mockito.mock(HttpServletResponse.class);
conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, true);
Assert.assertFalse(HttpServer.hasAdministratorAccess(context, request, response));
- Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.anyString());
+ Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED),
+ Mockito.anyString());
//authorization ON & user NOT NULL & ACLs NULL
response = Mockito.mock(HttpServletResponse.class);
@@ -503,7 +490,8 @@ public class TestHttpServer extends HttpServerFunctionalTest {
Mockito.when(acls.isUserAllowed(Mockito.any())).thenReturn(false);
Mockito.when(context.getAttribute(HttpServer.ADMINS_ACL)).thenReturn(acls);
Assert.assertFalse(HttpServer.hasAdministratorAccess(context, request, response));
- Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED), Mockito.anyString());
+ Mockito.verify(response).sendError(Mockito.eq(HttpServletResponse.SC_UNAUTHORIZED),
+ Mockito.anyString());
//authorization ON & user NOT NULL & ACLs NOT NULL & user in in ACLs
response = Mockito.mock(HttpServletResponse.class);
@@ -533,7 +521,8 @@ public class TestHttpServer extends HttpServerFunctionalTest {
Assert.assertFalse(HttpServer.isInstrumentationAccessAllowed(context, request, response));
}
- @Test public void testBindAddress() throws Exception {
+ @Test
+ public void testBindAddress() throws Exception {
checkBindAddress("localhost", 0, false).stop();
// hang onto this one for a bit more testing
HttpServer myServer = checkBindAddress("localhost", 0, false);
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestPathFilter.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestPathFilter.java
index 47e6ea26f1..4192c74a83 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestPathFilter.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestPathFilter.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -44,13 +44,12 @@ import org.slf4j.LoggerFactory;
@Category({MiscTests.class, SmallTests.class})
public class TestPathFilter extends HttpServerFunctionalTest {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestPathFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(HttpServer.class);
- static final Set RECORDS = new TreeSet<>();
+ private static final Set RECORDS = new TreeSet<>();
/** A very simple filter that records accessed uri's */
static public class RecordingFilter implements Filter {
@@ -69,8 +68,9 @@ public class TestPathFilter extends HttpServerFunctionalTest {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
- if (filterConfig == null)
- return;
+ if (filterConfig == null) {
+ return;
+ }
String uri = ((HttpServletRequest)request).getRequestURI();
LOG.info("filtering " + uri);
@@ -89,9 +89,10 @@ public class TestPathFilter extends HttpServerFunctionalTest {
}
}
-
- /** access a url, ignoring some IOException such as the page does not exist */
- static void access(String urlstring) throws IOException {
+ /**
+ * access a url, ignoring some IOException such as the page does not exist
+ */
+ private static void access(String urlstring) throws IOException {
LOG.warn("access " + urlstring);
URL url = new URL(urlstring);
@@ -99,12 +100,11 @@ public class TestPathFilter extends HttpServerFunctionalTest {
connection.connect();
try {
- BufferedReader in = new BufferedReader(new InputStreamReader(
- connection.getInputStream()));
- try {
- for(; in.readLine() != null; );
- } finally {
- in.close();
+ try (BufferedReader in = new BufferedReader(
+ new InputStreamReader(connection.getInputStream()))) {
+ for (; in.readLine() != null; ) {
+ // Ignoring the content of the URLs. Only checking if something is there.
+ }
}
} catch(IOException ioe) {
LOG.warn("urlstring=" + urlstring, ioe);
@@ -130,8 +130,7 @@ public class TestPathFilter extends HttpServerFunctionalTest {
final String rootURL = "/";
final String allURL = "/*";
- final String[] filteredUrls = {baseURL, baseSlashURL, addedURL,
- addedSlashURL, longURL};
+ final String[] filteredUrls = { baseURL, baseSlashURL, addedURL, addedSlashURL, longURL };
final String[] notFilteredUrls = {rootURL, allURL};
// access the urls and verify our paths specs got added to the
@@ -139,11 +138,11 @@ public class TestPathFilter extends HttpServerFunctionalTest {
final String prefix = "http://"
+ NetUtils.getHostPortString(http.getConnectorAddress(0));
try {
- for(int i = 0; i < filteredUrls.length; i++) {
- access(prefix + filteredUrls[i]);
+ for (String filteredUrl : filteredUrls) {
+ access(prefix + filteredUrl);
}
- for(int i = 0; i < notFilteredUrls.length; i++) {
- access(prefix + notFilteredUrls[i]);
+ for (String notFilteredUrl : notFilteredUrls) {
+ access(prefix + notFilteredUrl);
}
} finally {
http.stop();
@@ -152,8 +151,8 @@ public class TestPathFilter extends HttpServerFunctionalTest {
LOG.info("RECORDS = " + RECORDS);
//verify records
- for(int i = 0; i < filteredUrls.length; i++) {
- assertTrue(RECORDS.remove(filteredUrls[i]));
+ for (String filteredUrl : filteredUrls) {
+ assertTrue(RECORDS.remove(filteredUrl));
}
assertTrue(RECORDS.isEmpty());
}
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestServletFilter.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestServletFilter.java
index 6c70dbc9d8..c417fe265b 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestServletFilter.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestServletFilter.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -46,13 +46,12 @@ import org.slf4j.LoggerFactory;
@Category({MiscTests.class, SmallTests.class})
public class TestServletFilter extends HttpServerFunctionalTest {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestServletFilter.class);
private static final Logger LOG = LoggerFactory.getLogger(HttpServer.class);
- static volatile String uri = null;
+ private static volatile String uri = null;
/** A very simple filter which record the uri filtered. */
static public class SimpleFilter implements Filter {
@@ -71,8 +70,9 @@ public class TestServletFilter extends HttpServerFunctionalTest {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
- if (filterConfig == null)
- return;
+ if (filterConfig == null) {
+ return;
+ }
uri = ((HttpServletRequest)request).getRequestURI();
LOG.info("filtering " + uri);
@@ -90,27 +90,28 @@ public class TestServletFilter extends HttpServerFunctionalTest {
}
}
- public static void assertExceptionContains(String string, Throwable t) {
+ private static void assertExceptionContains(String string, Throwable t) {
String msg = t.getMessage();
Assert.assertTrue(
"Expected to find '" + string + "' but got unexpected exception:"
+ StringUtils.stringifyException(t), msg.contains(string));
}
- /** access a url, ignoring some IOException such as the page does not exist */
- static void access(String urlstring) throws IOException {
+ /**
+ * access a url, ignoring some IOException such as the page does not exist
+ */
+ private static void access(String urlstring) throws IOException {
LOG.warn("access " + urlstring);
URL url = new URL(urlstring);
URLConnection connection = url.openConnection();
connection.connect();
try {
- BufferedReader in = new BufferedReader(new InputStreamReader(
- connection.getInputStream()));
- try {
- for(; in.readLine() != null; );
- } finally {
- in.close();
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(
+ connection.getInputStream()))) {
+ for (; in.readLine() != null; ) {
+ // Ignoring the content of the URLs. Only checking if something is there.
+ }
}
} catch(IOException ioe) {
LOG.warn("urlstring=" + urlstring, ioe);
@@ -150,14 +151,14 @@ public class TestServletFilter extends HttpServerFunctionalTest {
final String prefix = "http://"
+ NetUtils.getHostPortString(http.getConnectorAddress(0));
try {
- for(int i = 0; i < sequence.length; i++) {
- access(prefix + urls[sequence[i]]);
+ for (int aSequence : sequence) {
+ access(prefix + urls[aSequence]);
//make sure everything except fsck get filtered
- if (sequence[i] == 0) {
- assertEquals(null, uri);
+ if (aSequence == 0) {
+ assertNull(uri);
} else {
- assertEquals(urls[sequence[i]], uri);
+ assertEquals(urls[aSequence], uri);
uri = null;
}
}
@@ -218,5 +219,4 @@ public class TestServletFilter extends HttpServerFunctionalTest {
assertExceptionContains("Unable to initialize WebAppContext", e);
}
}
-
}
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
index 1262b0c1d4..8d3cd9568a 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
@@ -69,7 +69,6 @@ import org.slf4j.LoggerFactory;
*/
@Category({MiscTests.class, SmallTests.class})
public class TestSpnegoHttpServer extends HttpServerFunctionalTest {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestSpnegoHttpServer.class);
@@ -208,35 +207,35 @@ public class TestSpnegoHttpServer extends HttpServerFunctionalTest {
final String principalName = clientPrincipals.iterator().next().getName();
// Run this code, logged in as the subject (the client)
- HttpResponse resp = Subject.doAs(clientSubject,
- new PrivilegedExceptionAction() {
- @Override
- public HttpResponse run() throws Exception {
- // Logs in with Kerberos via GSS
- GSSManager gssManager = GSSManager.getInstance();
- // jGSS Kerberos login constant
- Oid oid = new Oid("1.2.840.113554.1.2.2");
- GSSName gssClient = gssManager.createName(principalName, GSSName.NT_USER_NAME);
- GSSCredential credential = gssManager.createCredential(gssClient,
- GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.INITIATE_ONLY);
-
- HttpClientContext context = HttpClientContext.create();
- Lookup authRegistry = RegistryBuilder.create()
- .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true, true))
- .build();
-
- HttpClient client = HttpClients.custom().setDefaultAuthSchemeRegistry(authRegistry).build();
- BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
- credentialsProvider.setCredentials(AuthScope.ANY, new KerberosCredentials(credential));
-
- URL url = new URL(getServerURL(server), "/echo?a=b");
- context.setTargetHost(new HttpHost(url.getHost(), url.getPort()));
- context.setCredentialsProvider(credentialsProvider);
- context.setAuthSchemeRegistry(authRegistry);
-
- HttpGet get = new HttpGet(url.toURI());
- return client.execute(get, context);
- }
+ HttpResponse resp = Subject.doAs(clientSubject, new PrivilegedExceptionAction() {
+ @Override
+ public HttpResponse run() throws Exception {
+ // Logs in with Kerberos via GSS
+ GSSManager gssManager = GSSManager.getInstance();
+ // jGSS Kerberos login constant
+ Oid oid = new Oid("1.2.840.113554.1.2.2");
+ GSSName gssClient = gssManager.createName(principalName, GSSName.NT_USER_NAME);
+ GSSCredential credential = gssManager.createCredential(gssClient,
+ GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.INITIATE_ONLY);
+
+ HttpClientContext context = HttpClientContext.create();
+ Lookup authRegistry = RegistryBuilder.create()
+ .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true, true))
+ .build();
+
+ HttpClient client = HttpClients.custom().setDefaultAuthSchemeRegistry(authRegistry)
+ .build();
+ BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(AuthScope.ANY, new KerberosCredentials(credential));
+
+ URL url = new URL(getServerURL(server), "/echo?a=b");
+ context.setTargetHost(new HttpHost(url.getHost(), url.getPort()));
+ context.setCredentialsProvider(credentialsProvider);
+ context.setAuthSchemeRegistry(authRegistry);
+
+ HttpGet get = new HttpGet(url.toURI());
+ return client.execute(get, context);
+ }
});
assertNotNull(resp);
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
index 9da48193e6..77880fb88c 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
@@ -1,4 +1,4 @@
-/**
+/*
* 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
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.hbase.http.log;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
@@ -24,6 +25,7 @@ import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URI;
import java.net.URL;
+import java.util.Objects;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.http.HttpServer;
import org.apache.hadoop.hbase.testclassification.MiscTests;
@@ -40,12 +42,11 @@ import org.slf4j.impl.Log4jLoggerAdapter;
@Category({MiscTests.class, SmallTests.class})
public class TestLogLevel {
-
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestLogLevel.class);
- static final PrintStream out = System.out;
+ private static final PrintStream out = System.out;
@Test
@SuppressWarnings("deprecation")
@@ -53,7 +54,7 @@ public class TestLogLevel {
String logName = TestLogLevel.class.getName();
org.slf4j.Logger testlog = LoggerFactory.getLogger(logName);
- //only test Log4JLogger
+ // only test Log4JLogger
if (testlog instanceof Log4jLoggerAdapter) {
Logger log = LogManager.getLogger(logName);
log.debug("log.debug1");
@@ -71,17 +72,17 @@ public class TestLogLevel {
String authority = NetUtils.getHostPortString(server
.getConnectorAddress(0));
- //servlet
+ // servlet
URL url =
new URL("http://" + authority + "/logLevel?log=" + logName + "&level=" + Level.ERROR);
out.println("*** Connecting to " + url);
try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
- for(String line; (line = in.readLine()) != null; out.println(line));
+ in.lines().filter(Objects::nonNull).forEach(out::println);
}
log.debug("log.debug2");
log.info("log.info2");
log.error("log.error2");
- assertTrue(Level.ERROR.equals(log.getEffectiveLevel()));
+ assertEquals(Level.ERROR, log.getEffectiveLevel());
//command line
String[] args = {"-setlevel", authority, logName, Level.DEBUG.toString()};
@@ -89,14 +90,13 @@ public class TestLogLevel {
log.debug("log.debug3");
log.info("log.info3");
log.error("log.error3");
- assertTrue(Level.DEBUG.equals(log.getEffectiveLevel()));
+ assertEquals(Level.DEBUG, log.getEffectiveLevel());
} finally {
if (server != null) {
server.stop();
}
}
- }
- else {
+ } else {
out.println(testlog.getClass() + " not tested.");
}
}
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
index 31ff0ed4e0..593b1c2224 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
@@ -52,7 +52,7 @@ public class JerseyResource {
public Response get(
@PathParam(PATH) @DefaultValue("UNKNOWN_" + PATH) final String path,
@QueryParam(OP) @DefaultValue("UNKNOWN_" + OP) final String op
- ) throws IOException {
+ ) throws IOException {
LOG.info("get: " + PATH + "=" + path + ", " + OP + "=" + op);
final Map m = new TreeMap<>();
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
index 35d6236949..aa8c2446c6 100644
--- a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
@@ -49,7 +49,9 @@ import org.apache.hadoop.security.ssl.FileBasedKeyStoresFactory;
import org.apache.hadoop.security.ssl.SSLFactory;
import org.bouncycastle.x509.X509V1CertificateGenerator;
-public class KeyStoreTestUtil {
+public final class KeyStoreTestUtil {
+ private KeyStoreTestUtil() {
+ }
public static String getClasspathDir(Class> klass) throws Exception {
String file = klass.getName();
@@ -69,11 +71,12 @@ public class KeyStoreTestUtil {
* @param algorithm the signing algorithm, eg "SHA1withRSA"
* @return the self-signed certificate
*/
- public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
- throws CertificateEncodingException, InvalidKeyException, IllegalStateException,
- NoSuchProviderException, NoSuchAlgorithmException, SignatureException {
+ public static X509Certificate generateCertificate(String dn, KeyPair pair, int days,
+ String algorithm) throws CertificateEncodingException, InvalidKeyException,
+ IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException,
+ SignatureException {
Date from = new Date();
- Date to = new Date(from.getTime() + days * 86400000l);
+ Date to = new Date(from.getTime() + days * 86400000L);
BigInteger sn = new BigInteger(64, new SecureRandom());
KeyPair keyPair = pair;
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
--
2.17.1