All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.crazyyak.dev.jerseyclient.SimpleRestClient Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
package org.crazyyak.dev.jerseyclient;

import org.crazyyak.dev.common.IoUtils;
import org.crazyyak.dev.common.StringUtils;
import org.crazyyak.dev.common.exceptions.ApiException;
import org.crazyyak.dev.common.json.JsonTranslator;
import org.crazyyak.dev.common.net.HttpStatusCode;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.glassfish.jersey.uri.internal.JerseyUriBuilder;

import javax.ws.rs.client.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SimpleRestClient {


  public static final Map EMPTY_QUERY = Collections.emptyMap();

  private final boolean notFoundToNull;
  private final JsonTranslator translator;

  private final String apiUrl;
  private final String userName;
  private final String password;

  public SimpleRestClient(JsonTranslator translator, String apiUrl) {
    this(true, translator, parseUrl(apiUrl), parseUserFromUrl(apiUrl), parsePassFromUrl(apiUrl));
  }

  public SimpleRestClient(JsonTranslator translator, String apiUrl, String authentication) {
    this(true, translator, parseUrl(apiUrl), parseUserFromAuth(authentication), parsePassFromAuth(authentication));
  }

  public SimpleRestClient(JsonTranslator translator, String apiUrl, String userName, String password) {
    this(true, translator, parseUrl(apiUrl), userName, password);
  }

  public SimpleRestClient(boolean notFoundToNull, JsonTranslator translator, String apiUrl, String userName, String password) {
    this.apiUrl = apiUrl;
    this.userName = userName;
    this.password = password;

    this.translator = translator;
    this.notFoundToNull = notFoundToNull;
  }


  public static String parseUrl(String apiUrl) {
    if (StringUtils.isBlank(apiUrl)) {
      return null;
    }

    String auth = parseAuth(apiUrl);

    if (StringUtils.isBlank(auth)) {
      return apiUrl;
    } else if (apiUrl.toLowerCase().startsWith("http://")) {
      return apiUrl.replace("http://"+auth+"@", "http://");
    } else if (apiUrl.toLowerCase().startsWith("https://")) {
      return apiUrl.replace("https://"+auth+"@", "https://");
    } else {
      String msg = String.format("Unable to parse the specified URL - does not start with \"http://\" or \"https://\".");
      throw new IllegalArgumentException(msg);
    }
  }

  public static String parseAuth(String apiUrl) {
    int pos;
    if (StringUtils.isBlank(apiUrl)) {
      return null;
    } else if (apiUrl.toLowerCase().startsWith("http://")) {
      pos = 7;
    } else if (apiUrl.toLowerCase().startsWith("https://")) {
      pos = 8;
    } else {
      String msg = String.format("Unable to parse the specified URL - does not start with \"http://\" or \"https://\".");
      throw new IllegalArgumentException(msg);
    }

    String contents = apiUrl.substring(pos);
    pos = contents.indexOf("/");
    if (pos < 0) pos = contents.length();

    String left = contents.substring(0, pos);

    pos = left.indexOf("@");

    if (pos < 0) {
      return null;
    } else {
      return left.substring(0, pos);
    }
  }
  public static String parseUserFromUrl(String apiUrl) {
    String auth = parseAuth(apiUrl);
    return parseUserFromAuth(auth);
  }
  public static String parsePassFromUrl(String apiUrl) {
    String auth = parseAuth(apiUrl);
    return parsePassFromAuth(auth);
  }
  public static String parseUserFromAuth(String authentication) {
    if (StringUtils.isBlank(authentication)) {
      return null;
    }

    int pos = authentication.indexOf(":");
    if (pos < 0) return authentication;

    String name = authentication.substring(0, pos);
    return StringUtils.isNotBlank(name) ? name : null;
  }
  public static String parsePassFromAuth(String authentication) {
    if (StringUtils.isBlank(authentication)) {
      return null;
    }

    int pos = authentication.indexOf(":");
    if (pos < 0) return null;

    String pass = authentication.substring(pos+1);
    return StringUtils.isNotBlank(pass) ? pass : null;
  }


  public void post(String subUrl) {
    post(null, subUrl, null);
  }

  public void post(String subUrl, Object entity) {
    post(null, subUrl, entity);
  }

  public  T post(Class returnType, String subUrl) {
    return post(returnType, subUrl, null);
  }

  public  T post(Class returnType, String subUrl, Object entity) {

    Invocation.Builder builder = builder(subUrl, Collections.emptyMap(), MediaType.APPLICATION_JSON);
    String json = (entity == null) ? null : translator.toJson(entity);

    Response response = builder.post(Entity.entity(json, MediaType.APPLICATION_JSON_TYPE));
    return translateResponse(returnType, response);
  }



  public  T get(Class returnType, String subUrl, String... queryStrings) {
    Map queryMap = new HashMap<>();
    queryMap.putAll(toMap(queryStrings));
    return get(returnType, subUrl, queryMap, "application/json");
  }

  public  T get(Class returnType, String subUrl, Map queryMap) {
    return get(returnType, subUrl, queryMap, "application/json");
  }

  public  T get(Class returnType, String subUrl, Map queryMap, String...acceptedResponseTypes) {

    Invocation.Builder builder = builder(subUrl, queryMap, acceptedResponseTypes);

    Response response = builder.get(Response.class);
    return translateResponse(returnType, response);
  }



  private  T translateResponse(Class returnType, Response response) {

    if (response.getStatus() == 404 && notFoundToNull) return null;
    assertResponse(response.getStatus());

    Object retValue;

    if (returnType == null) {
      // return object not expected
      return null;

    } else if (Response.class.equals(returnType)) {
      retValue = response;

    } else {
      // The return type will use the string content...
      String content = response.readEntity(String.class);

      if (String.class.equals(returnType)) {
        // A simple string - clean up after MS Windows
        retValue = content.replaceAll("\r", "");

      } else {
        // A json object to be translated.
        retValue = translator.fromJson(returnType, content);
      }
    }

    // noinspection unchecked
    return (T)retValue;
  }


  public byte[] getBytes(String subUrl, Map queryMap, String...acceptedResponseTypes) throws IOException {
    Invocation.Builder builder = builder(subUrl, queryMap, acceptedResponseTypes);
    Response response = builder.get(Response.class);

    if (response.getStatus() == 404 && notFoundToNull) return null;
    assertResponse(response.getStatus());

    InputStream in = (InputStream)response.getEntity();
    return IoUtils.toBytes(in);
  }

  public  List getList(Class returnType, String subUrl, String...queryStrings) {
    Map queryMap = new HashMap<>();
    queryMap.putAll(toMap(queryStrings));
    return getList(returnType, subUrl, queryMap);
  }

  public  List getList(Class returnType, String subUrl, Map queryMap) {
    Invocation.Builder builder = builder(subUrl, queryMap, "application/json");
    Response response = builder.get();

    if (response.getStatus() == 404 && notFoundToNull) return null;
    assertResponse(response.getStatus());

    String content = response.readEntity(String.class);

    // A json object to be translated.
    // noinspection unchecked
    return translator.fromJson(List.class, content, returnType);
  }



  public JsonTranslator getTranslator() {
    return translator;
  }

  public String getApiUrl() {
    return apiUrl;
  }

  public String getUserName() {
    return userName;
  }

  public String getPassword() {
    return password;
  }

  protected void assertResponse(int status) {
    HttpStatusCode statusCode = HttpStatusCode.findByCode(status);
    if (statusCode.isOk() == false) {
      String msg = String.format("Unexpected response: %s %s", status, statusCode.getReason());
      throw new ApiException(statusCode, msg);
    }
  }

  protected Map toMap(String...keyValuePairs) {

    if (keyValuePairs == null) {
      return new HashMap<>();
    }

    Map map = new HashMap<>();
    for (String pair : keyValuePairs) {
      int pos = (pair == null) ? -1 : pair.indexOf("=");
      if (pair == null) {
        map.put(null,null);
      } else if (pos < 0) {
        map.put(pair, null);
      } else {
        String key = pair.substring(0, pos);
        String value = pair.substring(pos+1);
        map.put(key, value);
      }
    }
    return map;
  }

  protected Invocation.Builder builder(String url, Map queryMap, String...acceptedResponseTypes) {
    Client client = ClientBuilder.newBuilder().build();
    UriBuilder uriBuilder = new JerseyUriBuilder().uri(getApiUrl()).path(url);

    for (Map.Entry queryParam : queryMap.entrySet()) {
      uriBuilder.queryParam(queryParam.getKey(), queryParam.getValue());
    }

    WebTarget target = client.target(uriBuilder);
    if (StringUtils.isNotBlank(getUserName())) {
      target = target.register(HttpAuthenticationFeature.basic(getUserName(), getPassword()));
    }

    return target.request(acceptedResponseTypes);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy