PageRenderTime 55ms CodeModel.GetById 13ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/AuthenticRoast/AuthenticRoast-Impl/src/main/java/name/aikesommer/authenticator/RegistryImpl.java

http://authenticroast.googlecode.com/
Java | 242 lines | 140 code | 29 blank | 73 comment | 37 complexity | 1180539aaa77c94304c7df80278b2c13 MD5 | raw file
  1/**
  2 *    Copyright (C) 2007-2010 Aike J Sommer (http://aikesommer.name/)
  3 *
  4 *    This file is part of AuthenticRoast.
  5 *
  6 *    This library is free software; you can redistribute it and/or
  7 *    modify it under the terms of the GNU Lesser General Public
  8 *    License as published by the Free Software Foundation; either
  9 *    version 3 of the License, or (at your option) any later version.
 10 *
 11 *    This library is distributed in the hope that it will be useful,
 12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14 *    Lesser General Public License for more details.
 15 *
 16 *    You should have received a copy of the GNU Lesser General
 17 *    Public License along with this library; if not, write to the
 18 *    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 19 *    Boston, MA 02110-1301 USA
 20 *
 21 *    You can reach the author and get more information about this
 22 *    project at: http://aikesommer.name/
 23 */
 24package name.aikesommer.authenticator;
 25
 26import java.util.logging.Level;
 27import java.util.logging.Logger;
 28import javax.servlet.ServletContext;
 29
 30
 31/**
 32 * Allows web-applications to register a PluggableAuthenticator to use
 33 * for requests to its resources.
 34 * You can also specify the class as init-parameter
 35 * <code>roast.authenticator.class</code>.
 36 * 
 37 * @author Aike J Sommer
 38 */
 39public class RegistryImpl extends Registry {
 40
 41    private static final String AUTHENTICATOR_NOTE = RegistryImpl.class.getName() + ".AUTHENTICATOR";
 42
 43    private static final String CROSS_CONTEXT_NOTE = RegistryImpl.class.getName() + ".CROSS_CONTEXT";
 44
 45    private static final String PRINCIPALSTORE_FACTORY_NOTE = RegistryImpl.class.getName()
 46            + ".PRINCIPALSTORE_FACTORY";
 47
 48    private static final String PRINCIPALSTORE_NOTE = RegistryImpl.class.getName()
 49            + ".PRINCIPALSTORE";
 50
 51    private static ClassLoaderResolver resolver = null;
 52
 53    /**
 54     * Create or find an instance that will use context to store the
 55     * authenticator.
 56     *
 57     * @param context The ServletContext instance for the current web-app.
 58     */
 59    public static RegistryImpl forContext(ServletContext context) {
 60        return new RegistryImpl(context);
 61    }
 62
 63    protected static void setResolver(ClassLoaderResolver resolver) {
 64        RegistryImpl.resolver = resolver;
 65    }
 66
 67    private ServletContext context;
 68
 69    /**
 70     * Create an instance that will use context to store the authenticator
 71     * class.
 72     * 
 73     * @param context The ServletContext instance for the current web-app.
 74     */
 75    public RegistryImpl(ServletContext context) {
 76        this.context = context;
 77    }
 78
 79    /**
 80     * Register a as authenticator for this Web-App.
 81     *
 82     * @param a The PluggableAuthenticator to use for this web-app.
 83     */
 84    public void register(PluggableAuthenticator a) {
 85        context.setAttribute(AUTHENTICATOR_NOTE, a);
 86    }
 87
 88    /**
 89     * Register f as principal-store factory for this Web-App.
 90     *
 91     * @param s The PrincipalStore.Factory to use for this web-app.
 92     */
 93    public void register(PrincipalStore.Factory f) {
 94        context.setAttribute(PRINCIPALSTORE_FACTORY_NOTE, f);
 95    }
 96
 97    /**
 98     * This will be called by the AuthModule to create the authenticator
 99     * instance.
100     *
101     * @return A PluggableAuthenticator instance from the previously registered
102     *         class.
103     */
104    protected PluggableAuthenticator authenticator() {
105        try {
106            PluggableAuthenticator authenticator = (PluggableAuthenticator) context.getAttribute(
107                    AUTHENTICATOR_NOTE);
108            if (authenticator == null) {
109                String className = context.getInitParameter("roast.authenticator.class");
110                if (className != null) {
111                    Class<? extends PluggableAuthenticator> c = null;
112                    if (resolver != null) {
113                        try {
114                            c = (Class<? extends PluggableAuthenticator>) resolver.resolve(context).loadClass(
115                                    className);
116                        } catch (ClassNotFoundException ex) {
117                        }
118                    }
119                    if (c == null) {
120                        try {
121                            c = (Class<? extends PluggableAuthenticator>) Thread.currentThread().getContextClassLoader().loadClass(
122                                    className);
123                        } catch (ClassNotFoundException ex) {
124                            c = (Class<? extends PluggableAuthenticator>) Class.forName(className);
125                        }
126                    }
127
128                    authenticator = c.newInstance();
129                } else {
130                    String delegateName = context.getInitParameter("roast.delegate");
131
132                    if (delegateName != null) {
133                        ServletContext delegate = context.getContext(delegateName);
134                        if (delegate == null) {
135                            throw new IllegalArgumentException("The context '" + delegateName
136                                    + "' does not exist!");
137                        }
138
139                        RegistryImpl delegateRegistry = RegistryImpl.forContext(delegate);
140                        if (delegateRegistry.isDelegate()) {
141                            authenticator = new DelegatingAuthenticator(
142                                    delegateRegistry.authenticator(), delegate);
143                        } else {
144                            throw new IllegalArgumentException("The context '" + delegateName
145                                    + "' does not allow to be used as a delegate!");
146                        }
147                    }
148                }
149
150                if (authenticator != null) {
151                    register(authenticator);
152                }
153            }
154            return authenticator;
155        } catch (Throwable t) {
156            Logger log = Logger.getLogger(getClass().getName());
157            log.severe("failed to create authenticator: " + t);
158            log.log(Level.FINE, "failed to create authenticator", t);
159            return null;
160        }
161    }
162
163    /**
164     * Get wether cross-context authentication should be enabled.
165     */
166    protected boolean isCrossContext() {
167        Boolean result = (Boolean) context.getAttribute(CROSS_CONTEXT_NOTE);
168
169        if (result == null) {
170            result = context.getInitParameter("roast.delegate") != null || isDelegate();
171        }
172
173        result = result == null ? false : result;
174        context.setAttribute(CROSS_CONTEXT_NOTE, result);
175        return result;
176    }
177
178    /**
179     * Get wether this context allows to be used as a delegate.
180     */
181    private boolean isDelegate() {
182        return "true".equals(context.getInitParameter("roast.is-delegate"));
183    }
184
185    /**
186     * This will be called by the AuthModule to create the principal-store
187     * instance.
188     *
189     * @return A PrincipalStore instance from the previously registered
190     *         class.
191     */
192    protected PrincipalStore principalStore() {
193        ThreadLocal<PrincipalStore> stores = (ThreadLocal<PrincipalStore>) context.getAttribute(
194                PRINCIPALSTORE_NOTE);
195        if (stores != null) {
196            return stores.get();
197        }
198
199        return null;
200    }
201
202    protected void createPrincipalStore(AuthenticationRequest request) {
203        ThreadLocal<PrincipalStore> stores = (ThreadLocal<PrincipalStore>) context.getAttribute(
204                PRINCIPALSTORE_NOTE);
205        if (stores == null) {
206            stores = new ThreadLocal<PrincipalStore>();
207            context.setAttribute(PRINCIPALSTORE_NOTE, stores);
208        }
209        stores.remove();
210
211        PrincipalStore store = null;
212        try {
213            PrincipalStore.Factory factory = (PrincipalStore.Factory) context.getAttribute(
214                    PRINCIPALSTORE_FACTORY_NOTE);
215            if (factory == null) {
216                String name = context.getInitParameter("roast.principal-store.factory");
217                if (name == null) {
218                    store = isCrossContext() ? 
219                        new CrossContextPrincipalStore(request.getHttpServletRequest(), request.getHttpServletResponse()) :
220                        new DefaultPrincipalStore(request.getHttpServletRequest().getSession());
221                } else {
222                    Class<? extends PrincipalStore.Factory> c = (Class<? extends PrincipalStore.Factory>) Class.forName(
223                            name);
224                    factory = c.newInstance();
225                    register(factory);
226                }
227            }
228            if (store == null && factory != null) {
229                store = factory.factory(request);
230            }
231        } catch (Throwable t) {
232            Logger log = Logger.getLogger(getClass().getName());
233            log.severe("failed to create principal-store: " + t);
234            log.log(Level.FINE, "failed to create principal-store", t);
235        }
236
237        if (store != null) {
238            stores.set(store);
239        }
240    }
241
242}