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

csip.Client Maven / Gradle / Ivy

Go to download

The Cloud Services Integration Platform is a SoA implementation to offer a Model-as-a-Service framework, Application Programming Interface, deployment infrastructure, and service implementations for environmental modeling.

There is a newer version: 2.6.30
Show newest version
/*
 * $Id: Client.java 820b0b8fd71e 2020-07-14 od $
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API and application suite.
 *
 * 2012-2019, Olaf David and others, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package csip;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import static java.net.HttpURLConnection.HTTP_OK;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.codehaus.jettison.json.JSONObject;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

/**
 * HTTP Client for easier CSIP service calling.
 *
 * @author od
 */
public class Client {

  private Logger log;
  private static final PoolingHttpClientConnectionManager cm
      = new PoolingHttpClientConnectionManager(
          RegistryBuilder.create()
              .register("http", PlainConnectionSocketFactory.getSocketFactory())
              .register("https", new SSLConnectionSocketFactory(SSLContexts.createSystemDefault()))
              .build()
      );

  private CloseableHttpClient httpClient;

  static final int DEF_TIMEOUT = 3600; // 1 h timeout

  private CredentialsProvider creds;
  private BasicHttpContext context;

  private static class HttpsTrustManager implements X509TrustManager {

    static TrustManager[] trustManagers;
    static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};


    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
        throws java.security.cert.CertificateException {
    }


    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
        throws java.security.cert.CertificateException {
    }


    public boolean isClientTrusted(X509Certificate[] chain) {
      return true;
    }


    public boolean isServerTrusted(X509Certificate[] chain) {
      return true;
    }


    @Override
    public X509Certificate[] getAcceptedIssuers() {
      return _AcceptedIssuers;
    }


