org.codice.ddf.endpoints.subscriptions.SubscriptionService.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.endpoints.subscriptions.SubscriptionService.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or any later version. 
 *
 * This program 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. A copy of the GNU Lesser General Public License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 *
 **/

package org.codice.ddf.endpoints.subscriptions;

import java.io.InputStream;
import java.io.StringReader;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.io.IOUtils;
import org.apache.cxf.jaxrs.model.wadl.ElementClass;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ddf.catalog.event.EventProcessor;
import ddf.catalog.event.Subscription;
import ddf.catalog.event.SubscriptionNotFoundException;
import ddf.subscriptions.GetAllSubscriptionsResponse;
import ddf.subscriptions.GetSubscriptionIdsResponse;

/**
 * This is a REST Service supporting JSON-formatted queries for Catalog
 * Providers.
 * 
 * This class handles HTTP POST requests for queries of catalog entries matching
 * the query's search criteria. The payload of the request is JSON-formatted and
 * can contain search criteria for Contextual, Entry, Temporal, Spatial,
 * Datatype, or MultiID queries. A Compound query is also supported, which
 * consists of up to one each of Contextual, Entry, Temporal, Spatial, Datatype.
 * (MultiID is not supported in the Compound query).
 * 
 * Searches can be done for the local site only, a specific site (by name), or
 * an enterprise-wide search (which includes all available federated sites and
 * the local site). The scope of the search is determined by the URL used to
 * execute the query.
 * 
 * @author rodgersh
 * 
 */
