com.adobe.acs.commons.adobeio.service.impl.EndpointServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.acs.commons.adobeio.service.impl.EndpointServiceImpl.java

Source

/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2013 - 2018 Adobe
 * %%
 * 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.
 * #L%
 */
package com.adobe.acs.commons.adobeio.service.impl;

import static com.adobe.acs.commons.adobeio.service.impl.AdobeioConstants.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.sling.api.servlets.HttpConstants.METHOD_GET;
import static org.apache.sling.api.servlets.HttpConstants.METHOD_POST;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.acs.commons.adobeio.service.EndpointService;
import com.adobe.acs.commons.adobeio.service.IntegrationService;
import com.adobe.acs.commons.util.ParameterUtil;
import com.drew.lang.annotations.NotNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

@Component(service = EndpointService.class)
@Designate(ocd = EndpointConfiguration.class, factory = true)
public class EndpointServiceImpl implements EndpointService {

    private static final Logger LOGGER = LoggerFactory.getLogger(EndpointServiceImpl.class);

    private String id;
    private String url;
    private String method;
    private List<Map.Entry<String, String>> specificServiceHeaders;
    private EndpointConfiguration config;

    @Reference
    private IntegrationService integrationService;

    @Reference
    private AdobeioHelper helper;

    @Activate
    protected void activate(final EndpointConfiguration config) throws Exception {
        LOGGER.debug("Start ACTIVATE Endpoint {}", config.id());
        this.id = config.id();
        this.url = config.endpoint();
        this.method = config.method();
        this.config = config;
        this.specificServiceHeaders = convertServiceSpecificHeaders(config.specificServiceHeaders());
        LOGGER.debug("End ACTIVATE Endpoint {}", id);
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public String getMethod() {
        return this.method;
    }

    @Override
    public String getUrl() {
        return this.url;
    }

    @Override
    public String[] getConfigServiceSpecificHeaders() {
        return config.specificServiceHeaders();
    }

    @Override
    public JsonObject performIO_Action() {
        return performio(url, Collections.emptyMap());
    }

    @Override
    public JsonObject performIO_Action(String url, String method, String[] headers, JsonObject payload) {
        return process(url, Collections.emptyMap(), method, headers, payload);
    }

    @Override
    public JsonObject performIO_Action(@NotNull Map<String, String> queryParameters) {
        return performio(url, queryParameters);
    }

    @Override
    public JsonObject performIO_Action(@NotNull JsonObject payload) {
        return handleAdobeIO_Action(payload);
    }

    @Override
    public boolean isConnected() {
        try {
            JsonObject response = processGet(new URIBuilder(url).build(), null);
            return !response.has(RESULT_ERROR);
        } catch (Exception e) {
            LOGGER.error("Problem testing the connection for {}", id, e);
        }
        return false;
    }

    // --------------- PRIVATE METHODS ----------------- //

    /**
     * This method performs the Adobe I/O action
     *
     * @param payload
     *            Payload of the call
     * @return JsonObject containing the result
     */
    private JsonObject handleAdobeIO_Action(@NotNull final JsonObject payload) {
        // initialize jsonobject
        JsonObject processResponse = new JsonObject();

        // perform action, if the action is defined in the configuration
        try {
            LOGGER.debug("ActionUrl = {} . method = {}", url, method);
            // process the Adobe I/O action
            processResponse = process(url, Collections.emptyMap(), method, null, payload);
        } catch (Exception e) {
            processResponse.addProperty(RESULT_ERROR, "Problem processing");
            LOGGER.error("Problem processing action {} in handleAdobeIO_Action", url);
        }

        return processResponse;
    }

    /**
     * Process the Adobe I/O action
     * 
     * @param actionUrl
     *            The url to be executed
     * @param queryParameters
     *            The query parameters to pass
     * @param method
     *            The method to be executed
     * @param payload
     *            The payload of the call
     * @return JsonObject containing the result of the action
     * @throws Exception
     *             Thrown when process-action throws an exception
     */
    private JsonObject process(@NotNull final String actionUrl, @NotNull final Map<String, String> queryParameters,
            @NotNull final String method, final String[] headers, @NotNull final JsonObject payload) {
        if (isBlank(actionUrl) || isBlank(method)) {
            LOGGER.error("Method or url is null");
            return new JsonObject();
        }

        URI uri = null;

        try {
            URIBuilder builder = new URIBuilder(actionUrl);
            queryParameters.forEach((k, v) -> builder.addParameter(k, v));
            uri = builder.build();

        } catch (URISyntaxException uriexception) {
            LOGGER.error(uriexception.getMessage());
            return new JsonObject();
        }

        LOGGER.debug("Performing method = {}. queryParameters = {}. actionUrl = {}. payload = {}", method,
                queryParameters, uri, payload);

        try {
            if (StringUtils.equalsIgnoreCase(method, METHOD_POST)) {
                return processPost(uri, payload, headers);
            } else if (StringUtils.equalsIgnoreCase(method, METHOD_GET)) {
                return processGet(uri, headers);
            } else if (StringUtils.equalsIgnoreCase(method, "PATCH")) {
                return processPatch(uri, payload, headers);
            } else {
                return new JsonObject();
            }
        } catch (IOException ioexception) {
            LOGGER.error(ioexception.getMessage());
            return new JsonObject();

        }

    }

    private JsonObject processGet(@NotNull final URI uri, String[] headers) throws IOException {
        StopWatch stopWatch = new StopWatch();
        LOGGER.debug("STARTING STOPWATCH {}", uri);
        stopWatch.start();

        HttpGet get = new HttpGet(uri);
        get.setHeader(AUTHORIZATION, BEARER + integrationService.getAccessToken());
        get.setHeader(CACHE_CONTRL, NO_CACHE);
        get.setHeader(X_API_KEY, integrationService.getApiKey());
        if (headers == null || headers.length == 0) {
            addHeaders(get, specificServiceHeaders);
        } else {
            addHeaders(get, convertServiceSpecificHeaders(headers));
        }
        Header[] contentTypeHeaders = get.getHeaders(CONTENT_TYPE);
        // If no content type is given, then default to application/json
        if (ArrayUtils.isEmpty(contentTypeHeaders)) {
            get.setHeader(CONTENT_TYPE, CONTENT_TYPE_APPLICATION_JSON);
        }

        try (CloseableHttpClient httpClient = helper.getHttpClient(integrationService.getTimeoutinMilliSeconds())) {
            CloseableHttpResponse response = httpClient.execute(get);
            final JsonObject result = responseAsJson(response);

            LOGGER.debug("Response-code {}", response.getStatusLine().getStatusCode());
            LOGGER.debug("STOPPING STOPWATCH {}", uri);
            stopWatch.stop();
            LOGGER.debug("Stopwatch time: {}", stopWatch);
            stopWatch.reset();

            return result;
        }
    }

    private JsonObject processPost(@NotNull final URI uri, @NotNull final JsonObject payload, String[] headers)
            throws IOException {
        HttpPost post = new HttpPost(uri);
        return (payload != null) && isNotBlank(payload.toString()) ? processRequestWithBody(post, payload, headers)
                : new JsonObject();
    }

    private JsonObject processPatch(@NotNull final URI uri, @NotNull final JsonObject payload, String[] headers)
            throws IOException {
        HttpPatch patch = new HttpPatch(uri);
        return (payload != null) && isNotBlank(payload.toString()) ? processRequestWithBody(patch, payload, headers)
                : new JsonObject();
    }

    private JsonObject processRequestWithBody(@NotNull final HttpEntityEnclosingRequestBase base,
            @NotNull final JsonObject payload, String[] headers) throws IOException {

        StopWatch stopWatch = new StopWatch();
        LOGGER.debug("STARTING STOPWATCH processRequestWithBody");
        stopWatch.start();

        base.setHeader(AUTHORIZATION, BEARER + integrationService.getAccessToken());
        base.setHeader(CACHE_CONTRL, NO_CACHE);
        base.setHeader(X_API_KEY, integrationService.getApiKey());
        base.setHeader(CONTENT_TYPE, CONTENT_TYPE_APPLICATION_JSON);
        if (headers == null || headers.length == 0) {
            addHeaders(base, specificServiceHeaders);
        } else {
            addHeaders(base, convertServiceSpecificHeaders(headers));
        }

        StringEntity input = new StringEntity(payload.toString());
        input.setContentType(CONTENT_TYPE_APPLICATION_JSON);

        if (!base.getClass().isInstance(HttpGet.class)) {
            base.setEntity(input);
        }

        LOGGER.debug("Process call. uri = {}. payload = {}", base.getURI().toString(), payload);

        try (CloseableHttpClient httpClient = helper.getHttpClient(integrationService.getTimeoutinMilliSeconds())) {
            CloseableHttpResponse response = httpClient.execute(base);
            final JsonObject result = responseAsJson(response);

            LOGGER.debug("STOPPING STOPWATCH processRequestWithBody");
            stopWatch.stop();
            LOGGER.debug("Stopwatch time processRequestWithBody: {}", stopWatch);
            stopWatch.reset();
            return result;
        }
    }

    private JsonObject responseAsJson(@NotNull final HttpResponse response) throws IOException {
        String result = IOUtils.toString(response.getEntity().getContent(), CharEncoding.UTF_8);
        JsonParser parser = new JsonParser();
        JsonObject resultJson = new JsonObject();
        try {
            LOGGER.debug("Call result = {}", result);
            resultJson = parser.parse(result).getAsJsonObject();
        } catch (Exception e) {
            resultJson.addProperty(RESULT_ERROR, result);
        }

        LOGGER.debug("JSON result from Service: {}", resultJson);
        return resultJson;
    }

    private JsonObject performio(@NotNull String actionUrl, @NotNull Map<String, String> queryParameters) {
        try {
            return process(actionUrl, queryParameters, StringUtils.upperCase(method), null, null);
        } catch (Exception e) {
            LOGGER.error("Problem processing action {} in performIO", actionUrl, e);
        }
        return new JsonObject();
    }

    private void addHeaders(HttpRequest request, List<Map.Entry<String, String>> headers) {
        headers.forEach(e -> request.addHeader(e.getKey(), e.getValue()));
    }

    protected List<Map.Entry<String, String>> convertServiceSpecificHeaders(String[] specificServiceHeaders) {
        if (specificServiceHeaders == null) {
            return Collections.emptyList();
        } else {
            return Arrays.asList(specificServiceHeaders).stream().map(s -> ParameterUtil.toMapEntry(s, ":"))
                    .filter(e -> e != null).collect(Collectors.toList());
        }
    }

}