-4

I have a situation where the application developers and the framework provider are not the people. As a framework provider, I would like to be able to hand the developers what looks like a single Filter, but is in fact a chain of standard Filters (such as authentication, setting up invocation context, metrics, ++).

I don't seem to find this functionality in the standard library, but maybe there is an extension with it.

Niclas Hedhman
  • 584
  • 4
  • 14

1 Answers1

0

Instead of waiting for an answer, I went ahead with my own implementation and sharing here if some needs this.

/**
 * Composes an array of Restlet Filters into a single Filter.
 */
public class ComposingFilter extends Filter
{
    private final Filter first;
    private final Filter last;

    public ComposingFilter( Filter... composedOf )
    {
        Objects.requireNonNull( composedOf );
        if( composedOf.length == 0 )
        {
            throw new IllegalArgumentException( "Filter chain can't be empty." );
        }
        first = composedOf[ 0 ];
        Filter prev = first;
        for( int i = 1; i < composedOf.length; i++ )
        {
            Filter next = composedOf[ i ];
            prev.setNext( next );
            prev = next;
        }
        last = composedOf[ composedOf.length - 1 ];
    }

    @Override
    protected int doHandle( Request request, Response response )
    {
        if( first != null )
        {
            first.handle( request, response );
            Response.setCurrent( response );
            if( getContext() != null )
            {
                Context.setCurrent( getContext() );
            }
        }
        else
        {
            response.setStatus( Status.SERVER_ERROR_INTERNAL );
            getLogger().warning( "The filter " + getName() + " was executed without a next Restlet attached to it." );
        }
        return CONTINUE;
    }

    @Override
    public synchronized void start()
        throws Exception
    {
        if( isStopped() )
        {
            first.start();
            super.start();
        }
    }

    @Override
    public synchronized void stop()
        throws Exception
    {
        if( isStarted() )
        {
            super.stop();
            first.stop();
        }
    }

    @Override
    public Restlet getNext()
    {
        return last.getNext();
    }

    @Override
    public void setNext( Class<? extends ServerResource> targetClass )
    {
        last.setNext( targetClass );
    }

    @Override
    public void setNext( Restlet next )
    {
        last.setNext( next );
    }
}

NOTE: Not tested yet.

Niclas Hedhman
  • 584
  • 4
  • 14