    /**
     * it's not safe for production phase, because it will allow all SSL
     * certificate although the SSL certificate is not valid
     */
    public static void allowAllSSL() {
      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
          return true;
        }
      });

      SSLContext context = null;
      if (trustManagers == null) {
        trustManagers = new TrustManager[]{new HttpsTrustManager()};
      }

      try {
        context = SSLContext.getInstance("TLS");
        context.init(null, trustManagers, new SecureRandom());
      } catch (NoSuchAlgorithmException | KeyManagementException e) {
        throw new RuntimeException(e);
      }
      HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    }
  }

  private static class DummyTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) {
    }


    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) {
    }


    @Override
    public X509Certificate[] getAcceptedIssuers() {
      return new X509Certificate[0];
    }
  }


  static {

    try {
      cm.setMaxTotal(250);
      // Increase default max connection per route to 75
      cm.setDefaultMaxPerRoute(100);
      // Increase max connections for localhost:80 to 125
      HttpHost localhost = new HttpHost("locahost", 80);
      cm.setMaxPerRoute(new HttpRoute(localhost), 150);
    } catch (Exception E) {
      Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "Static Init Error", E);
    }
  }

  private static final PoolingHttpClientConnectionManager connPM = createCM();

  private static SSLConnectionSocketFactory factory;


  @SuppressWarnings("unchecked")
  private static PoolingHttpClientConnectionManager createCM() {
    try {
      SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build();
      sslcontext.init(new KeyManager[0], new TrustManager[]{new DummyTrustManager()}, new SecureRandom());
      sslcontext.init(null, new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
      factory = new SSLConnectionSocketFactory(sslcontext, new HostnameVerifier() {
        @Override
        public boolean verify(final String s, final SSLSession sslSession) {
          return true;
        }
      });

      org.apache.http.config.Registry r = RegistryBuilder.create()
          .register("http", PlainConnectionSocketFactory.getSocketFactory())
          .register("https", factory).build();

      PoolingHttpClientConnectionManager connPool = new PoolingHttpClientConnectionManager(r);
      // Increase max total connection to 200
      connPool.setMaxTotal(250);
      connPool.setDefaultMaxPerRoute(100);

      return connPool;
    } catch (Exception e) {
      System.err.println("Error initiliazing ConnectionPool :: " + e.toString());
      return null;
    }
  }


  /**
   * Create a Client
   */
  public Client() {
    this(DEF_TIMEOUT, Logger.getLogger(Client.class.getName()));
  }


  /**
   * Create a client with a logger.
   * @param log the Logger
   *
   */
  public Client(Logger log) {
    this(DEF_TIMEOUT, log);
  }


  /**
   * Create a client with a custom timeout.
   *
   * @param timeout the timeout in
   */
  public Client(int timeout) {
    this(timeout, Logger.getLogger(Client.class.getName()));
  }


  public Client(int timeout, Logger log) {
    httpClient = createHttpClient(timeout, log);
//    RequestConfig reqConfig = init(timeout, log);
//    httpClient = HttpClientBuilder.create()
//        .setDefaultRequestConfig(reqConfig)
//        .setConnectionManager(cm)
//        .setConnectionManagerShared(true)
//        .build();
  }


  public Client(int timeout, Logger log, String username, String password) {
    RequestConfig reqConfig = init(timeout, log);
    context = new BasicHttpContext();
    context.setAttribute("preemptive-auth", new BasicScheme());
    creds = new BasicCredentialsProvider();
    creds.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
    httpClient = HttpClientBuilder.create()
        .setDefaultRequestConfig(reqConfig)
        .setConnectionManager(cm)
        .addInterceptorFirst(new PreemptiveAuthInterceptor())
        .build();
  }


  public void close() {
    try {
      httpClient.close();
    } catch (IOException ex) {
      log.log(Level.SEVERE, null, ex);
    }
  }


  private RequestConfig createRequestConfig(int timeout, Logger log) {
    this.log = log;
    return RequestConfig.custom()
        .setConnectTimeout(timeout * 1000)
        .setSocketTimeout(timeout * 1000)
        .build();
  }


  private CloseableHttpClient createHttpClient(int timeout, Logger log) {
    RequestConfig c = createRequestConfig(timeout, log);
    return HttpClients.custom()
        .setDefaultRequestConfig(c)
        .setConnectionManagerShared(true)
        .setConnectionManager(connPM)
        .setSSLSocketFactory(factory)
        .build();
  }


  private RequestConfig init(int timeout, Logger log) {
    this.log = log;
    RequestConfig reqConfig = RequestConfig.custom()
        .setConnectTimeout(timeout * 1000)
        .setConnectionRequestTimeout(timeout * 1000)
        .setSocketTimeout(timeout * 1000) // 10 minute max per model run
        //        .setCookieSpec(CookieSpecs.BEST_MATCH)
        .setExpectContinueEnabled(true)
        //        .setStaleConnectionCheckEnabled(true)
        .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
        .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
        .build();
    return reqConfig;
  }

  private class PreemptiveAuthInterceptor implements HttpRequestInterceptor {

    @Override
    @SuppressWarnings("deprecation")
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
      request.addHeader(BasicScheme.authenticate(creds.getCredentials(AuthScope.ANY), "US-ASCII", false));
    }
  }


  /**
   * Pings a HTTP URL. This effectively sends a HEAD request and returns
   * true if the response code is in the 200-399 range.
   * @param url The HTTP URL to be pinged.
   * @param timeout The timeout in millis for both the connection timeout and
   * the response read timeout. Note that the total timeout is effectively two
   * times the given timeout.
   * @return the time to respond if the given HTTP URL has returned response
   * code 200-399 on a HEAD request within the given timeout, otherwise
   * -1.
   */
  public static long ping(String url, int timeout) {
    url = url.replaceFirst("^https", "http");
    try {
      HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
      connection.setConnectTimeout(timeout);
      connection.setReadTimeout(timeout);
      connection.setRequestMethod("HEAD");
      long start = System.currentTimeMillis();
      int responseCode = connection.getResponseCode();
      long end = System.currentTimeMillis();
      return (200 <= responseCode && responseCode <= 399) ? (end - start) : -1;
    } catch (Exception E) {
      return -1;
    }
  }


  public File doGET(String url, File file) throws Exception {
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("GET : " + url + " -> " + file.toString());
    }
    HttpGet get = new HttpGet(url);
    try (CloseableHttpResponse resultsResponse = httpClient.execute(get)) {
      InputStream output = resultsResponse.getEntity().getContent();
      FileUtils.copyInputStreamToFile(output, file);
    } finally {
      get.releaseConnection();
    }
    return file;
  }


  public String doGET(String url) throws Exception {
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("GET : " + url);
    }
    HttpGet get = new HttpGet(url);
    try (CloseableHttpResponse resultsResponse = httpClient.execute(get)) {
      InputStream output = resultsResponse.getEntity().getContent();
      return IOUtils.toString(output, "UTF-8");
    } finally {
      get.releaseConnection();
    }
  }


  public int doDelete(String url) throws Exception {
    HttpDelete del = new HttpDelete(url);
    int status = 0;
    try {
      HttpResponse resultsResponse = httpClient.execute(del);
      status = resultsResponse.getStatusLine().getStatusCode();
    } finally {
      del.releaseConnection();
    }
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("DELETE : " + url + " -> " + status);
    }
    return status;
  }


  /**
   * HTTP Post with the request JSON and files attached.
   *
   * @param uri the endpoint
   * @param req the request JSON
   * @param files the files to attach
   * @return the response JSON
   * @throws Exception if something goes wrong
   */
  public JSONObject doPOST(String uri, JSONObject req, File[] files) throws Exception {
    return doPOST(uri, req, files, null);
  }


  /**
   * HTTP Post with the request JSON.
   *
   * @param uri the endpoint
   * @param req the request JSON
   * @return the response JSON
   * @throws Exception if something goes wrong
   */
  public JSONObject doPOST(String uri, JSONObject req) throws Exception {
    return doPOST(uri, req, new File[]{}, new String[]{});
  }


  public JSONObject doPOST(String uri, JSONObject req, Map header) throws Exception {
    return doPOST(uri, req, new File[]{}, new String[]{}, header);
  }


  public String doPOST(String uri, String req) throws Exception {
    HttpPost post = new HttpPost(uri);
    post.addHeader("Content-Type", "application/json");
    StringEntity entity = new StringEntity(req, "UTF-8");
    entity.setContentType("application/json");
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("attaching : " + req.toString());
    }
    post.setEntity(entity);
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("POST : " + uri);
    }
    int statusCode;
    String str = null;
    try (CloseableHttpResponse response = httpClient.execute(post)) {
      statusCode = response.getStatusLine().getStatusCode();
      if (statusCode == HTTP_OK) {
        InputStream responseStream = response.getEntity().getContent();
        str = IOUtils.toString(responseStream, "UTF-8");
      }
    } finally {
      post.releaseConnection();
    }
    return str;
  }


  public JSONObject doPOST(String uri, JSONObject req, File[] files, String[] names) throws Exception {
    return doPOST(uri, req, files, names, null);
  }


  public JSONObject doPOST(String uri, JSONObject req, File[] files,
      String[] names, Map header) throws Exception {
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info(" attaching request as 'param':" + req.toString(2));
    }

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addPart("param", new StringBody(req.toString(), ContentType.APPLICATION_JSON));
    for (int i = 0; i < files.length; i++) {
      FileBody b = new FileBody(files[i], ContentType.APPLICATION_OCTET_STREAM,
          names == null ? files[i].getName() : names[i]);
      builder.addPart("file" + (i + 1), b);
      if (log != null && log.isLoggable(Level.INFO)) {
        log.info(" attached file" + b.getFile().toString() + " as " + b.getFilename());
      }
    }
    HttpEntity reqEntity = builder.build();
    HttpPost post = new HttpPost(uri);

    if (header != null) {
      for (Map.Entry entry : header.entrySet()) {
        post.addHeader(entry.getKey(), entry.getValue());
      }
    }

    post.setEntity(reqEntity);

    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("POST: " + uri + " ...");
    }
    String response;
    try (CloseableHttpResponse httpResponse = httpClient.execute(post)) {
      InputStream responseStream = httpResponse.getEntity().getContent();
      response = IOUtils.toString(responseStream, "UTF-8");
      if (log != null && log.isLoggable(Level.INFO)) {
        log.info("response: " + response);
        PoolStats ps = cm.getTotalStats();
        log.info("http-client-connections pool [avail=" + ps.getAvailable()
            + " leased=" + ps.getLeased() + " pending=" + ps.getPending() + "] ");
      }
    } finally {
      post.releaseConnection();
    }
    return new JSONObject(response);
  }


  public boolean doPUT(String uri, JSONObject req) throws Exception {
    HttpPut put = new HttpPut(uri);
    put.addHeader("Content-Type", "application/json");
    StringEntity entity = new StringEntity(req.toString(), "UTF-8");
    entity.setContentType("application/json");
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("attaching : " + req.toString());
    }
    put.setEntity(entity);
    if (log != null && log.isLoggable(Level.INFO)) {
      log.info("PUT : " + uri);
    }
    int statusCode;
    try (CloseableHttpResponse response = httpClient.execute(put)) {
      statusCode = response.getStatusLine().getStatusCode();
    } finally {
      put.releaseConnection();
    }
    return statusCode == HTTP_OK;
  }


//    static String parseEndpoint(String ep) {
////   [ http://129.82.226.52:8080/csip-gras/m/gras/wgtavgforageprod/1.0   ] , [http://129.82.226.52:8080/csip-gras/m/gras//1.0]"));
//        int s = ep.indexOf('[');
//        int e = ep.indexOf(']', s);
//        if (s == -1 || e == -1) {
//            return null;
//        }
//        String first = ep.substring(s + 1, e);
//        return first.trim();
//    }
  public static void main(String[] args) throws Exception {
////        JSONObject o = new JSONObject("{\"metainfo\":{},\"parameter\":[{\"name\":\"cokey\",\"value\":\"11790680\"}]}");
////        JSONObject r = new Client().doPOST("http://csip.engr.colostate.edu:8092/csip-soils/d/rusle2soilinput/1.0", o);
////        JSONObject r = new Client().doPOST("http://localhost:8080/csip-soils/d/rusle2soilinput/1.0", o);
////    JSONObject req = new JSONObject("{}");
//
    String res = new Client().doPOST("https://ecoproducer.com/environmental/post?token=1opMZAuq6vUhu9B9aBSnlMGpDDpcXtu8", "{'ttt':1}");
    System.out.println(res);
////    
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy