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

org.neo4j.server.rest.web.BatchOperationService Maven / Gradle / Ivy

There is a newer version: 5.26.1
Show newest version
/*
 * Copyright (c) 2002-2016 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.server.rest.web;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;

import org.neo4j.server.rest.batch.BatchOperationResults;
import org.neo4j.server.rest.batch.NonStreamingBatchOperations;
import org.neo4j.server.rest.repr.OutputFormat;
import org.neo4j.server.rest.repr.RepresentationWriteHandler;
import org.neo4j.server.rest.repr.StreamingFormat;
import org.neo4j.server.web.HttpHeaderUtils;
import org.neo4j.server.web.WebServer;
import org.neo4j.udc.UsageData;

import static org.neo4j.udc.UsageDataKeys.Features.http_batch_endpoint;
import static org.neo4j.udc.UsageDataKeys.features;

@Path("/batch")
public class BatchOperationService {

    private static final Logger LOGGER = Log.getLogger(BatchOperationService.class);

    private final OutputFormat output;
    private final WebServer webServer;
    private final UsageData usage;
    private RepresentationWriteHandler representationWriteHandler = RepresentationWriteHandler.DO_NOTHING;

    public BatchOperationService( @Context WebServer webServer, @Context OutputFormat output, @Context UsageData usage )
    {
        this.output = output;
        this.webServer = webServer;
        this.usage = usage;
    }

    public void setRepresentationWriteHandler( RepresentationWriteHandler representationWriteHandler )
    {
        this.representationWriteHandler = representationWriteHandler;
    }

    @POST
    public Response performBatchOperations(@Context UriInfo uriInfo,
            @Context HttpHeaders httpHeaders, @Context HttpServletRequest req, InputStream body)
    {
        usage.get( features ).flag( http_batch_endpoint );
        if ( isStreaming( httpHeaders ) )
        {
            return batchProcessAndStream( uriInfo, httpHeaders, req, body );
        }
        return batchProcess( uriInfo, httpHeaders, req, body );
    }

    private Response batchProcessAndStream( final UriInfo uriInfo, final HttpHeaders httpHeaders,
                                            final HttpServletRequest req, final InputStream body )
    {
        try
        {
            final StreamingOutput stream = new StreamingOutput()
            {
                @Override
                public void write( final OutputStream output ) throws IOException, WebApplicationException
                {
                    try
                    {
                        final ServletOutputStream servletOutputStream = new ServletOutputStream()
                        {
                            @Override
                            public void write( int i ) throws IOException
                            {
                                output.write( i );
                            }

                            @Override
                            public boolean isReady()
                            {
                                return true;
                            }

                            @Override
                            public void setWriteListener( WriteListener writeListener )
                            {
                                try
                                {
                                    writeListener.onWritePossible();
                                }
                                catch ( IOException e )
                                {
                                    // Ignore
                                }
                            }
                        };
                        new StreamingBatchOperations( webServer ).readAndExecuteOperations( uriInfo, httpHeaders, req,
                                body, servletOutputStream );
                        representationWriteHandler.onRepresentationWritten();
                    }
                    catch ( Exception e )
                    {
                        LOGGER.warn( "Error executing batch request ", e );
                    }
                    finally
                    {
                        representationWriteHandler.onRepresentationFinal();
                    }
                }
            };
            return Response.ok(stream)
                    .type( HttpHeaderUtils.mediaTypeWithCharsetUtf8(MediaType.APPLICATION_JSON_TYPE) ).build();
        }
        catch ( Exception e )
        {
            return output.serverError( e );
        }
    }

    private Response batchProcess( UriInfo uriInfo, HttpHeaders httpHeaders, HttpServletRequest req, InputStream body )
    {
        try
        {
            NonStreamingBatchOperations batchOperations = new NonStreamingBatchOperations( webServer );
            BatchOperationResults results = batchOperations.performBatchJobs( uriInfo, httpHeaders, req, body );

            Response res = Response.ok().entity(results.toJSON())
                    .type(HttpHeaderUtils.mediaTypeWithCharsetUtf8(MediaType.APPLICATION_JSON_TYPE)).build();
            representationWriteHandler.onRepresentationWritten();
            return res;
        }
        catch ( Exception e )
        {
            return output.serverError( e );
        }
        finally
        {
            representationWriteHandler.onRepresentationFinal();
        }
    }

    private boolean isStreaming( HttpHeaders httpHeaders )
    {
        if ( "true".equalsIgnoreCase( httpHeaders.getRequestHeaders().getFirst( StreamingFormat.STREAM_HEADER ) ) )
        {
            return true;
        }
        for ( MediaType mediaType : httpHeaders.getAcceptableMediaTypes() )
        {
            Map parameters = mediaType.getParameters();
            if ( parameters.containsKey( "stream" ) && "true".equalsIgnoreCase( parameters.get( "stream" ) ) )
            {
                return true;
            }
        }
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy