/* * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.UncheckedIOException; import java.lang.reflect.UndeclaredThrowableException; import java.net.Authenticator; import java.net.InetSocketAddress; import java.net.ProxySelector; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpClient.Redirect; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandler; import java.net.http.HttpResponse.BodyHandlers; import java.net.http.HttpResponse.BodySubscriber; import java.net.http.HttpResponse.BodySubscribers; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Flow; import java.util.function.Supplier; import java.util.regex.Pattern; import static java.nio.charset.StandardCharsets.UTF_8; /* * THE CONTENTS OF THIS FILE HAVE TO BE IN SYNC WITH THE EXAMPLES USED IN THE * JAVADOC. * * @test * @compile JavadocExamples.java */ public class JavadocExamples { HttpRequest request = null; HttpClient client = null; Pattern p = null; void fromHttpClientClasslevelDescription() throws Exception { //Synchronous Example HttpClient client = HttpClient.newBuilder() .version(Version.HTTP_1_1) .followRedirects(Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(20)) .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80))) .authenticator(Authenticator.getDefault()) .build(); HttpResponse response = client.send(request, BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body()); //Asynchronous Example HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://foo.com/")) .timeout(Duration.ofMinutes(2)) .header("Content-Type", "application/json") .POST(BodyPublishers.ofFile(Paths.get("file.json"))) .build(); client.sendAsync(request, BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println); } void fromHttpRequest() throws Exception { // HttpRequest class-level description HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://foo.com/")) .build(); client.sendAsync(request, BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println) .join(); // HttpRequest.BodyPublishers class-level description // Request body from a String HttpRequest request1 = HttpRequest.newBuilder() .uri(URI.create("https://foo.com/")) .header("Content-Type", "text/plain; charset=UTF-8") .POST(BodyPublishers.ofString("some body text")) .build(); // Request body from a File HttpRequest request2 = HttpRequest.newBuilder() .uri(URI.create("https://foo.com/")) .header("Content-Type", "application/json") .POST(BodyPublishers.ofFile(Paths.get("file.json"))) .build(); // Request body from a byte array HttpRequest request3 = HttpRequest.newBuilder() .uri(URI.create("https://foo.com/")) .POST(BodyPublishers.ofByteArray(new byte[] { /*...*/ })) .build(); } void fromHttpResponse() throws Exception { // HttpResponse class-level description HttpResponse response = client .send(request, BodyHandlers.ofString()); // HttpResponse.BodyHandler class-level description HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://www.foo.com/")) .build(); client.sendAsync(request, BodyHandlers.ofFile(Paths.get("/tmp/f"))) .thenApply(HttpResponse::body) .thenAccept(System.out::println); HttpRequest request1 = HttpRequest.newBuilder() .uri(URI.create("http://www.foo.com/")) .build(); BodyHandler bodyHandler = (info) -> info.statusCode() == 200 ? BodySubscribers.ofFile(Paths.get("/tmp/f")) : BodySubscribers.replacing(Paths.get("/NULL")); client.sendAsync(request, bodyHandler) .thenApply(HttpResponse::body) .thenAccept(System.out::println); // HttpResponse.BodyHandlers class-level description // Receives the response body as a String HttpResponse response1 = client .send(request, BodyHandlers.ofString()); // Receives the response body as a file HttpResponse response2 = client .send(request, BodyHandlers.ofFile(Paths.get("example.html"))); // Receives the response body as an InputStream HttpResponse respons3 = client .send(request, BodyHandlers.ofInputStream()); // Discards the response body HttpResponse respons4 = client .send(request, BodyHandlers.discarding()); // HttpResponse.BodySubscribers class-level description // Streams the response body to a File HttpResponse response5 = client .send(request, responseInfo -> BodySubscribers.ofFile(Paths.get("example.html"))); // Accumulates the response body and returns it as a byte[] HttpResponse response6 = client .send(request, responseInfo -> BodySubscribers.ofByteArray()); // Discards the response body HttpResponse response7 = client .send(request, responseInfo -> BodySubscribers.discarding()); // Accumulates the response body as a String then maps it to its bytes HttpResponse response8 = client .send(request, responseInfo -> BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes)); // Maps an InputStream to a Foo object. HttpResponse> response9 = client.send(request, (resp) -> FromMappingSubscriber.asJSON(Foo.class)); String resp = response9.body().get().asString(); } /** * @apiNote This method can be used as an adapter between a {@code * BodySubscriber} and a text based {@code Flow.Subscriber} that parses * text line by line. * *

For example: *

 {@code  // A PrintSubscriber that implements Flow.Subscriber
     *  // and print lines received by onNext() on System.out
     *  PrintSubscriber subscriber = new PrintSubscriber(System.out);
     *  client.sendAsync(request, BodyHandlers.fromLineSubscriber(subscriber))
     *      .thenApply(HttpResponse::statusCode)
     *      .thenAccept((status) -> {
     *          if (status != 200) {
     *              System.err.printf("ERROR: %d status received%n", status);
     *          }
     *      }); }
*/ void fromLineSubscriber1() { // A PrintSubscriber that implements Flow.Subscriber // and print lines received by onNext() on System.out PrintSubscriber subscriber = new PrintSubscriber(System.out); client.sendAsync(request, BodyHandlers.fromLineSubscriber(subscriber)) .thenApply(HttpResponse::statusCode) .thenAccept((status) -> { if (status != 200) { System.err.printf("ERROR: %d status received%n", status); } }); } /** * @apiNote This method can be used as an adapter between a {@code * BodySubscriber} and a text based {@code Flow.Subscriber} that parses * text line by line. * *

For example: *

 {@code  // A LineParserSubscriber that implements Flow.Subscriber
     *  // and accumulates lines that match a particular pattern
     *  Pattern pattern = ...;
     *  LineParserSubscriber subscriber = new LineParserSubscriber(pattern);
     *  HttpResponse> response = client.send(request,
     *      BodyHandlers.fromLineSubscriber(subscriber, s -> s.getMatchingLines(), "\n"));
     *  if (response.statusCode() != 200) {
     *      System.err.printf("ERROR: %d status received%n", response.statusCode());
     *  } }
* */ void fromLineSubscriber2() throws IOException, InterruptedException { // A LineParserSubscriber that implements Flow.Subscriber // and accumulates lines that match a particular pattern Pattern pattern = p; LineParserSubscriber subscriber = new LineParserSubscriber(pattern); HttpResponse> response = client.send(request, BodyHandlers.fromLineSubscriber(subscriber, s -> s.getMatchingLines(), "\n")); if (response.statusCode() != 200) { System.err.printf("ERROR: %d status received%n", response.statusCode()); } } static final class PrintSubscriber implements Flow.Subscriber { final PrintStream out; PrintSubscriber(PrintStream out) { this.out = out; } @Override public void onSubscribe(Flow.Subscription subscription) { subscription.request(Long.MAX_VALUE); } @Override public void onNext(String item) { out.println(item); } @Override public void onError(Throwable throwable) { throwable.printStackTrace(); } @Override public void onComplete() { } } static final class LineParserSubscriber implements Flow.Subscriber { final Pattern pattern; final CopyOnWriteArrayList matches = new CopyOnWriteArrayList<>(); LineParserSubscriber(Pattern pattern) { this.pattern = pattern; } @Override public void onSubscribe(Flow.Subscription subscription) { subscription.request(Long.MAX_VALUE); } @Override public void onNext(String item) { if (pattern.matcher(item).matches()) { matches.add(item); } } @Override public void onError(Throwable throwable) { throwable.printStackTrace(); } @Override public void onComplete() { } public List getMatchingLines() { return Collections.unmodifiableList(matches); } } public static class Foo { byte[] bytes; public Foo(byte[] bytes) { this.bytes = bytes; } public String asString() { return new String(bytes, UTF_8); } } static class ObjectMapper { W readValue(InputStream is, Class targetType) throws IOException { byte[] bytes = is.readAllBytes(); return map(bytes, targetType); } static W map(byte[] bytes, Class targetType) { try { return targetType.getConstructor(byte[].class).newInstance(bytes); } catch (RuntimeException | Error x) { throw x; } catch (Exception x) { throw new UndeclaredThrowableException(x); } } } static class FromMappingSubscriber { public static BodySubscriber> asJSON(Class targetType) { BodySubscriber upstream = BodySubscribers.ofInputStream(); BodySubscriber> downstream = BodySubscribers.mapping( upstream, (InputStream is) -> () -> { try (InputStream stream = is) { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(stream, targetType); } catch (IOException e) { throw new UncheckedIOException(e); } }); return downstream; } } }