Package org.apache.hivemind.servlet

Source Code of org.apache.hivemind.servlet.HiveMindFilter

//  Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.hivemind.servlet;

import java.io.IOException;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.Registry;
import org.apache.hivemind.impl.DefaultClassResolver;
import org.apache.hivemind.impl.RegistryBuilder;

/**
* Servlet filter that constructs the Registry at startup. It ensures that each request is
* properly terminated with a call to
* {@link org.apache.hivemind.service.ThreadEventNotifier#fireThreadCleanup()}.
* It also makes the Registry available during the request by
* storing it as a request attribute.
*
* @author Howard Lewis Ship
*/
public class HiveMindFilter implements Filter
{
    private static final Log LOG = LogFactory.getLog(HiveMindFilter.class);

    /**
     * Request attribute key that stores the Registry.
     */

    static final String REQUEST_KEY = "org.apache.hivemind.RequestRegistry";

    static final String REBUILD_REQUEST_KEY = "org.apache.hivemind.RebuildRegistry";

    private FilterConfig _filterConfig;
    private Registry _registry;

    /**
     * Package private method used for testing.
     */
    Registry getRegistry()
    {
        return _registry;
    }

    /**
     * Constructs a {@link Registry} and stores it into the
     * <code>ServletContext</code>. Any exception throws is logged.
     */
    public void init(FilterConfig config) throws ServletException
    {
        _filterConfig = config;

        initializeRegistry();

    }

    private void initializeRegistry()
    {
        long startTime = System.currentTimeMillis();

        LOG.info(ServletMessages.filterInit());

        try
        {
            _registry = constructRegistry(_filterConfig);

            LOG.info(
                ServletMessages.constructedRegistry(
                    _registry,
                    System.currentTimeMillis() - startTime));
        }
        catch (Exception ex)
        {
            LOG.error(ex.getMessage(), ex);
        }
    }

    /**
     * Invoked from {@link #init(FilterConfig)} to actually
     * construct the Registry.  Subclasses may override if
     * they have specific initialization needs, or have nonstandard
     * rules for finding HiveMind module deployment descriptors.
     */
    protected Registry constructRegistry(FilterConfig config)
    {
        ClassResolver resolver = new DefaultClassResolver();
        RegistryBuilder builder = new RegistryBuilder();

        builder.processModules(resolver);

        return builder.constructRegistry(getRegistryLocale());
    }

    /**
     * Returns the default Locale.  Subclasses may override to select a particular
     * locale for the Registry.
     */
    protected Locale getRegistryLocale()
    {
        return Locale.getDefault();
    }

    /**
     * Passes the request to the filter chain, but then invokes
     * {@link ThreadEventNotifier#fireThreadCleanup()} (from a finally block).
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException
    {
        try
        {
            request.setAttribute(REQUEST_KEY, _registry);

            chain.doFilter(request, response);
        }
        finally
        {
            cleanupThread();
           
      checkRegistryRebuild(request);
        }
    }

    private synchronized void checkRegistryRebuild(ServletRequest request)
    {
        if (request.getAttribute(REBUILD_REQUEST_KEY) == null)
            return;

        // This is so not threadsafe, but you don't do this very often.
        // This method is synchronized, but other threads may be actively using
        // the Registry we're shutting down.
       
        // What we really need is some good concurrence support to track the number
        // of threads that may be using the old registry, set a write lock, and wait
        // for that number to drop to one (this thread).  Instead, we'll just swap in the
        // new Registry and hope for the best.

        Registry oldRegistry = _registry;

        // Replace the old Registry with a new one.  All other threads, but this
        // one, will begin using the new Registry. Hopefully, we didn't get
        // rebuild requests on multiple threads.

        initializeRegistry();

        // Shutdown the old Registry. Perhaps we should sleep for a moment, first,
        // to help ensure that other threads have "cleared out". If not, we'll see some
        // instability at the instant we shutdown (i.e., all the proxies will get disabled).

    oldRegistry.shutdown();
    }

    /**
     * Cleanup the thread, ignoring any exceptions that may be thrown.
     */
    private void cleanupThread()
    {
        try
        {
            _registry.cleanupThread();
        }
        catch (Exception ex)
        {
            LOG.error(ServletMessages.filterCleanupError(ex), ex);
        }
    }

    /**
     * Invokes {@link Registry#shutdown()}.
     */
    public void destroy()
    {
        if (_registry != null)
            _registry.shutdown();

        _filterConfig = null;
    }

    /**
     * Returns the {@link Registry} that was stored as a request attribute
     * inside method {@link #doFilter(ServletRequest, ServletResponse, FilterChain)}.
     */
    public static Registry getRegistry(HttpServletRequest request)
    {
        return (Registry) request.getAttribute(REQUEST_KEY);
    }

  /**
   * Sets a flag in the request that will cause the current Registry to be shutdown
   * and replaced with a new Registry (at the end of the current request).
   */
    public static void rebuildRegistry(HttpServletRequest request)
    {
        request.setAttribute(REBUILD_REQUEST_KEY, Boolean.TRUE);
    }

}
TOP

Related Classes of org.apache.hivemind.servlet.HiveMindFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.