Package org.genesys2.client.oauth

Source Code of org.genesys2.client.oauth.GenesysClient

/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package org.genesys2.client.oauth;

import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.genesys2.client.oauth.api.GenesysApi;
import org.scribe.builder.ServiceBuilder;
import org.scribe.exceptions.OAuthConnectionException;
import org.scribe.exceptions.OAuthException;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class GenesysClient {
  private static final Logger _log = LogManager.getLogger(GenesysClient.class);
  public static final Token EMPTY_TOKEN = null;

  private static final String SCOPE = "read,write";

  private static ObjectMapper mapper = new ObjectMapper();

  private OAuthService service;
  private Token accessToken;
  private Token refreshToken;

  private GenesysApi genesysApi;
  private String apiKey;
  private String apiSecret;

  public GenesysClient() {
  }

  public GenesysClient setBaseUrl(String baseUrl) {
    genesysApi.setBaseUrl(baseUrl);
    return this;
  }

  public void setGenesysApi(GenesysApi genesysApi) {
    this.genesysApi = genesysApi;
  }

  public GenesysApi getGenesysApi() {
    return genesysApi;
  }

  /**
   * Load client configuration from {@link Properties}
   *
   * @param properties
   */
  public void loadProperties(Properties properties) {

    final String baseUrl = properties.getProperty("base.url");
    genesysApi.setBaseUrl(baseUrl);

    final String httpAuth = properties.getProperty("http.auth");

    if (StringUtils.isNotBlank(httpAuth) && httpAuth.contains(":")) {
      _log.warn("Using HTTP AUTH " + httpAuth);
      Authenticator.setDefault(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
          return new PasswordAuthentication(httpAuth.split(":", 2)[0], httpAuth.split(":", 2)[1].toCharArray());
        }
      });
    }

    setAccessToken(properties.getProperty("access.token"));
    setRefreshToken(properties.getProperty("refresh.token"));

    // CropHub auth service
    connect(properties.getProperty("client.key"), properties.getProperty("client.secret"), properties.getProperty("client.callback"));
  }

  public void connect(String clientId, String clientSecret, String callback) {
    this.apiKey = clientId;
    this.apiSecret = clientSecret;
    this.service = new ServiceBuilder().provider(this.genesysApi).apiKey(clientId).apiSecret(clientSecret).callback(callback).scope(SCOPE).build();
  }

  public GenesysClient setAccessToken(String tokenKey) {
    accessToken = new Token(tokenKey, "");
    return this;
  }

  public GenesysClient setRefreshToken(String tokenKey) {
    refreshToken = new Token(tokenKey, "");
    return this;
  }

  public String query(String url) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.GET, url, null, null);
  }

  public String query(Verb method, String url, Map<String, String> queryString, String postBody) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {

    if (accessToken == null) {
      refreshAccessToken();
    }

    for (int i = 0; i < 2; i++) {
      OAuthRequest request = new OAuthRequest(method, getApiUrl(url));

      if (queryString != null && queryString.size() > 0) {
        for (String key : queryString.keySet()) {
          request.addQuerystringParameter(key, queryString.get(key));
        }
      }

      if (_log.isDebugEnabled()) {
        _log.debug(method + " " + request.getCompleteUrl());
      }

      if (postBody != null) {
        // System.err.println("Adding data: " + data);
        request.addPayload(postBody);
        request.addHeader("Content-Type", "application/json;charset=utf-8");
      }

      service.signRequest(accessToken, request);
      request.setConnectionKeepAlive(true);
      request.setConnectTimeout(10, TimeUnit.SECONDS);
      request.setReadTimeout(30, TimeUnit.SECONDS);
      request.setCharset("UTF-8");
      Response response = null;

      try {
        response = request.send();
      } catch (OAuthConnectionException e) {
        throw e;
      }

      String responseBody = response.getBody();
      if (response.isSuccessful()) {
        return responseBody + "\n";
      } else {
        if (response.getCode() == 401) {
          _log.warn("Response error: " + response.getCode());
          System.err.println(responseBody);
          if (i == 0) {
            refreshAccessToken();
          } else {
            throw new OAuthAuthenticationException("Unauthorized");
          }
        } else {
          _log.error(method + " " + request.getCompleteUrl());
          _log.error(postBody);
          _log.error("HTTP response code: " + response.getCode());
          _log.error("Response: " + responseBody);
          if (responseBody.contains("Deadlock found when trying to get lock; try restarting transaction")
              || responseBody.contains("nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement")) {
            throw new PleaseRetryException(responseBody);
          } else
            throw new GenesysApiException("Unexpected error: " + responseBody);
        }
      }
    }
    return null;
  }

  private String getApiUrl(String url) {
    return genesysApi.getBaseUrl().concat("/api/v0").concat(url);
  }

  /**
   * Refresh accessToken with refreshToken
   *
   * @throws OAuthAuthenticationException
   */
  public void refreshAccessToken() throws OAuthAuthenticationException {
    if (this.refreshToken != null) {
      _log.info("Using Refresh Token to get new access token");
      try {
        accessToken = genesysApi.getAccessToken(this.apiKey, this.apiSecret, this.refreshToken);
        _log.info("Got new Access Token!");
      } catch (OAuthException e) {
        _log.info("Refresh token didn't work: " + e.getMessage());
        throw new OAuthAuthenticationException("Refresh token not valid, please re-authenticate");
      }
    } else {
      throw new OAuthAuthenticationException("No refresh token, please re-authenticate");
    }
  }

  public String accessionExists(String instCode, String acceNumb, String genus) throws GenesysApiException {

    try {
      HashMap<String, String> queryString = new HashMap<String, String>();
      queryString.put("acceNumb", acceNumb);

      return query(Verb.GET, new URI(null, null, "/acn/exists/" + instCode + "/" + genus, null).toString(), queryString, null);
    } catch (URISyntaxException e) {
      e.printStackTrace();
      return null;
    }
  }

  public static ObjectNode makeAid3(String instCode, String genus, String acceNumb) {
    ObjectNode json = mapper.createObjectNode();
    json.put("instCode", instCode);
    json.put("acceNumb", acceNumb);
    json.put("genus", genus);
    return json;
  }

  public String updateMLS(String instCode, Collection<ObjectNode> accns) throws GenesysApiException {

    ArrayNode arr = mapper.createArrayNode();
    for (ObjectNode accn : accns) {
      arr.add(accn);
    }

    _log.debug("Sending: " + arr);
    return query(Verb.PUT, "/acn/" + instCode + "/update", null, arr.toString());
  }

  public String accessionExists(String instCode, Collection<ObjectNode> accns) throws GenesysApiException {
    ArrayNode arr = mapper.createArrayNode();
    for (ObjectNode accn : accns) {
      arr.add(accn);
    }

    _log.debug("Sending: " + arr);
    return query(Verb.PUT, "/acn/" + instCode + "/check", null, arr.toString());
  }

  public String updateAccessions(String instCode, Collection<ObjectNode> accns) throws GenesysApiException, InterruptedException {

    if (accns == null || accns.size() == 0) {
      return null;
    }

    ArrayNode arr = mapper.createArrayNode();
    for (ObjectNode accn : accns) {
      arr.add(accn);
    }

    return updateAccessions(instCode, arr);
  }

  public String updateAccessions(String instCode, ArrayNode arr) throws OAuthAuthenticationException, GenesysApiException, InterruptedException {
    _log.debug("Sending: " + arr);

    for (int retry = 0; retry < 5; retry++) {
      try {
        return query(Verb.PUT, "/acn/" + instCode + "/upsert", null, arr.toString());
      } catch (PleaseRetryException e) {
        long sleepTime = (long) (Math.pow(2, retry) * 100 + Math.pow(2, retry) * 2500 * Math.random());
        _log.warn("Retrying PUT after " + sleepTime + " ms.");
        Thread.sleep(sleepTime);
      }
    }

    throw new RuntimeException("All retries failed");
  }

  public String updateOrganizationMembers(String organizationSlug, ArrayNode institutes) throws GenesysApiException {
    _log.debug("Sending: " + institutes);
    try {
      return query(Verb.PUT, "/org/" + organizationSlug + "/set-institutes", null, institutes.toString());
    } catch (PleaseRetryException e) {
      _log.warn("Retrying PUT after some time...");
      try {
        Thread.sleep((long) (1000 * Math.random()));
      } catch (InterruptedException e1) {
        e1.printStackTrace();
      }
      return query(Verb.PUT, "/org/" + organizationSlug + "/set-institutes", null, institutes.toString());
    }
  }

  public String updateAccessionNames(String instCode, Collection<ObjectNode> batch) throws GenesysApiException {
    _log.debug("Sending: " + batch);
    try {
      return query(Verb.PUT, "/acn/" + instCode + "/names", null, batch.toString());
    } catch (PleaseRetryException e) {
      _log.warn("Retrying PUT after some time...");
      try {
        Thread.sleep((long) (1000 * Math.random()));
      } catch (InterruptedException e1) {
        e1.printStackTrace();
      }
      _log.warn("Retrying PUT");
      return query(Verb.PUT, "/acn/" + instCode + "/names", null, batch.toString());
    }
  }

  public String deleteAccessions(String instCode, ArrayNode array) throws GenesysApiException {
    return query(Verb.PUT, "/acn/" + instCode + "/delete", null, array.toString());
  }

  public String deleteAccession(String instCode, ArrayNode ids) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/acn/" + instCode + "/delete", null, ids.toString());
  }

  public String getAuthorizationUrl(Token accessToken) {
    return this.service.getAuthorizationUrl(accessToken);
  }

  /**
   * Obtain access and refresh tokens with verifier code
   *
   * @param verifierCode
   */
  public void authenticate(String verifierCode) {
    Verifier verifier = new Verifier(verifierCode);
    accessToken = service.getAccessToken(GenesysClient.EMPTY_TOKEN, verifier);

    _log.info("ACCESS TOKEN: " + accessToken.getToken() + " sec=" + accessToken.getSecret() + " raw=" + accessToken.getRawResponse());

    refreshToken = genesysApi.getRefreshToken(accessToken);
    _log.info("REFRESH TOKEN: " + refreshToken.getToken() + " sec=" + refreshToken.getSecret() + " raw=" + refreshToken.getRawResponse());
  }

  public Token getAccessToken() {
    return accessToken;
  }

  public Token getRefreshToken() {
    return refreshToken;
  }

  public String me() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/me");
  }

  public String getCrop(String shortName) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    if (!shortName.matches("^\\w+$")) {
      throw new GenesysApiException("Crop shortname can only contain characters");
    }
    return query("/crops/" + shortName);
  }

  public String listParameters() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/parameter/list");
  }

  public String putParameter(ObjectNode node) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/kpi/parameter", null, node.toString());
  }

  public String getParameter(String name) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/parameter/" + name);
  }

  public String listDimensions() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/dimension/list");
  }

  public String getDimension(long id) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/dimension/" + id);
  }

  public String putDimension(ObjectNode node) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/kpi/dimension", null, node.toString());
  }

  public String listExecutions() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/execution/list");
  }

  public String getExecution(String name) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/kpi/execution/" + name);
  }

  public String putExecution(ObjectNode node) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/kpi/execution", null, node.toString());
  }

  public String kpiExecute(String name) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/kpi/execution/" + name + "/execute", null, null);
  }

  public String deleteDimension(long id) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.DELETE, "/kpi/dimension/" + id, null, null);
  }

  public String deleteExecution(String name) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.DELETE, "/kpi/execution/" + name, null, null);
  }

  public String deleteParameter(String name) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.DELETE, "/kpi/parameter/" + name, null, null);
  }

  public String listCrops() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/crops");
  }

  public String putCrop(ObjectNode node) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/crops", null, node.toString());
  }

  public String deleteCrop(String shortName) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.DELETE, "/crops/" + shortName, null, null);
  }

  public String getCropRules(String shortName) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/crops/" + shortName + "/rules");
  }

  public String putCropRules(String shortName, ArrayNode currentCropRules) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.PUT, "/crops/" + shortName + "/rules", null, currentCropRules.toString());
  }

  public String rebuildCropTaxa() throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/crops/rebuild", null, null);
  }

  public String rebuildCropTaxa(String shortName) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/crops/" + shortName + "/rebuild", null, null);
  }

  public String listOrganizations(int page) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    Map<String, String> qs = new HashMap<String, String>();
    qs.put("page", String.valueOf(page));
    return query(Verb.GET, "/org", qs, null);
  }

  public String getOrganization(String slug) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/org/" + slug);
  }

  public String updateOrganization(ObjectNode org) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.POST, "/org", null, org.toString());
  }

  public String deleteOrganization(String slug) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.DELETE, "/org/" + slug, null, null);
  }

  public String getOrganizationMembers(String slug) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/org/" + slug + "/institutes");
  }

  public String putOrganizationMembers(String slug, ArrayNode currentMembers) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.PUT, "/org/" + slug + "/set-institutes", null, currentMembers.toString());
  }

  public String getOrganizationBlurp(String slug, String language) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query("/org/" + slug + "/blurp/" + language);
  }

  public String updateOrganizationBlurp(String slug, ObjectNode blurp) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    return query(Verb.PUT, "/org/" + slug + "/blurp", null, blurp.toString());
  }

  public String listObservations(String executionName, String dimensionFilter, int page) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    Map<String, String> qs = new HashMap<String, String>();
    qs.put("page", String.valueOf(page));
    return query(Verb.POST, "/kpi/observation/" + executionName + "/", qs, StringUtils.defaultIfBlank(dimensionFilter, ""));
  }

  public String listAccessions(String instCode, int page, String query) throws OAuthAuthenticationException, PleaseRetryException, GenesysApiException {
    Map<String, String> params = new HashMap<String, String>();
    params.put("page", String.valueOf(page));
    params.put("query", query);
    return query(Verb.GET, "/acn/" + instCode + "/list", params, null);
  }
}
TOP

Related Classes of org.genesys2.client.oauth.GenesysClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.