Package org.neo4j.smack.pipeline.database.event

Source Code of org.neo4j.smack.pipeline.database.event.NettyChannelBackedOutput

/**
* Copyright (c) 2002-2011 "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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.smack.pipeline.database.event;

import static org.jboss.netty.handler.codec.http.HttpResponseStatus.CREATED;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import org.jboss.netty.buffer.DynamicChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.neo4j.smack.pipeline.database.ThreadTransactionManagement;
import org.neo4j.smack.serialization.SerializationFactory;
import org.neo4j.smack.serialization.SerializationStrategy;
import org.neo4j.smack.serialization.Serializer;

/**
* Note: There are lots of these instances, keep it as slim as possible to
* keep memory usage down.
*/
public class NettyChannelBackedOutput implements Output {

    private SerializationFactory serializationFactory;

    private boolean outputStarted;
    private Channel channel;
    private SerializationStrategy<Object> defaultSerializationStrategy;
    private boolean isPersistentConnection;

    private ThreadTransactionManagement txManage;

    private HttpResponseStatus status;

    private Object data;

    private String location;

    private SerializationStrategy serializationStrategy;

    public NettyChannelBackedOutput(SerializationFactory serializationFactory)
    {
        this.serializationFactory = serializationFactory;
    }

    @Override
    public void created()
    {
        send(CREATED, null, null);
    }

    @Override
    public void created(Object value)
    {
        send(CREATED, value, null);
    }

    @Override
    public void createdAt(String location)
    {
        send(CREATED, null, location);
    }

    @Override
    public void createdAt(String location, Object value)
    {
        send(CREATED, value, location);
    }

    @Override
    public void ok()
    {
        send(OK, null, null);
    }

    @Override
    public void ok(Object value)
    {
        send(OK, value, null);
    }

    @Override
    public void okNoContent()
    {
        send(NO_CONTENT, null, null);
    }

    @Override
    public void okAt(String location, Object value)
    {
        send(OK, value, location);
    }
   
    @Override
    public void notFound()
    {
        send(NOT_FOUND, null, null);
    }

    protected boolean started()
    {
        return outputStarted;
    }

    public void send(HttpResponseStatus status, Object data, String location)
    {
        send(status, data, location, defaultSerializationStrategy);
    }

    public void send(
            HttpResponseStatus status,
            Object data,
            String location,
            @SuppressWarnings("rawtypes") SerializationStrategy serializationStrategy)
    {
        this.status = status;
        this.data = data;
        this.location = location;
        this.serializationStrategy = serializationStrategy;
    }

    // TODO: Make this garbage free
    @SuppressWarnings("unchecked")
    protected void flush() {
        if (outputStarted)
        {
            throw new RuntimeException(
                    "Response has already been sent, can only send once per invocation.");
        }

        outputStarted = true;

        DefaultHttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);

        if (location != null)
        {
            response.addHeader(HttpHeaders.Names.LOCATION, location);
        }

        if (data == null)
        {
            response.addHeader(HttpHeaders.Names.CONTENT_LENGTH, 0);
        } else
        {
            // TODO: Hack to get tests green, refactor
            // add support for streaming output, and look into how we could
            // make this garbage free (eg. reuse output buffers). To do that,
            // we probably need to patch netty. It brings this buffer all the
            // way down to it's deepest dungeons, and then eventually copies it into
            // kernel space. We need to know when that has happened and reuse the buffer.
            // Perhaps introduce a ring buffer to rotate used buffers back up here?
            final DynamicChannelBuffer content = new DynamicChannelBuffer(
                    1000);
            Serializer serializer = serializationFactory.getSerializer(content);
            serializationStrategy.serialize(data, serializer);
            serializer.flush();
           
            response.setHeader(HttpHeaders.Names.CONTENT_TYPE, serializer.getContentType().toString());
            response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, content.writerIndex());
            response.setContent(content);
        }

        ChannelFuture future = channel.write(response);

        if (!isPersistentConnection)
        {
            try
            {
                future.await().addListener(ChannelFutureListener.CLOSE);
            } catch (InterruptedException e)
            {
                // TODO: Create specific exception?
                throw new RuntimeException(
                        "Waiting for channel to be done to close it failed.", e);
            }
        }
    }

    @SuppressWarnings("unchecked")
    protected void reset(Channel channel,
            SerializationStrategy<?> serializationStrategy,
            boolean isPersistentConnection)
    {
        this.channel = channel;
        this.defaultSerializationStrategy = (SerializationStrategy<Object>) serializationStrategy;
        this.isPersistentConnection = isPersistentConnection;

        this.outputStarted = false;
        this.status = null;
        this.data = null;
        this.location = null;
        this.serializationStrategy = null;
    }
   
    //private void writeResponse(Serializer serializer)
}
TOP

Related Classes of org.neo4j.smack.pipeline.database.event.NettyChannelBackedOutput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.