@Override
    public void messageReceived( ChannelHandlerContext ctx, MessageEvent e )
        throws Exception
    {
        HttpRequest request = (HttpRequest) e.getMessage();
        if ( request.getMethod() != GET )
        {
            sendError( ctx, METHOD_NOT_ALLOWED );
            return;
        }

        final File file = sanitizeUri( request.getUri() );
        if ( file == null )
        {
            sendError( ctx, FORBIDDEN );
            return;
        }

        if ( file.isHidden() || !file.exists() )
        {
            sendError( ctx, NOT_FOUND );
            return;
        }
        if ( !file.isFile() )
        {
            sendError( ctx, FORBIDDEN );
            return;
        }

        Integer numberOfTimesToRepeat = null;
        int pos = request.getUri().indexOf( '?' );
        if ( pos > 0 )
        {
            try
            {
                numberOfTimesToRepeat = Integer.parseInt( request.getUri().substring( pos + 1 ) );
            }
            catch ( NumberFormatException nfe )
            {
                numberOfTimesToRepeat = 1;
            }
        }

        RandomAccessFile raf;
        try
        {
            raf = new RandomAccessFile( file, "r" );
        }
        catch ( FileNotFoundException fnfe )
        {
            sendError( ctx, NOT_FOUND );
            return;
        }
        long fileLength = raf.length();

        HttpResponse response = new DefaultHttpResponse( HTTP_1_1, OK );

        Channel ch = e.getChannel();

        // Write the initial line and the header.
        ch.write( response );

        // Write the content.
        final FileRegion region = new RepeatingFileRegion( raf.getChannel(), fileLength, numberOfTimesToRepeat );

        final ChannelFuture writeFuture = ch.write( region );
        writeFuture.addListener( new ChannelFutureProgressListener()
        {
            //                @Override
            public void operationComplete( ChannelFuture future )
            {
                region.releaseExternalResources();
            }

            //                @Override
            public void operationProgressed( ChannelFuture future, long amount, long current, long total )
            {
                if ( log.isDebugEnabled() )
                {
                    log.debug( String.format( "%s: %d / %d (+%d)%n", file.getAbsolutePath(), current, total, amount ) );
                }
            }
        } );

        // Force closing the connection.
        writeFuture.addListener( ChannelFutureListener.CLOSE );
    }