Exemple #1
0
/**
 * Class deals with JSON objects serialization and sending requests to REST API endpoint.
 *
 * @author Pawel Domas
 */
public class ApiHandler {

  /** Default maximum retries number for requests on conference create API endpoint */
  private final int CONFERENCE_CREATE_MAX_RETRIES = 8;

  /** Default maximum retries number for requests on conference create API endpoint */
  private final int CONFERENCE_RESOLVE_CONFLICT_RETRIES = 8;

  /** Default maximum retries number for requests on conference create API endpoint */
  private final int CONFERENCE_DELETE_MAX_RETRIES = 13;

  /** The logger */
  private static final Logger logger = Logger.getLogger(ApiHandler.class);

  /** Base URL of the REST API. */
  private final String baseUrl;

  /** Apache HTTP client instance used for communicating with reservation REST API over HTTP */
  private final HttpClient httpClient;

  /** <tt>JSONParser</tt> instance used for parsing JSON. */
  private final JSONParser jsonParser = new JSONParser();

  /** JSON handler for <tt>Conference</tt> objects. */
  private final ConferenceJsonHandler conferenceJson = new ConferenceJsonHandler();

  /** JSON handler for error responses. */
  private final ErrorJsonHandler errorJson = new ErrorJsonHandler();

  /** Maximum retry number for create conference API endpoint */
  private final int retriesCreate;

  /** Maximum retry number for resolve conflict conference API endpoint */
  private final int retriesResolveConflict;

  /** Maximum retry number for delete conference API endpoint */
  private final int retriesDelete;

  /**
   * Creates new instance of <tt>ApiHandler</tt>.
   *
   * @param baseUrl the base URL of REST API.
   */
  public ApiHandler(String baseUrl) {
    this.baseUrl = baseUrl;
    this.httpClient = new DefaultHttpClient();
    this.retriesCreate = CONFERENCE_CREATE_MAX_RETRIES;
    this.retriesResolveConflict = CONFERENCE_RESOLVE_CONFLICT_RETRIES;
    this.retriesDelete = CONFERENCE_DELETE_MAX_RETRIES;
  }

  /** Creates new instance of <tt>ApiHandler</tt> with custom HTTP client */
  public ApiHandler(String baseUrl, HttpClient httpClient) {
    this.baseUrl = baseUrl;
    this.httpClient = httpClient;
    this.retriesCreate = CONFERENCE_CREATE_MAX_RETRIES;
    this.retriesResolveConflict = CONFERENCE_RESOLVE_CONFLICT_RETRIES;
    this.retriesDelete = CONFERENCE_DELETE_MAX_RETRIES;
  }

  /** Creates new instance of <tt>ApiHandler</tt> with custom retries numbers for API endpoints */
  public ApiHandler(
      String baseUrl,
      HttpClient httpClient,
      int retriesCreate,
      int retriesResolveConflict,
      int retriesDelete) {
    this.baseUrl = baseUrl;
    this.httpClient = httpClient;
    this.retriesCreate = retriesCreate;
    this.retriesDelete = retriesDelete;
    this.retriesResolveConflict = retriesResolveConflict;
  }

  /**
   * Send Conference POST request to API endpoint which is used for allocating new conferences in
   * reservation system.
   *
   * @param ownerEmail email of new conference owner
   * @param mucRoomName full name of MUC room that is hosting the conference.
   *     {room_name}@{muc.server.net}
   * @return <tt>ApiResult</tt> that contains system response. It will contain <tt>Conference</tt>
   *     instance filled with data from the reservation system if everything goes OK.
   * @throws FaultTolerantRESTRequest.RetryExhaustedException When the number of retries to submit
   *     the request for the conference data is reached
   * @throws UnsupportedEncodingException When the room data have the encoding that does not play
   *     with UTF8 standard
   */
  public ApiResult createNewConference(String ownerEmail, String mucRoomName)
      throws FaultTolerantRESTRequest.RetryExhaustedException, UnsupportedEncodingException {
    Conference conference = new Conference(mucRoomName, ownerEmail, new Date());

    HttpPost post = new HttpPost(baseUrl + "/conference");

    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
    Map<String, Object> jsonMap = conference.createJSonMap();

    for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
      nameValuePairs.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
    }

    post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF8"));

    logger.info("Sending post: " + jsonMap);

    CreateConferenceResponseParser conferenceResponseParser =
        new CreateConferenceResponseParser(conference);

    FaultTolerantRESTRequest faultTolerantRESTRequest =
        new FaultTolerantRESTRequest(post, conferenceResponseParser, retriesCreate, httpClient);

    return faultTolerantRESTRequest.submit();
  }

  /**
   * Sends Conference GET request to the REST API endpoint. Is used to read info about the
   * conference from the reservation system.
   *
   * @param conferenceId the identifier of the conference for which we want to read the data.
   * @return <tt>ApiResult</tt> which describes the response. It will contain <tt>Conference</tt> if
   *     data has been read successfully.
   * @throws FaultTolerantRESTRequest.RetryExhaustedException when the number of retries to submit
   *     the request for the conference data is reached
   */
  public ApiResult getConference(Number conferenceId)
      throws FaultTolerantRESTRequest.RetryExhaustedException {
    HttpGet get = new HttpGet(baseUrl + "/conference/" + conferenceId);

    GetConferenceResponseParser conferenceResponseParser = new GetConferenceResponseParser();

    FaultTolerantRESTRequest faultTolerantRESTRequest =
        new FaultTolerantRESTRequest(
            get, conferenceResponseParser, retriesResolveConflict, httpClient);

    return faultTolerantRESTRequest.submit();
  }

  /**
   * Sends conference DELETE request to the REST API endpoint.
   *
   * @param conferenceId the identifier of the conference to be destroyed.
   * @return <tt>ApiResult</tt> that describes the response. Check <tt>ApiResult#statusCode</tt> to
   *     see if it went OK.
   * @throws FaultTolerantRESTRequest.RetryExhaustedException When the number of retries to submit
   *     the request for the conference data is reached
   */
  public ApiResult deleteConference(Number conferenceId)
      throws FaultTolerantRESTRequest.RetryExhaustedException {
    HttpDelete delete = new HttpDelete(baseUrl + "/conference/" + conferenceId);

    DeleteConferenceResponseParser conferenceResponseParser = new DeleteConferenceResponseParser();

    FaultTolerantRESTRequest faultTolerantRESTRequest =
        new FaultTolerantRESTRequest(delete, conferenceResponseParser, retriesDelete, httpClient);

    return faultTolerantRESTRequest.submit();
  }

  /**
   * Parses error response.
   *
   * @param response parsed <tt>ErrorResponse</tt>
   * @return <tt>ErrorResponse</tt> parsed from HTTP content stream.
   * @throws IOException if any IO issues occur.
   * @throws ParseException if any issues with JSON parsing occur.
   */
  private ErrorResponse readErrorResponse(HttpResponse response)
      throws IOException, ParseException {
    BufferedReader rd =
        new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

    jsonParser.parse(rd, errorJson);

    return errorJson.getResult();
  }

  /**
   * Parses JSON string returned in HTTP response and converts it to <tt>Conference</tt> instance.
   *
   * @param conference <tt>Conference</tt> instance that contains the data returned by API endpoint.
   * @param response HTTP response returned by the API endpoint.
   * @return <tt>Conference</tt> instance that contains the data returned by API endpoint.
   * @throws IOException if any IO problems occur.
   * @throws ParseException if any problems with JSON parsing occur.
   */
  private Conference readConferenceResponse(Conference conference, HttpResponse response)
      throws IOException, ParseException {
    BufferedReader rd =
        new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

    if (conference != null) {
      conferenceJson.setForUpdate(conference);
    }

    jsonParser.parse(rd, conferenceJson);

    if (conference == null) {
      conference = conferenceJson.getResult();
    }

    logger.info("ID: " + conference.getId());
    logger.info("PIN: " + conference.getPin());
    logger.info("URL: " + conference.getUrl());
    logger.info("SIP ID: " + conference.getSipId());
    logger.info("START TIME: " + conference.getStartTime());
    logger.info("DURATION: " + conference.getDuration());

    return conference;
  }

  /** This class will be used to parse the response for room deletion reservation callback. */
  protected class DeleteConferenceResponseParser extends AbstractRESTResponseParser {

    /**
     * @param response The Apache HC client response
     * @throws org.json.simple.parser.ParseException
     */
    @Override
    protected void parse(HttpResponse response)
        throws IOException, ParseException, FaultTolerantRESTRequest.RetryRequestedException {
      int statusCode = response.getStatusLine().getStatusCode();

      if (200 == statusCode || 201 == statusCode) {
        // OK
        result = new ApiResult(statusCode);
      } else if ((statusCode >= 400) && (statusCode < 500)) {
        // Client side error, indicates that the
        // reservation backend do not want the resubmission
        ErrorResponse error = readErrorResponse(response);

        result = new ApiResult(statusCode, error);
      } else {
        // Unusual status code, request the retry
        throw new FaultTolerantRESTRequest.RetryRequestedException();
      }
    }
  }

  /** The base class for dealing with conference data JSON response handling */
  protected class ReadConferenceResponseParser extends AbstractRESTResponseParser {

    /** The conference instance that relates to this parti */
    protected Conference conference;

    /**
     * Parse the room read response received from reservation backend.
     *
     * <p>This will request the retry if the response status code differs from 200, 201 or 4xx.
     *
     * @param response The Apache HTTP client response
     * @throws IOException
     * @throws ParseException
     * @throws FaultTolerantRESTRequest.RetryRequestedException
     */
    @Override
    protected void parse(HttpResponse response)
        throws IOException, ParseException, FaultTolerantRESTRequest.RetryRequestedException {

      int statusCode = response.getStatusLine().getStatusCode();

      logger.info("STATUS CODE: " + statusCode);

      if (200 == statusCode || 201 == statusCode) {
        // OK
        conference = readConferenceResponse(conference, response);

        result = new ApiResult(statusCode, conference);
      } else if ((statusCode >= 400) && (statusCode < 500)) {
        // Client side error, indicates that the reservation
        // backend do not want the resubmission
        ErrorResponse error = readErrorResponse(response);

        result = new ApiResult(statusCode, error);

      } else {

        // Unusual status code, request the retry
        throw new FaultTolerantRESTRequest.RetryRequestedException();
      }
    }
  }

  /** The response parser to use for conflict resolving reservation system callback */
  protected class GetConferenceResponseParser extends ReadConferenceResponseParser {

    /** Instantiate the <tt>GetConferenceResponseParser</tt> */
    public GetConferenceResponseParser() {
      this.conference = null;
    }
  }

  /** The response parser to use for conference creating reservation system callback */
  protected class CreateConferenceResponseParser extends ReadConferenceResponseParser {

    /**
     * Instantiate the <tt>GetConferenceResponseParser</tt> with a given conference instance
     *
     * @param conference the <tt>Conference</tt> instance that is ought to perform communication
     *     callback
     */
    public CreateConferenceResponseParser(Conference conference) {
      this.conference = conference;
    }
  }
}
public class BaseService {

