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

com.cloudbees.api.event.EventApi Maven / Gradle / Ivy

package com.cloudbees.api.event;


import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * Event API lets you publish and query for events. The events are related to a CloudBees services Subscription or
 * Resource or it could be for a Cloud Resource.
 *
 * @author Vivek Pandey
 */
public class EventApi {

    private static final Logger logger = LoggerFactory.getLogger(EventApi.class);
    static final String SP_PORD_BASE_URL = "https://services-platform.cloudbees.com/";
    private static final String EVENT_API_PATH = "/api/events/";

    private final String accessToken;
    public final String eventApiUrl;
    private final String eventEndpoint;
    private final RestClient restClient = new RestClient();

    /**
     * Create an EventApi instance using a valid Oauth access_token with following scopes:
     *
     * https://api.cloudbees.com/services/api/events/read - For reading/querying events
     * https://api.cloudbees.com/services/api/events/write - For publishing events
     *
     * CloudResource READ capability scope. For example for a git CR, https://acme.org/testdb, the token must
     * be granted with OAuth scope: crs://acme.org/!https://types.cloudbees.com/resource/read
     *
     *
     * @param accessToken valid access token with
     *
     * @throws IOException
     */
    public EventApi(@Nonnull String accessToken) throws IOException, EventApiException {
        this(accessToken, UriBuilder.fromUri(SP_PORD_BASE_URL).path(EVENT_API_PATH).build().toString());
    }


    /**
     * Constructs EventApi with provided event endpoint values.
     *
     * Possible values are
     *
     *  https://services-dev.apps.cloudbees.com - For development
     *  https://services-platform.cloudbees.com - For production
     *
     * @throws IOException
     */
    public EventApi(@Nonnull String accessToken, @Nonnull String eventEndpoint) throws EventApiException {
        this.accessToken = accessToken;
        this.eventEndpoint = eventEndpoint;
        this.eventApiUrl =UriBuilder.fromUri(this.eventEndpoint).path(EVENT_API_PATH).build().toString();
    }




    /**
     * Posts a given {@link com.cloudbees.api.event.Event} using given token
     *
     * @param eventRequest event
     *
     * @return Returns Location header of the newly created event. A GET on the Location header will give EventApi details.
     *
     * @throws IOException
     */
    public  String publish(Event eventRequest) throws EventApiException {
        if(eventRequest.getEvent() == null){
            throw new EventApiException("No event data to be sent. Please set event data before publishing");
        }else if(eventRequest.getEvent().get("title") == null){
            throw new EventApiException("'title' must be set in the event data");
        }
        WebResource wr = restClient.client.resource(UriBuilder.fromPath(eventApiUrl).build());
        wr.addFilter(new BearerTokenFilter(accessToken));
        ClientResponse cr = wr.type(MediaType.APPLICATION_JSON_TYPE).post(ClientResponse.class, eventRequest);
        if(cr.getStatus() >= 300){
            String error = String.format("EvenApi.publish() returned HTTP status: %s, message: %s",cr.getStatus(), cr.toString());
            logger.error(error);
            throw new EventApiException(error);
        }
        return cr.getLocation().toString();
    }

    /**
     * Reads an event given a URL identifying an event id
     *
     */
    public Event readEvent(@Nonnull String eventUrl) throws EventApiException {

        logger.info("GET " + eventUrl);

        WebResource wr = restClient.client.resource(UriBuilder.fromPath(eventUrl).build());
        wr.addFilter(new BearerTokenFilter(accessToken));
        try{
            wr.header("Authorization", createBearerAuthorizationHeader(accessToken));
            ClientResponse cr = wr.get(ClientResponse.class);
            if(cr.getStatus() >= 300){
                String error = String.format("EvenApi.readEvent() returned HTTP status: %s, message: %s",cr.getStatus(), cr.toString());
                logger.error(error);
                throw new EventApiException(error);
            }
            return restClient.objectMapper.readValue(cr.getEntityInputStream(), Event.class);
        }catch(IOException e){
            throw new EventApiException(e.getMessage(), e);
        }

    }

    /**
     *
     * @param evenQueryUrl - Event API with query parameter for events
     * @return
     * @throws IOException
     */
    public  List query(String evenQueryUrl) throws EventApiException {
        logger.info("Query: "+evenQueryUrl);
        WebResource wr = restClient.client.resource(evenQueryUrl);
        wr.addFilter(new BearerTokenFilter(accessToken));
        try{
            wr.header("Authorization", createBearerAuthorizationHeader(accessToken));
            ClientResponse cr = wr.get(ClientResponse.class);
            if(cr.getStatus() >= 300){
                String error = String.format("EvenApi.query() returned HTTP status: %s, message: %s",cr.getStatus(), cr.toString());
                logger.error(error);
                throw new EventApiException(error);
            }

            return restClient.objectMapper.readValue(cr.getEntityInputStream(), new TypeReference>() {});
        }catch(IOException e){
            throw new EventApiException(e.getMessage(), e);
        }
    }


    public boolean delete(@Nonnull String eventUrl) throws EventApiException {
        logger.info("Delete " + eventUrl);

        WebResource wr = restClient.client.resource(UriBuilder.fromPath(eventUrl).build());
        wr.addFilter(new BearerTokenFilter(accessToken));

        try {
            wr.header("Authorization", createBearerAuthorizationHeader(accessToken));
        } catch (UnsupportedEncodingException e) {
            throw new EventApiException(e.getMessage(), e);
        }
        ClientResponse cr = wr.delete(ClientResponse.class);
        if(cr.getStatus() >= 300){
            String error = String.format("EvenApi.delete() returned HTTP status: %s, message: %s",cr.getStatus(), cr.toString());
            logger.error(error);
            throw new EventApiException(error);
        }

        return cr.getStatus() == 200;
    }

    private  String createBearerAuthorizationHeader(String token) throws UnsupportedEncodingException {
        return String.format("Bearer %s", Base64.encode(token.getBytes("UTF-8")));
    }


    public static class RestClient{
        private Client client;
        private final ObjectMapper objectMapper = createObjectMapper();

        public RestClient() {
            ClientConfig cc = new DefaultClientConfig();
            JacksonConfigurator jc = new JacksonConfigurator(objectMapper);
            cc.getSingletons().add(jc);
            cc.getClasses().add(JacksonJsonProvider.class);
            this.client =  Client.create(cc);
            this.client.addFilter(new LoggingFilter());
        }

        public Client getJerseyClient() {
            return client;
        }

        public ObjectMapper getObjectMapper() {
            return objectMapper;
        }
    }

    private static ObjectMapper createObjectMapper(){
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
        mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);

        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return mapper;
    }

    private class  BearerTokenFilter extends ClientFilter{

        private final String accessToken;

        private BearerTokenFilter(String accessToken) {
            this.accessToken = accessToken;
        }

        @Override
        public ClientResponse handle(ClientRequest cr) throws ClientHandlerException {
            if (!cr.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
                try {
                    cr.getHeaders().add(HttpHeaders.AUTHORIZATION, createBearerAuthorizationHeader(accessToken));
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
            return getNext().handle(cr);

        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy