org.sead.nds.repository.C3PRPubRequestFacade.java Source code

Java tutorial

Introduction

Here is the source code for org.sead.nds.repository.C3PRPubRequestFacade.java

Source

/*
 * Copyright 2015 University of Michigan
 *
 * 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.
 *
 * @author myersjd@umich.edu
 */

package org.sead.nds.repository;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Properties;

import javax.ws.rs.core.MediaType;

import org.apache.commons.compress.parallel.InputStreamSupplier;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class C3PRPubRequestFacade extends PubRequestFacade {

    private static final Logger log = Logger.getLogger(C3PRPubRequestFacade.class);

    private int timeout = 300;
    private RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000)
            .setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();

    private static HttpClientContext localContext = HttpClientContext.create();

    private PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    protected CloseableHttpClient client;

    Properties props = null;
    String RO_ID = null;
    String bearerToken = null;

    protected JSONObject request = null;
    protected JSONObject repository = null;
    protected JSONObject oremap = null;

    public C3PRPubRequestFacade(String RO_ID, Properties props) {
        this.RO_ID = RO_ID;
        this.props = props;
        cm.setDefaultMaxPerRoute(Repository.getNumThreads());
        cm.setMaxTotal(Repository.getNumThreads() > 20 ? Repository.getNumThreads() : 20);
        client = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(config).build();

    }

    protected String proxyIfNeeded(String urlString) {

        if (props.containsKey("proxyserver")) {
            return props.getProperty("c3pr.address") + urlString.substring(urlString.indexOf("api"));
        } else {
            return urlString;
        }
    }

    public JSONObject getPublicationRequest() {
        if (request == null) {
            String c3prServer = props.getProperty("c3pr.address");
            HttpGet getPubRequest;
            try {
                log.debug("Retrieving: " + c3prServer + "api/researchobjects/" + URLEncoder.encode(RO_ID, "UTF-8"));
                getPubRequest = new HttpGet(
                        c3prServer + "api/researchobjects/" + URLEncoder.encode(RO_ID, "UTF-8"));

                getPubRequest.addHeader("accept", "application/json");

                CloseableHttpResponse response = client.execute(getPubRequest, getLocalContext());

                if (response.getStatusLine().getStatusCode() == 200) {
                    String mapString = EntityUtils.toString(response.getEntity());
                    log.trace(mapString);
                    request = new JSONObject(mapString);

                }
            } catch (UnsupportedEncodingException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                log.error("Unable to retrieve pub request document", e);
                e.printStackTrace();
            }

            // Set the bearerToekn for any calls to the originating space
            // related to
            // this RO
            if (request.has("Bearer Token")) {
                bearerToken = request.getString("Bearer Token");
            } else if (props.containsKey("bearertoken.default")) {
                bearerToken = props.getProperty("bearertoken.default");
            }
        }
        return request;
    }

    public JSONObject getRepositoryProfile() {
        if (repository == null) {
            // Make sure we have retrieved the request so we can look for the
            // repository being requested
            if (request == null) {
                request = getPublicationRequest();
            }
            if (request.has("Repository")) {
                String repo = request.getString("Repository");

                String c3prServer = props.getProperty("c3pr.address");
                HttpGet getRepoRequest;
                try {
                    log.debug("Retrieving: " + c3prServer + "api/repositories/" + URLEncoder.encode(repo, "UTF-8"));
                    getRepoRequest = new HttpGet(
                            c3prServer + "api/repositories/" + URLEncoder.encode(repo, "UTF-8"));

                    getRepoRequest.addHeader("accept", "application/json");

                    CloseableHttpResponse response = client.execute(getRepoRequest, getLocalContext());

                    if (response.getStatusLine().getStatusCode() == 200) {
                        String mapString = EntityUtils.toString(response.getEntity());
                        log.trace(mapString);
                        repository = new JSONObject(mapString);

                    }
                } catch (UnsupportedEncodingException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    log.error("Unable to retrieve repository document", e);
                    e.printStackTrace();
                }
            }
        }
        return repository;
    }

    private URI getOREMapURI() {
        try {
            return new URI(proxyIfNeeded(request.getJSONObject("Aggregation").getString("@id")));
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public JSONObject getOREMap() {
        if (oremap == null) {

            log.debug("Retreiving: " + getOREMapURI().toString());

            HttpGet getMap = new HttpGet(getOREMapURI());
            getMap.addHeader("accept", MediaType.APPLICATION_JSON);

            try {
                CloseableHttpResponse response = client.execute(getMap, getLocalContext());

                if (response.getStatusLine().getStatusCode() == 200) {
                    String mapString = EntityUtils.toString(response.getEntity());
                    log.trace("OREMAP: " + mapString);
                    oremap = new JSONObject(mapString);
                }
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                log.error("Unable to retrieve OREMap", e);
                e.printStackTrace();
            }
        }
        return oremap;
    }

    private HttpGet createNewGetRequest(URI url, String returnType) {

        HttpGet request = null;

        if (bearerToken != null) {
            // Clowder Kluge - don't add key once Auth header is accepted
            try {
                request = new HttpGet(new URI(url.toURL().toString() + "?key=" + bearerToken));
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (URISyntaxException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            request.addHeader("Authorization", "Bearer " + bearerToken);
        } else {
            request = new HttpGet(url);
        }
        if (returnType != null) {
            request.addHeader("accept", returnType);
        }
        return request;
    }

    InputStreamSupplier getInputStreamSupplier(final String uri) {

        return new InputStreamSupplier() {
            public InputStream get() {
                int tries = 0;
                while (tries < 5) {
                    try {
                        HttpGet getMap = createNewGetRequest(new URI(uri), null);
                        log.trace("Retrieving " + tries + ": " + uri);
                        CloseableHttpResponse response;
                        response = client.execute(getMap, getLocalContext());
                        if (response.getStatusLine().getStatusCode() == 200) {
                            log.trace("Retrieved: " + uri);
                            return response.getEntity().getContent();
                        }
                        log.debug("Status: " + response.getStatusLine().getStatusCode());
                        tries++;

                    } catch (ClientProtocolException e) {
                        tries += 5;
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // Retry if this is a potentially temporary error such
                        // as a timeout
                        tries++;
                        log.warn("Attempt# " + tries + " : Unable to retrieve file: " + uri, e);
                        if (tries == 5) {
                            log.error("Final attempt failed for " + uri);
                        }
                        e.printStackTrace();
                    } catch (URISyntaxException e) {
                        tries += 5;
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                log.error("Could not read: " + uri);
                return null;
            }
        };
    }

    JSONArray expandPeople(String[] people) {

        JSONArray peopleArray = new JSONArray();
        if ((people != null) && (people.length != 0)) {
            String c3prServer = props.getProperty("c3pr.address");
            for (int i = 0; i < people.length; i++) {
                log.debug("Expanding: " + people[i]);
                try {
                    log.debug(URLEncoder.encode(people[i], "UTF-8"));
                } catch (UnsupportedEncodingException e2) {
                    // TODO Auto-generated catch block
                    e2.printStackTrace();
                }
                HttpGet getPerson;
                try {
                    getPerson = new HttpGet(c3prServer + "api/people/" + URLEncoder.encode(people[i], "UTF-8"));

                    getPerson.addHeader("accept", "application/json");
                    log.trace("getPerson created" + getPerson.getURI());
                    CloseableHttpResponse response = client.execute(getPerson, getLocalContext());

                    if (response.getStatusLine().getStatusCode() == 200) {
                        String mapString = EntityUtils.toString(response.getEntity());
                        log.trace("Expanded: " + mapString);
                        peopleArray.put(new JSONObject(mapString));

                    } else {
                        log.trace("Adding unexpanded person: " + people[i]);
                        peopleArray.put(people[i]);
                    }
                    // Required to avoid some calls hanging in execute() even
                    // though we do not reuse the HttpGet object
                    getPerson.reset();

                } catch (UnsupportedEncodingException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException ia) {
                    ia.printStackTrace();
                }
            }
            log.debug("Expansion complete");
        }
        return peopleArray;
    }

    public void sendStatus(String stage, String message) {

        String c3prServer = props.getProperty("c3pr.address");
        try {
            String statusUrl = c3prServer + "api/researchobjects/" + URLEncoder.encode(RO_ID, "UTF-8") + "/status";

            log.debug("Posting status to: " + statusUrl);
            HttpPost postStatus = new HttpPost(statusUrl);

            postStatus.addHeader("accept", MediaType.APPLICATION_JSON);
            String statusString = "{\"reporter\":\"" + Repository.getID() + "\", \"stage\":\"" + stage
                    + "\", \"message\":\"" + message + "\"}";
            StringEntity status = new StringEntity(statusString);
            log.trace("Status: " + statusString);
            postStatus.addHeader("content-type", MediaType.APPLICATION_JSON);
            postStatus.setEntity(status);

            CloseableHttpResponse response = client.execute(postStatus, getLocalContext());

            if (response.getStatusLine().getStatusCode() == 200) {
                log.debug("Status Successfully posted");
            } else {
                log.warn("Failed to post status, response code: " + response.getStatusLine().getStatusCode());
            }
            // Must consume entity to allow connection to be released
            // If this line is not here, the third try to send status will
            // result in a
            // org.apache.http.conn.ConnectionPoolTimeoutException: Timeout
            // waiting for connection from pool
            // (or a blocked call/hung program if timeouts weren't set
            EntityUtils.consumeQuietly(response.getEntity());

        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            log.error("Error posting status.", e);

            e.printStackTrace();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            log.error("Error posting status.", e);

            e.printStackTrace();
        } catch (IOException e) {
            log.error("Error posting status.", e);
            e.printStackTrace();
        } catch (Exception e) {
            log.error("Odd Error posting status.", e);
            e.printStackTrace();

        }

        if (echoToConsole) {
            System.out.println("*********************Status Message******************************");
            System.out.println("Reporter: " + Repository.getID() + ", Stage: " + stage);
            System.out.println("Message Text: " + message);
            System.out.println("*****************************************************************");
        }
    }

    public HttpClientContext getLocalContext() {
        return localContext;
    }

    public void setLocalContext(HttpClientContext lc) {
        localContext = lc;
    }

}