  protected Logger log = Logger.getLogger(this.getClass());

  protected int resultCode;
  protected String resultMessage = "";

  protected String bonitaApiHost;
  protected String bonitaApiUsername;
  protected String bonitaApiPassword;
  protected String bonitaApiHttpUsername;
  protected String bonitaApiHttpPassword;
  protected String bonitaApiPath;
  // protected String bonitaProcessId;

  protected String workflowServiceUrl;

  protected String rallyApiHost;
  protected String rallyApiHttpUsername;
  protected String rallyApiHttpPassword;
  protected String rallyProjectIds;

  protected Properties confProperties;

  protected String confFileName;

  protected AuthUser user;

  public BaseService() {}

  public BaseService(String confFileName) {
    this.confFileName = confFileName;

    loadProperty();
  }

  public void setUser(AuthUser user) {
    this.user = user;
  }

  public void setConfigFile(String confFileName) {
    this.confFileName = confFileName;

    loadProperty();
  }

  public void loadProperty() {

    try {

      File file = new File(confFileName);

      log.debug("file=" + file.getAbsolutePath());

      confProperties = new Properties();
      confProperties.loadFromXML(new FileInputStream(file));

      bonitaApiHost = confProperties.getProperty("bonita.api.host");
      bonitaApiUsername = confProperties.getProperty("bonita.api.username");
      bonitaApiPassword = confProperties.getProperty("bonita.api.password");
      bonitaApiHttpUsername = confProperties.getProperty("bonita.api.http.username");
      bonitaApiHttpPassword = confProperties.getProperty("bonita.api.http.password");
      bonitaApiPath = confProperties.getProperty("bonita.api.path");

      rallyApiHost = confProperties.getProperty("rally.api.host");
      rallyApiHttpUsername = confProperties.getProperty("rally.api.http.username");
      rallyApiHttpPassword = confProperties.getProperty("rally.api.http.password");
      rallyProjectIds = confProperties.getProperty("rally.project.ids");

      // bonitaProcessId=properties.getProperty("bonita.process.xp_code.id");

      workflowServiceUrl = confProperties.getProperty("service.url");

    } catch (Exception e) {
      log.error("", e);
    }
  }

  protected String getRallyXML(String apiUrl) throws Exception {
    String responseXML = "";

    DefaultHttpClient httpClient = new DefaultHttpClient();

    Base64 base64 = new Base64();
    String encodeString =
        new String(base64.encode((rallyApiHttpUsername + ":" + rallyApiHttpPassword).getBytes()));

    HttpGet httpGet = new HttpGet(apiUrl);
    httpGet.addHeader("Authorization", "Basic " + encodeString);
    HttpResponse response = httpClient.execute(httpGet);
    HttpEntity entity = response.getEntity();

    if (entity != null) {

      InputStreamReader reader = new InputStreamReader(entity.getContent());
      BufferedReader br = new BufferedReader(reader);

      StringBuilder sb = new StringBuilder();
      String line = "";
      while ((line = br.readLine()) != null) {
        sb.append(line);
      }

      responseXML = sb.toString();
    }

    log.debug("responseXML=" + responseXML);

    return responseXML;
  }

  protected String postRallyXML(String apiUrl, String requestXML) throws Exception {
    String responseXML = "";

    DefaultHttpClient httpClient = new DefaultHttpClient();

    Base64 base64 = new Base64();
    String encodeString =
        new String(base64.encode((rallyApiHttpUsername + ":" + rallyApiHttpPassword).getBytes()));

    HttpPost httpPost = new HttpPost(apiUrl);
    httpPost.addHeader("Authorization", "Basic " + encodeString);

    httpPost.setEntity(new StringEntity(requestXML));

    HttpResponse response = httpClient.execute(httpPost);
    HttpEntity entity = response.getEntity();

    responseXML = getEntityString(entity);

    return responseXML;
  }

  protected String getRallyAPIError(String responseXML) {
    String errorMsg = "";

    try {

      org.jdom.input.SAXBuilder bSAX = new org.jdom.input.SAXBuilder();
      org.jdom.Document doc = bSAX.build(new StringReader(responseXML));
      Element root = doc.getRootElement();

      XPath xpath = XPath.newInstance("//Errors");
      List xlist = xpath.selectNodes(root);

      Iterator iter = xlist.iterator();
      while (iter.hasNext()) {

        Element item = (Element) iter.next();
        errorMsg = item.getChildText("OperationResultError");
      }

    } catch (Exception e) {
      errorMsg = e.toString();
    }

    return errorMsg;
  }

  public String getEntityString(HttpEntity entity) throws Exception {
    StringBuilder sb = new StringBuilder();

    if (entity != null) {
      InputStreamReader reader = new InputStreamReader(entity.getContent());
      BufferedReader br = new BufferedReader(reader);

      String line = "";
      while ((line = br.readLine()) != null) {
        sb.append(line);
      }
    }

    return sb.toString();
  }

  public String loadStream(InputStream is) {
    StringBuilder sb = new StringBuilder();

    try {
      InputStreamReader reader = new InputStreamReader(is);
      BufferedReader br = new BufferedReader(reader);

      String line = "";
      while ((line = br.readLine()) != null) {
        sb.append(line);
      }
    } catch (Exception e) {
      log.error("", e);
    }

    return sb.toString();
  }

  public int getResultCode() {
    return resultCode;
  }

  public String getResultMessage() {
    return resultMessage;
  }

  public static void main(String[] argv) {}
}