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

org.littleshoot.proxy.DefaultCachedHttpChunks Maven / Gradle / Ivy

package org.littleshoot.proxy;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.jboss.netty.buffer.ChannelBuffer;
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.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class that keep track of the cached HTTP chunks for a single HTTP response.
 */
public class DefaultCachedHttpChunks implements CachedHttpChunks {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final CacheManager cacheManager;
    private volatile int chunkCount = 0;
    private final String uri;
    private volatile boolean complete = false;
    private final ChannelFutureListener writeListener;

    /**
     * Creates a new class for caching HTTP chunks for a single response.
     * 
     * @param cacheManager The class that manages the cache.
     * @param httpRequest The original request.
     * @param writeListener The class for listening to write events
     * that takes appropriate actions such as closing the connection.
     */
    public DefaultCachedHttpChunks(final CacheManager cacheManager, 
        final HttpRequest httpRequest, 
        final ChannelFutureListener writeListener) {
        this.cacheManager = cacheManager;
        this.writeListener = writeListener;
        this.uri = ProxyUtils.cacheUri(httpRequest);
    }
    
    public void cache(final HttpChunk chunk, final ChannelBuffer encoded) {
        final Cache cache = 
            this.cacheManager.getCache(ProxyConstants.CHUNK_CACHE);
        final String chunkUri = this.uri + chunkCount;

        log.info("Caching chunk {}", chunkUri);
        final Element elem = new Element(chunkUri, encoded);
        cache.put(elem);
        if (chunk.isLast()) {
            this.complete = true;
        }
        chunkCount++;
    }

    public boolean isComplete() {
        return complete;
    }

    public boolean writeAllChunks(final Channel channel) {
        if (!complete) {
            throw new IllegalStateException(
                "Trying to write incomplete cached chunks!!");
        }
        final Cache cache = 
            this.cacheManager.getCache(ProxyConstants.CHUNK_CACHE);
        ChannelFuture cf = null;
        for (int i = 0; i < chunkCount; i++) {
            final String chunkUri = this.uri + i;
            final Element elem = cache.get(chunkUri);
            
            if (elem == null) {
                // This indicates a serious problem. The cache has expelled
                // a chunk in the middle of us trying to write the responses.
                log.error("Could not find chunk!!! {}", chunkUri);
                throw new IllegalStateException("Missing chunk for: "+chunkUri);
            }
            final ChannelBuffer encoded = (ChannelBuffer) elem.getObjectValue();
            cf = channel.write(encoded);
        }
        if (cf == null) {
            log.error("Channel future is null?");
            throw new IllegalStateException("No future? Chunks: "+chunkCount);
        }
        cf.addListener(this.writeListener);
        return true;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy