diff --git a/google-oauth-client-jetty/pom.xml b/google-oauth-client-jetty/pom.xml
index d37ca4e60..1bcfbc6b7 100644
--- a/google-oauth-client-jetty/pom.xml
+++ b/google-oauth-client-jetty/pom.xml
@@ -86,10 +86,6 @@
com.google.oauth-client
google-oauth-client-java6
-
- org.eclipse.jetty
- jetty-server
-
junit
junit
diff --git a/google-oauth-client-jetty/src/main/java/com/google/api/client/extensions/jetty/auth/oauth2/LocalServerReceiver.java b/google-oauth-client-jetty/src/main/java/com/google/api/client/extensions/jetty/auth/oauth2/LocalServerReceiver.java
index 06f26f873..341661a10 100644
--- a/google-oauth-client-jetty/src/main/java/com/google/api/client/extensions/jetty/auth/oauth2/LocalServerReceiver.java
+++ b/google-oauth-client-jetty/src/main/java/com/google/api/client/extensions/jetty/auth/oauth2/LocalServerReceiver.java
@@ -14,17 +14,24 @@
package com.google.api.client.extensions.jetty.auth.oauth2;
+import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
+import static java.net.HttpURLConnection.HTTP_OK;
+
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
import com.google.api.client.util.Throwables;
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.Semaphore;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
/**
* OAuth 2.0 verification code receiver that runs a Jetty server on a free port, waiting for a
@@ -34,8 +41,8 @@
* Implementation is thread-safe.
*
*
- * @since 1.11
* @author Yaniv Inbar
+ * @since 1.11
*/
public final class LocalServerReceiver implements VerificationCodeReceiver {
@@ -43,25 +50,39 @@ public final class LocalServerReceiver implements VerificationCodeReceiver {
private static final String CALLBACK_PATH = "/Callback";
- /** Server or {@code null} before {@link #getRedirectUri()}. */
- private Server server;
+ /**
+ * Server or {@code null} before {@link #getRedirectUri()}.
+ */
+ private HttpServer server;
- /** Verification code or {@code null} for none. */
+ /**
+ * Verification code or {@code null} for none.
+ */
String code;
- /** Error code or {@code null} for none. */
+ /**
+ * Error code or {@code null} for none.
+ */
String error;
- /** To block until receiving an authorization response or stop() is called. */
+ /**
+ * To block until receiving an authorization response or stop() is called.
+ */
final Semaphore waitUnlessSignaled = new Semaphore(0 /* initially zero permit */);
- /** Port to use or {@code -1} to select an unused port in {@link #getRedirectUri()}. */
+ /**
+ * Port to use or {@code -1} to select an unused port in {@link #getRedirectUri()}.
+ */
private int port;
- /** Host name to use. */
+ /**
+ * Host name to use.
+ */
private final String host;
- /** Callback path of redirect_uri */
+ /**
+ * Callback path of redirect_uri.
+ */
private final String callbackPath;
/**
@@ -71,8 +92,8 @@ public final class LocalServerReceiver implements VerificationCodeReceiver {
private String successLandingPageUrl;
/**
- * URL to an HTML page to be shown (via redirect) after failed login. If null, a canned
- * default landing page will be shown (via direct response).
+ * URL to an HTML page to be shown (via redirect) after failed login. If null, a canned default
+ * landing page will be shown (via direct response).
*/
private String failureLandingPageUrl;
@@ -94,7 +115,7 @@ public LocalServerReceiver() {
* @param port Port to use or {@code -1} to select an unused port
*/
LocalServerReceiver(String host, int port,
- String successLandingPageUrl, String failureLandingPageUrl) {
+ String successLandingPageUrl, String failureLandingPageUrl) {
this(host, port, CALLBACK_PATH, successLandingPageUrl, failureLandingPageUrl);
}
@@ -105,7 +126,7 @@ public LocalServerReceiver() {
* @param port Port to use or {@code -1} to select an unused port
*/
LocalServerReceiver(String host, int port, String callbackPath,
- String successLandingPageUrl, String failureLandingPageUrl) {
+ String successLandingPageUrl, String failureLandingPageUrl) {
this.host = host;
this.port = port;
this.callbackPath = callbackPath;
@@ -115,28 +136,42 @@ public LocalServerReceiver() {
@Override
public String getRedirectUri() throws IOException {
- server = new Server(port != -1 ? port : 0);
- Connector connector = server.getConnectors()[0];
- connector.setHost(host);
- server.setHandler(new CallbackHandler());
+
+ server = HttpServer.create(new InetSocketAddress(port != -1 ? port : findOpenPort()), 0);
+ HttpContext context = server.createContext(callbackPath, new CallbackHandler());
+ server.setExecutor(null);
+
try {
server.start();
- port = connector.getLocalPort();
+ port = server.getAddress().getPort();
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new IOException(e);
}
- return "http://" + connector.getHost() + ":" + port + callbackPath;
+ return "http://" + this.getHost() + ":" + port + callbackPath;
+ }
+
+ /*
+ *Copied from Jetty findFreePort() as referenced by: https://gist.github.com/vorburger/3429822
+ */
+
+ private int findOpenPort() {
+ try (ServerSocket socket = new ServerSocket(0)) {
+ socket.setReuseAddress(true);
+ return socket.getLocalPort();
+ } catch (IOException e) {
+ throw new IllegalStateException("No free TCP/IP port to start embedded HTTP Server on");
+ }
}
/**
- * Blocks until the server receives a login result, or the server is stopped
- * by {@link #stop()}, to return an authorization code.
+ * Blocks until the server receives a login result, or the server is stopped by {@link #stop()},
+ * to return an authorization code.
*
- * @return authorization code if login succeeds; may return {@code null} if the server
- * is stopped by {@link #stop()}
- * @throws IOException if the server receives an error code (through an HTTP request
- * parameter {@code error})
+ * @return authorization code if login succeeds; may return {@code null} if the server is stopped
+ * by {@link #stop()}
+ * @throws IOException if the server receives an error code (through an HTTP request parameter
+ * {@code error})
*/
@Override
public String waitForCode() throws IOException {
@@ -152,7 +187,7 @@ public void stop() throws IOException {
waitUnlessSignaled.release();
if (server != null) {
try {
- server.stop();
+ server.stop(0);
} catch (Exception e) {
Throwables.propagateIfPossible(e);
throw new IOException(e);
@@ -161,7 +196,9 @@ public void stop() throws IOException {
}
}
- /** Returns the host name to use. */
+ /**
+ * Returns the host name to use.
+ */
public String getHost() {
return host;
}
@@ -189,10 +226,14 @@ public String getCallbackPath() {
*/
public static final class Builder {
- /** Host name to use. */
+ /**
+ * Host name to use.
+ */
private String host = LOCALHOST;
- /** Port to use or {@code -1} to select an unused port. */
+ /**
+ * Port to use or {@code -1} to select an unused port.
+ */
private int port = -1;
private String successLandingPageUrl;
@@ -200,40 +241,54 @@ public static final class Builder {
private String callbackPath = CALLBACK_PATH;
- /** Builds the {@link LocalServerReceiver}. */
+ /**
+ * Builds the {@link LocalServerReceiver}.
+ */
public LocalServerReceiver build() {
return new LocalServerReceiver(host, port, callbackPath,
- successLandingPageUrl, failureLandingPageUrl);
+ successLandingPageUrl, failureLandingPageUrl);
}
- /** Returns the host name to use. */
+ /**
+ * Returns the host name to use.
+ */
public String getHost() {
return host;
}
- /** Sets the host name to use. */
+ /**
+ * Sets the host name to use.
+ */
public Builder setHost(String host) {
this.host = host;
return this;
}
- /** Returns the port to use or {@code -1} to select an unused port. */
+ /**
+ * Returns the port to use or {@code -1} to select an unused port.
+ */
public int getPort() {
return port;
}
- /** Sets the port to use or {@code -1} to select an unused port. */
+ /**
+ * Sets the port to use or {@code -1} to select an unused port.
+ */
public Builder setPort(int port) {
this.port = port;
return this;
}
- /** Returns the callback path of redirect_uri */
+ /**
+ * Returns the callback path of redirect_uri.
+ */
public String getCallbackPath() {
return callbackPath;
}
- /** Set the callback path of redirect_uri */
+ /**
+ * Set the callback path of redirect_uri.
+ */
public Builder setCallbackPath(String callbackPath) {
this.callbackPath = callbackPath;
return this;
@@ -247,44 +302,63 @@ public Builder setLandingPages(String successLandingPageUrl, String failureLandi
}
/**
- * Jetty handler that takes the verifier token passed over from the OAuth provider and stashes it
- * where {@link #waitForCode} will find it.
+ * HttpServer handler that takes the verifier token passed over from the OAuth provider and
+ * stashes it where {@link #waitForCode} will find it.
*/
- class CallbackHandler extends AbstractHandler {
+ class CallbackHandler implements HttpHandler {
@Override
- public void handle(
- String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response
- )
- throws IOException {
- if (!callbackPath.equals(target)) {
+ public void handle(HttpExchange httpExchange) throws IOException {
+
+ if (!callbackPath.equals(httpExchange.getRequestURI().getPath())) {
return;
}
+ StringBuilder body = new StringBuilder();
+
try {
- ((Request) request).setHandled(true);
- error = request.getParameter("error");
- code = request.getParameter("code");
+ Map parms =
+ this.queryToMap(httpExchange.getRequestURI().getQuery());
+ error = parms.get("error");
+ code = parms.get("code");
+ Headers respHeaders = httpExchange.getResponseHeaders();
if (error == null && successLandingPageUrl != null) {
- response.sendRedirect(successLandingPageUrl);
+ respHeaders.add("Location", successLandingPageUrl);
+ httpExchange.sendResponseHeaders(HTTP_MOVED_TEMP, -1);
} else if (error != null && failureLandingPageUrl != null) {
- response.sendRedirect(failureLandingPageUrl);
+ respHeaders.add("Location", failureLandingPageUrl);
+ httpExchange.sendResponseHeaders(HTTP_MOVED_TEMP, -1);
} else {
- writeLandingHtml(response);
+ writeLandingHtml(httpExchange, respHeaders);
}
- response.flushBuffer();
- }
- finally {
+ httpExchange.close();
+ } finally {
waitUnlessSignaled.release();
}
}
- private void writeLandingHtml(HttpServletResponse response) throws IOException {
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentType("text/html");
+ private Map queryToMap(String query) {
+ Map result = new HashMap();
+ if (query != null) {
+ for (String param : query.split("&")) {
+ String pair[] = param.split("=");
+ if (pair.length > 1) {
+ result.put(pair[0], pair[1]);
+ } else {
+ result.put(pair[0], "");
+ }
+ }
+ }
+ return result;
+ }
+
+ private void writeLandingHtml(HttpExchange exchange, Headers headers) throws IOException {
+ OutputStream os = exchange.getResponseBody();
+ exchange.sendResponseHeaders(HTTP_OK, 0);
+ headers.add("ContentType", "text/html");
- PrintWriter doc = response.getWriter();
+ PrintWriter doc = new PrintWriter(os);
doc.println("");
doc.println("OAuth 2.0 Authentication Token Received");
doc.println("");
@@ -292,6 +366,9 @@ private void writeLandingHtml(HttpServletResponse response) throws IOException {
doc.println("");
doc.println("");
doc.flush();
+ os.close();
}
+
}
+
}
diff --git a/pom.xml b/pom.xml
index 71a42f8b8..b3dd6d9dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -150,11 +150,6 @@
google-oauth-client-jetty
${project.version}
-
- org.eclipse.jetty
- jetty-server
- ${project.jetty.version}
-
org.datanucleus
datanucleus-core
@@ -399,6 +394,9 @@
java17
1.0
+
+ com.sun.net.httpserver.*
+