package com.palbrattberg.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Provides static access to our Spring {@link ApplicationContext}. <p/> To use
 * this class make sure you havethe following in your <tt>WEB-INF/web.xml</tt>
 * file:
 * 
 * <pre><code>
 *  &lt;listener&gt;
 *  &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
 *  &lt;/listener&gt;
 * </code></pre>
 * 
 * And at least this is your <tt>WEB-INF/applicationContext.xml</tt> file:
 * 
 * <pre><code>
 *  &lt;bean id=&quot;StaticSpringApplicationContext&quot; class=&quot;com.palbrattberg.spring.StaticSpringApplicationContext&quot; /&gt;
 * </code></pre>
 * 
 * You can now retrieve any Spring configured beans like this:
 * 
 * <pre><code>
 * MyBean myBean = (MyBean) StaticSpringApplicationContext.getBean(&quot;myBean&quot;);
 * </code></pre>
 * 
 * @author <a href="mailto:brattberg@gmail.com">P&aring;l Brattberg</a>
 * @since 2008-03-02
 */
public class StaticSpringApplicationContext implements ApplicationContextAware {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /** Static reference to our pre-configured {@link ApplicationContext}. */
    private static ApplicationContext applicationContext = null;

    /**
     * Assign an {@link ApplicationContext}.
     * 
     * @throws IllegalStateException
     *             If there was already an ApplicationContext defined.
     */
    public void setApplicationContext(final ApplicationContext anApplicationContext) {
        if (applicationContext != null) {
            log.warn("Spring ApplicationContext was previously set! Setting this "
                        + "twice is unexpected. Please check your web.xml file for a single reference to <listener><listener-class>"
                        + "org.springframework.web.context.ContextLoaderListener</listener-class>"
                        + "</listener>. You may also wish to check the application server logs for more information.");
        }
        applicationContext = anApplicationContext;
        log.debug("Successfully set ApplicationContext reference to StaticSpringApplicationContext");
    }

    /**
     * Retrieve the current {@link ApplicationContext}.
     * 
     * @throws IllegalStateException
     *             If there was no ApplicationContext defined.
     */
    public static ApplicationContext getApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("Spring ApplicationContext was unexpectedly null, are you "
                    + "sure the web.xml file has a reference to <listener><listener-class>"
                    + "org.springframework.web.context.ContextLoaderListener</listener-class>"
                    + "</listener> and an applicationContext.xml file exists in the WEB-INF folder? "
                    + "Check the application server logs for more information.");
        }
        return applicationContext;
    }

    /**
     * Shortcut method to get a bean from the current context. This is
     * equivalent to doing
     * 
     * <pre><code>
     * MyBean myBean = (MyBean) StaticSpringApplicationContext.getApplicationContext().getBean(&quot;myBean&quot;);
     * </code></pre>
     * 
     * @throws IllegalStateException
     *             If there was no ApplicationContext defined.
     */
    public static Object getBean(final String beanIdentifier) {
        return getApplicationContext().getBean(beanIdentifier);
    }
}
