Chris Lee <chris.lee <at> leeprinting.com> writes:

> 
> Jonathan Hall <jonrhall <at> gmail.com> writes:
> 
> > Maybe down to: "Important Context Changes" dated 29/07/2008
> > 
> > "- the Context instance given to an application (or any Restlet 
> > actually) will be the one effectively used. If parameters are set, they 
> > will be directly and permanently accessible. If none is given, a null 
> > context will be returned by getContext(), no default context will be 
> > returned anymore."
> 
> Thanks! I changed the line from Context.getCurrent() to
> Application.getCurrent().getContext() and at first blush it seems to work. 
> I'll
> continue working with it to make sure it bears up and post the new
> FinderFactoryModule.java with Tim's update and this tweak.
> 
> Chris Lee
> 
> 

I don't see any way to attach a fil here, but below you can find a listing for
FinderFactoryModule.java with Tim's recommended updates and the workaround I am
using. I hope it helps someone. Thanks for all your help!

FinderFactoryModule.java:

package net.peierls.restlet.util;

import static java.util.Collections.emptyList;

import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Finder;
import org.restlet.Handler;
import org.restlet.data.Request;
import org.restlet.data.Response;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;

/**
 * A Guice module that doubles as a factory for creating Finders that look up
 * Handler or Resource instances from a given class or Guice Key. On first use
 * of these Finders, if the module hasn't been used to create an Injector, this
 * module creates its own Injector.
 */
public class FinderFactoryModule extends AbstractModule implements
        FinderFactory {

    /**
     * Creates a FinderFactoryModule that will install the given modules.
     */
    public FinderFactoryModule(Module... modules) {
        this.moduleArray = modules;
        this.modules = emptyList();
    }

    /**
     * Creates a FinderFactoryModule that will install the given modules.
     */
    public FinderFactoryModule(Iterable<Module> modules) {
        this.moduleArray = new Module[0];
        this.modules = modules;
    }

    //
    // FinderFactory methods
    //

    public Finder finderFor(Key<? extends Handler> key) {
        return new KeyFinder(key);
    }

    public Finder finderFor(Class<? extends Handler> cls) {
        return new KeyFinder(Key.get(cls));
    }

    /**
     * This method must be called by any method that overrides it.
     */
    @Override
    protected final void configure() {

        if (injector != null) {
            throw new IllegalStateException("can't reconfigure with existing
Injector");
        }

        if (!alreadyBound.get()) {
            alreadyBound.set(true);

            bind(Context.class).toProvider(newContextProvider());
            bind(Request.class).toProvider(newRequestProvider());
            bind(Response.class).toProvider(newResponseProvider());
            bind(FinderFactory.class).toInstance(this);
        }

        for (Module module : moduleArray)
            install(module);
        for (Module module : modules)
            install(module);
    }

    /**
     * Creates a Provider for the Context. This can be overridden to supply a
     * Context in a customized fashion.
     */
    protected Provider<Context> newContextProvider() {
        return new Provider<Context>() {
            public Context get() {
                return Application.getCurrent().getContext();
            }
        };
    }

    /**
     * Creates a Provider for the Request. This can be overridden to supply a
     * Request in a customized fashion.
     */
    protected Provider<Request> newRequestProvider() {
        return new Provider<Request>() {
            public Request get() {
                return Request.getCurrent();
            }
        };
    }

    /**
     * Creates a Provider for the Response. This can be overridden to supply a
     * Response in a customized fashion.
     */
    protected Provider<Response> newResponseProvider() {
        return new Provider<Response>() {
            public Response get() {
                return Response.getCurrent();
            }
        };
    }

    class KeyFinder extends Finder {
        private final Key<? extends Handler> key;

        KeyFinder(Key<? extends Handler> key) {
            this.key = key;
        }

        @Override
        protected Handler findTarget(Request request, Response response) {
            return getInjector().getInstance(key);
        }

        private Injector getInjector() {
            Injector inj = injector;
            if (inj == null) {
                synchronized (FinderFactoryModule.this) {
                    inj = injector;
                    if (inj == null) {
                        inj = Guice.createInjector(FinderFactoryModule.this);
                    }
                }
            }
            return inj;
        }
    }

    private final Module[] moduleArray;
    private final Iterable<Module> modules;
    @Inject
    private volatile Injector injector;

    @SuppressWarnings("unused")
    @Inject
    private void clearAlreadyBound() {
        alreadyBound.set(false);
    }

    private static ThreadLocal<Boolean> alreadyBound =
            new ThreadLocal<Boolean>() {
                @Override
                protected Boolean initialValue() {
                    return false;
                }
            };
}


Reply via email to