You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2015/09/16 04:55:52 UTC
aurora git commit: Convert all of our servlet implementations to
jax-rs endpoints.
Repository: aurora
Updated Branches:
refs/heads/master 44e472642 -> 9dff05714
Convert all of our servlet implementations to jax-rs endpoints.
Reviewed at https://reviews.apache.org/r/38332/
Project: http://git-wip-us.apache.org/repos/asf/aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/9dff0571
Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/9dff0571
Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/9dff0571
Branch: refs/heads/master
Commit: 9dff05714b3e317f9473105a6ebbcd4d1dee100d
Parents: 44e4726
Author: Bill Farner <wf...@apache.org>
Authored: Tue Sep 15 19:55:46 2015 -0700
Committer: Bill Farner <wf...@apache.org>
Committed: Tue Sep 15 19:55:46 2015 -0700
----------------------------------------------------------------------
.../aurora/build/CoverageReportCheck.groovy | 8 +-
.../common/net/http/handlers/AbortHandler.java | 27 +-
.../common/net/http/handlers/AssetHandler.java | 191 ----------
.../net/http/handlers/ContentionPrinter.java | 26 +-
.../common/net/http/handlers/HealthHandler.java | 35 +-
.../common/net/http/handlers/LogConfig.java | 83 ++--
.../common/net/http/handlers/QuitHandler.java | 29 +-
.../http/handlers/StringTemplateServlet.java | 96 -----
.../net/http/handlers/TextResponseHandler.java | 58 ---
.../net/http/handlers/ThreadStackPrinter.java | 21 +-
.../net/http/handlers/TimeSeriesDataSource.java | 35 +-
.../common/net/http/handlers/VarsHandler.java | 16 +-
.../net/http/handlers/VarsJsonHandler.java | 33 +-
.../net/http/handlers/AssetHandlerTest.java | 378 -------------------
.../net/http/handlers/VarsHandlerTest.java | 7 +-
config/legacy_untested_classes.txt | 2 +-
.../scheduler/http/JettyServerModule.java | 97 +++--
17 files changed, 216 insertions(+), 926 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy b/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
index b996d45..b471756 100644
--- a/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
+++ b/buildSrc/src/main/groovy/org/apache/aurora/build/CoverageReportCheck.groovy
@@ -85,13 +85,15 @@ class CoverageReportCheck extends DefaultTask {
def isAnonymous = { c -> c.@name ==~ /.*\$\d+/ }
def methodFilter = isAnonymous(cls) ? { m -> m.@name != '<init>' } : { true }
- def matchedMethods = cls.method.findAll(methodFilter)
- if (isAnonymous(cls) && matchedMethods.isEmpty()) {
+ // Always ignore static code, it should not count as test coverage.
+ def matchedMethods = cls.method.findAll({ m -> m.@name != '<clinit>' }).findAll(methodFilter)
+ if (matchedMethods.isEmpty()) {
// Ignore anonymous classes that only have a constructor. This will avoid tripping for
// things like TypeLiteral and Clazz.
if (cls.@name in legacyClassesWithoutCoverage) {
return 'Please remove ' + cls.@name + ' from the legacyClassesWithoutCoverage list' \
- + ', this check does not apply for constructor-only anonymous classes.'
+ + ', this check does not apply for constructor-only anonymous classes' \
+ + ' or classes with only static class initialization code.'
} else {
return null
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AbortHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AbortHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AbortHandler.java
index e97bd82..42e668d 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AbortHandler.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AbortHandler.java
@@ -14,13 +14,14 @@
package org.apache.aurora.common.net.http.handlers;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
@@ -29,7 +30,8 @@ import com.google.inject.name.Named;
/**
* A servlet that provides a way to remotely terminate the running process immediately.
*/
-public class AbortHandler extends HttpServlet {
+@Path("/abortabortabort")
+public class AbortHandler {
/**
* A {@literal @Named} binding key for the QuitHandler listener.
@@ -53,19 +55,12 @@ public class AbortHandler extends HttpServlet {
this.abortListener = Preconditions.checkNotNull(abortListener);
}
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public void abort(@Context HttpServletRequest req) throws IOException {
LOG.info(String.format("Received abort HTTP signal from %s (%s)",
req.getRemoteAddr(), req.getRemoteHost()));
- resp.setContentType("text/plain");
- PrintWriter writer = resp.getWriter();
- try {
- writer.println("Aborting process NOW!");
- writer.close();
- abortListener.run();
- } catch (Exception e) {
- LOG.log(Level.WARNING, "Abort failed.", e);
- }
+ abortListener.run();
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AssetHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AssetHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AssetHandler.java
deleted file mode 100644
index 7a44f07..0000000
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/AssetHandler.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * Licensed 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.aurora.common.net.http.handlers;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
-import com.google.common.io.ByteSource;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Closeables;
-
-import org.apache.aurora.common.quantity.Amount;
-import org.apache.aurora.common.quantity.Time;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.codec.digest.DigestUtils;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Servlet that is responsible for serving an asset.
- *
- * @author William Farner
- */
-public class AssetHandler extends HttpServlet {
-
- @VisibleForTesting
- static final Amount<Integer, Time> CACHE_CONTROL_MAX_AGE_SECS = Amount.of(30, Time.DAYS);
- private static final String GZIP_ENCODING = "gzip";
-
- private final StaticAsset staticAsset;
-
- public static class StaticAsset {
- private final ByteSource byteSource;
- private final String contentType;
- private final boolean cacheLocally;
-
- private byte[] gzipData = null;
- private String hash = null;
-
- /**
- * Creates a new static asset.
- *
- * @param byteSource Source of the asset.
- * @param contentType HTTP content type of the asset.
- * @param cacheLocally If {@code true} the asset will be loaded once and stored in memory, if
- * {@code false} it will be loaded on each request.
- */
- public StaticAsset(ByteSource byteSource,
- String contentType, boolean cacheLocally) {
- this.byteSource = checkNotNull(byteSource);
- this.contentType = checkNotNull(contentType);
- this.cacheLocally = cacheLocally;
- }
-
- public String getContentType() {
- return contentType;
- }
-
- public synchronized byte[] getRawData() throws IOException {
- byte[] zipData = getGzipData();
- GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(zipData));
- return ByteStreams.toByteArray(in);
- }
-
- public synchronized byte[] getGzipData() throws IOException {
- byte[] data = gzipData;
- // Ensure we don't double-read after a call to getChecksum().
- if (!cacheLocally || gzipData == null) {
- load();
- data = gzipData;
- }
- if (!cacheLocally) {
- gzipData = null;
- }
-
- return data;
- }
-
- public synchronized String getChecksum() throws IOException {
- if (hash == null) {
- load();
- }
- return hash;
- }
-
- private void load() throws IOException {
- ByteArrayOutputStream gzipBaos = new ByteArrayOutputStream();
- GZIPOutputStream gzipStream = new GZIPOutputStream(gzipBaos);
- try (InputStream inputStream = byteSource.openStream()) {
- ByteStreams.copy(inputStream, gzipStream);
- }
- gzipStream.flush(); // copy() does not flush or close output stream.
- gzipStream.close();
- gzipData = gzipBaos.toByteArray();
-
- // Calculate a checksum of the gzipped data.
- hash = Base64.encodeBase64String(DigestUtils.md5(gzipData)).trim();
- }
- }
-
- /**
- * Creates a new asset handler.
- *
- * @param staticAsset The asset to serve.
- */
- public AssetHandler(StaticAsset staticAsset) {
- this.staticAsset = checkNotNull(staticAsset);
- }
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- OutputStream responseBody = resp.getOutputStream();
-
- if (checksumMatches(req)) {
- resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- } else {
- setPayloadHeaders(resp);
-
- boolean gzip = supportsGzip(req);
- if (gzip) {
- resp.setHeader("Content-Encoding", GZIP_ENCODING);
- }
-
- InputStream in = new ByteArrayInputStream(
- gzip ? staticAsset.getGzipData() : staticAsset.getRawData());
- ByteStreams.copy(in, responseBody);
- }
-
- Closeables.close(responseBody, /* swallowIOException */ true);
- }
-
- private void setPayloadHeaders(HttpServletResponse resp) throws IOException {
- resp.setStatus(HttpServletResponse.SC_OK);
- resp.setContentType(staticAsset.getContentType());
- resp.setHeader("Cache-Control", "public,max-age=" + CACHE_CONTROL_MAX_AGE_SECS);
-
- String checksum = staticAsset.getChecksum();
- if (checksum != null) {
- resp.setHeader("ETag", checksum);
- }
- }
-
- private boolean checksumMatches(HttpServletRequest req) throws IOException {
- // TODO(William Farner): Change this to more fully comply with
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
- // Specifically - a response to 'If-None-Match: *' should include ETag as well as other
- // cache-related headers.
- String suppliedETag = req.getHeader("If-None-Match");
- if ("*".equals(suppliedETag)) {
- return true;
- }
-
- String checksum = staticAsset.getChecksum();
- // Note - this isn't a completely accurate check since the tag we end up matching against could
- // theoretically be the actual tag with some extra characters appended.
- return (checksum != null) && (suppliedETag != null) && suppliedETag.contains(checksum);
- }
-
- private static boolean supportsGzip(HttpServletRequest req) {
- String header = req.getHeader("Accept-Encoding");
- return (header != null)
- && Iterables.contains(Splitter.on(",").trimResults().split(header), GZIP_ENCODING);
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ContentionPrinter.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ContentionPrinter.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ContentionPrinter.java
index 1f8c453..8f14626 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ContentionPrinter.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ContentionPrinter.java
@@ -13,12 +13,6 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.primitives.Longs;
-
-import javax.servlet.http.HttpServletRequest;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
@@ -26,18 +20,30 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.Longs;
+
/**
* HTTP request handler that prints information about blocked threads.
*
* @author William Farner
*/
-public class ContentionPrinter extends TextResponseHandler {
+@Path("/contention")
+public class ContentionPrinter {
public ContentionPrinter() {
ManagementFactory.getThreadMXBean().setThreadContentionMonitoringEnabled(true);
}
- @Override
- public Iterable<String> getLines(HttpServletRequest request) {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getContention() {
List<String> lines = Lists.newLinkedList();
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
@@ -67,7 +73,7 @@ public class ContentionPrinter extends TextResponseHandler {
}
}
- return lines;
+ return String.join("\n", lines);
}
private static List<String> getThreadInfo(ThreadInfo t, StackTraceElement[] stack) {
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/HealthHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/HealthHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/HealthHandler.java
index cc5ad4d..731151c 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/HealthHandler.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/HealthHandler.java
@@ -13,27 +13,24 @@
*/
package org.apache.aurora.common.net.http.handlers;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
import com.google.inject.name.Named;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
/**
* A servlet that provides a crude mechanism for monitoring a service's health. If the servlet
* returns {@link #IS_HEALTHY} then the containing service should be deemed healthy.
*
* @author John Sirois
*/
-public class HealthHandler extends HttpServlet {
+@Path("/health")
+public class HealthHandler {
/**
* A {@literal @Named} binding key for the Healthz servlet health checker.
@@ -49,8 +46,6 @@ public class HealthHandler extends HttpServlet {
private static final String IS_NOT_HEALTHY = "SICK";
- private static final Logger LOG = Logger.getLogger(HealthHandler.class.getName());
-
private final Supplier<Boolean> healthChecker;
/**
@@ -66,17 +61,9 @@ public class HealthHandler extends HttpServlet {
this.healthChecker = Preconditions.checkNotNull(healthChecker);
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- resp.setContentType("text/plain");
- PrintWriter writer = resp.getWriter();
- try {
- writer.println(Boolean.TRUE.equals(healthChecker.get()) ? IS_HEALTHY : IS_NOT_HEALTHY);
- } catch (Exception e) {
- writer.println(IS_NOT_HEALTHY);
- LOG.log(Level.WARNING, "Health check failed.", e);
- }
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getHealth() {
+ return healthChecker.get() ? IS_HEALTHY : IS_NOT_HEALTHY;
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java
index 5520fb6..aaaa348 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java
@@ -13,33 +13,38 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import java.io.IOException;
+import java.io.StringWriter;
import java.util.List;
+import java.util.Optional;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.LoggingMXBean;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
-import com.google.inject.Inject;
import org.antlr.stringtemplate.StringTemplate;
-import org.apache.commons.lang.StringUtils;
-
import org.apache.aurora.common.base.Closure;
+import org.apache.aurora.common.util.templating.StringTemplateHelper;
+import org.apache.aurora.common.util.templating.StringTemplateHelper.TemplateException;
+import org.apache.commons.lang.StringUtils;
/**
* Servlet that allows for dynamic adjustment of the logging configuration.
*
* @author William Farner
*/
-public class LogConfig extends StringTemplateServlet {
+@Path("/logconfig")
+public class LogConfig {
private static final List<String> LOG_LEVELS = Lists.newArrayList(
Level.SEVERE.getName(),
Level.WARNING.getName(),
@@ -51,43 +56,45 @@ public class LogConfig extends StringTemplateServlet {
"INHERIT" // Display value for a null level, the logger inherits from its ancestor.
);
- @Inject
- public LogConfig(@CacheTemplates boolean cacheTemplates) {
- super("logconfig", cacheTemplates);
- }
+ private final StringTemplateHelper template =
+ new StringTemplateHelper(getClass(), "logconfig", false);
+
+ @POST
+ @Produces(MediaType.TEXT_HTML)
+ public String post(
+ @FormParam("logger") String loggerName,
+ @FormParam("level") String loggerLevel) throws TemplateException {
+
+ Optional<String> configChange = Optional.empty();
+ if (loggerName != null && loggerLevel != null) {
+ Logger logger = Logger.getLogger(loggerName);
+ Level newLevel = loggerLevel.equals("INHERIT") ? null : Level.parse(loggerLevel);
+ logger.setLevel(newLevel);
+ if (newLevel != null) {
+ maybeAdjustHandlerLevels(logger, newLevel);
+ }
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- displayPage(req, resp, true);
+ configChange = Optional.of(String.format("%s level changed to %s", loggerName, loggerLevel));
+ }
+
+ return displayPage(configChange);
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- displayPage(req, resp, false);
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ public String get() throws TemplateException {
+ return displayPage(Optional.empty());
}
- protected void displayPage(final HttpServletRequest req, HttpServletResponse resp,
- final boolean posted) throws ServletException, IOException {
- writeTemplate(resp, new Closure<StringTemplate>() {
+ protected String displayPage(Optional<String> configChange) throws TemplateException {
+ StringWriter writer = new StringWriter();
+
+ template.writeTemplate(writer, new Closure<StringTemplate>() {
@Override public void execute(StringTemplate stringTemplate) {
LoggingMXBean logBean = LogManager.getLoggingMXBean();
- if (posted) {
- String loggerName = req.getParameter("logger");
- String loggerLevel = req.getParameter("level");
- if (loggerName != null && loggerLevel != null) {
- Logger logger = Logger.getLogger(loggerName);
- Level newLevel = loggerLevel.equals("INHERIT") ? null : Level.parse(loggerLevel);
- logger.setLevel(newLevel);
- if (newLevel != null) {
- maybeAdjustHandlerLevels(logger, newLevel);
- }
-
- stringTemplate.setAttribute("configChange",
- String.format("%s level changed to %s", loggerName, loggerLevel));
- }
+ if (configChange.isPresent()) {
+ stringTemplate.setAttribute("configChange", configChange.get());
}
List<LoggerConfig> loggerConfigs = Lists.newArrayList();
@@ -99,6 +106,8 @@ public class LogConfig extends StringTemplateServlet {
stringTemplate.setAttribute("levels", LOG_LEVELS);
}
});
+
+ return writer.toString();
}
private void maybeAdjustHandlerLevels(Logger logger, Level newLevel) {
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/QuitHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/QuitHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/QuitHandler.java
index 4ce3c97..40872e2 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/QuitHandler.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/QuitHandler.java
@@ -13,14 +13,14 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
@@ -30,7 +30,8 @@ import com.google.inject.name.Named;
* A servlet that provides a way to remotely signal the process to initiate a clean shutdown
* sequence.
*/
-public class QuitHandler extends HttpServlet {
+@Path("/quitquitquit")
+public class QuitHandler {
private static final Logger LOG = Logger.getLogger(QuitHandler.class.getName());
/**
@@ -53,19 +54,13 @@ public class QuitHandler extends HttpServlet {
this.quitListener = Preconditions.checkNotNull(quitListener);
}
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String quit(@Context HttpServletRequest req) {
LOG.info(String.format("Received quit HTTP signal from %s (%s)",
req.getRemoteAddr(), req.getRemoteHost()));
- resp.setContentType("text/plain");
- PrintWriter writer = resp.getWriter();
- try {
- writer.println("Notifying quit listener.");
- writer.close();
- new Thread(quitListener).start();
- } catch (Exception e) {
- LOG.log(Level.WARNING, "Quit failed.", e);
- }
+ new Thread(quitListener).start();
+ return "Notifying quit listener.";
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/StringTemplateServlet.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/StringTemplateServlet.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/StringTemplateServlet.java
deleted file mode 100644
index 60e0abb..0000000
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/StringTemplateServlet.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * Licensed 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.aurora.common.net.http.handlers;
-
-import com.google.common.base.Preconditions;
-import com.google.inject.BindingAnnotation;
-
-import org.apache.aurora.common.base.Closure;
-import org.apache.aurora.common.base.MorePreconditions;
-import org.apache.aurora.common.util.templating.StringTemplateHelper;
-import org.apache.aurora.common.util.templating.StringTemplateHelper.TemplateException;
-
-import org.antlr.stringtemplate.StringTemplate;
-
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * A base class for servlets that render using the string template templating system. Subclasses
- * can call one of the {@link #writeTemplate} methods to render their content with the associated
- * template.
- */
-public abstract class StringTemplateServlet extends HttpServlet {
- private static final String CONTENT_TYPE_TEXT_HTML = "text/html";
-
- /**
- * A {@literal @BindingAnnotation} that allows configuration of whether or not
- * StringTemplateServlets should cache their templates.
- */
- @BindingAnnotation
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER, ElementType.METHOD})
- public @interface CacheTemplates {}
-
- private static final Logger LOG = Logger.getLogger(StringTemplateServlet.class.getName());
-
- private final StringTemplateHelper templateHelper;
-
- /**
- * Creates a new StringTemplateServlet that expects to find its template located in the same
- * package on the classpath at '{@code templateName}.st'.
- *
- * @param templateName The name of the string template to use.
- * @param cacheTemplates {@code true} to re-use loaded templates, {@code false} to reload the
- * template for each request.
- */
- protected StringTemplateServlet(String templateName, boolean cacheTemplates) {
- templateHelper = new StringTemplateHelper(getClass(), templateName, cacheTemplates);
- }
-
- protected final void writeTemplate(
- HttpServletResponse response,
- Closure<StringTemplate> parameterSetter) throws IOException {
-
- writeTemplate(response, CONTENT_TYPE_TEXT_HTML, HttpServletResponse.SC_OK, parameterSetter);
- }
-
- protected final void writeTemplate(
- HttpServletResponse response,
- String contentType,
- int status,
- Closure<StringTemplate> parameterSetter) throws IOException {
-
- Preconditions.checkNotNull(response);
- MorePreconditions.checkNotBlank(contentType);
- Preconditions.checkArgument(status > 0);
- Preconditions.checkNotNull(parameterSetter);
-
- try {
- templateHelper.writeTemplate(response.getWriter(), parameterSetter);
- response.setStatus(status);
- response.setContentType(contentType);
- } catch (TemplateException e) {
- LOG.log(Level.SEVERE, "Unknown exception.", e);
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TextResponseHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TextResponseHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TextResponseHandler.java
deleted file mode 100644
index 23068eb..0000000
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TextResponseHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Licensed 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.aurora.common.net.http.handlers;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * A handler that responds to all requests in HTML format.
- *
- * @author William Farner
- */
-public abstract class TextResponseHandler extends HttpServlet {
- private final String textContentType;
-
- public TextResponseHandler() {
- this("text/plain");
- }
-
- public TextResponseHandler(String textContentType) {
- this.textContentType = textContentType;
- }
-
- /**
- * Returns the lines to be printed as the body of the response.
- *
- * @return An iterable collection of lines to respond to the request with.
- */
- public abstract Iterable<String> getLines(HttpServletRequest request);
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- resp.setContentType(textContentType);
- resp.setStatus(HttpServletResponse.SC_OK);
- PrintWriter responseBody = resp.getWriter();
- for (String line : getLines(req)) {
- responseBody.println(line);
- }
- responseBody.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ThreadStackPrinter.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ThreadStackPrinter.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ThreadStackPrinter.java
index 5dd8804..ab3af86 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ThreadStackPrinter.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/ThreadStackPrinter.java
@@ -13,20 +13,27 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import com.google.common.collect.Lists;
-
-import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
/**
* HTTP handler to print the stacks of all live threads.
*
* @author William Farner
*/
-public class ThreadStackPrinter extends TextResponseHandler {
- @Override
- public Iterable<String> getLines(HttpServletRequest request) {
+@Path("/threads")
+public class ThreadStackPrinter {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getThreadStacks() {
List<String> lines = Lists.newLinkedList();
for (Map.Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
Thread t = entry.getKey();
@@ -36,6 +43,6 @@ public class ThreadStackPrinter extends TextResponseHandler {
lines.add(" " + s.toString());
}
}
- return lines;
+ return Joiner.on("\n").join(lines);
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TimeSeriesDataSource.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TimeSeriesDataSource.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TimeSeriesDataSource.java
index e87fe2c..8039def 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TimeSeriesDataSource.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/TimeSeriesDataSource.java
@@ -13,15 +13,14 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.util.List;
import javax.annotation.Nullable;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
@@ -33,7 +32,6 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import com.google.common.net.MediaType;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.inject.Inject;
@@ -45,7 +43,8 @@ import org.apache.aurora.common.stats.TimeSeriesRepository;
/**
* A servlet that provides time series data in JSON format.
*/
-public class TimeSeriesDataSource extends HttpServlet {
+@Path("/graphdata/")
+public class TimeSeriesDataSource {
@VisibleForTesting static final String TIME_METRIC = "time";
@@ -96,21 +95,17 @@ public class TimeSeriesDataSource extends HttpServlet {
ResponseStruct response = new ResponseStruct(
ImmutableList.<String>builder().add(TIME_METRIC).addAll(names).build(),
FluentIterable.from(Iterables2.zip(tsData, 0)).filter(sinceFilter).toList());
+ // TODO(wfarner): Let the jax-rs provider handle serialization.
return gson.toJson(response);
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- resp.setContentType(MediaType.JSON_UTF_8.toString());
- PrintWriter out = resp.getWriter();
- try {
- out.write(getResponse(req.getParameter(METRICS), req.getParameter(SINCE)));
- } catch (MetricException e) {
- resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- out.write(e.getMessage());
- }
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getData(
+ @QueryParam(METRICS) String metrics,
+ @QueryParam(SINCE) String since) throws MetricException {
+
+ return getResponse(metrics, since);
}
@VisibleForTesting
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsHandler.java
index bf04525..d1f23de 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsHandler.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsHandler.java
@@ -16,9 +16,13 @@ package org.apache.aurora.common.net.http.handlers;
import java.util.Collections;
import java.util.List;
-import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
import com.google.common.base.Function;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
@@ -32,7 +36,8 @@ import org.apache.aurora.common.stats.Stat;
*
* @author William Farner
*/
-public class VarsHandler extends TextResponseHandler {
+@Path("/vars")
+public class VarsHandler {
private static final Function<Stat, String> VAR_PRINTER = new Function<Stat, String>() {
@Override public String apply(Stat stat) {
@@ -52,10 +57,11 @@ public class VarsHandler extends TextResponseHandler {
this.statSupplier = Preconditions.checkNotNull(statSupplier);
}
- @Override
- public Iterable<String> getLines(HttpServletRequest request) {
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String getVars() {
List<String> lines = Lists.newArrayList(Iterables.transform(statSupplier.get(), VAR_PRINTER));
Collections.sort(lines);
- return lines;
+ return Joiner.on("\n").join(lines);
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsJsonHandler.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsJsonHandler.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsJsonHandler.java
index e97ec60..850c784 100644
--- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsJsonHandler.java
+++ b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/VarsJsonHandler.java
@@ -13,14 +13,13 @@
*/
package org.apache.aurora.common.net.http.handlers;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.util.Map;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
@@ -45,9 +44,10 @@ import org.apache.aurora.common.stats.Stat;
* If the optional URL parameter 'pretty' is used, the output will be pretty-printed
* (similar to the above example).
*
- * @author William Farner
+ * TODO(wfarner): Handle this request in VarsHandler.
*/
-public class VarsJsonHandler extends HttpServlet {
+@Path("/vars.json")
+public class VarsJsonHandler {
private final Supplier<Iterable<Stat<?>>> statSupplier;
@@ -67,21 +67,14 @@ public class VarsJsonHandler extends HttpServlet {
for (Stat<?> var : statSupplier.get()) {
vars.put(var.getName(), var.read());
}
+ // TODO(wfarner): Let the jax-rs provider handle serialization.
return getGson(pretty).toJson(vars);
}
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
-
- resp.setContentType("application/json");
- resp.setStatus(HttpServletResponse.SC_OK);
- PrintWriter responseBody = resp.getWriter();
- try {
- responseBody.print(getBody(req.getParameter("pretty") != null));
- } finally {
- responseBody.close();
- }
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getVars(@QueryParam("pretty") boolean pretty) {
+ return getBody(pretty);
}
private Gson getGson(boolean pretty) {
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/test/java/org/apache/aurora/common/net/http/handlers/AssetHandlerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/net/http/handlers/AssetHandlerTest.java b/commons/src/test/java/org/apache/aurora/common/net/http/handlers/AssetHandlerTest.java
deleted file mode 100644
index 740c42f..0000000
--- a/commons/src/test/java/org/apache/aurora/common/net/http/handlers/AssetHandlerTest.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/**
- * Licensed 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.aurora.common.net.http.handlers;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.google.common.io.ByteSource;
-import com.google.common.io.ByteStreams;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import org.apache.aurora.common.testing.easymock.EasyMockTest;
-
-import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-import static org.easymock.EasyMock.createMockBuilder;
-import static org.easymock.EasyMock.expect;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * @author William Farner
- */
-public class AssetHandlerTest extends EasyMockTest {
-
- private static final String TEST_DATA = "here is my great test data";
- // Checksum of the gzipped TEST_DATA.
- private static final String TEST_DATA_CHECKSUM = "ePvVhtAeVRu85KSOLKL0oQ==";
- private static final String CONTENT_TYPE = "text/plain";
-
- private ByteSource byteSource;
-
- @Before
- public void setUp() {
- byteSource = createMock(ByteSource.class);
- }
-
- private static class Request {
- private final HttpServletRequest req;
- private final HttpServletResponse resp;
- private final ByteArrayOutputStream responseBody;
-
- Request(HttpServletRequest req, HttpServletResponse resp, ByteArrayOutputStream responseBody) {
- this.req = req;
- this.resp = resp;
- this.responseBody = responseBody;
- }
- }
-
- private Request doGet(String suppliedChecksum, String supportedEncodings,
- int expectedResponseCode, boolean expectRead) throws Exception {
- HttpServletRequest req = createMock(HttpServletRequest.class);
- HttpServletResponse resp = createMock(HttpServletResponse.class);
-
- if (expectRead) {
- expect(byteSource.openStream()).andReturn(new ByteArrayInputStream(TEST_DATA.getBytes()));
- }
-
- expect(req.getHeader("If-None-Match")).andReturn(suppliedChecksum);
-
- resp.setStatus(expectedResponseCode);
- if (expectedResponseCode == SC_OK) {
- expect(req.getHeader("Accept-Encoding")).andReturn(supportedEncodings);
- resp.setHeader("Cache-Control", "public,max-age=" + AssetHandler.CACHE_CONTROL_MAX_AGE_SECS);
- resp.setHeader("ETag", TEST_DATA_CHECKSUM);
- resp.setContentType(CONTENT_TYPE);
-
- if (supportedEncodings != null && supportedEncodings.contains("gzip")) {
- resp.setHeader("Content-Encoding", "gzip");
- }
- }
- return new Request(req, resp, expectPayload(resp));
- }
-
- @Test
- public void testCached() throws Exception {
-
- // First request - no cached value
- Request test1 = doGet(
- null, // No local checksum.
- null, // No encodings supported.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Second request - client performs conditional GET with wrong checksum.
- Request test2 = doGet(
- "foo", // Wrong checksum.
- null, // No encodings supported.
- SC_OK,
- false // No read.
- );
-
- // Third request - client performs conditional GET with correct checksum.
- Request test3 = doGet(
- TEST_DATA_CHECKSUM, // Correct checksum.
- null, // No encodings supported.
- SC_NOT_MODIFIED,
- false // No read.
- );
-
- control.replay();
-
- AssetHandler handler = new AssetHandler(new AssetHandler.StaticAsset(byteSource, CONTENT_TYPE, true));
-
- handler.doGet(test1.req, test1.resp);
- assertThat(new String(test1.responseBody.toByteArray()), is(TEST_DATA));
-
- handler.doGet(test2.req, test2.resp);
- assertThat(new String(test2.responseBody.toByteArray()), is(TEST_DATA));
-
- handler.doGet(test3.req, test3.resp);
- assertThat(new String(test3.responseBody.toByteArray()), is(""));
- }
-
- @Test
- public void testCachedGzipped() throws Exception {
-
- // First request - no cached value
- Request test1 = doGet(
- null, // No local checksum.
- "gzip", // Supported encodings.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Second request - client performs conditional GET with wrong checksum.
- Request test2 = doGet(
- "foo", // Wrong checksum.
- "gzip,fakeencoding", // Supported encodings.
- SC_OK,
- false // No read.
- );
-
- // Third request - client performs conditional GET with correct checksum.
- Request test3 = doGet(
- TEST_DATA_CHECKSUM, // Correct checksum.
- "gzip,deflate", // Supported encodings.
- SC_NOT_MODIFIED,
- false // No read.
- );
-
- control.replay();
-
- AssetHandler handler = new AssetHandler(new AssetHandler.StaticAsset(byteSource, CONTENT_TYPE, true));
-
- handler.doGet(test1.req, test1.resp);
- assertThat(unzip(test1.responseBody), is(TEST_DATA));
-
- handler.doGet(test2.req, test2.resp);
- assertThat(unzip(test2.responseBody), is(TEST_DATA));
-
- handler.doGet(test3.req, test3.resp);
- assertThat(new String(test3.responseBody.toByteArray()), is(""));
- }
-
- @Test
- public void testUncached() throws Exception {
-
- // First request - no cached value
- Request test1 = doGet(
- null, // No local checksum.
- null, // No encodings supported.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Second request - client performs conditional GET with wrong checksum.
- Request test2 = doGet(
- "foo", // Wrong checksum.
- null, // No encodings supported.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Third request - client performs conditional GET with correct checksum.
- Request test3 = doGet(
- TEST_DATA_CHECKSUM, // Correct checksum.
- null, // No encodings supported.
- SC_NOT_MODIFIED,
- true // Triggers a data read.
- );
-
- control.replay();
-
- AssetHandler handler = new AssetHandler(new AssetHandler.StaticAsset(byteSource, CONTENT_TYPE, false));
-
- handler.doGet(test1.req, test1.resp);
- assertThat(new String(test1.responseBody.toByteArray()), is(TEST_DATA));
-
- handler.doGet(test2.req, test2.resp);
- assertThat(new String(test2.responseBody.toByteArray()), is(TEST_DATA));
-
- handler.doGet(test3.req, test3.resp);
- assertThat(new String(test3.responseBody.toByteArray()), is(""));
- }
-
- @Test
- public void testUncachedGzipped() throws Exception {
-
- // First request - no cached value
- Request test1 = doGet(
- null, // No local checksum.
- "gzip", // Supported encodings.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Second request - client performs conditional GET with wrong checksum.
- Request test2 = doGet(
- "foo", // Wrong checksum.
- "gzip,fakeencoding", // Supported encodings.
- SC_OK,
- true // Triggers a data read.
- );
-
- // Third request - client performs conditional GET with correct checksum.
- Request test3 = doGet(
- TEST_DATA_CHECKSUM, // Correct checksum.
- "gzip,deflate", // Supported encodings.
- SC_NOT_MODIFIED,
- true // Triggers a data read.
- );
-
- control.replay();
-
- AssetHandler handler = new AssetHandler(new AssetHandler.StaticAsset(byteSource, CONTENT_TYPE, false));
-
- handler.doGet(test1.req, test1.resp);
- assertThat(unzip(test1.responseBody), is(TEST_DATA));
-
- handler.doGet(test2.req, test2.resp);
- assertThat(unzip(test2.responseBody), is(TEST_DATA));
-
- handler.doGet(test3.req, test3.resp);
- assertThat(new String(test3.responseBody.toByteArray()), is(""));
- }
-
- private static ByteArrayOutputStream expectPayload(HttpServletResponse resp) throws Exception {
- ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
- expect(resp.getOutputStream()).andReturn(new FakeServletOutputStream(responseBody));
- return responseBody;
- }
-
- private static String unzip(ByteArrayOutputStream streamData) throws IOException {
- ByteArrayInputStream in = new ByteArrayInputStream(streamData.toByteArray());
- GZIPInputStream unzip = new GZIPInputStream(in);
- return new String(ByteStreams.toByteArray(unzip));
- }
-
- private static class FakeServletOutputStream extends ServletOutputStream {
- private final OutputStream realStream;
-
- FakeServletOutputStream(OutputStream realStream) {
- this.realStream = realStream;
- }
-
- @Override
- public void write(int b) throws IOException {
- realStream.write(b);
- }
-
- @Override
- public void write(byte[] b) throws IOException {
- realStream.write(b);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- realStream.write(b, off, len);
- }
-
- @Override
- public void flush() throws IOException {
- realStream.flush();
- }
-
- @Override
- public void close() throws IOException {
- realStream.close();
- }
-
- @Override
- public void print(String s) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(boolean b) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(char c) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(int i) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(long l) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(float f) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void print(double d) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println() throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(String s) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(boolean b) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(char c) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(int i) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(long l) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(float f) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
-
- @Override
- public void println(double d) throws IOException {
- throw new UnsupportedOperationException("Not implemented");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/commons/src/test/java/org/apache/aurora/common/net/http/handlers/VarsHandlerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/org/apache/aurora/common/net/http/handlers/VarsHandlerTest.java b/commons/src/test/java/org/apache/aurora/common/net/http/handlers/VarsHandlerTest.java
index 34f62fb..6c4feaf 100644
--- a/commons/src/test/java/org/apache/aurora/common/net/http/handlers/VarsHandlerTest.java
+++ b/commons/src/test/java/org/apache/aurora/common/net/http/handlers/VarsHandlerTest.java
@@ -20,14 +20,12 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import org.apache.aurora.common.stats.Stat;
import org.junit.Before;
import org.junit.Test;
-import org.apache.aurora.common.stats.Stat;
-
import static org.junit.Assert.assertEquals;
/**
@@ -72,7 +70,6 @@ public class VarsHandlerTest extends StatSupplierTestBase {
}
private void checkOutput(List<String> expectedLines) {
- assertEquals(expectedLines,
- ImmutableList.copyOf(vars.getLines(request)));
+ assertEquals(String.join("\n", expectedLines), vars.getVars());
}
}
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/config/legacy_untested_classes.txt
----------------------------------------------------------------------
diff --git a/config/legacy_untested_classes.txt b/config/legacy_untested_classes.txt
index 7b891b2..88a71df 100644
--- a/config/legacy_untested_classes.txt
+++ b/config/legacy_untested_classes.txt
@@ -9,9 +9,9 @@ org/apache/aurora/scheduler/async/OfferQueue$OfferQueueImpl$2
org/apache/aurora/scheduler/base/Conversions$1
org/apache/aurora/scheduler/base/Conversions$2
org/apache/aurora/scheduler/base/Conversions$3
-org/apache/aurora/scheduler/base/Conversions$4
org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl
org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl$1
+org/apache/aurora/scheduler/http/AbortCallback
org/apache/aurora/scheduler/http/JerseyTemplateServlet
org/apache/aurora/scheduler/http/Maintenance
org/apache/aurora/scheduler/http/Maintenance$1
http://git-wip-us.apache.org/repos/asf/aurora/blob/9dff0571/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
index c503dcc..f9b0687 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
@@ -17,6 +17,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.EnumSet;
import java.util.Map;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -24,15 +25,19 @@ import javax.annotation.Nonnegative;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.ServletContextListener;
-import javax.servlet.http.HttpServlet;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
import com.google.common.net.HostAndPort;
import com.google.common.util.concurrent.AbstractIdleService;
import com.google.inject.AbstractModule;
@@ -56,7 +61,6 @@ import org.apache.aurora.common.net.http.handlers.ContentionPrinter;
import org.apache.aurora.common.net.http.handlers.HealthHandler;
import org.apache.aurora.common.net.http.handlers.LogConfig;
import org.apache.aurora.common.net.http.handlers.QuitHandler;
-import org.apache.aurora.common.net.http.handlers.StringTemplateServlet;
import org.apache.aurora.common.net.http.handlers.ThreadStackPrinter;
import org.apache.aurora.common.net.http.handlers.TimeSeriesDataSource;
import org.apache.aurora.common.net.http.handlers.VarsHandler;
@@ -143,8 +147,6 @@ public class JettyServerModule extends AbstractModule {
.annotatedWith(Names.named(HealthHandler.HEALTH_CHECKER_KEY))
.toInstance(Suppliers.ofInstance(true));
- bindConstant().annotatedWith(StringTemplateServlet.CacheTemplates.class).to(true);
-
final Optional<String> hostnameOverride = Optional.fromNullable(HOSTNAME_OVERRIDE.get());
if (hostnameOverride.isPresent()) {
try {
@@ -195,6 +197,48 @@ public class JettyServerModule extends AbstractModule {
}
};
+ private static final Set<String> LEADER_ENDPOINTS = ImmutableSet.of(
+ "api",
+ "cron",
+ "locks",
+ "maintenance",
+ "mname",
+ "offers",
+ "pendingtasks",
+ "quotas",
+ "slaves",
+ "utilization"
+ );
+
+ private static final Multimap<Class<?>, String> JAX_RS_ENDPOINTS =
+ ImmutableMultimap.<Class<?>, String>builder()
+ .put(AbortHandler.class, "abortabortabort")
+ .put(ContentionPrinter.class, "contention")
+ .put(Cron.class, "cron")
+ .put(Locks.class, "locks")
+ .put(LogConfig.class, "logconfig")
+ .put(Maintenance.class, "maintenance")
+ .put(Mname.class, "mname")
+ .put(Offers.class, "offers")
+ .put(PendingTasks.class, "pendingtasks")
+ .put(QuitHandler.class, "quitquitquit")
+ .put(Quotas.class, "quotas")
+ .put(Services.class, "services")
+ .put(Slaves.class, "slaves")
+ .put(StructDump.class, "structdump")
+ .put(ThreadStackPrinter.class, "threads")
+ .put(TimeSeriesDataSource.class, "graphdata")
+ .put(Utilization.class, "utilization")
+ .put(VarsHandler.class, "vars")
+ .put(VarsJsonHandler.class, "vars.json")
+ .build();
+
+ private static String allOf(Set<String> paths) {
+ return "^(?:"
+ + Joiner.on("|").join(Iterables.transform(paths, path -> "/" + path))
+ + ").*$";
+ }
+
// TODO(ksweeney): Factor individual servlet configurations to their own ServletModules.
@VisibleForTesting
static ServletContextListener makeServletContextListener(
@@ -207,22 +251,18 @@ public class JettyServerModule extends AbstractModule {
return parentInjector.createChildInjector(
childModule,
new JerseyServletModule() {
- private void registerJerseyEndpoint(String indexPath, Class<?> servlet) {
- filter(indexPath + "*").through(LeaderRedirectFilter.class);
- filter(indexPath + "*").through(GuiceContainer.class, GUICE_CONTAINER_PARAMS);
- bind(servlet);
- }
-
- private void registerServlet(String pathSpec, Class<? extends HttpServlet> servlet) {
- bind(servlet).in(Singleton.class);
- serve(pathSpec).with(servlet);
- }
-
@Override
protected void configureServlets() {
bind(HttpStatsFilter.class).in(Singleton.class);
filter("*").through(HttpStatsFilter.class);
+
bind(LeaderRedirectFilter.class).in(Singleton.class);
+ filterRegex(allOf(LEADER_ENDPOINTS))
+ .through(LeaderRedirectFilter.class);
+
+ bind(GuiceContainer.class).in(Singleton.class);
+ filterRegex(allOf(ImmutableSet.copyOf(JAX_RS_ENDPOINTS.values())))
+ .through(GuiceContainer.class, GUICE_CONTAINER_PARAMS);
filterRegex("/assets/.*").through(new GzipFilter());
filterRegex("/assets/scheduler(?:/.*)?").through(LeaderRedirectFilter.class);
@@ -232,28 +272,9 @@ public class JettyServerModule extends AbstractModule {
"resourceBase", STATIC_ASSETS_ROOT,
"dirAllowed", "false"));
- bind(GuiceContainer.class).in(Singleton.class);
- registerJerseyEndpoint("/cron", Cron.class);
- registerJerseyEndpoint("/locks", Locks.class);
- registerJerseyEndpoint("/maintenance", Maintenance.class);
- registerJerseyEndpoint("/mname", Mname.class);
- registerJerseyEndpoint("/offers", Offers.class);
- registerJerseyEndpoint("/pendingtasks", PendingTasks.class);
- registerJerseyEndpoint("/quotas", Quotas.class);
- registerJerseyEndpoint("/services", Services.class);
- registerJerseyEndpoint("/slaves", Slaves.class);
- registerJerseyEndpoint("/structdump", StructDump.class);
- registerJerseyEndpoint("/utilization", Utilization.class);
-
- registerServlet("/abortabortabort", AbortHandler.class);
- registerServlet("/contention", ContentionPrinter.class);
- registerServlet("/health", HealthHandler.class);
- registerServlet("/logconfig", LogConfig.class);
- registerServlet("/quitquitquit", QuitHandler.class);
- registerServlet("/threads", ThreadStackPrinter.class);
- registerServlet("/graphdata/", TimeSeriesDataSource.class);
- registerServlet("/vars", VarsHandler.class);
- registerServlet("/vars.json", VarsJsonHandler.class);
+ for (Class<?> jaxRsHandler : JAX_RS_ENDPOINTS.keySet()) {
+ bind(jaxRsHandler);
+ }
}
});
}
@@ -353,7 +374,7 @@ public class JettyServerModule extends AbstractModule {
new ServletContextHandler(server, "/", ServletContextHandler.NO_SESSIONS);
servletHandler.addServlet(DefaultServlet.class, "/");
- servletHandler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
+ servletHandler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
servletHandler.addEventListener(servletContextListener);
HandlerCollection rootHandler = new HandlerCollection();