se.vgregion.pubsub.push.web.PushController.java Source code

Java tutorial

Introduction

Here is the source code for se.vgregion.pubsub.push.web.PushController.java

Source

/**
 * Copyright 2010 Vstra Gtalandsregionen
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of version 2.1 of the GNU Lesser General Public
 *   License as published by the Free Software Foundation.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the
 *   Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *   Boston, MA 02111-1307  USA
 *
 */

package se.vgregion.pubsub.push.web;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import se.vgregion.pubsub.push.PushSubscriber;
import se.vgregion.pubsub.push.SubscriptionMode;
import se.vgregion.pubsub.push.impl.PushSubscriberManager;
import se.vgregion.pubsub.push.repository.PushSubscriberRepository;

/**
 * Spring MVC controller for handling the HTTP parts of PuSH. Receives publications, subscriptions and unsubscriptions.
 *
 */
@Controller
public class PushController {

    private final static Logger LOG = LoggerFactory.getLogger(PushController.class);

    private final static List<String> ALLOWED_SCHEMES = Arrays.asList("http", "https");

    @Resource
    private PushSubscriberRepository subscriberRepository;

    @Resource
    private PushSubscriberManager pushSubscriberManager;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public void get(HttpServletResponse response) throws IOException {
        response.sendError(405, "This is the endpoint for the PubSubHubbub hub. "
                + "It only support POST requests according to the PubSubHubbub protocol");
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public void post(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String mode = request.getParameter("hub.mode");
        if ("publish".equals(mode)) {
            publish(request, response);
        } else if ("subscribe".equals(mode)) {
            subscribe(request, response, SubscriptionMode.SUBSCRIBE);
        } else if ("unsubscribe".equals(mode)) {
            subscribe(request, response, SubscriptionMode.UNSUBSCRIBE);
        } else {
            response.sendError(500, "Unknown hub.mode parameter");
        }
    }

    private void subscribe(HttpServletRequest request, HttpServletResponse response, SubscriptionMode mode)
            throws IOException {
        URI callback = notNullAndValidUrl(request.getParameter("hub.callback"));
        if (callback != null) {
            URI topicUrl = notNullAndValidUrl(request.getParameter("hub.topic"));

            if (topicUrl != null) {
                String verify = request.getParameter("hub.verify");
                if ("sync".equals(verify) || "async".equals(verify)) {
                    if (mode == SubscriptionMode.SUBSCRIBE) {
                        LOG.info("Received subscription request");

                        String leaseSecondsString = request.getParameter("hub.lease_seconds");
                        try {
                            int leaseSeconds = leaseSecondsString != null ? Integer.parseInt(leaseSecondsString)
                                    : PushSubscriber.DEFAULT_LEASE_SECONDS;

                            String secret = request.getParameter("hub.secret");
                            String verifyToken = request.getParameter("hub.verify_token");
                            String jmsLoggAddress = request.getParameter("hub.jmsLoggAddress");

                            try {
                                pushSubscriberManager.subscribe(topicUrl, callback, jmsLoggAddress, leaseSeconds,
                                        verifyToken, secret, true, true);

                                response.setStatus(204);
                                LOG.info("Subscription request for topic {} with callback {} successful", topicUrl,
                                        callback);
                            } catch (Exception e) {
                                LOG.warn("Exception thrown during subscription from callback " + callback, e);
                                response.sendError(500);
                            }
                        } catch (NumberFormatException e) {
                            LOG.warn("Invalid hub.lease_seconds from callback {}", callback);

                            response.sendError(500, "Invalid hub.lease_seconds");
                        }
                    } else {
                        LOG.info("Received unsubscription request");
                        try {
                            pushSubscriberManager.unsubscribe(topicUrl, callback, true);
                            response.setStatus(204);
                            LOG.info("Unsubscription request for topic {} with callback {} successful", topicUrl,
                                    callback);
                        } catch (Exception e) {
                            LOG.warn("Exception thrown during unsubscription from callback " + callback, e);
                            response.sendError(500);
                        }
                    }
                } else {
                    LOG.warn("Invalid hub.verify from callback {}", callback);
                    response.sendError(500, "Invalid hub.verify");
                }
            } else {
                LOG.warn("Invalid hub.topic from callback {}", callback);
                response.sendError(500, "Invalid hub.topic");
            }
        } else {
            LOG.warn("Invalid hub.callback from {}", request.getRemoteAddr());
            response.sendError(500, "Invalid hub.callback");
        }
    }

    private void publish(HttpServletRequest request, HttpServletResponse response) throws IOException {
        LOG.info("Received publish request");
        String[] urls = request.getParameterValues("hub.url");
        if (urls != null) {
            try {
                for (String url : urls) {
                    publish(url);
                }

                LOG.info("Published feeds successfully queued, returning 204 to publisher");
                response.setStatus(204);
            } catch (Exception e) {
                LOG.warn("Exception thrown during publication", e);
                response.sendError(500);
            }
        } else {
            response.sendError(500, "Missing hub.url parameter");
        }

    }

    private void publish(String url) throws IOException, InterruptedException {
        try {
            URI uri = new URI(url);

            if (allowScheme(uri)) {
                pushSubscriberManager.retrive(uri);
            } else {
                throw new RuntimeException("Only HTTP URLs allowed: " + url);
            }
        } catch (URISyntaxException e1) {
            throw new RuntimeException("Invalid hub.url value: " + url);
        }
    }

    public PushSubscriberRepository getSubscriberRepository() {
        return subscriberRepository;
    }

    public void setSubscriberRepository(PushSubscriberRepository subscriberRepository) {
        this.subscriberRepository = subscriberRepository;
    }

    public PushSubscriberManager getPushSubscriberManager() {
        return pushSubscriberManager;
    }

    public void setPushSubscriberManager(PushSubscriberManager pushSubscriberManager) {
        this.pushSubscriberManager = pushSubscriberManager;
    }

    private URI notNullAndValidUrl(String url) {
        if (url != null) {
            try {
                return new URI(url);
            } catch (URISyntaxException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    private boolean allowScheme(URI uri) {
        return ALLOWED_SCHEMES.contains(uri.getScheme());
    }
}