@Path("/")
public class SubscriptionService {
    /** The logger for this class */
    private static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionService.class);

    /** 
     * Time (in milliseconds) to wait for the subscription's DeliveryMethod callback service to come up
     * during subscription restoration.
     */
    private static int DELIVERY_METHOD_SERVICE_TRACKER_TIMEOUT = 10000;

    /** The context for this class' bundle */
    private BundleContext context;

    /** The DDF subscription manager invoked to create/delete subscriptions */
    private EventProcessor eventProcessor;

    private Unmarshaller unmarshaller;

    /**
     * Constructor for Subscription REST service.
     * 
     * @param EventProcessor the MTS EventProcessor to use to
     *            create/update/delete/query subscriptions
     */
    public SubscriptionService(BundleContext context, EventProcessor EventProcessor) {
        this.context = context;
        this.eventProcessor = EventProcessor;

        try {
            JAXBContext jc = JAXBContext.newInstance(Subscription.class);
            this.unmarshaller = jc.createUnmarshaller();
        } catch (JAXBException e) {
            LOGGER.warn(e.getMessage(), e);
        }

    }

    @POST
    @Path("/subscription/create")
    public boolean createSubscription(InputStream message) {
        String methodName = "createSubscription";
        LOGGER.debug("ENTERING:{} ", methodName);

        try {
            if (message != null) {
                String request = IOUtils.toString(message);
                LOGGER.debug("request:\n{}", request);

                Subscription subscription = (Subscription) unmarshaller.unmarshal(new StringReader(request));
                performCreateSubscription(subscription);
            } else {
                LOGGER.warn("message is NULL");
            }
        } catch (Exception e) {
            LOGGER.error("Exception processing create subscription request", e);
        }

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return true;
    }

    @POST
    @Path("/subscriptions/create")
    @Produces("text/plain")
    public int createSubscriptions(InputStream message) {
        String methodName = "createSubscriptions";
        LOGGER.debug("ENTERING: {}", methodName);

        //        Response response = null;
        int numSubscriptionsCreated = 0;

        try {
            if (message != null) {
                String request = IOUtils.toString(message);
                LOGGER.debug("request:\n" + request);

                List<Subscription> subscriptions = (List<Subscription>) unmarshaller
                        .unmarshal(new StringReader(request));
                LOGGER.debug("subscriptions.size() = {}", subscriptions.size());

                if (subscriptions != null && !subscriptions.isEmpty()) {
                    for (Subscription subscription : subscriptions) {
                        performCreateSubscription(subscription);
                        numSubscriptionsCreated++;
                    }
                }

                //                Response.ResponseBuilder responseBuilder = Response.ok();
                //                response = responseBuilder.build();
            } else {
                LOGGER.warn("message is NULL");
            }
        } catch (Exception e) {
            LOGGER.error("Exception processing create subscription request", e);
            //            response = Response.serverError().build();
        }

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return numSubscriptionsCreated;
    }

    // Update subscription actually consists of deleting existing current subscription and creating a new subscription.
    // The subscriptionId passed in should match the subscription ID in the message's ServiceCallback.subscriptionId element,
    // but this is not checked or enforced.
    @PUT
    @Path("/subscription/update/{subscriptionId}")
    public Response updateSubscription(@PathParam("subscriptionId") String subscriptionId, InputStream message) {
        String methodName = "updateSubscription";
        LOGGER.debug("ENTERING: {}", methodName);

        LOGGER.debug("subscriptionId:\n" + subscriptionId);

        Response response = null;

        try {
            if (message != null) {
                String request = IOUtils.toString(message);
                LOGGER.debug("request:\n" + request);

                // Delete the existing subscription
                eventProcessor.deleteSubscription(subscriptionId);

                Subscription subscription = (Subscription) unmarshaller.unmarshal(new StringReader(request));
                performCreateSubscription(subscription);
                //                performCreateSubscription( request );

                Response.ResponseBuilder responseBuilder = Response.ok();
                response = responseBuilder.build();
            } else {
                LOGGER.warn("message is NULL");
            }
        } catch (Exception e) {
            LOGGER.error("Exception processing update subscription request", e);
            response = Response.serverError().build();
        }

        LOGGER.debug("EXITING: {}", methodName);

        return response;
    }

    @DELETE
    @Path("/subscription/delete/{subscriptionId}")
    @Produces("text/plain")
    public boolean deleteSubscription(@PathParam("subscriptionId") String subscriptionId) {
        String methodName = "deleteSubscription";
        LOGGER.debug("ENTERING: {}", methodName);

        LOGGER.debug("subscriptionId:\n {}", subscriptionId);

        boolean status = false;

        //        Response response = null;

        // Delete the existing subscription
        try {
            eventProcessor.deleteSubscription(subscriptionId);
            status = true;

        } catch (SubscriptionNotFoundException e) {
            LOGGER.error("SubscriptionNotFoundExeption", e);

        }

        //        Response.ResponseBuilder responseBuilder = Response.noContent();
        //        response = responseBuilder.build();

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return status;
    }

    @DELETE
    @Path("/subscriptions/delete")
    @Produces("text/plain")
    public int deleteSubscriptions(@QueryParam("subscriptionIds") List<String> subscriptionIds) {
        String methodName = "deleteSubscriptions";
        LOGGER.debug("ENTERING: {}", methodName);

        LOGGER.debug("subscriptionIds.size() = {}", subscriptionIds.size());

        //        Response response = null;
        int numSubscriptionsDeleted = 0;

        // Delete the existing subscriptions
        if (subscriptionIds != null && !subscriptionIds.isEmpty()) {
            for (String subscriptionId : subscriptionIds) {
                LOGGER.debug("Deleting subscription for ID = {}", subscriptionId);
                try {
                    eventProcessor.deleteSubscription(subscriptionId);
                    numSubscriptionsDeleted++;
                } catch (SubscriptionNotFoundException e) {
                    LOGGER.error("SubscriptionNotFoundExeption", e);

                }

            }
        }

        //        Response.ResponseBuilder responseBuilder = Response.noContent();
        //        response = responseBuilder.build();

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return numSubscriptionsDeleted;
    }

    @GET
    @Path("/subscription/{subscriptionId}")
    @Produces("text/xml")
    //    public Response getSubscription( @PathParam( "subscriptionId" ) String subscriptionId )
    public String getSubscription(@PathParam("subscriptionId") String subscriptionId)
            throws SubscriptionServiceException {
        String methodName = "getSubscription";
        LOGGER.debug("ENTERING: {}", methodName);

        //        Response response = null;
        //
        //        String subscriptionXml = EventProcessor.getSubscription( subscriptionId );
        //        
        //        logger.debug( "subscriptionXml = " + subscriptionXml );
        //        
        //        Response.ResponseBuilder responseBuilder = Response.ok( subscriptionXml );
        //        response = responseBuilder.build();

        String subscriptionXml = null;

        //        try
        //        {
        //  TODO: How do you get a subscription?          subscriptionXml = eventProcessor.getSubscription( subscriptionId );
        //        }
        //        catch ( Exception e )
        //        {
        //            throw new SubscriptionServiceException( e.getMessage(), e );
        //        }
        //        
        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return subscriptionXml;
    }

    // Get all subscriptions
    @GET
    @Path("/subscriptions")
    @Produces("text/xml")
    @ElementClass(response = ddf.subscriptions.GetAllSubscriptionsResponse.class)
    //    public Response getSubscriptions()
    public GetAllSubscriptionsResponse getSubscriptions() throws SubscriptionServiceException {
        String methodName = "getSubscriptions";
        LOGGER.debug("ENTERING: {}", methodName);

        //        Response response = null;
        GetAllSubscriptionsResponse getAllSubscriptionsResponse = new GetAllSubscriptionsResponse();

        //        try
        //        {
        //            Collection<String> subscriptions = eventProcessor.getAllSubscriptions();
        //            List<String> subscriptionsList = getAllSubscriptionsResponse.getSubscriptions();
        //            subscriptionsList.addAll( subscriptions );
        //        }
        //        catch ( Exception e )
        //        {
        //            throw new SubscriptionServiceException( e.getMessage(), e );
        //        }

        //        try
        //        {
        //            JAXBContext jc = JAXBContext.newInstance( GetAllSubscriptionsResponse.class );
        //            Marshaller marshaller = jc.createMarshaller();
        //            
        //            //Marshal object into XML file
        //            ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //            marshaller.marshal( getAllSubscriptionsResponse, bos );
        //            logger.debug( "GetAllSubscriptionsResponse XML:\n" + bos.toString() );
        //            
        //            Response.ResponseBuilder responseBuilder = Response.ok( bos.toString() );
        //            response = responseBuilder.build();
        //        }
        //        catch ( JAXBException e )
        //        {
        //            logger.warn( e.getMessage(), e );
        //        }

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return getAllSubscriptionsResponse;
    }

    // Get all subscription IDs
    @GET
    @Path("/subscriptions/ids")
    @Produces("text/xml")
    @ElementClass(response = ddf.subscriptions.GetSubscriptionIdsResponse.class)
    //    public Response getSubscriptionIds()
    public GetSubscriptionIdsResponse getSubscriptionIds() throws SubscriptionServiceException {
        String methodName = "getSubscriptionIds";
        LOGGER.debug("ENTERING: {}", methodName);

        //        Response response = null;
        GetSubscriptionIdsResponse getSubscriptionIdsResponse = new GetSubscriptionIdsResponse();

        //        try
        //        {
        //            Set<String> subscriptionIds = eventProcessor.getSubscriptionIds();
        //            List<String> subscriptionIdsList = getSubscriptionIdsResponse.getSubscriptionIds();
        //            subscriptionIdsList.addAll( subscriptionIds );
        //        }
        //        catch ( Exception e )
        //        {
        //            throw new SubscriptionServiceException( e.getMessage(), e );
        //        }

        //        try
        //        {
        //            JAXBContext jc = JAXBContext.newInstance( GetSubscriptionIdsResponse.class );
        //            Marshaller marshaller = jc.createMarshaller();
        //            
        //            //Marshal object into XML file
        //            ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //            marshaller.marshal( getSubscriptionIdsResponse, bos );
        //            logger.debug( "GetSubscriptionIdsResponse XML:\n" + bos.toString() );
        //            
        //            Response.ResponseBuilder responseBuilder = Response.ok( bos.toString() );
        //            response = responseBuilder.build();
        //        }
        //        catch ( JAXBException e )
        //        {
        //            logger.warn( e.getMessage(), e );
        //        }

        LOGGER.debug("EXITING: {}", methodName);

        //        return response;
        return getSubscriptionIdsResponse;
    }

    //private void performCreateSubscription( String request )
    private void performCreateSubscription(Subscription subscription) {
        String methodName = "performCreateSubscription";
        LOGGER.debug("ENTERING: {}", methodName);
        //TODO UPDATE to new OGC FILTER
        //        
        //        try
        //        {
        //            //Subscription subscription = (Subscription) unmarshaller.unmarshal( new StringReader( request ) );
        //            
        //            //TODO make persistSubscription an arg to this URL/method - default to true for now
        //            Subject user = null;
        //            
        //            //TODO Determine how to implement DeliveryMethod
        //            String callbackUrl = subscription.getServiceCallback().getCallbackUrl();
        //            String subscriptionId = subscription.getServiceCallback().getSubscriptionId();
        //            //HUGH DeliveryMethod deliveryMethod = new WebServiceAdapter( callbackUrl, subscriptionId );
        //            
        //            // Retrieve the Managed Service Factory PID from the subscription's callback info configuration.
        //            // This PID is used to instantiate the subscription's DeliveryMethod callback service
        //            String serviceCallbackFactoryPid = subscription.getServiceCallback().getFactoryPid();
        //            logger.info( "serviceCallbackFactoryPid = " + serviceCallbackFactoryPid );
        //            
        //            ServiceReference configAdminRef = context.getServiceReference( ConfigurationAdmin.class.getName() );
        //                
        //            if ( serviceCallbackFactoryPid != null && configAdminRef != null )
        //            {
        //                ConfigurationAdmin configAdmin = (ConfigurationAdmin) context.getService( configAdminRef );
        //
        //                // Instantiate the DeliveryMethod callback service for this subscription
        //                Configuration deliveryMethodConfig = configAdmin.createFactoryConfiguration( serviceCallbackFactoryPid, null );
        //                logger.info( "Adding DeliveryMethod props to dictionary" );
        //
        //                // Configure the properties for the DeliveryMethod callback service
        //                Dictionary<String,String> deliveryMethodProps = new Hashtable<String,String>();
        //                deliveryMethodProps.put( "subscriptionId", subscription.getServiceCallback().getSubscriptionId() );
        //                deliveryMethodProps.put( "callbackUrl", subscription.getServiceCallback().getCallbackUrl() );
        //                deliveryMethodConfig.update( deliveryMethodProps );
        //                logger.info( "Done configuring DeliveryMethod for " + serviceCallbackFactoryPid );
        //                                                  
        //                try
        //                {
        //                    // Setup a ServiceTracker to monitor for the creation of the DeliveryMethod
        //                    // service callback services for each subscription being restored
        //                    ServiceTracker deliveryMethodServiceTracker = new ServiceTracker( context, DeliveryMethod.class.getName(), null );
        //                    
        //                    // Start the DeliveryMethod service tracker to detect when the DeliveryMethod callback service
        //                    // just instantiated is registered and functional
        //                    deliveryMethodServiceTracker.open();
        //                    logger.info( "Waiting up to " + DELIVERY_METHOD_SERVICE_TRACKER_TIMEOUT + " for DeliveryMethod service to be detected" );
        //                    DeliveryMethod deliveryMethod = (DeliveryMethod) deliveryMethodServiceTracker.waitForService( DELIVERY_METHOD_SERVICE_TRACKER_TIMEOUT );
        //                    
        //                    if ( deliveryMethod != null )
        //                    {
        //                        // Detected the DeliveryMethod callback service is up - go create the subscription.
        //                        // (The "true" argument indicates this subscription should be persisted.
        //                        .createSubscription( user, subscription, deliveryMethod, true );
        //                        logger.info( "Subscription created for id = " + subscription.getServiceCallback().getSubscriptionId() );
        //                    }
        //                    else
        //                    {
        //                        logger.info( "ServiceTracker never found a DeliveryMethod - cannot create subscription for ID = " + 
        //                            subscription.getServiceCallback().getSubscriptionId() );
        //                    }
        //                    
        //                    deliveryMethodServiceTracker.close();
        //                }
        //                catch ( InterruptedException e )
        //                {
        //                  logger.error( "Unable to setup DeliveryMethod ServiceTracker", e );
        //                }
        //            }
        //        }
        ////        catch ( JAXBException e )
        ////        {
        ////            logger.warn( e.getMessage(), e );
        ////        }
        //        catch ( IOException e )
        //        {
        //            logger.warn( "Error creating subscription", e );
        //        }
        //        
        LOGGER.debug("EXITING: {}", methodName);
    }

}