Package rabbit.handler

Source Code of rabbit.handler.GZipHandler

package rabbit.handler;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.zip.GZIPOutputStream;
import rabbit.http.HttpHeader;
import rabbit.proxy.BlockSender;
import rabbit.proxy.Connection;
import rabbit.proxy.TrafficLoggerHandler;
import rabbit.util.Logger;
import rabbit.util.SProperties;

/** This handler compresses the data passing through it.
*
* @author <a href="mailto:robo@khelekore.org">Robert Olofsson</a>
*/
public class GZipHandler extends BaseHandler {
    protected boolean compress = true;
    protected GZIPOutputStream gz = null;
    private boolean isCompressing = false;
    private boolean addListener = false;
    private boolean waitingForBlockSent = false;

    /** For creating the factory.
     */
    public GZipHandler () {
    }
   
    /** Create a new GZipHandler for the given request.
     * @param con the Connection handling the request.
     * @param request the actual request made.
     * @param clientBuffer the client side buffer.
     * @param response the actual response.
     * @param content the resource.
     * @param mayCache May we cache this request?
     * @param mayFilter May we filter this request?
     * @param size the size of the data beeing handled.
     * @param compress if we want this handler to compress or not.
     */
    public GZipHandler (Connection con, TrafficLoggerHandler tlh,
      HttpHeader request, ByteBuffer clientBuffer,
      HttpHeader response, ResourceSource content,
      boolean mayCache, boolean mayFilter, long size,
      boolean compress) {
  super (con, tlh, request, clientBuffer, response, content,
         mayCache, mayFilter, size);
  this.compress = compress;
  if (compress) {
      String gzip = response.getHeader ("Content-Encoding");
      isCompressing = !(gzip != null
            && (gzip.equalsIgnoreCase ("gzip")
          || gzip.equalsIgnoreCase ("compress")
          || gzip.equalsIgnoreCase ("deflate")));
      if (isCompressing) {
    response.removeHeader ("Content-Length");
    response.setHeader ("Content-Encoding", "gzip");
    if (!con.getChunking ())
        con.setKeepalive (false);
      } else {
    this.mayFilter = false;
      }
  }
    }   

    @Override
    public Handler getNewInstance (Connection con, TrafficLoggerHandler tlh,
           HttpHeader header, ByteBuffer buffer,
           HttpHeader webHeader,
           ResourceSource content, boolean mayCache,
           boolean mayFilter, long size) {
  return new GZipHandler (con, tlh, header, buffer, webHeader, content,
        mayCache, mayFilter, size,
        compress && mayFilter);
    }

    /**
     * ®return true this handler modifies the content.
     */
    @Override public boolean changesContentSize () {
  return true;
    }

    @Override
    protected void prepare () throws IOException {
  super.prepare ();
  if (isCompressing) {
      Stream2Channel s2c = new GZStream2Channel ();
      gz = new GZIPOutputStream (s2c);
  }
    }
   
    @Override
    protected void finishData () throws IOException {
  addListener = false;
  if (isCompressing)
      gz.finish ();
  super.finishData ();
    }

    /** Check if this handler supports direct transfers.
     * @return this handler always return false.
     */
    @Override
    protected boolean mayTransfer () {
  return false;
    }

    protected class Stream2Channel extends OutputStream {
  public void write (byte[] b) throws IOException {
      write (b, 0, b.length);
  }

  public void write (byte[] b, int off, int len) throws IOException {
      ByteBuffer buf = ByteBuffer.wrap (b, off, len);
      if (cacheChannel != null)
    writeCache (buf);
      new BlockSender (con.getChannel (), con.getSelector (),
           getLogger (), tlh.getClient (), buf,
           con.getChunking (), GZipHandler.this);     
  }

  public void write (int b) throws IOException {
      byte[] buf = new byte[1];
      buf[0] = (byte)b;
      write (buf);
  }
    }

    protected class GZStream2Channel extends Stream2Channel {
  public void write (byte[] b, int off, int len) throws IOException {
      waitingForBlockSent = true;
      super.write (b, off, len);
  }
    }
   
    public void blockSent () {
  if (addListener) {
      addListener = false;
      content.addBlockListener (this);
  }
    }
   
    /** Write the current block of data to the gzipper.
     *  If you override this method you probably want to override
     *  the modifyBuffer(ByteBuffer) as well.
     * @param arr the data to write to the gzip stream.
     */
    protected void writeDataToGZipper (byte[] arr) throws IOException {
  gz.write (arr)
    }

    /** This method is used when we are not compressing data.
     *  This method will just call "super.bufferRead (buf);"
     * @param buf the buffer that was just read.
     */
    protected void modifyBuffer (ByteBuffer buf) {
  super.bufferRead (buf)
    }

    @Override
    public void bufferRead (ByteBuffer buf) {
  if (isCompressing) {
      try {
    // we normally have direct buffers and we can not use
    // array() on them. Create a new byte[] and copy data into it.
    byte[] arr = new byte[buf.remaining ()];
    buf.get (arr);
    addListener = true;
    waitingForBlockSent = false;
    writeDataToGZipper (arr);
    if (!waitingForBlockSent)
        content.addBlockListener (this);
      } catch (IOException e) {
    failed (e);
      }
  } else {
      addListener = true;
      modifyBuffer (buf);
  }
    }
   
    @Override
    public void setup (Logger logger, SProperties prop) {
  if (prop != null) {
      String comp = prop.getProperty ("compress", "true");
      if (comp.equalsIgnoreCase ("false"))
    compress = false;
      else
    compress = true;
  }
    }
}
TOP

Related Classes of rabbit.handler.GZipHandler

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.