Package org.atmosphere.nettosphere

Source Code of org.atmosphere.nettosphere.ChannelWriter

/*
* Copyright 2014 Jeanfrancois Arcand
*
* 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 org.atmosphere.nettosphere;

import org.atmosphere.cpr.AsyncIOWriter;
import org.atmosphere.cpr.AtmosphereInterceptorWriter;
import org.atmosphere.cpr.AtmosphereResponse;
import org.atmosphere.util.ByteArrayAsyncWriter;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class ChannelWriter extends AtmosphereInterceptorWriter {
    protected final static Logger logger = LoggerFactory.getLogger(StreamWriter.class);
    protected final static String END = Integer.toHexString(0);
    protected final static byte[] CHUNK_DELIMITER = "\r\n".getBytes();
    protected final static byte[] ENDCHUNK = (END + "\r\n\r\n").getBytes();

    protected final Channel channel;
    protected final AtomicBoolean doneProcessing = new AtomicBoolean(false);
    protected final ByteArrayAsyncWriter transformCacheBuffer = new ByteArrayAsyncWriter();
    protected final boolean writeHeader;

    protected long lastWrite = 0;
    protected boolean keepAlive;

    public ChannelWriter(Channel channel, boolean writeHeader, boolean keepAlive) {
        this.channel = channel;
        this.writeHeader = writeHeader;
        this.keepAlive = keepAlive;
    }

    public boolean isClosed() {
        return doneProcessing.get();
    }

    @Override
    public AsyncIOWriter writeError(AtmosphereResponse response, int errorCode, String message) throws IOException {
        if (!channel.isOpen()) {
            return this;
        }

        try {
            DefaultHttpResponse r = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
                    HttpResponseStatus.valueOf(errorCode));
            channel.write(r).addListener(ChannelFutureListener.CLOSE);
        } catch (Throwable ex) {
            logger.debug("", ex);
        }
        return this;
    }

    @Override
    public AsyncIOWriter write(AtmosphereResponse response, String data) throws IOException {
        byte[] b = data.getBytes("ISO-8859-1");
        write(response, b);
        return this;
    }

    @Override
    public AsyncIOWriter write(AtmosphereResponse response, byte[] data) throws IOException {
        write(response, data, 0, data.length);
        return this;
    }

    protected byte[] transform(AtmosphereResponse response, byte[] b, int offset, int length) throws IOException {
        AsyncIOWriter a = response.getAsyncIOWriter();
        try {
            response.asyncIOWriter(transformCacheBuffer);
            invokeInterceptor(response, b, offset, length);
            return transformCacheBuffer.stream().toByteArray();
        } finally {
            transformCacheBuffer.close(null);
            response.asyncIOWriter(a);
        }
    }

    @Override
    public AsyncIOWriter write(AtmosphereResponse response, byte[] data, int offset, int length) throws IOException {

        if (doneProcessing.get()) {
            throw new IOException(channel + ": content already processed for " + response.uuid());
        }

        boolean transform = filters.size() > 0 && response.getStatus() < 400;
        if (transform) {
            data = transform(response, data, offset, length);
            offset = 0;
            length = data.length;
        }

        logger.trace("About to write to {}", channel);
        if (channel.isOpen()) {
            asyncWrite(response, data, offset, length);
        } else {
            logger.trace("Trying to write on a closed channel {}", channel);
            throw new IOException("Channel closed");
        }
        return this;
    }


    public long lastTick() {
        return lastWrite == -1 ? System.currentTimeMillis() : lastWrite;
    }

    protected String constructStatusAndHeaders(AtmosphereResponse response, int contentLength) {
        StringBuffer b = new StringBuffer("HTTP/1.1")
                .append(" ")
                .append(response.getStatus())
                .append(" ")
                .append(response.getStatusMessage())
                .append("\n");

        Map<String, String> headers = response.headers();
        String contentType = response.getContentType();

        b.append("Content-Type").append(":").append(headers.get("Content-Type") == null ? contentType : headers.get("Content-Type")).append("\n");
        if (contentLength != -1) {
            b.append("Content-Length").append(":").append(contentLength).append("\n");
        }

        for (String s : headers.keySet()) {
            if (!s.equalsIgnoreCase("Content-Type")) {
                b.append(s).append(":").append(headers.get(s)).append("\n");
            }
        }
        b.deleteCharAt(b.length() - 1);
        b.append("\r\n\r\n");
        return b.toString();
    }

    abstract public AsyncIOWriter asyncWrite(AtmosphereResponse response, byte[] data, int offset, int length) throws IOException;

}
TOP

Related Classes of org.atmosphere.nettosphere.ChannelWriter

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.