//  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.tapestry.engine;

import org.apache.bsf.BSFManager;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.*;
import org.apache.tapestry.asset.ResourceChecksumSource;
import org.apache.tapestry.asset.ResourceChecksumSourceImpl;
import org.apache.tapestry.enhance.DefaultComponentClassEnhancer;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.pageload.PageSource;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.request.ResponseOutputStream;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.*;
import org.apache.tapestry.util.exception.ExceptionAnalyzer;
import org.apache.tapestry.util.io.DataSqueezer;
import org.apache.tapestry.util.pool.Pool;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;

/**
 *  Basis for building real Tapestry applications.  Immediate subclasses
 *  provide different strategies for managing page state and other resources
 *  between request cycles.
 *
 *  Uses a shared instance of
 *  {@link ITemplateSource}, {@link ISpecificationSource},
 *  {@link IScriptSource} and {@link IComponentMessagesSource}
 *  stored as attributes of the  {@link ServletContext}
 *  (they will be shared by all sessions).
 *
 *  <p>An application is designed to be very lightweight.
 *  Particularily, it should <b>never</b> hold references to any
 *  {@link IPage} or {@link org.apache.tapestry.IComponent} objects.  The entire system is
 *  based upon being able to quickly rebuild the state of any page(s).
 *
 * <p>Where possible, instance variables should be transient.  They
 * can be restored inside {@link #setupForRequest(RequestContext)}.
 *
 *  <p>In practice, a subclass (usually {@link BaseEngine})
 *  is used without subclassing.  Instead, a
 *  visit object is specified.  To facilitate this, the application specification
 *  may include a property, <code>org.apache.tapestry.visit-class</code>
 *  which is the class name  to instantiate when a visit object is first needed.  See
 *  {@link #createVisit(IRequestCycle)} for more details.
 *
 * <p>Some of the classes' behavior is controlled by JVM system properties
 * (typically only used during development):
 *
 * <table border=1>
 * 	<tr> <th>Property</th> <th>Description</th> </tr>
 *  <tr> <td>org.apache.tapestry.enable-reset-service</td>
 *		<td>If true, enabled an additional service, reset, that
 *		allow page, specification and template caches to be cleared on demand.
 *  	See {@link #isResetServiceEnabled()}. </td>
 * </tr>
 * <tr>
 *		<td>org.apache.tapestry.disable-caching</td>
 *	<td>If true, then the page, specification, template and script caches
 *  will be cleared after each request. This slows things down,
 *  but ensures that the latest versions of such files are used.
 *  Care should be taken that the source directories for the files
 *  preceeds any versions of the files available in JARs or WARs. </td>
 * </tr>
 * </table>
 *
 *
 *  @author Howard Lewis Ship
 *  @version $Id$
 *
 **/

