8174745: Httpclient source update for JDK 8

Reviewed-by: dfuchs
This commit is contained in:
Michael McMahon 2017-02-10 21:58:45 +00:00
parent 62274dc8df
commit f7c7a3c8b2
11 changed files with 61 additions and 110 deletions

@ -609,11 +609,13 @@ class AsyncSSLDelegate implements ExceptionallyCloseable, AsyncConnection {
}
// SSLParameters.getApplicationProtocols() can't return null
// JDK 8 EXCL START
for (String approto : p.getApplicationProtocols()) {
sb.append("\n application protocol: {")
.append(params.size()).append("}");
params.add(approto);
}
// JDK 8 EXCL END
if (p.getProtocols() != null) {
for (String protocol : p.getProtocols()) {

@ -91,11 +91,13 @@ class DefaultPublisher<T> implements Flow.Publisher<T> {
for (long i = 0; i < nbItemsDemanded && !done.get(); i++) {
try {
Optional<T> item = Objects.requireNonNull(supplier.get());
item.ifPresentOrElse(subscriber::onNext, () -> {
if (item.isPresent()) {
subscriber.onNext(item.get());
} else {
if (done.compareAndSet(false, true)) {
subscriber.onComplete();
}
});
}
} catch (RuntimeException e) {
if (done.compareAndSet(false, true)) {
subscriber.onError(e);

@ -30,6 +30,8 @@ import java.io.UncheckedIOException;
import java.net.URI;
import jdk.incubator.http.ResponseProcessors.MultiFile;
import jdk.incubator.http.ResponseProcessors.MultiProcessorImpl;
import static jdk.incubator.http.internal.common.Utils.unchecked;
import static jdk.incubator.http.internal.common.Utils.charsetFrom;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@ -269,19 +271,6 @@ public abstract class HttpResponse<T> {
};
}
/**
* Get the Charset from the Content-encoding header. Defaults to
* UTF_8
*/
private static Charset charsetFrom(HttpHeaders headers) {
String encoding = headers.firstValue("Content-encoding")
.orElse("UTF_8");
try {
return Charset.forName(encoding);
} catch (IllegalArgumentException e) {
return StandardCharsets.UTF_8;
}
}
/**
* Returns a {@code BodyHandler<Path>} that returns a
@ -342,10 +331,6 @@ public abstract class HttpResponse<T> {
};
}
private static UncheckedIOException unchecked(IOException e) {
return new UncheckedIOException(e);
}
/**
* Returns a {@code BodyHandler<Path>} that returns a
* {@link BodyProcessor BodyProcessor}{@code <Path>} obtained from
@ -743,48 +728,5 @@ public abstract class HttpResponse<T> {
return asMap(pushHandler, true);
}
/**
* Returns a {@code MultiProcessor} which writes the response bodies to
* files under a given root directory and which returns an aggregate
* response map that is a {@code Map<HttpRequest, HttpResponse<Path>>}.
* The keyset of the {@code Map} represents the original request and any
* additional requests generated by the server. The values are the
* responses containing the paths of the destination files. Each file
* uses the URI path of the request relative to the destination parent
* directorycprovided.
*
* <p>
* All incoming additional requests (push promises) are accepted by this
* multi response processor. Errors are effectively ignored and any
* failed responses are simply omitted from the result {@code Map}.
* Other implementations of {@code MultiProcessor} may handle these
* situations.
*
* <p>
* <b>Example usage</b>
* <pre>
* {@code
* HttpClient client = ..
* HttpRequest request = HttpRequest
* .create(new URI("https://www.foo.com/"))
* .version(Version.HTTP2)
* .GET();
*
* Map<HttpRequest, HttpResponse<Path>>> map = client
* .sendAsync(HttpResponse.MultiProcessor.multiFile("/usr/destination"))
* .join();
*
* }
* </pre>
* TEMPORARILY REMOVING THIS FROM API. MIGHT NOT BE NEEDED.
*
* @param destination the destination parent directory of all response
* bodies
* @return a MultiProcessor
*/
private static MultiProcessor<MultiMapResult<Path>,Path> multiFile(Path destination) {
MultiFile mf = new MultiFile(destination);
return new MultiProcessorImpl<Path>(mf::handlePush, true);
}
}
}

@ -252,7 +252,7 @@ class ResponseProcessors {
@Override
public void onError(HttpRequest request, Throwable t) {
results.put(request, CompletableFuture.failedFuture(t));
results.put(request, MinimalFuture.failedFuture(t));
}
@Override

@ -449,9 +449,11 @@ class SSLDelegate {
for (String cipher : p.getCipherSuites()) {
System.out.printf("cipher: %s\n", cipher);
}
// JDK 8 EXCL START
for (String approto : p.getApplicationProtocols()) {
System.out.printf("application protocol: %s\n", approto);
}
// JDK 8 EXCL END
for (String protocol : p.getProtocols()) {
System.out.printf("protocol: %s\n", protocol);
}

@ -110,7 +110,6 @@ public final class MinimalFuture<T> extends CompletableFuture<T> {
}
}
@Override
public <U> MinimalFuture<U> newIncompleteFuture() {
return new MinimalFuture<>();
}

@ -118,11 +118,13 @@ public class Queue<T> implements ExceptionallyCloseable {
public synchronized void closeExceptionally(Throwable t) {
if (exception == null) exception = t;
else if (t != null && t != exception) {
Stream.of(exception.getSuppressed())
if (!Stream.of(exception.getSuppressed())
.filter(x -> x == t)
.findFirst()
.ifPresentOrElse((x) -> {},
() -> exception.addSuppressed(t));
.isPresent())
{
exception.addSuppressed(t);
}
}
close();
}

@ -32,12 +32,14 @@ import javax.net.ssl.SSLParameters;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.NetPermission;
import java.net.URI;
import java.net.URLPermission;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
@ -54,6 +56,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Predicate;
import jdk.incubator.http.HttpHeaders;
/**
* Miscellaneous utilities
@ -259,9 +262,11 @@ public final class Utils {
SSLParameters p1 = new SSLParameters();
p1.setAlgorithmConstraints(p.getAlgorithmConstraints());
p1.setCipherSuites(p.getCipherSuites());
// JDK 8 EXCL START
p1.setEnableRetransmissions(p.getEnableRetransmissions());
p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm());
p1.setMaximumPacketSize(p.getMaximumPacketSize());
// JDK 8 EXCL END
p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm());
p1.setNeedClientAuth(p.getNeedClientAuth());
String[] protocols = p.getProtocols();
if (protocols != null) {
@ -475,4 +480,21 @@ public final class Utils {
return newb;
}
/**
* Get the Charset from the Content-encoding header. Defaults to
* UTF_8
*/
public static Charset charsetFrom(HttpHeaders headers) {
String encoding = headers.firstValue("Content-encoding")
.orElse("UTF_8");
try {
return Charset.forName(encoding);
} catch (IllegalArgumentException e) {
return StandardCharsets.UTF_8;
}
}
public static UncheckedIOException unchecked(IOException e) {
return new UncheckedIOException(e);
}
}

@ -26,6 +26,7 @@
package jdk.incubator.http.internal.websocket;
import jdk.incubator.http.WebSocket.MessagePart;
import jdk.incubator.http.internal.common.Log;
import jdk.incubator.http.internal.websocket.Frame.Opcode;
import java.nio.ByteBuffer;
@ -33,13 +34,11 @@ import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import static java.lang.String.format;
import static java.lang.System.Logger.Level.TRACE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static jdk.incubator.http.internal.common.Utils.dump;
import static jdk.incubator.http.internal.websocket.StatusCodes.NO_STATUS_CODE;
import static jdk.incubator.http.internal.websocket.StatusCodes.checkIncomingCode;
import static jdk.incubator.http.internal.websocket.WebSocketImpl.logger;
/*
* Consumes frame parts and notifies a message consumer, when there is
@ -71,17 +70,13 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void fin(boolean value) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading fin: {0}", value);
}
Log.logTrace("Reading fin: {0}", value);
fin = value;
}
@Override
public void rsv1(boolean value) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading rsv1: {0}", value);
}
Log.logTrace("Reading rsv1: {0}", value);
if (value) {
throw new FailWebSocketException("Unexpected rsv1 bit");
}
@ -89,9 +84,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void rsv2(boolean value) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading rsv2: {0}", value);
}
Log.logTrace("Reading rsv2: {0}", value);
if (value) {
throw new FailWebSocketException("Unexpected rsv2 bit");
}
@ -99,9 +92,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void rsv3(boolean value) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading rsv3: {0}", value);
}
Log.logTrace("Reading rsv3: {0}", value);
if (value) {
throw new FailWebSocketException("Unexpected rsv3 bit");
}
@ -109,7 +100,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void opcode(Opcode v) {
logger.log(TRACE, "Reading opcode: {0}", v);
Log.logTrace("Reading opcode: {0}", v);
if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
if (!fin) {
throw new FailWebSocketException("Fragmented control frame " + v);
@ -137,9 +128,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void mask(boolean value) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading mask: {0}", value);
}
Log.logTrace("Reading mask: {0}", value);
if (value) {
throw new FailWebSocketException("Masked frame received");
}
@ -147,10 +136,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void payloadLen(long value) {
if (logger.isLoggable(TRACE)) {
// Checked for being loggable because of autoboxing of 'value'
logger.log(TRACE, "Reading payloadLen: {0}", value);
}
Log.logTrace("Reading payloadLen: {0}", value);
if (opcode.isControl()) {
if (value > 125) {
throw new FailWebSocketException(
@ -178,9 +164,7 @@ class FrameConsumer implements Frame.Consumer {
@Override
public void payloadData(ByteBuffer data) {
if (logger.isLoggable(TRACE)) {
logger.log(TRACE, "Reading payloadData: data={0}", data);
}
Log.logTrace("Reading payloadData: data={0}", data);
unconsumedPayloadLen -= data.remaining();
boolean isLast = unconsumedPayloadLen == 0;
if (opcode.isControl()) {

@ -25,6 +25,8 @@
package jdk.incubator.http.internal.websocket;
import jdk.incubator.http.internal.common.Log;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
@ -32,10 +34,8 @@ import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import static java.lang.System.Logger.Level.WARNING;
import static java.nio.charset.StandardCharsets.UTF_8;
import static jdk.incubator.http.internal.common.Utils.EMPTY_BYTEBUFFER;
import static jdk.incubator.http.internal.websocket.WebSocketImpl.logger;
final class UTF8AccumulatingDecoder {
@ -74,9 +74,8 @@ final class UTF8AccumulatingDecoder {
// Since it's UTF-8, the assumption is leftovers.remaining() < 4
// (i.e. small). Otherwise a shared buffer should be used
if (!(leftovers.remaining() < 4)) {
logger.log(WARNING,
"The size of decoding leftovers is greater than expected: {0}",
leftovers.remaining());
Log.logError("The size of decoding leftovers is greater than expected: {0}",
leftovers.remaining());
}
b.position(b.limit()); // As if we always read to the end
// Decoder promises that in the case of endOfInput == true:

@ -26,6 +26,7 @@
package jdk.incubator.http.internal.websocket;
import jdk.incubator.http.WebSocket;
import jdk.incubator.http.internal.common.Log;
import jdk.incubator.http.internal.common.Pair;
import jdk.incubator.http.internal.websocket.OpeningHandshake.Result;
import jdk.incubator.http.internal.websocket.OutgoingMessage.Binary;
@ -47,8 +48,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.TRACE;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.CompletableFuture.failedFuture;
import static jdk.incubator.http.internal.common.Pair.pair;
@ -61,8 +60,6 @@ import static jdk.incubator.http.internal.websocket.StatusCodes.checkOutgoingCod
*/
final class WebSocketImpl implements WebSocket {
static final System.Logger logger = System.getLogger("jdk.httpclient.WebSocket");
private final URI uri;
private final String subprotocol;
private final RawChannel channel;
@ -142,7 +139,7 @@ final class WebSocketImpl implements WebSocket {
try {
channel.close();
} catch (IOException e) {
logger.log(ERROR, e);
Log.logError(e);
} finally {
closed.set(true);
}
@ -168,14 +165,14 @@ final class WebSocketImpl implements WebSocket {
private void signalError(Throwable error) {
synchronized (lock) {
if (lastMethodInvoked) {
logger.log(ERROR, error);
Log.logError(error);
} else {
lastMethodInvoked = true;
receiver.close();
try {
listener.onError(this, error);
} catch (Exception e) {
logger.log(ERROR, e);
Log.logError(e);
}
}
}
@ -190,7 +187,7 @@ final class WebSocketImpl implements WebSocket {
try {
channel.shutdownInput();
} catch (IOException e) {
logger.log(ERROR, e);
Log.logError(e);
}
boolean wasComplete = !closeReceived.complete(null);
if (wasComplete) {
@ -210,7 +207,7 @@ final class WebSocketImpl implements WebSocket {
enqueueClose(new Close(code, ""))
.whenComplete((r1, error1) -> {
if (error1 != null) {
logger.log(ERROR, error1);
Log.logError(error1);
}
});
});
@ -223,14 +220,14 @@ final class WebSocketImpl implements WebSocket {
private CompletionStage<?> signalClose(int statusCode, String reason) {
synchronized (lock) {
if (lastMethodInvoked) {
logger.log(TRACE, "Close: {0}, ''{1}''", statusCode, reason);
Log.logTrace("Close: {0}, ''{1}''", statusCode, reason);
} else {
lastMethodInvoked = true;
receiver.close();
try {
return listener.onClose(this, statusCode, reason);
} catch (Exception e) {
logger.log(ERROR, e);
Log.logError(e);
}
}
}
@ -289,7 +286,7 @@ final class WebSocketImpl implements WebSocket {
try {
channel.shutdownOutput();
} catch (IOException e) {
logger.log(ERROR, e);
Log.logError(e);
}
boolean wasComplete = !closeSent.complete(null);
if (wasComplete) {