github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/java/libraries/retrofit2/play26/Play26CallFactory.mustache (about)

     1  package {{invokerPackage}};
     2  
     3  import okhttp3.*;
     4  import okio.AsyncTimeout;
     5  import okio.Buffer;
     6  import okio.BufferedSource;
     7  import okio.Timeout;
     8  import play.libs.ws.WSClient;
     9  import play.libs.ws.WSRequest;
    10  import play.libs.ws.WSResponse;
    11  import play.libs.ws.WSRequestFilter;
    12  import play.libs.ws.WSCookie;
    13  import play.libs.ws.WSCookieBuilder;
    14  
    15  import java.io.IOException;
    16  import java.net.MalformedURLException;
    17  import java.net.URI;
    18  import java.net.URISyntaxException;
    19  import java.util.ArrayList;
    20  import java.util.HashMap;
    21  import java.util.List;
    22  import java.util.Map;
    23  import java.util.concurrent.CompletionStage;
    24  import java.util.concurrent.Executor;
    25  
    26  /**
    27   * Creates {@link Call} instances that invoke underlying {@link WSClient}
    28   */
    29  public class Play26CallFactory implements okhttp3.Call.Factory {
    30  
    31      /** PlayWS http client */
    32      private final WSClient wsClient;
    33  
    34      /** Extra headers to add to request */
    35      private Map<String, String> extraHeaders = new HashMap<>();
    36  
    37      /** Extra cookies to add to request */
    38      private Map<String, String> extraCookies = new HashMap<>();
    39  
    40      /** Extra query parameters to add to request */
    41      private List<Pair> extraQueryParams = new ArrayList<>();
    42  
    43      /** Filters (interceptors) */
    44      private List<WSRequestFilter> filters = new ArrayList<>();
    45  
    46      /** Executor for WSClient */
    47      private Executor executor;
    48  
    49      public Play26CallFactory(WSClient wsClient) {
    50          this.wsClient = wsClient;
    51      }
    52  
    53      public Play26CallFactory(WSClient wsClient, List<WSRequestFilter> filters) {
    54          this.wsClient = wsClient;
    55          this.filters.addAll(filters);
    56      }
    57  
    58      public Play26CallFactory(WSClient wsClient, Map<String, String> extraHeaders,
    59          Map<String, String> extraCookies,
    60          List<Pair> extraQueryParams) {
    61          this.wsClient = wsClient;
    62  
    63          this.extraHeaders.putAll(extraHeaders);
    64          this.extraCookies.putAll(extraCookies);
    65          this.extraQueryParams.addAll(extraQueryParams);
    66      }
    67  
    68      public Play26CallFactory withExecutor(Executor executor) {
    69          this.executor = executor;
    70          return this;
    71      }
    72  
    73      @Override
    74      public Call newCall(Request request) {
    75          // add extra headers
    76          Request.Builder rb = request.newBuilder();
    77          for (Map.Entry<String, String> header : this.extraHeaders.entrySet()) {
    78              rb.addHeader(header.getKey(), header.getValue());
    79          }
    80          for (Map.Entry<String, String> cookie : this.extraCookies.entrySet()) {
    81              rb.addHeader("Cookie", String.format("%s=%s", cookie.getKey(), cookie.getValue()));
    82          }
    83  
    84          // add extra query params
    85          if (!this.extraQueryParams.isEmpty()) {
    86              String newQuery = request.url().uri().getQuery();
    87              for (Pair queryParam : this.extraQueryParams) {
    88                  String param = String.format("%s=%s", queryParam.getName(), queryParam.getValue());
    89                  if (newQuery == null) {
    90                      newQuery = param;
    91                  } else {
    92                      newQuery += "&" + param;
    93                  }
    94              }
    95  
    96              URI newUri;
    97              try {
    98                  newUri = new URI(request.url().uri().getScheme(), request.url().uri().getAuthority(),
    99                          request.url().uri().getPath(), newQuery, request.url().uri().getFragment());
   100                  rb.url(newUri.toURL());
   101              } catch (MalformedURLException | URISyntaxException e) {
   102                  throw new RuntimeException("Error while updating an url", e);
   103              }
   104          }
   105  
   106          return new PlayWSCall(wsClient, this.executor, this.filters, rb.build());
   107      }
   108  
   109      /**
   110       * Call implementation that delegates to Play WS Client
   111       */
   112      static class PlayWSCall implements Call {
   113  
   114          private final WSClient wsClient;
   115          private WSRequest wsRequest;
   116          private List<WSRequestFilter> filters;
   117          private Executor executor = java.util.concurrent.ForkJoinPool.commonPool();
   118  
   119          private final Request request;
   120          private final AsyncTimeout timeout;
   121  
   122          public PlayWSCall(WSClient wsClient, Executor executor, List<WSRequestFilter> filters, Request request) {
   123              this.wsClient = wsClient;
   124              this.request = request;
   125              this.filters = filters;
   126              this.timeout = new AsyncTimeout();
   127  
   128              if (executor != null) {
   129                  this.executor = executor;
   130              }
   131          }
   132  
   133          @Override
   134          public Request request() {
   135              return request;
   136          }
   137  
   138          @Override
   139          public Timeout timeout() {
   140              return timeout;
   141          }
   142  
   143          @Override
   144          public void enqueue(final okhttp3.Callback responseCallback) {
   145              final Call call = this;
   146              final CompletionStage<WSResponse> promise = executeAsync();
   147  
   148              promise.whenCompleteAsync((v, t) -> {
   149                  if (t != null) {
   150                      if (t instanceof IOException) {
   151                          responseCallback.onFailure(call, (IOException) t);
   152                      } else {
   153                          responseCallback.onFailure(call, new IOException(t));
   154                      }
   155                  } else {
   156                      try {
   157                          responseCallback.onResponse(call, PlayWSCall.this.toWSResponse(v));
   158                      } catch (Exception e) {
   159                          responseCallback.onFailure(call, new IOException(e));
   160                      }
   161                  }
   162              }, this.executor);
   163          }
   164  
   165          CompletionStage<WSResponse> executeAsync() {
   166              try {
   167                  HttpUrl url = request.url();
   168                  wsRequest = wsClient.url(url.scheme()+ "://" + url.host() + ":" + url.port() + url.encodedPath());
   169                  url.queryParameterNames().forEach(queryParam -> {
   170                      wsRequest.addQueryParameter(queryParam, url.queryParameter(queryParam));
   171                  });
   172                  addHeaders(wsRequest);
   173                  addCookies(wsRequest);
   174                  if (request.body() != null) {
   175                      addBody(wsRequest);
   176                  }
   177                  filters.stream().forEach(f -> wsRequest.setRequestFilter(f));
   178  
   179                  return wsRequest.execute(request.method());
   180              } catch (Exception e) {
   181                  throw new RuntimeException(e.getMessage(), e);
   182              }
   183          }
   184  
   185          private void addHeaders(WSRequest wsRequest) {
   186              for(Map.Entry<String, List<String>> entry : request.headers().toMultimap().entrySet()) {
   187                  List<String> values = entry.getValue();
   188                  for (String value : values) {
   189                      wsRequest.setHeader(entry.getKey(), value);
   190                  }
   191              }
   192          }
   193  
   194          private void addCookies(WSRequest wsRequest) {
   195              for (final WSCookie cookie : getCookies()) {
   196                  wsRequest.addCookie(cookie);
   197              }
   198          }
   199  
   200          List<WSCookie> getCookies() {
   201              final List<WSCookie> cookies = new ArrayList<>();
   202              for (final String cookieString : request.headers("Cookie")) {
   203                  for (String cookie : cookieString.split(";")) {
   204                      cookie = cookie.trim();
   205                      final String[] nameAndValue = cookie.split("=");
   206                      if (nameAndValue.length != 2) {
   207                          continue;
   208                      }
   209                      cookies.add(
   210                          new WSCookieBuilder()
   211                              .setName(nameAndValue[0])
   212                              .setValue(nameAndValue[1])
   213                              .build()
   214                      );
   215                  }
   216              }
   217              return cookies;
   218          }
   219  
   220          private void addBody(WSRequest wsRequest) throws IOException {
   221              MediaType mediaType = request.body().contentType();
   222              if (mediaType != null) {
   223                  wsRequest.setContentType(mediaType.toString());
   224              }
   225  
   226              Buffer buffer = new Buffer();
   227              request.body().writeTo(buffer);
   228              wsRequest.setBody(buffer.inputStream());
   229          }
   230  
   231          private Response toWSResponse(final WSResponse r) {
   232              final Response.Builder builder = new Response.Builder();
   233              builder.request(request)
   234                     .code(r.getStatus())
   235                     .body(new ResponseBody() {
   236  
   237                         @Override
   238                         public MediaType contentType() {
   239                            return r.getSingleHeader("Content-Type")
   240                                    .map(MediaType::parse)
   241                                    .orElse(null);
   242                         }
   243  
   244                         @Override
   245                         public long contentLength() {
   246                             return r.asByteArray().length;
   247                         }
   248  
   249                         @Override
   250                         public BufferedSource source() {
   251                             return new Buffer().write(r.asByteArray());
   252                         }
   253                     });
   254  
   255              for (Map.Entry<String, List<String>> entry : r.getAllHeaders().entrySet()) {
   256                  for (String value : entry.getValue()) {
   257                      builder.addHeader(entry.getKey(), value);
   258                  }
   259              }
   260              for (final WSCookie cookie : r.getCookies()) {
   261                  builder.addHeader("Cookie", String.format("%s=%s", cookie.getName(), cookie.getValue()));
   262              }
   263  
   264              builder.message(r.getStatusText());
   265              builder.protocol(Protocol.HTTP_1_1);
   266              return builder.build();
   267          }
   268  
   269          @Override
   270          public Response execute() throws IOException {
   271              throw new UnsupportedOperationException("Not supported");
   272          }
   273  
   274          @Override
   275          public void cancel() {
   276              throw new UnsupportedOperationException("Not supported");
   277          }
   278  
   279          @Override
   280          public PlayWSCall clone() {
   281              throw new UnsupportedOperationException("Not supported");
   282          }
   283  
   284          @Override
   285          public boolean isExecuted() {
   286              return false;
   287          }
   288  
   289          @Override
   290          public boolean isCanceled() {
   291              return false;
   292          }
   293      }
   294  }