public abstract class AbstractEngine
        implements IEngine, IEngineServiceView, Externalizable, HttpSessionBindingListener
{
    private static final Log LOG = LogFactory.getLog(AbstractEngine.class);

    /**
     *  @since 2.0.4
     *
     **/

    private static final long serialVersionUID = 6884834397673817117L;

    private transient String _contextPath;
    private transient String _servletPath;
    private transient String _clientAddress;
    private transient String _sessionId;
    private transient boolean _stateful;
    private transient ListenerMap _listeners;

    /** @since 2.2 **/

    private transient DataSqueezer _dataSqueezer;

    /**
     *  An object used to contain application-specific server side state.
     *
     **/

    private Object _visit;

    /**
     *  The globally shared application object.  Typically, this is created
     *  when first needed, shared between sessions and engines, and
     *  stored in the {@link ServletContext}.
     *
     *  @since 2.3
     *
     **/

    private transient Object _global;

    /**
     *  The base name for the servlet context key used to store
     *  the application-defined Global object, if any.
     *
     *  @since 2.3
     *
     **/

    public static final String GLOBAL_NAME = "org.apache.tapestry.global";

    /**
     *  The name of the application property that will be used to
     *  determine the encoding to use when generating the output
     *
     *  @since 3.0
     **/

    public static final String OUTPUT_ENCODING_PROPERTY_NAME =
            "org.apache.tapestry.output-encoding";

    /**
     *  The default encoding that will be used when generating the output.
     *  It is used if no output encoding property has been specified.
     *
     *  @since 3.0
     */

    public static final String DEFAULT_OUTPUT_ENCODING = "UTF-8";

    /**
     *  The curent locale for the engine, which may be changed at any time.
     *
     **/

    private Locale _locale;

    /**
     *  Set by {@link #setLocale(Locale)} when the locale is changed;
     *  this allows the locale cookie to be updated.
     *
     **/

    private boolean _localeChanged;

    /**
     *  The specification for the application, which
     *  lives in the {@link ServletContext}.  If the
     *  session (and application) moves to a different context (i.e.,
     *  a different JVM), then
     *  we want to reconnect to the specification in the new context.
     *  A check is made on every request
     *  cycle as needed.
     *
     **/

    protected transient IApplicationSpecification _specification;

    /**
     *  The source for template data. The template source is stored
     *  in the {@link ServletContext} as a named attribute.
     *  After de-serialization, the application can re-connect to
     *  the template source (or create a new one).
     *
     **/

    protected transient ITemplateSource _templateSource;

    /**
     *  The source for component specifications, stored in the
     *  {@link ServletContext} (like {@link #_templateSource}).
     *
     **/

    protected transient ISpecificationSource _specificationSource;

    /**
     *  The source for parsed scripts, again, stored in the
     *  {@link ServletContext}.
     *
     *  @since 1.0.2
     *
     **/

    private transient IScriptSource _scriptSource;

    /**
     *  The name of the context attribute for the {@link IScriptSource} instance.
     *  The application's name is appended.
     *
     *  @since 1.0.2
     *
     **/

    protected static final String SCRIPT_SOURCE_NAME = "org.apache.tapestry.ScriptSource";

    /**
     *  The name of the context attribute for the {@link IComponentMessagesSource}
     *  instance.  The application's name is appended.
     *
     *  @since 2.0.4
     *
     **/

    protected static final String STRINGS_SOURCE_NAME = "org.apache.tapestry.StringsSource";

    private transient IComponentMessagesSource _stringsSource;

    /**
     *  The name of the application specification property used to specify the
     *  class of the visit object.
     *
     **/

    public static final String VISIT_CLASS_PROPERTY_NAME = "org.apache.tapestry.visit-class";

    /**
     *  Servlet context attribute name for the default {@link ITemplateSource}
     *  instance.  The application's name is appended.
     *
     **/

    protected static final String TEMPLATE_SOURCE_NAME = "org.apache.tapestry.TemplateSource";

    /**
     *  Servlet context attribute name for the default {@link ISpecificationSource}
     *  instance.  The application's name is appended.
     *
     **/

    protected static final String SPECIFICATION_SOURCE_NAME =
            "org.apache.tapestry.SpecificationSource";

    /**
     *  Servlet context attribute name for the {@link IPageSource}
     *  instance.  The application's name is appended.
     *
     **/

    protected static final String PAGE_SOURCE_NAME = "org.apache.tapestry.PageSource";

    /**
     *  Servlet context attribute name for a shared instance
     *  of {@link DataSqueezer}.  The instance is actually shared
     *  between Tapestry applications within the same context
     *  (which will have the same ClassLoader).
     *
     *  @since 2.2
     *
     **/

    protected static final String DATA_SQUEEZER_NAME = "org.apache.tapestry.DataSqueezer";

    /**
     * Servlet context attribute name for a shared instance
     * of {@link ResourceChecksumSource}.
     * @since 3.0.3
     */
    protected static final String RESOURCE_CHECKSUM_SOURCE_NAME =
            "org.apache.tapestry.ResourceChecksumSource";

    /**
     *  The source for pages, which acts as a pool, but is capable of
     *  creating pages as needed.  Stored in the
     *  {@link ServletContext}, like {@link #_templateSource}.
     *
     **/

    private transient IPageSource _pageSource;

    /**
     *  If true (set from JVM system parameter
     *  <code>org.apache.tapestry.enable-reset-service</code>)
     *  then the reset service will be enabled, allowing
     *  the cache of pages, specifications and template
     *  to be cleared on demand.
     *
     **/

    private static final boolean _resetServiceEnabled =
            Boolean.getBoolean("org.apache.tapestry.enable-reset-service");

    /**
     * If true (set from the JVM system parameter
     * <code>org.apache.tapestry.disable-caching</code>)
     * then the cache of pages, specifications and template
     * will be cleared after each request.
     *
     **/

    private static final boolean _disableCaching =
            Boolean.getBoolean("org.apache.tapestry.disable-caching");

    private transient IResourceResolver _resolver;

    /**
     *  Constant used to store a {@link org.apache.tapestry.util.IPropertyHolder}
     *  in the servlet context.
     *
     *  @since 2.3
     *
     **/

    protected static final String PROPERTY_SOURCE_NAME = "org.apache.tapestry.PropertySource";

    /**
     *  A shared instance of {@link IPropertySource}
     *
     *  @since 3.0
     *  @see #createPropertySource(RequestContext)
     *
     **/

    private transient IPropertySource _propertySource;

    /**
     *  Map from service name to service instance.
     *
     *  @since 1.0.9
     *
     **/

    private transient Map _serviceMap;

    protected static final String SERVICE_MAP_NAME = "org.apache.tapestry.ServiceMap";

    /**
     *  A shared instance of {@link Pool}.
     *
     *  @since 3.0
     *  @see #createPool(RequestContext)
     *
     **/

    private transient Pool _pool;

    protected static final String POOL_NAME = "org.apache.tapestry.Pool";

    /**
     *  Name of a shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer}
     *  stored in the {@link ServletContext}.
     *
     *  @since 3.0
     *
     **/

    protected static final String ENHANCER_NAME = "org.apache.tapestry.ComponentClassEnhancer";

    /**
     *  A shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer}.
     *
     *  @since 3.0
     *  @see #createComponentClassEnhancer(RequestContext)
     *
     **/

    private transient IComponentClassEnhancer _enhancer;

    /**
     *  Set to true when there is a (potential)
     *  change to the internal state of the engine, set
     *  to false when the engine is stored into the
     *  {@link HttpSession}.
     *
     *  @since 3.0
     *
     **/

    private transient boolean _dirty;

    /**
     * The instance of {@link IMonitorFactory} used to create a monitor.
     *
     * @since 3.0
     */

    private transient IMonitorFactory _monitorFactory;

    /**
     * Used to obtain resource checksums for the asset service.
     * @since 3.0.3
     */
    private transient ResourceChecksumSource _resourceChecksumSource;

    /**
     *  Sets the Exception page's exception property, then renders the Exception page.
     *
     *  <p>If the render throws an exception, then copious output is sent to
     *  <code>System.err</code> and a {@link ServletException} is thrown.
     *
     **/

    protected void activateExceptionPage(
            IRequestCycle cycle,
            ResponseOutputStream output,
            Throwable cause)
            throws ServletException
    {
        try
        {
            IPage exceptionPage = cycle.getPage(getExceptionPageName());

            exceptionPage.setProperty("exception", cause);

            cycle.activate(exceptionPage);

            renderResponse(cycle, output);

        }
        catch (Throwable ex)
        {
            // Worst case scenario.  The exception page itself is broken, leaving
            // us with no option but to write the cause to the output.

            reportException(
                    Tapestry.getMessage("AbstractEngine.unable-to-process-client-request"),
                    cause);

            // Also, write the exception thrown when redendering the exception
            // page, so that can get fixed as well.

            reportException(
                    Tapestry.getMessage("AbstractEngine.unable-to-present-exception-page"),
                    ex);

            // And throw the exception.

            throw new ServletException(ex.getMessage(), ex);
        }
    }

    /**
     *  Writes a detailed report of the exception to <code>System.err</code>.
     *
     **/

    public void reportException(String reportTitle, Throwable ex)
    {
        LOG.warn(reportTitle, ex);

        System.err.println("\n\n**********************************************************\n\n");

        System.err.println(reportTitle);

        System.err.println(
                "\n\n      Session id: "
                + _sessionId
                + "\n  Client address: "
                + _clientAddress
                + "\n\nExceptions:\n");

        new ExceptionAnalyzer().reportException(ex, System.err);

        System.err.println("\n**********************************************************\n");

    }

    /**
     *  Invoked at the end of the request cycle to release any resources specific
     *  to the request cycle.
     *
     **/

    protected abstract void cleanupAfterRequest(IRequestCycle cycle);

    /**
     *  Extends the description of the class generated by {@link #toString()}.
     *  If a subclass adds additional instance variables that should be described
     *  in the instance description, it may overide this method. This implementation
     *  does nothing.
     *
     *  @see #toString()
     *
     **/

    protected void extendDescription(ToStringBuilder builder)
    {

    }

    /**
     *  Returns the locale for the engine.  This is initially set
     *  by the {@link ApplicationServlet} but may be updated
     *  by the application.
     *
     **/

    public Locale getLocale()
    {
        return _locale;
    }

    /**
     * Overriden in subclasses that support monitoring.  Should create and return
     * an instance of {@link IMonitor} that is appropriate for the request cycle described
     * by the {@link RequestContext}.
     *
     * <p>The monitor is used to create a {@link RequestCycle}.
     *
     * <p>This implementation uses a {@link IMonitorFactory}
     * to create the monitor instance.  The factory
     * is provided as an application extension.  If the application
     * extension does not exist, {@link DefaultMonitorFactory} is used.
     *
     * <p>As of release 3.0, this method should <em>not</em> return null.
     *
     *
     */

    public IMonitor getMonitor(RequestContext context)
    {
        if (_monitorFactory == null)
        {
            if (_specification.checkExtension(Tapestry.MONITOR_FACTORY_EXTENSION_NAME))
                _monitorFactory =
                        (IMonitorFactory) _specification.getExtension(
                                Tapestry.MONITOR_FACTORY_EXTENSION_NAME,
                                IMonitorFactory.class);
            else
                _monitorFactory = DefaultMonitorFactory.SHARED;
        }

        return _monitorFactory.createMonitor(context);
    }

    public IPageSource getPageSource()
    {
        return _pageSource;
    }

    /**
     *  Returns a service with the given name.  Services are created by the
     *  first call to {@link #setupForRequest(RequestContext)}.
     **/

    public IEngineService getService(String name)
    {
        IEngineService result = (IEngineService) _serviceMap.get(name);

        if (result == null)
            throw new ApplicationRuntimeException(
                    Tapestry.format("AbstractEngine.unknown-service", name));

        return result;
    }

    public String getServletPath()
    {
        return _servletPath;
    }

    /**
     * Returns the context path, the prefix to apply to any URLs so that they
     * are recognized as belonging to the Servlet 2.2 context.
     *
     *  @see org.apache.tapestry.asset.ContextAsset
     *
     **/

    public String getContextPath()
    {
        return _contextPath;
    }

    /**
     *  Returns the specification, if available, or null otherwise.
     *
     *  <p>To facilitate deployment across multiple servlet containers, the
     *  application is serializable.  However, the reference to the specification
     *  is transient.   When an application instance is deserialized, it reconnects
     *  with the application specification by locating it in the {@link ServletContext}
     *  or parsing it fresh.
     *
     **/

    public IApplicationSpecification getSpecification()
    {
        return _specification;
    }

    public ISpecificationSource getSpecificationSource()
    {
        return _specificationSource;
    }

    public ITemplateSource getTemplateSource()
    {
        return _templateSource;
    }

    /**
     *  Reads the state serialized by {@link #writeExternal(ObjectOutput)}.
     *
     *  <p>This always set the stateful flag.  By default, a deserialized
     *  session is stateful (else, it would not have been serialized).
     **/

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {
        _stateful = true;

        String localeName = in.readUTF();
        _locale = Tapestry.getLocale(localeName);

        _visit = in.readObject();
    }

    /**
     *  Writes the following properties:
     *
     *  <ul>
     *  <li>locale name ({@link Locale#toString()})
     *  <li>visit
     *  </ul>
     *
     **/

    public void writeExternal(ObjectOutput out) throws IOException
    {
        out.writeUTF(_locale.toString());
        out.writeObject(_visit);
    }

    /**
     *  Invoked, typically, when an exception occurs while servicing the request.
     *  This method resets the output, sets the new page and renders it.
     *
     **/

    protected void redirect(
            String pageName,
            IRequestCycle cycle,
            ResponseOutputStream out,
            ApplicationRuntimeException exception)
            throws IOException, ServletException
    {
        // Discard any output from the previous page.

        out.reset();

        IPage page = cycle.getPage(pageName);

        cycle.activate(page);

        renderResponse(cycle, out);
    }

    public void renderResponse(IRequestCycle cycle, ResponseOutputStream output)
            throws ServletException, IOException
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Begin render response.");

        // If the locale has changed during this request cycle then
        // do the work to propogate the locale change into
        // subsequent request cycles.

        if (_localeChanged)
        {
            _localeChanged = false;

            RequestContext context = cycle.getRequestContext();
            ApplicationServlet servlet = context.getServlet();

            servlet.writeLocaleCookie(_locale, this, context);
        }

        // Commit all changes and ignore further changes.

        IPage page = cycle.getPage();

        IMarkupWriter writer = page.getResponseWriter(output);

        output.setContentType(writer.getContentType());

        boolean discard = true;

        try
        {
            cycle.renderPage(writer);

            discard = false;
        }
        finally
        {
            // Closing the writer closes its PrintWriter and a whole stack of java.io objects,
            // which tend to stream a lot of output that eventually hits the
            // ResponseOutputStream.  If we are discarding output anyway (due to an exception
            // getting thrown during the render), we can save ourselves some trouble
            // by ignoring it.

            if (discard)
                output.setDiscard(true);

            writer.close();

            if (discard)
                output.setDiscard(false);
        }

    }

    /**
     * Invalidates the session, then redirects the client web browser to
     * the servlet's prefix, starting a new visit.
     *
     * <p>Subclasses should perform their own restart (if necessary, which is
     * rarely) before invoking this implementation.
     *
     **/

    public void restart(IRequestCycle cycle) throws IOException
    {
        RequestContext context = cycle.getRequestContext();

        HttpSession session = context.getSession();

        if (session != null)
        {
            try
            {
                session.invalidate();
            }
            catch (IllegalStateException ex)
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("Exception thrown invalidating HttpSession.", ex);

                // Otherwise, ignore it.
            }
        }

        // Make isStateful() return false, so that the servlet doesn't
        // try to store the engine back into the (now invalid) session.

        _stateful = false;

        String url = context.getAbsoluteURL(_servletPath);

        context.redirect(url);
    }

    /**
     *  Delegate method for the servlet.  Services the request.
     *
     **/

    public boolean service(RequestContext context) throws ServletException, IOException
    {
        ApplicationServlet servlet = context.getServlet();
        IRequestCycle cycle = null;
        ResponseOutputStream output = null;
        IMonitor monitor = null;

        if (LOG.isDebugEnabled())
            LOG.debug("Begin service " + context.getRequestURI());

        if (_specification == null)
            _specification = servlet.getApplicationSpecification();

        // The servlet invokes setLocale() before invoking service().  We want
        // to ignore that setLocale() ... that is, not force a cookie to be
        // written.

        _localeChanged = false;

        if (_resolver == null)
            _resolver = servlet.getResourceResolver();

        try
        {
            setupForRequest(context);

            monitor = getMonitor(context);

            output = new ResponseOutputStream(context.getResponse());
        }
        catch (Exception ex)
        {
            reportException(Tapestry.getMessage("AbstractEngine.unable-to-begin-request"), ex);

            throw new ServletException(ex.getMessage(), ex);
        }

        IEngineService service = null;

        try
        {
            try
            {
                String serviceName;

                try
                {
                    serviceName = extractServiceName(context);

                    if (Tapestry.isBlank(serviceName))
                        serviceName = Tapestry.HOME_SERVICE;

                    // Must have a service to create the request cycle.
                    // Must have a request cycle to report an exception.

                    service = getService(serviceName);
                }
                catch (Exception ex)
                {
                    service = getService(Tapestry.HOME_SERVICE);
                    cycle = createRequestCycle(context, service, monitor);

                    throw ex;
                }

                cycle = createRequestCycle(context, service, monitor);

                monitor.serviceBegin(serviceName, context.getRequestURI());

                // Invoke the service, which returns true if it may have changed
                // the state of the engine (most do return true).

                service.service(this, cycle, output);

                // Return true only if the engine is actually dirty.  This cuts down
                // on the number of times the engine is stored into the
                // session unceccesarily.

                return _dirty;
            }
            catch (PageRedirectException ex)
            {
                handlePageRedirectException(ex, cycle, output);
            }
            catch (RedirectException ex)
            {
                handleRedirectException(cycle, ex);
            }
            catch (StaleLinkException ex)
            {
                handleStaleLinkException(ex, cycle, output);
            }
            catch (StaleSessionException ex)
            {
                handleStaleSessionException(ex, cycle, output);
            }
        }
        catch (Exception ex)
        {
            monitor.serviceException(ex);

            // Discard any output (if possible).  If output has already been sent to
            // the client, then things get dicey.  Note that this block
            // gets activated if the StaleLink or StaleSession pages throws
            // any kind of exception.

            // Attempt to switch to the exception page.  However, this may itself fail
            // for a number of reasons, in which case a ServletException is thrown.

            output.reset();

            if (LOG.isDebugEnabled())
                LOG.debug("Uncaught exception", ex);

            activateExceptionPage(cycle, output, ex);
        }
        finally
        {
            if (service != null)
                monitor.serviceEnd(service.getName());

            try
            {
                cycle.cleanup();

                // Closing the buffered output closes the underlying stream as well.

                if (output != null)
                    output.forceFlush();
            }
            catch (Exception ex)
            {
                reportException(Tapestry.getMessage("AbstractEngine.exception-during-cleanup"), ex);
            }
            finally
            {
                cleanupAfterRequest(cycle);
            }

            if (_disableCaching)
            {
                try
                {
                    clearCachedData();
                }
                catch (Exception ex)
                {
                    reportException(
                            Tapestry.getMessage("AbstractEngine.exception-during-cache-clear"),
                            ex);
                }
            }

            if (LOG.isDebugEnabled())
                LOG.debug("End service");

        }

        return _dirty;
    }

    /**
     *  Handles {@link PageRedirectException} which involves
     *  executing {@link IPage#validate(IRequestCycle)} on the target page
     *  (of the exception), until either a loop is found, or a page
     *  succesfully validates and can be activated.
     *
     *  <p>This should generally not be overriden in subclasses.
     *
     *  @since 3.0
     */

    protected void handlePageRedirectException(
            PageRedirectException ex,
            IRequestCycle cycle,
            ResponseOutputStream output)
            throws IOException, ServletException
    {
        List pageNames = new ArrayList();

        String pageName = ex.getTargetPageName();

        while (true)
        {
            if (pageNames.contains(pageName))
            {
                // Add the offending page to pageNames so it shows in the
                // list.

                pageNames.add(pageName);

                StringBuffer buffer = new StringBuffer();
                int count = pageNames.size();

                for (int i = 0; i < count; i++)
                {
                    if (i > 0)
                        buffer.append("; ");

                    buffer.append(pageNames.get(i));
                }

                throw new ApplicationRuntimeException(
                        Tapestry.format("AbstractEngine.validate-cycle", buffer.toString()));
            }

            // Record that this page has been a target.

            pageNames.add(pageName);

            try
            {
                // Attempt to activate the new page.

                cycle.activate(pageName);

                break;
            }
            catch (PageRedirectException ex2)
            {
                pageName = ex2.getTargetPageName();
            }
        }

        // Discard any output from the previous page.

        output.reset();

        renderResponse(cycle, output);
    }

    /**
     *  Invoked from {@link #service(RequestContext)} to create an instance of
     *  {@link IRequestCycle} for the current request.  This implementation creates
     *  an returns an instance of {@link RequestCycle}.
     *
     *  @since 3.0
     *
     **/

    protected IRequestCycle createRequestCycle(
            RequestContext context,
            IEngineService service,
            IMonitor monitor)
    {
        return new RequestCycle(this, context, service, monitor);
    }

    /**
     *  Invoked by {@link #service(RequestContext)} if a {@link StaleLinkException}
     *  is thrown by the {@link IEngineService service}.  This implementation
     *  sets the message property of the StaleLink page to the
     *  message provided in the exception,
     *  then invokes
     *  {@link #redirect(String, IRequestCycle, ResponseOutputStream, ApplicationRuntimeException)}
     *  to render the StaleLink page.
     *
     *  <p>Subclasses may overide this method (without
     *  invoking this implementation).  A common practice
     *  is to present an error message on the application's
     *  Home page.
     *
     *  <p>Alternately, the application may provide its own version of
     *  the StaleLink page, overriding
     *  the framework's implementation (probably a good idea, because the
     *  default page hints at "application errors" and isn't localized).
     *  The overriding StaleLink implementation must
     *  implement a message property of type String.
     *
     *  @since 0.2.10
     *
     **/

    protected void handleStaleLinkException(
            StaleLinkException ex,
            IRequestCycle cycle,
            ResponseOutputStream output)
            throws IOException, ServletException
    {
        String staleLinkPageName = getStaleLinkPageName();
        IPage page = cycle.getPage(staleLinkPageName);

        page.setProperty("message", ex.getMessage());

        redirect(staleLinkPageName, cycle, output, ex);
    }

    /**
     *  Invoked by {@link #service(RequestContext)} if a {@link StaleSessionException}
     *  is thrown by the {@link IEngineService service}.  This implementation
     *  invokes
     *  {@link #redirect(String, IRequestCycle, ResponseOutputStream, ApplicationRuntimeException)}
     *  to render the StaleSession page.
     *
     *  <p>Subclasses may overide this method (without
     *  invoking this implementation).  A common practice
     *  is to present an eror message on the application's
     *  Home page.
     *
     *  @since 0.2.10
     **/

    protected void handleStaleSessionException(
            StaleSessionException ex,
            IRequestCycle cycle,
            ResponseOutputStream output)
            throws IOException, ServletException
    {
        redirect(getStaleSessionPageName(), cycle, output, ex);
    }

    /**
     *  Discards all cached pages, component specifications and templates.
     *  Subclasses who override this method should invoke this implementation
     *  as well.
     *
     *  @since 1.0.1
     *
     **/

    public void clearCachedData()
    {
        _pool.clear();
        _pageSource.reset();
        _specificationSource.reset();
        _templateSource.reset();
        _scriptSource.reset();
        _stringsSource.reset();
        _enhancer.reset();
        _resourceChecksumSource.reset();
    }

    /**
     *  Changes the locale for the engine.
     *
     **/

    public void setLocale(Locale value)
    {
        if (value == null)
            throw new IllegalArgumentException("May not change engine locale to null.");

        // Because locale changes are expensive (it involves writing a cookie and all that),
        // we're careful not to really change unless there's a true change in value.

        if (!value.equals(_locale))
        {
            _locale = value;
            _localeChanged = true;
            markDirty();
        }
    }

    /**
     *  Invoked from {@link #service(RequestContext)} to ensure that the engine's
     *  instance variables are setup.  This allows the application a chance to
     *  restore transient variables that will not have survived deserialization.
     *
     *  Determines the servlet prefix:  this is the base URL used by
     *  {@link IEngineService services} to build URLs.  It consists
     *  of two parts:  the context path and the servlet path.
     *
     *  <p>The servlet path is retrieved from {@link HttpServletRequest#getServletPath()}.
     *
     *  <p>The context path is retrieved from {@link HttpServletRequest#getContextPath()}.
     *
     *  <p>The global object is retrieved from {@link IEngine#getGlobal()} method.
     *
     *  <p>The final path is available via the {@link #getServletPath()} method.
     *
     *  <p>In addition, this method locates and/or creates the:
     *  <ul>
     *  <li>{@link IComponentClassEnhancer}
     *  <li>{@link Pool}
     *  <li>{@link ITemplateSource}
     *  <li>{@link ISpecificationSource}
     *  <li>{@link IPageSource}
     *  <li>{@link IEngineService} {@link Map}
     *  <ll>{@link IScriptSource}
     *  <li>{@link IComponentMessagesSource}
     *  <li>{@link IPropertySource}
     *  </ul>
     *
     *  <p>This order is important, because some of the later shared objects
     *  depend on some of the earlier shared objects already having
     *  been located or created
     *  (especially {@link #getPool() pool}).
     *
     *  <p>Subclasses should invoke this implementation first, then perform their
     *  own setup.
     *
     **/

    protected void setupForRequest(RequestContext context)
    {
        HttpServlet servlet = context.getServlet();
        ServletContext servletContext = servlet.getServletContext();
        HttpServletRequest request = context.getRequest();
        HttpSession session = context.getSession();

        if (session != null)
            _sessionId = context.getSession().getId();
        else
            _sessionId = null;

        // Previously, this used getRemoteHost(), but that requires an
        // expensive reverse DNS lookup. Possibly, the host name lookup
        // should occur ... but only if there's an actual error message
        // to display.

        if (_clientAddress == null)
            _clientAddress = request.getRemoteAddr();

        // servletPath is null, so this means either we're doing the
        // first request in this session, or we're handling a subsequent
        // request in another JVM (i.e. another server in the cluster).
        // In any case, we have to do some late (re-)initialization.

        if (_servletPath == null)
        {
            // Get the path *within* the servlet context

            // In rare cases related to the tagsupport service, getServletPath() is wrong
            // (its a JSP, which invokes Tapestry as an include, thus muddling what
            // the real servlet and servlet path is).  In those cases, the JSP tag
            // will inform us.

            String path =
                    (String) request.getAttribute(Tapestry.TAG_SUPPORT_SERVLET_PATH_ATTRIBUTE);

            if (path == null)
                path = request.getServletPath();

            // Get the context path, which may be the empty string
            // (but won't be null).

            _contextPath = request.getContextPath();

            _servletPath = _contextPath + path;
        }

        String servletName = context.getServlet().getServletName();

        if (_propertySource == null)
        {
            String name = PROPERTY_SOURCE_NAME + ":" + servletName;

            _propertySource = (IPropertySource) servletContext.getAttribute(name);

            if (_propertySource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _propertySource = (IPropertySource) servletContext.getAttribute(name);

                    if (_propertySource == null)
                    {
                        _propertySource = createPropertySource(context);

                        servletContext.setAttribute(name, _propertySource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_enhancer == null)
        {
            String name = ENHANCER_NAME + ":" + servletName;

            _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);

            if (_enhancer == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);

                    if (_enhancer == null)
                    {
                        _enhancer = createComponentClassEnhancer(context);

                        servletContext.setAttribute(name, _enhancer);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_pool == null)
        {
            String name = POOL_NAME + ":" + servletName;

            _pool = (Pool) servletContext.getAttribute(name);

            if (_pool == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _pool = (Pool) servletContext.getAttribute(name);

                    if (_pool == null)
                    {
                        _pool = createPool(context);

                        servletContext.setAttribute(name, _pool);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_templateSource == null)
        {
            String name = TEMPLATE_SOURCE_NAME + ":" + servletName;

            _templateSource = (ITemplateSource) servletContext.getAttribute(name);

            if (_templateSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _templateSource = (ITemplateSource) servletContext.getAttribute(name);

                    if (_templateSource == null)
                    {
                        _templateSource = createTemplateSource(context);

                        servletContext.setAttribute(name, _templateSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_specificationSource == null)
        {
            String name = SPECIFICATION_SOURCE_NAME + ":" + servletName;

            _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);

            if (_specificationSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);

                    if (_specificationSource == null)
                    {
                        _specificationSource = createSpecificationSource(context);

                        servletContext.setAttribute(name, _specificationSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_pageSource == null)
        {
            String name = PAGE_SOURCE_NAME + ":" + servletName;

            _pageSource = (IPageSource) servletContext.getAttribute(name);

            if (_pageSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _pageSource = (IPageSource) servletContext.getAttribute(name);

                    if (_pageSource == null)
                    {
                        _pageSource = createPageSource(context);

                        servletContext.setAttribute(name, _pageSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_scriptSource == null)
        {
            String name = SCRIPT_SOURCE_NAME + ":" + servletName;

            _scriptSource = (IScriptSource) servletContext.getAttribute(name);

            if (_scriptSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _scriptSource = (IScriptSource) servletContext.getAttribute(name);

                    if (_scriptSource == null)
                    {
                        _scriptSource = createScriptSource(context);

                        servletContext.setAttribute(name, _scriptSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_serviceMap == null)
        {
            String name = SERVICE_MAP_NAME + ":" + servletName;

            _serviceMap = (Map) servletContext.getAttribute(name);

            if (_serviceMap == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _serviceMap = (Map) servletContext.getAttribute(name);

                    if (_serviceMap == null)
                    {
                        _serviceMap = createServiceMap();

                        servletContext.setAttribute(name, _serviceMap);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_stringsSource == null)
        {
            String name = STRINGS_SOURCE_NAME + ":" + servletName;

            _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);

            if (_stringsSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);

                    if (_stringsSource == null)
                    {
                        _stringsSource = createComponentStringsSource(context);

                        servletContext.setAttribute(name, _stringsSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_dataSqueezer == null)
        {
            String name = DATA_SQUEEZER_NAME + ":" + servletName;

            _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);

            if (_dataSqueezer == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);

                    if (_dataSqueezer == null)
                    {
                        _dataSqueezer = createDataSqueezer();

                        servletContext.setAttribute(name, _dataSqueezer);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_global == null)
        {
            String name = GLOBAL_NAME + ":" + servletName;

            _global = servletContext.getAttribute(name);

            if (_global == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _global = servletContext.getAttribute(name);

                    if (_global == null)
                    {
                        _global = createGlobal(context);

                        servletContext.setAttribute(name, _global);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        if (_resourceChecksumSource == null)
        {
            String name = RESOURCE_CHECKSUM_SOURCE_NAME + ":" + servletName;

            _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);

            if (_resourceChecksumSource == null)
            {
                try
                {
                    context.getServlet().getLock().lock();

                    _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);

                    if (_resourceChecksumSource == null)
                    {
                        _resourceChecksumSource = createResourceChecksumSource();

                        servletContext.setAttribute(name, _resourceChecksumSource);
                    }
                } finally
                {
                    context.getServlet().getLock().unlock();
                }
            }
        }

        String encoding = request.getCharacterEncoding();
        if (encoding == null)
        {
            encoding = getOutputEncoding();
            try
            {
                request.setCharacterEncoding(encoding);
            }
            catch (UnsupportedEncodingException e)
            {
                throw new IllegalArgumentException(Tapestry.format("illegal-encoding", encoding));
            }
            catch (NoSuchMethodError e)
            {
                // Servlet API 2.2 compatibility
                // Behave okay if the setCharacterEncoding() method is unavailable
            }
            catch (AbstractMethodError e)
            {
                // Servlet API 2.2 compatibility
                // Behave okay if the setCharacterEncoding() method is unavailable
            }
        }
    }

    /**
     *
     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
     *  a new instance of {@link IComponentMessagesSource}.
     *
     *  @return an instance of {@link DefaultComponentMessagesSource}
     *  @since 2.0.4
     *
     **/

    public IComponentMessagesSource createComponentStringsSource(RequestContext context)
    {
        return new DefaultComponentMessagesSource();
    }

    /**
     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
     *  an instance of {@link IScriptSource} that will be stored into
     *  the {@link ServletContext}.  Subclasses may override this method
     *  to provide a different implementation.
     *
     *
     *  @return an instance of {@link DefaultScriptSource}
     *  @since 1.0.9
     *
     **/

    protected IScriptSource createScriptSource(RequestContext context)
    {
        return new DefaultScriptSource(getResourceResolver());
    }

    /**
     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
     *  an instance of {@link IPageSource} that will be stored into
     *  the {@link ServletContext}.  Subclasses may override this method
     *  to provide a different implementation.
     *
     *  @return an instance of {@link PageSource}
     *  @since 1.0.9
     *
     **/

    protected IPageSource createPageSource(RequestContext context)
    {
        return new PageSource(this);
    }

    /**
     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
     *  an instance of {@link ISpecificationSource} that will be stored into
     *  the {@link ServletContext}.  Subclasses may override this method
     *  to provide a different implementation.
     *
     *  @return an instance of {@link DefaultSpecificationSource}
     *  @since 1.0.9
     **/

    protected ISpecificationSource createSpecificationSource(RequestContext context)
    {
        return new DefaultSpecificationSource(getResourceResolver(), _specification, _pool);
    }

    /**
     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
     *  an instance of {@link ITemplateSource} that will be stored into
     *  the {@link ServletContext}.  Subclasses may override this method
     *  to provide a different implementation.
     *
     *  @return an instance of {@link DefaultTemplateSource}
     *  @since 1.0.9
     *
     **/

    protected ITemplateSource createTemplateSource(RequestContext context)
    {
        return new DefaultTemplateSource();
    }

    /**
     * Invoked from {@link #setupForRequest(RequestContext)} to provide
     * an instance of {@link ResourceChecksumSource} that will be stored into
     * the {@link ServletContext}.  Subclasses may override this method
     * to provide a different implementation.
     * @return an instance of {@link ResourceChecksumSourceImpl} that uses MD5 and Hex encoding.
     * @since 3.0.3
     */
    protected ResourceChecksumSource createResourceChecksumSource()
    {
        return new ResourceChecksumSourceImpl("MD5", new Hex());
    }

    /**
     *  Returns an object which can find resources and classes.
     *
     **/

    public IResourceResolver getResourceResolver()
    {
        return _resolver;
    }

    /**
     *  Generates a description of the instance.
     *  Invokes {@link #extendDescription(ToStringBuilder)}
     *  to fill in details about the instance.
     *
     *  @see #extendDescription(ToStringBuilder)
     *
     **/

    public String toString()
    {
        ToStringBuilder builder = new ToStringBuilder(this);

        builder.append(
                "name",
                _specification == null
                        ? Tapestry.getMessage("AbstractEngine.unknown-specification")
                        : _specification.getName());

        builder.append("dirty", _dirty);
        builder.append("locale", _locale);
        builder.append("stateful", _stateful);
        builder.append("visit", _visit);

        extendDescription(builder);

        return builder.toString();
    }

    /**
     *  Returns true if the reset service is curently enabled.
     *
     **/

    public boolean isResetServiceEnabled()
    {
        return _resetServiceEnabled;
    }

    /**
     *  Implemented by subclasses to return the names of the active pages
     *  (pages for which recorders exist).  May return the empty list,
     *  but should not return null.
     *
     **/

    abstract public Collection getActivePageNames();

    /**
     *  Gets the visit object, if it has been created already.
     *
     *  <p>
     *  If the visit is non-null then
     *  the {@link #isDirty()} flag is set (because
     *  the engine can't tell what the caller will
     *  <i>do</i> with the visit).
     *
     **/

    public Object getVisit()
    {
        if (_visit != null)
            markDirty();

        return _visit;
    }

    /**
     *  Gets the visit object, invoking {@link #createVisit(IRequestCycle)} to create
     *  it lazily if needed.  If cycle is null, the visit will not be lazily created.
     *
     *  <p>
     *  After creating the visit, but before returning,
     *  the {@link HttpSession} will be created, and
     *  {@link #setStateful()} will be invoked.
     *
     *  <p>
     *  Sets the {@link #isDirty()} flag, if the return value
     *  is not null.
     *
     *
     **/

    public Object getVisit(IRequestCycle cycle)
    {
        if (_visit == null && cycle != null)
        {
            _visit = createVisit(cycle);

            // Now that a visit object exists, we need to force the creation
            // of a HttpSession.

            cycle.getRequestContext().createSession();

            setStateful();
        }

        if (_visit != null)
            markDirty();

        return _visit;
    }

    /**
     *  Updates the visit object and
     *  sets the {@link #isDirty() dirty flag}.
     *
     **/

    public void setVisit(Object value)
    {
        _visit = value;

        markDirty();
    }

    public boolean getHasVisit()
    {
        return _visit != null;
    }

    /**
     *  Invoked to lazily create a new visit object when it is first
     *  referenced (by {@link #getVisit(IRequestCycle)}).  This implementation works
     *  by looking up the name of the class to instantiate
     *  in the {@link #getPropertySource() configuration}.
     *
     *  <p>Subclasses may want to overide this method if some other means
     *  of instantiating a visit object is required.
     **/

    protected Object createVisit(IRequestCycle cycle)
    {
        String visitClassName;
        Class visitClass;
        Object result = null;

        visitClassName = _propertySource.getPropertyValue(VISIT_CLASS_PROPERTY_NAME);

        if (LOG.isDebugEnabled())
            LOG.debug("Creating visit object as instance of " + visitClassName);

        visitClass = _resolver.findClass(visitClassName);

        try
        {
            result = visitClass.newInstance();
        }
        catch (Throwable t)
        {
            throw new ApplicationRuntimeException(
                    Tapestry.format("AbstractEngine.unable-to-instantiate-visit", visitClassName),
                    t);
        }

        return result;
    }

    /**
     *  Returns the global object for the application.  The global object is created at the start
     *  of the request ({@link #setupForRequest(RequestContext)} invokes
     *  {@link #createGlobal(RequestContext)} if needed),
     *  and is stored into the {@link ServletContext}.  All instances of the engine for
     *  the application share
     *  the global object; however, the global object is explicitly <em>not</em>
     *  replicated to other servers within
     *  a cluster.
     *
     *  @since 2.3
     *
     **/

    public Object getGlobal()
    {
        return _global;
    }

    public IScriptSource getScriptSource()
    {
        return _scriptSource;
    }

    public boolean isStateful()
    {
        return _stateful;
    }

    /**
     *  Invoked by subclasses to indicate that some state must now be stored
     *  in the engine (and that the engine should now be stored in the
     *  HttpSession).  The caller is responsible for actually creating
     *  the HttpSession (it will have access to the {@link RequestContext}).
     *
     *  @since 1.0.2
     *
     **/

    protected void setStateful()
    {
        _stateful = true;
    }

    /**
     *  Allows subclasses to include listener methods easily.
     *
     * @since 1.0.2
     **/

    public ListenerMap getListeners()
    {
        if (_listeners == null)
            _listeners = new ListenerMap(this);

        return _listeners;
    }

    private static class RedirectAnalyzer
    {
        private boolean _internal;
        private String _location;

        private RedirectAnalyzer(String location)
        {
            if (Tapestry.isBlank(location))
            {
                _location = "";
                _internal = true;

                return;
            }

            _location = location;

            _internal = !(location.startsWith("/") || location.indexOf("://") > 0);
        }

        public void process(IRequestCycle cycle)
        {
            RequestContext context = cycle.getRequestContext();

            if (_internal)
                forward(context);
            else
                redirect(context);
        }

        private void forward(RequestContext context)
        {
            HttpServletRequest request = context.getRequest();
            HttpServletResponse response = context.getResponse();

            RequestDispatcher dispatcher = request.getRequestDispatcher("/" + _location);

            if (dispatcher == null)
                throw new ApplicationRuntimeException(
                        Tapestry.format("AbstractEngine.unable-to-find-dispatcher", _location));

            try
            {
                dispatcher.forward(request, response);
            }
            catch (ServletException ex)
            {
                throw new ApplicationRuntimeException(
                        Tapestry.format("AbstractEngine.unable-to-forward", _location),
                        ex);
            }
            catch (IOException ex)
            {
                throw new ApplicationRuntimeException(
                        Tapestry.format("AbstractEngine.unable-to-forward", _location),
                        ex);
            }
        }

        private void redirect(RequestContext context)
        {
            HttpServletResponse response = context.getResponse();

            String finalURL = response.encodeRedirectURL(_location);

            try
            {
                response.sendRedirect(finalURL);
            }
            catch (IOException ex)
            {
                throw new ApplicationRuntimeException(
                        Tapestry.format("AbstractEngine.unable-to-redirect", _location),
                        ex);
            }
        }

    }

    /**
     *  Invoked when a {@link RedirectException} is thrown during the processing of a request.
     *
     *  @throws ApplicationRuntimeException if an {@link IOException},
     *  {@link ServletException} is thrown by the redirect, or if no
     *  {@link RequestDispatcher} can be found for local resource.
     *
     *  @since 2.2
     *
     **/

    protected void handleRedirectException(IRequestCycle cycle, RedirectException ex)
    {
        String location = ex.getRedirectLocation();

        if (LOG.isDebugEnabled())
            LOG.debug("Redirecting to: " + location);

        RedirectAnalyzer analyzer = new RedirectAnalyzer(location);

        analyzer.process(cycle);
    }

    /**
     *  Creates a Map of all the services available to the application.
     *
     *  <p>Note: the Map returned is not synchronized, on the theory that returned
     *  map is not further modified and therefore threadsafe.
     *
     **/

    private Map createServiceMap()
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Creating service map.");

        ISpecificationSource source = getSpecificationSource();

        // Build the initial version of the result map,
        // where each value is the *name* of a class.

        Map result = new HashMap();

        // Do the framework first.

        addServices(source.getFrameworkNamespace(), result);

        // And allow the application to override the framework.

        addServices(source.getApplicationNamespace(), result);

        IResourceResolver resolver = getResourceResolver();

        Iterator i = result.entrySet().iterator();

        while (i.hasNext())
        {
            Map.Entry entry = (Map.Entry) i.next();

            String name = (String) entry.getKey();
            String className = (String) entry.getValue();

            if (LOG.isDebugEnabled())
                LOG.debug("Creating service " + name + " as instance of " + className);

            Class serviceClass = resolver.findClass(className);

            try
            {
                IEngineService service = (IEngineService) serviceClass.newInstance();
                String serviceName = service.getName();

                if (!service.getName().equals(name))
                    throw new ApplicationRuntimeException(
                            Tapestry.format(
                                    "AbstractEngine.service-name-mismatch",
                                    name,
                                    className,
                                    serviceName));

                // Replace the class name with an instance
                // of the named class.

                entry.setValue(service);
            }
            catch (InstantiationException ex)
            {
                String message =
                        Tapestry.format(
                                "AbstractEngine.unable-to-instantiate-service",
                                name,
                                className);

                LOG.error(message, ex);

                throw new ApplicationRuntimeException(message, ex);
            }
            catch (IllegalAccessException ex)
            {
                String message =
                        Tapestry.format(
                                "AbstractEngine.unable-to-instantiate-service",
                                name,
                                className);

                LOG.error(message, ex);

                throw new ApplicationRuntimeException(message, ex);
            }
        }

        // Result should not be modified after this point, for threadsafety issues.
        // We could wrap it in an unmodifiable, but for efficiency we don't.

        return result;
    }

    /**
     *  Locates all services in the namespace and adds key/value
     *  pairs to the map (name and class name).  Then recursively
     *  descendends into child namespaces to collect more
     *  service names.
     *
     *  @since 2.2
     *
     **/

    private void addServices(INamespace namespace, Map map)
    {
        List names = namespace.getServiceNames();
        int count = names.size();

        for (int i = 0; i < count; i++)
        {
            String name = (String) names.get(i);

            map.put(name, namespace.getServiceClassName(name));
        }

        List namespaceIds = namespace.getChildIds();
        count = namespaceIds.size();

        for (int i = 0; i < count; i++)
        {
            String id = (String) namespaceIds.get(i);

            addServices(namespace.getChildNamespace(id), map);
        }
    }

    /**
     *  @since 2.0.4
     *
     **/

    public IComponentMessagesSource getComponentMessagesSource()
    {
        return _stringsSource;
    }

    /**
     *  @since 2.2
     *
     **/

    public DataSqueezer getDataSqueezer()
    {
        return _dataSqueezer;
    }

    /**
     *
     *  Invoked from {@link #setupForRequest(RequestContext)} to create
     *  a {@link DataSqueezer} when needed (typically, just the very first time).
     *  This implementation returns a standard, new instance.
     *
     *  @since 2.2
     *
     **/

    public DataSqueezer createDataSqueezer()
    {
        return new DataSqueezer(_resolver);
    }

    /**
     *  Invoked from {@link #service(RequestContext)} to extract, from the URL,
     *  the name of the service.  The current implementation expects the first
     *  pathInfo element to be the service name.  At some point in the future,
     *  the method of constructing and parsing URLs may be abstracted into
     *  a developer-selected class.
     *
     *  <p>Subclasses may override this method if the application defines
     *  specific services with unusual URL encoding rules.
     *
     *  <p>This implementation simply extracts the value for
     *  query parameter {@link Tapestry#SERVICE_QUERY_PARAMETER_NAME}
     *  and extracts the service name from that.
     *
     *  <p>
     *  For supporting the JSP tags, this method first
     *  checks for attribute {@link Tapestry#TAG_SUPPORT_SERVICE_ATTRIBUTE}.  If non-null,
     *  then {@link Tapestry#TAGSUPPORT_SERVICE} is returned.
     *
     *  @since 2.2
     *
     **/

    protected String extractServiceName(RequestContext context)
    {
        if (context.getRequest().getAttribute(Tapestry.TAG_SUPPORT_SERVICE_ATTRIBUTE) != null)
            return Tapestry.TAGSUPPORT_SERVICE;

        String serviceData = context.getParameter(Tapestry.SERVICE_QUERY_PARAMETER_NAME);

        if (serviceData == null)
            return Tapestry.HOME_SERVICE;

        // The service name is anything before the first slash,
        // if there is one.

        int slashx = serviceData.indexOf('/');

        if (slashx < 0)
            return serviceData;

        return serviceData.substring(0, slashx);
    }

    /** @since 2.3 **/

    public IPropertySource getPropertySource()
    {
        return _propertySource;
    }

    /** @since 3.0.3 */

    public ResourceChecksumSource getResourceChecksumSource()
    {
        return _resourceChecksumSource;
    }

    /** @since 3.0 **/

    protected String getExceptionPageName()
    {
        return EXCEPTION_PAGE;
    }

    /** @since 3.0 **/

    protected String getStaleLinkPageName()
    {
        return STALE_LINK_PAGE;
    }

    /** @since 3.0 **/

    protected String getStaleSessionPageName()
    {
        return STALE_SESSION_PAGE;
    }

    /**
     *  Name of an application extension that can provide configuration properties.
     *
     *  @see #createPropertySource(RequestContext)
     *  @since 2.3
     *
     **/

    private static final String EXTENSION_PROPERTY_SOURCE_NAME =
            "org.apache.tapestry.property-source";

    /**
     *  Creates a shared property source that will be stored into
     *  the servlet context.
     *  Subclasses may override this method to build thier
     *  own search path.
     *
     *  <p>If the application specification contains an extension
     *  named "org.apache.tapestry.property-source" it is inserted
     *  in the search path just before
     *  the property source for JVM System Properties.  This is a simple
     *  hook at allow application-specific methods of obtaining
     *  configuration values (typically, from a database or from JMX,
     *  in some way).  Alternately, subclasses may
     *  override this method to provide whatever search path
     *  is appropriate.
     *
     *
     *  @since 2.3
     *
     **/

    protected IPropertySource createPropertySource(RequestContext context)
    {
        DelegatingPropertySource result = new DelegatingPropertySource();

        ApplicationServlet servlet = context.getServlet();
        IApplicationSpecification spec = servlet.getApplicationSpecification();

        result.addSource(new PropertyHolderPropertySource(spec));
        result.addSource(new ServletPropertySource(servlet.getServletConfig()));
        result.addSource(new ServletContextPropertySource(servlet.getServletContext()));

        if (spec.checkExtension(EXTENSION_PROPERTY_SOURCE_NAME))
        {
            IPropertySource source =
                    (IPropertySource) spec.getExtension(
                            EXTENSION_PROPERTY_SOURCE_NAME,
                            IPropertySource.class);

            result.addSource(source);
        }

        result.addSource(SystemPropertiesPropertySource.getInstance());

        // Lastly, add a final source to handle "factory defaults".

        ResourceBundle bundle =
                ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");

        result.addSource(new ResourceBundlePropertySource(bundle));

        return result;
    }

    /**
     *  Creates the shared Global object.  This implementation looks for an configuration
     *  property, <code>org.apache.tapestry.global-class</code>, and instantiates that class
     *  using a no-arguments
     *  constructor.  If the property is not defined, a synchronized
     *  {@link java.util.HashMap} is created.
     *
     *  @since 2.3
     *
     **/

    protected Object createGlobal(RequestContext context)
    {
        String className = _propertySource.getPropertyValue("org.apache.tapestry.global-class");

        if (className == null)
            return Collections.synchronizedMap(new HashMap());

        Class globalClass = _resolver.findClass(className);

        try
        {
            return globalClass.newInstance();
        }
        catch (Exception ex)
        {
            throw new ApplicationRuntimeException(
                    Tapestry.format("AbstractEngine.unable-to-instantiate-global", className),
                    ex);
        }
    }

    /**
     *  Returns an new instance of {@link Pool}, with the standard
     *  set of adaptors, plus {@link BSFManagerPoolableAdaptor} for
     *  {@link BSFManager}.
     *
     *  <p>Subclasses may override this
     *  method to configure the Pool differently.
     *
     *  @since 3.0
     *
     **/

    protected Pool createPool(RequestContext context)
    {
        Pool result = new Pool();

        result.registerAdaptor(BSFManager.class, new BSFManagerPoolableAdaptor());

        return result;
    }

    /** @since 3.0 **/

    public Pool getPool()
    {
        return _pool;
    }

    /**
     *
     * Invoked from {@link #setupForRequest(RequestContext)}.  Creates
     * a new instance of {@link DefaultComponentClassEnhancer}.  Subclasses
     * may override to return a different object.
     *
     * <p>
     * Check the property <code>org.apache.tapestry.enhance.disable-abstract-method-validation</code>
     * and, if true, disables abstract method validation. This is used  in some
     * errant JDK's (such as IBM's 1.3.1) that incorrectly report concrete methods from
     * abstract classes as abstract.
     *
     * @since 3.0
     */

    protected IComponentClassEnhancer createComponentClassEnhancer(RequestContext context)
    {
        boolean disableValidation =
                "true".equals(
                        _propertySource.getPropertyValue(
                                "org.apache.tapestry.enhance.disable-abstract-method-validation"));

        return new DefaultComponentClassEnhancer(_resolver, disableValidation);
    }

    /** @since 3.0 **/

    public IComponentClassEnhancer getComponentClassEnhancer()
    {
        return _enhancer;
    }

    /**
     *  Returns true if the engine has (potentially) changed
     *  state since the last time it was stored
     *  into the {@link javax.servlet.http.HttpSession}.  Various
     *  events set this property to true.
     *
     *  @since 3.0
     *
     **/

    public boolean isDirty()
    {
        return _dirty;
    }

    /**
     *  Invoked to set the dirty flag, indicating that the
     *  engine should be stored into the
     *  {@link javax.servlet.http.HttpSession}.
     *
     *
     *  @since 3.0
     *
     **/

    protected void markDirty()
    {
        if (!_dirty)
            LOG.debug("Setting dirty flag.");

        _dirty = true;
    }

    /**
     *
     *  Clears the dirty flag when a engine is stored into the
     *  {@link HttpSession}.
     *
     *
     *  @since 3.0
     *
     **/

    public void valueBound(HttpSessionBindingEvent arg0)
    {
        LOG.debug(_dirty ? "Clearing dirty flag." : "Dirty flag already cleared.");

        _dirty = false;
    }

    /**
     *  Does nothing.
     *
     *  @since 3.0
     *
     **/

    public void valueUnbound(HttpSessionBindingEvent arg0)
    {
    }

    /**
     *
     *  The encoding to be used if none has been defined using the output encoding property.
     *  Override this method to change the default.
     *
     *  @return the default output encoding
     *  @since 3.0
     *
     **/
    protected String getDefaultOutputEncoding()
    {
        return DEFAULT_OUTPUT_ENCODING;
    }

    /**
     *
     *  Returns the encoding to be used to generate the servlet responses and
     *  accept the servlet requests.
     *
     *  The encoding is defined using the org.apache.tapestry.output-encoding
     *  and is UTF-8 by default
     *
     *  @since 3.0
     *  @see org.apache.tapestry.IEngine#getOutputEncoding()
     *
     **/
    public String getOutputEncoding()
    {
        IPropertySource source = getPropertySource();

        String encoding = source.getPropertyValue(OUTPUT_ENCODING_PROPERTY_NAME);
        if (encoding == null)
            encoding = getDefaultOutputEncoding();

        return encoding;
    }

}
