com.nebhale.buildmonitor.web.WebHookController.java Source code

Java tutorial

Introduction

Here is the source code for com.nebhale.buildmonitor.web.WebHookController.java

Source

/*
 * Copyright 2013-2014 the original author or authors.
 *
 * 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 com.nebhale.buildmonitor.web;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nebhale.buildmonitor.domain.Build;
import com.nebhale.buildmonitor.domain.Project;
import com.nebhale.buildmonitor.repository.BuildRepository;
import com.nebhale.buildmonitor.web.notify.BuildsChangedNotifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.util.Map;

/**
 * Controller for accessing WebHooks
 */
@Controller
@RequestMapping("/projects/{project}/webhook")
public final class WebHookController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final BuildsChangedNotifier buildsChangedNotifier;

    private final BuildRepository repository;

    private final JenkinsPayloadParser jenkinsPayloadParser;

    private final TravisPayloadParser travisPayloadParser;

    @Autowired
    WebHookController(BuildsChangedNotifier buildsChangedNotifier, BuildRepository repository,
            JenkinsPayloadParser jenkinsPayloadParser, TravisPayloadParser travisPayloadParser) {
        this.buildsChangedNotifier = buildsChangedNotifier;
        this.repository = repository;
        this.jenkinsPayloadParser = jenkinsPayloadParser;
        this.travisPayloadParser = travisPayloadParser;
    }

    @SuppressWarnings("unchecked")
    @Transactional
    @RequestMapping(method = RequestMethod.POST, value = "", params = "payload")
    ResponseEntity<?> travisWebHook(@PathVariable Project project, @RequestParam("payload") Map<String, ?> payload)
            throws IOException {
        return webHook(project, payload, this.travisPayloadParser);
    }

    @SuppressWarnings("unchecked")
    @Transactional
    @RequestMapping(method = RequestMethod.POST, value = "")
    ResponseEntity<?> jenkinsWebHook(@PathVariable Project project, @RequestBody Map<String, ?> payload)
            throws IOException {
        return webHook(project, payload, this.jenkinsPayloadParser);
    }

    private ResponseEntity<?> webHook(Project project, Map<String, ?> payload, PayloadParser payloadParser)
            throws JsonProcessingException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(this.objectMapper.writeValueAsString(payload));
        }

        if (project == null) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }

        String uri = payloadParser.getUri(payload);
        Build.State state = payloadParser.getState(payload);

        this.logger.info("Received {} webhook for {} with status {}", project.getKey(), uri, state);
        if (Build.State.UNKNOWN == state) {
            this.logger.warn(this.objectMapper.writeValueAsString(payload));
        }

        if (payloadParser.shouldProcess(payload)) {
            Build build = this.repository.findByUri(uri);
            if (build == null) {
                build = new Build(project, uri, state);
            } else {
                build.setState(state);
            }

            this.repository.saveAndFlush(build);
            this.buildsChangedNotifier.buildsChanged(project);
        } else {
            this.logger.info("Payload ignored");
        }

        return new ResponseEntity<>(HttpStatus.OK);
    }

    static interface PayloadParser {

        /**
         * Returns the state of the build represented by the payload
         *
         * @param payload the payload
         *
         * @return the state of the build represented by the payload
         */
        Build.State getState(Map<String, ?> payload);

        /**
         * Returns the uri of the build represented by the payload
         *
         * @param payload the payload
         *
         * @return the uri of the build represented by the payload
         */
        String getUri(Map<String, ?> payload);

        /**
         * Whether or not the payload should be processed
         *
         * @param payload the payload
         *
         * @return {@code true} if the payload should be processed, {@code false} otherwise
         */
        Boolean shouldProcess(Map<String, ?> payload);

    }

}