    001    // Copyright 2011 The Apache Software Foundation
    002    //
    003    // Licensed under the Apache License, Version 2.0 (the "License");
    004    // you may not use this file except in compliance with the License.
    005    // You may obtain a copy of the License at
    006    //
    007    // http://www.apache.org/licenses/LICENSE-2.0
    008    //
    009    // Unless required by applicable law or agreed to in writing, software
    010    // distributed under the License is distributed on an "AS IS" BASIS,
    011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012    // See the License for the specific language governing permissions and
    013    // limitations under the License.
    014
    015    package org.apache.tapestry5.internal.services.assets;
    016
    017    import org.apache.tapestry5.ioc.Resource;
    018    import org.apache.tapestry5.services.assets.*;
    019
    020    import java.io.BufferedOutputStream;
    021    import java.io.ByteArrayOutputStream;
    022    import java.io.IOException;
    023    import java.util.zip.GZIPOutputStream;
    024
    025    public class SRSCompressingInterceptor implements StreamableResourceSource
    026    {
    027        private final int compressionCutoff;
    028
    029        private final StreamableResourceSource delegate;
    030
    031        public SRSCompressingInterceptor(int compressionCutoff, StreamableResourceSource delegate)
    032        {
    033            this.compressionCutoff = compressionCutoff;
    034            this.delegate = delegate;
    035        }
    036
    037        public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
    038                throws IOException
    039        {
    040            StreamableResource streamable = delegate.getStreamableResource(baseResource, processing, dependencies);
    041
    042            return processing == StreamableResourceProcessing.COMPRESSION_ENABLED ? compress(streamable) : streamable;
    043        }
    044
    045        private StreamableResource compress(StreamableResource uncompressed) throws IOException
    046        {
    047            if (uncompressed.getCompression() != CompressionStatus.COMPRESSABLE)
    048            {
    049                return uncompressed;
    050            }
    051
    052            int size = uncompressed.getSize();
    053
    054            // Because of GZIP overhead, streams below a certain point actually get larger when compressed so
    055            // we don't even try.
    056
    057            if (size < compressionCutoff)
    058            {
    059                return uncompressed;
    060            }
    061
    062            ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
    063
    064            GZIPOutputStream gos = new GZIPOutputStream(bos);
    065            BufferedOutputStream buffered = new BufferedOutputStream(gos);
    066
    067            uncompressed.streamTo(buffered);
    068
    069            buffered.close();
    070
    071            BytestreamCache cache = new BytestreamCache(bos);
    072
    073            return new StreamableResourceImpl(uncompressed.getDescription(),
    074                    uncompressed.getContentType(), CompressionStatus.COMPRESSED,
    075                    uncompressed.getLastModified(), cache);
    076        }
    077    }