/* $$ Clover has instrumented this file $$ */// 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 java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
import org.apache.tapestry.ApplicationServlet;
import org.apache.tapestry.Constants;
import org.apache.tapestry.IEngine;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.INamespace;
import org.apache.tapestry.IPage;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.PageRedirectException;
import org.apache.tapestry.RedirectException;
import org.apache.tapestry.StaleLinkException;
import org.apache.tapestry.StaleSessionException;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.listener.ListenerMap;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.request.ResponseOutputStream;
import org.apache.tapestry.services.ComponentMessagesSource;
import org.apache.tapestry.services.DataSqueezer;
import org.apache.tapestry.services.Infrastructure;
import org.apache.tapestry.services.ObjectPool;
import org.apache.tapestry.services.TemplateSource;
import org.apache.tapestry.services.impl.ComponentMessagesSourceImpl;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.exception.ExceptionAnalyzer;
import org.apache.tapestry.util.io.DataSqueezerImpl;
import com.sun.jndi.ldap.pool.Pool;
/**
* Basis for building real Tapestry applications. Immediate subclasses provide different strategies
* for managing page state and other resources between request cycles.
* <p>
* Note: much of this description is <em>in transition</em> as part of Tapestry 3.1. All ad-hoc
* singletons and such are being replaced with HiveMind services.
* <p>
* 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 engine 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
*/
public abstract class AbstractEngine implements IEngine, IEngineServiceView, Externalizable,
HttpSessionBindingListener
{public static com.cortexeb.tools.clover.d __CLOVER_71_0 = com.cortexeb.tools.clover.aq.getRecorder(new char[] {67,58,92,119,111,114,107,115,112,97,99,101,92,106,97,107,97,114,116,97,45,116,97,112,101,115,116,114,121,92,102,114,97,109,101,119,111,114,107,92,116,97,114,103,101,116,92,99,108,111,118,101,114,45,100,98},1096998272901L);
private static final Log LOG = LogFactory.getLog(AbstractEngine.class);
/**
* @since 2.0.4
*/
private static final long serialVersionUID = 6884834397673817117L;
/**
* The link to the world of HiveMind services.
*
* @since 3.1
*/
private transient Infrastructure _infrastructure;
private transient String _contextPath;
private transient String _servletPath;
private transient String _clientAddress;
private transient String _sessionId;
private transient boolean _stateful;
private transient ListenerMap _listeners;
/**
* 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 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";
/**
* 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");
/**
* 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;
/**
* 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 { __CLOVER_71_0.M[373]++;
__CLOVER_71_0.S[1540]++;try
{
__CLOVER_71_0.S[1541]++;IPage exceptionPage = cycle.getPage(getExceptionPageName());
__CLOVER_71_0.S[1542]++;exceptionPage.setProperty("exception", cause);
__CLOVER_71_0.S[1543]++;cycle.activate(exceptionPage);
__CLOVER_71_0.S[1544]++;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.
__CLOVER_71_0.S[1545]++;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.
__CLOVER_71_0.S[1546]++;reportException(
Tapestry.getMessage("AbstractEngine.unable-to-present-exception-page"),
ex);
// And throw the exception.
__CLOVER_71_0.S[1547]++;throw new ServletException(ex.getMessage(), ex);
}
} finally { }}
/**
* Writes a detailed report of the exception to <code>System.err</code>.
*/
public void reportException(String reportTitle, Throwable ex)
{try { __CLOVER_71_0.M[374]++;
__CLOVER_71_0.S[1548]++;LOG.warn(reportTitle, ex);
__CLOVER_71_0.S[1549]++;System.err.println("\n\n**********************************************************\n\n");
__CLOVER_71_0.S[1550]++;System.err.println(reportTitle);
__CLOVER_71_0.S[1551]++;System.err.println("\n\n Session id: " + _sessionId + "\n Client address: "
+ _clientAddress + "\n\nExceptions:\n");
__CLOVER_71_0.S[1552]++;new ExceptionAnalyzer().reportException(ex, System.err);
__CLOVER_71_0.S[1553]++;System.err.println("\n**********************************************************\n");
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[375]++;
} finally { }}
/**
* Returns the locale for the engine. This is initially set by the {@link ApplicationServlet}
* but may be updated by the application.
*/
public Locale getLocale()
{try { __CLOVER_71_0.M[376]++;
__CLOVER_71_0.S[1554]++;return _locale;
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[377]++;
__CLOVER_71_0.S[1555]++;if ((((_monitorFactory == null) && (++__CLOVER_71_0.CT[297] != 0)) || (++__CLOVER_71_0.CF[297] == 0))){
{
__CLOVER_71_0.S[1556]++;IApplicationSpecification spec = getSpecification();
__CLOVER_71_0.S[1557]++;if ((((spec.checkExtension(Tapestry.MONITOR_FACTORY_EXTENSION_NAME)) && (++__CLOVER_71_0.CT[298] != 0)) || (++__CLOVER_71_0.CF[298] == 0))){
__CLOVER_71_0.S[1558]++;_monitorFactory = (IMonitorFactory) spec.getExtension(
Tapestry.MONITOR_FACTORY_EXTENSION_NAME,
IMonitorFactory.class);}
else{
__CLOVER_71_0.S[1559]++;_monitorFactory = DefaultMonitorFactory.SHARED;}
}}
__CLOVER_71_0.S[1560]++;return _monitorFactory.createMonitor(context);
} finally { }}
/** @see Infrastructure#getPageSource() */
public IPageSource getPageSource()
{try { __CLOVER_71_0.M[378]++;
__CLOVER_71_0.S[1561]++;return _infrastructure.getPageSource();
} finally { }}
/**
* Returns a service with the given name.
*
* @see Infrastructure#getServiceMap()
* @see org.apache.tapestry.services.ServiceMap
*/
public IEngineService getService(String name)
{try { __CLOVER_71_0.M[379]++;
__CLOVER_71_0.S[1562]++;return _infrastructure.getServiceMap().getService(name);
} finally { }}
public String getServletPath()
{try { __CLOVER_71_0.M[380]++;
__CLOVER_71_0.S[1563]++;return _servletPath;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[381]++;
__CLOVER_71_0.S[1564]++;return _contextPath;
} finally { }}
/** @see Infrastructure#getApplicationSpecification() */
public IApplicationSpecification getSpecification()
{try { __CLOVER_71_0.M[382]++;
__CLOVER_71_0.S[1565]++;return _infrastructure.getApplicationSpecification();
} finally { }}
/** @see Infrastructure#getSpecificationSource() */
public ISpecificationSource getSpecificationSource()
{try { __CLOVER_71_0.M[383]++;
__CLOVER_71_0.S[1566]++;return _infrastructure.getSpecificationSource();
} finally { }}
/** @see Infrastructure#getTemplateSource() */
public TemplateSource getTemplateSource()
{try { __CLOVER_71_0.M[384]++;
__CLOVER_71_0.S[1567]++;return _infrastructure.getTemplateSource();
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[385]++;
__CLOVER_71_0.S[1568]++;_stateful = true;
__CLOVER_71_0.S[1569]++;String localeName = in.readUTF();
__CLOVER_71_0.S[1570]++;_locale = Tapestry.getLocale(localeName);
__CLOVER_71_0.S[1571]++;_visit = in.readObject();
} finally { }}
/**
* Writes the following properties:
* <ul>
* <li>locale name ({@link Locale#toString()})
* <li>visit
* </ul>
*/
public void writeExternal(ObjectOutput out) throws IOException
{try { __CLOVER_71_0.M[386]++;
__CLOVER_71_0.S[1572]++;out.writeUTF(_locale.toString());
__CLOVER_71_0.S[1573]++;out.writeObject(_visit);
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[387]++;
// Discard any output from the previous page.
__CLOVER_71_0.S[1574]++;out.reset();
__CLOVER_71_0.S[1575]++;IPage page = cycle.getPage(pageName);
__CLOVER_71_0.S[1576]++;cycle.activate(page);
__CLOVER_71_0.S[1577]++;renderResponse(cycle, out);
} finally { }}
public void renderResponse(IRequestCycle cycle, ResponseOutputStream output)
throws ServletException, IOException
{try { __CLOVER_71_0.M[388]++;
__CLOVER_71_0.S[1578]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[299] != 0)) || (++__CLOVER_71_0.CF[299] == 0))){
__CLOVER_71_0.S[1579]++;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.
__CLOVER_71_0.S[1580]++;if ((((_localeChanged) && (++__CLOVER_71_0.CT[300] != 0)) || (++__CLOVER_71_0.CF[300] == 0))){
{
__CLOVER_71_0.S[1581]++;_localeChanged = false;
__CLOVER_71_0.S[1582]++;RequestContext context = cycle.getRequestContext();
__CLOVER_71_0.S[1583]++;ApplicationServlet.writeLocaleCookie(_locale, this, context);
}}
// Commit all changes and ignore further changes.
__CLOVER_71_0.S[1584]++;IPage page = cycle.getPage();
__CLOVER_71_0.S[1585]++;IMarkupWriter writer = page.getResponseWriter(output);
__CLOVER_71_0.S[1586]++;output.setContentType(writer.getContentType());
__CLOVER_71_0.S[1587]++;boolean discard = true;
__CLOVER_71_0.S[1588]++;try
{
__CLOVER_71_0.S[1589]++;cycle.renderPage(writer);
__CLOVER_71_0.S[1590]++;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.
__CLOVER_71_0.S[1591]++;if ((((discard) && (++__CLOVER_71_0.CT[301] != 0)) || (++__CLOVER_71_0.CF[301] == 0))){
__CLOVER_71_0.S[1592]++;output.setDiscard(true);}
__CLOVER_71_0.S[1593]++;writer.close();
__CLOVER_71_0.S[1594]++;if ((((discard) && (++__CLOVER_71_0.CT[302] != 0)) || (++__CLOVER_71_0.CF[302] == 0))){
__CLOVER_71_0.S[1595]++;output.setDiscard(false);}
}
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[389]++;
__CLOVER_71_0.S[1596]++;RequestContext context = cycle.getRequestContext();
__CLOVER_71_0.S[1597]++;HttpSession session = context.getSession();
__CLOVER_71_0.S[1598]++;if ((((session != null) && (++__CLOVER_71_0.CT[303] != 0)) || (++__CLOVER_71_0.CF[303] == 0))){
{
__CLOVER_71_0.S[1599]++;try
{
__CLOVER_71_0.S[1600]++;session.invalidate();
}
catch (IllegalStateException ex)
{
__CLOVER_71_0.S[1601]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[304] != 0)) || (++__CLOVER_71_0.CF[304] == 0))){
__CLOVER_71_0.S[1602]++;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.
__CLOVER_71_0.S[1603]++;_stateful = false;
__CLOVER_71_0.S[1604]++;String url = context.getAbsoluteURL(_servletPath);
__CLOVER_71_0.S[1605]++;context.redirect(url);
} finally { }}
/**
* Delegate method for the servlet. Services the request.
*/
public boolean service(RequestContext context) throws ServletException, IOException
{try { __CLOVER_71_0.M[390]++;
__CLOVER_71_0.S[1606]++;IRequestCycle cycle = null;
__CLOVER_71_0.S[1607]++;ResponseOutputStream output = null;
__CLOVER_71_0.S[1608]++;IMonitor monitor = null;
__CLOVER_71_0.S[1609]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[305] != 0)) || (++__CLOVER_71_0.CF[305] == 0))){
__CLOVER_71_0.S[1610]++;LOG.debug("Begin service " + context.getRequestURI());}
__CLOVER_71_0.S[1611]++;if ((((_infrastructure == null) && (++__CLOVER_71_0.CT[306] != 0)) || (++__CLOVER_71_0.CF[306] == 0))){
__CLOVER_71_0.S[1612]++;_infrastructure = (Infrastructure) context.getAttribute(Constants.INFRASTRUCTURE_KEY);}
// The servlet invokes setLocale() before invoking service(). We want
// to ignore that setLocale() ... that is, not force a cookie to be
// written.
__CLOVER_71_0.S[1613]++;_localeChanged = false;
__CLOVER_71_0.S[1614]++;try
{
__CLOVER_71_0.S[1615]++;setupForRequest(context);
__CLOVER_71_0.S[1616]++;monitor = getMonitor(context);
__CLOVER_71_0.S[1617]++;output = new ResponseOutputStream(context.getResponse());
}
catch (Exception ex)
{
__CLOVER_71_0.S[1618]++;reportException(Tapestry.getMessage("AbstractEngine.unable-to-begin-request"), ex);
__CLOVER_71_0.S[1619]++;throw new ServletException(ex.getMessage(), ex);
}
__CLOVER_71_0.S[1620]++;IEngineService service = null;
__CLOVER_71_0.S[1621]++;try
{
__CLOVER_71_0.S[1622]++;try
{
__CLOVER_71_0.S[1623]++;String serviceName;
__CLOVER_71_0.S[1624]++;try
{
__CLOVER_71_0.S[1625]++;serviceName = extractServiceName(context);
__CLOVER_71_0.S[1626]++;if ((((Tapestry.isBlank(serviceName)) && (++__CLOVER_71_0.CT[307] != 0)) || (++__CLOVER_71_0.CF[307] == 0))){
__CLOVER_71_0.S[1627]++;serviceName = Tapestry.HOME_SERVICE;}
// Must have a service to create the request cycle.
// Must have a request cycle to report an exception.
__CLOVER_71_0.S[1628]++;service = getService(serviceName);
}
catch (Exception ex)
{
__CLOVER_71_0.S[1629]++;service = getService(Tapestry.HOME_SERVICE);
__CLOVER_71_0.S[1630]++;cycle = createRequestCycle(context, service, monitor);
__CLOVER_71_0.S[1631]++;throw ex;
}
__CLOVER_71_0.S[1632]++;cycle = createRequestCycle(context, service, monitor);
__CLOVER_71_0.S[1633]++;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).
__CLOVER_71_0.S[1634]++;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.
__CLOVER_71_0.S[1635]++;return _dirty;
}
catch (PageRedirectException ex)
{
__CLOVER_71_0.S[1636]++;handlePageRedirectException(ex, cycle, output);
}
catch (RedirectException ex)
{
__CLOVER_71_0.S[1637]++;handleRedirectException(cycle, ex);
}
catch (StaleLinkException ex)
{
__CLOVER_71_0.S[1638]++;handleStaleLinkException(ex, cycle, output);
}
catch (StaleSessionException ex)
{
__CLOVER_71_0.S[1639]++;handleStaleSessionException(ex, cycle, output);
}
}
catch (Exception ex)
{
__CLOVER_71_0.S[1640]++;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.
__CLOVER_71_0.S[1641]++;output.reset();
__CLOVER_71_0.S[1642]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[308] != 0)) || (++__CLOVER_71_0.CF[308] == 0))){
__CLOVER_71_0.S[1643]++;LOG.debug("Uncaught exception", ex);}
__CLOVER_71_0.S[1644]++;activateExceptionPage(cycle, output, ex);
}
finally
{
__CLOVER_71_0.S[1645]++;if ((((service != null) && (++__CLOVER_71_0.CT[309] != 0)) || (++__CLOVER_71_0.CF[309] == 0))){
__CLOVER_71_0.S[1646]++;monitor.serviceEnd(service.getName());}
__CLOVER_71_0.S[1647]++;try
{
__CLOVER_71_0.S[1648]++;cycle.cleanup();
// Closing the buffered output closes the underlying stream as
// well.
__CLOVER_71_0.S[1649]++;if ((((output != null) && (++__CLOVER_71_0.CT[310] != 0)) || (++__CLOVER_71_0.CF[310] == 0))){
__CLOVER_71_0.S[1650]++;output.forceFlush();}
__CLOVER_71_0.S[1651]++;cleanupAfterRequest(cycle);
}
catch (Exception ex)
{
__CLOVER_71_0.S[1652]++;reportException(Tapestry.getMessage("AbstractEngine.exception-during-cleanup"), ex);
}
__CLOVER_71_0.S[1653]++;if ((((_disableCaching) && (++__CLOVER_71_0.CT[311] != 0)) || (++__CLOVER_71_0.CF[311] == 0))){
{
__CLOVER_71_0.S[1654]++;try
{
__CLOVER_71_0.S[1655]++;clearCachedData();
}
catch (Exception ex)
{
__CLOVER_71_0.S[1656]++;reportException(Tapestry
.getMessage("AbstractEngine.exception-during-cache-clear"), ex);
}
}}
__CLOVER_71_0.S[1657]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[312] != 0)) || (++__CLOVER_71_0.CF[312] == 0))){
__CLOVER_71_0.S[1658]++;LOG.debug("End service");}
}
__CLOVER_71_0.S[1659]++;return _dirty;
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[391]++;
__CLOVER_71_0.S[1660]++;List pageNames = new ArrayList();
__CLOVER_71_0.S[1661]++;String pageName = ex.getTargetPageName();
__CLOVER_71_0.S[1662]++;while (true){
{
__CLOVER_71_0.S[1663]++;if ((((pageNames.contains(pageName)) && (++__CLOVER_71_0.CT[313] != 0)) || (++__CLOVER_71_0.CF[313] == 0))){
{
// Add the offending page to pageNames so it shows in the
// list.
__CLOVER_71_0.S[1664]++;pageNames.add(pageName);
__CLOVER_71_0.S[1665]++;StringBuffer buffer = new StringBuffer();
__CLOVER_71_0.S[1666]++;int count = pageNames.size();
__CLOVER_71_0.S[1667]++;for (int i = 0; (((i < count) && (++__CLOVER_71_0.CT[314] != 0)) || (++__CLOVER_71_0.CF[314] == 0)); i++){
{
__CLOVER_71_0.S[1668]++;if ((((i > 0) && (++__CLOVER_71_0.CT[315] != 0)) || (++__CLOVER_71_0.CF[315] == 0))){
__CLOVER_71_0.S[1669]++;buffer.append("; ");}
__CLOVER_71_0.S[1670]++;buffer.append(pageNames.get(i));
}}
__CLOVER_71_0.S[1671]++;throw new ApplicationRuntimeException(Tapestry.format(
"AbstractEngine.validate-cycle",
buffer.toString()));
}}
// Record that this page has been a target.
__CLOVER_71_0.S[1672]++;pageNames.add(pageName);
__CLOVER_71_0.S[1673]++;try
{
// Attempt to activate the new page.
__CLOVER_71_0.S[1674]++;cycle.activate(pageName);
__CLOVER_71_0.S[1675]++;break;
}
catch (PageRedirectException ex2)
{
__CLOVER_71_0.S[1676]++;pageName = ex2.getTargetPageName();
}
}}
// Discard any output from the previous page.
__CLOVER_71_0.S[1677]++;output.reset();
__CLOVER_71_0.S[1678]++;renderResponse(cycle, output);
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[392]++;
__CLOVER_71_0.S[1679]++;return new RequestCycle(this, context, service, monitor);
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[393]++;
__CLOVER_71_0.S[1680]++;String staleLinkPageName = getStaleLinkPageName();
__CLOVER_71_0.S[1681]++;IPage page = cycle.getPage(staleLinkPageName);
__CLOVER_71_0.S[1682]++;page.setProperty("message", ex.getMessage());
__CLOVER_71_0.S[1683]++;redirect(staleLinkPageName, cycle, output, ex);
} finally { }}
/**
* 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
{try { __CLOVER_71_0.M[394]++;
__CLOVER_71_0.S[1684]++;redirect(getStaleSessionPageName(), cycle, output, ex);
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[395]++;
__CLOVER_71_0.S[1685]++;_infrastructure.getResetEventCoordinator().fireResetEvent();
} finally { }}
/**
* Changes the locale for the engine.
*/
public void setLocale(Locale value)
{try { __CLOVER_71_0.M[396]++;
__CLOVER_71_0.S[1686]++;Tapestry.notNull(value, "locale");
// 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.
__CLOVER_71_0.S[1687]++;if ((((!value.equals(_locale)) && (++__CLOVER_71_0.CT[316] != 0)) || (++__CLOVER_71_0.CF[316] == 0))){
{
__CLOVER_71_0.S[1688]++;_locale = value;
__CLOVER_71_0.S[1689]++;_localeChanged = true;
__CLOVER_71_0.S[1690]++;markDirty();
}}
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[397]++;
__CLOVER_71_0.S[1691]++;HttpServlet servlet = context.getServlet();
__CLOVER_71_0.S[1692]++;ServletContext servletContext = servlet.getServletContext();
__CLOVER_71_0.S[1693]++;HttpServletRequest request = context.getRequest();
__CLOVER_71_0.S[1694]++;HttpSession session = context.getSession();
__CLOVER_71_0.S[1695]++;if ((((session != null) && (++__CLOVER_71_0.CT[317] != 0)) || (++__CLOVER_71_0.CF[317] == 0))){
__CLOVER_71_0.S[1696]++;_sessionId = context.getSession().getId();}
else{
__CLOVER_71_0.S[1697]++;_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.
__CLOVER_71_0.S[1698]++;if ((((_clientAddress == null) && (++__CLOVER_71_0.CT[318] != 0)) || (++__CLOVER_71_0.CF[318] == 0))){
__CLOVER_71_0.S[1699]++;_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.
__CLOVER_71_0.S[1700]++;if ((((_servletPath == null) && (++__CLOVER_71_0.CT[319] != 0)) || (++__CLOVER_71_0.CF[319] == 0))){
{
// 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.
__CLOVER_71_0.S[1701]++;String path = (String) request
.getAttribute(Tapestry.TAG_SUPPORT_SERVLET_PATH_ATTRIBUTE);
__CLOVER_71_0.S[1702]++;if ((((path == null) && (++__CLOVER_71_0.CT[320] != 0)) || (++__CLOVER_71_0.CF[320] == 0))){
__CLOVER_71_0.S[1703]++;path = request.getServletPath();}
// Get the context path, which may be the empty string
// (but won't be null).
__CLOVER_71_0.S[1704]++;_contextPath = request.getContextPath();
__CLOVER_71_0.S[1705]++;_servletPath = _contextPath + path;
}}
__CLOVER_71_0.S[1706]++;String servletName = context.getServlet().getServletName();
__CLOVER_71_0.S[1707]++;if ((((_global == null) && (++__CLOVER_71_0.CT[321] != 0)) || (++__CLOVER_71_0.CF[321] == 0))){
{
__CLOVER_71_0.S[1708]++;String name = GLOBAL_NAME + ":" + servletName;
__CLOVER_71_0.S[1709]++;_global = servletContext.getAttribute(name);
__CLOVER_71_0.S[1710]++;if ((((_global == null) && (++__CLOVER_71_0.CT[322] != 0)) || (++__CLOVER_71_0.CF[322] == 0))){
{
__CLOVER_71_0.S[1711]++;_global = createGlobal(context);
__CLOVER_71_0.S[1712]++;servletContext.setAttribute(name, _global);
}}
}}
__CLOVER_71_0.S[1713]++;String encoding = request.getCharacterEncoding();
__CLOVER_71_0.S[1714]++;if ((((encoding == null) && (++__CLOVER_71_0.CT[323] != 0)) || (++__CLOVER_71_0.CF[323] == 0))){
{
__CLOVER_71_0.S[1715]++;encoding = getOutputEncoding();
__CLOVER_71_0.S[1716]++;try
{
__CLOVER_71_0.S[1717]++;request.setCharacterEncoding(encoding);
}
catch (UnsupportedEncodingException e)
{
__CLOVER_71_0.S[1718]++;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
}
}}
} finally { }}
/**
* @see Infrastructure#getClassResolver()
*/
public ClassResolver getClassResolver()
{try { __CLOVER_71_0.M[398]++;
__CLOVER_71_0.S[1719]++;return _infrastructure.getClassResolver();
} finally { }}
/**
* Generates a description of the instance. Invokes {@link #extendDescription(ToStringBuilder)}
* to fill in details about the instance.
*
* @see #extendDescription(ToStringBuilder)
*/
public String toString()
{try { __CLOVER_71_0.M[399]++;
__CLOVER_71_0.S[1720]++;ToStringBuilder builder = new ToStringBuilder(this);
__CLOVER_71_0.S[1721]++;builder.append("dirty", _dirty);
__CLOVER_71_0.S[1722]++;builder.append("locale", _locale);
__CLOVER_71_0.S[1723]++;builder.append("stateful", _stateful);
__CLOVER_71_0.S[1724]++;builder.append("visit", _visit);
__CLOVER_71_0.S[1725]++;extendDescription(builder);
__CLOVER_71_0.S[1726]++;return builder.toString();
} finally { }}
/**
* Returns true if the reset service is curently enabled.
*/
public boolean isResetServiceEnabled()
{try { __CLOVER_71_0.M[400]++;
__CLOVER_71_0.S[1727]++;return _resetServiceEnabled;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[401]++;
__CLOVER_71_0.S[1728]++;if ((((_visit != null) && (++__CLOVER_71_0.CT[324] != 0)) || (++__CLOVER_71_0.CF[324] == 0))){
__CLOVER_71_0.S[1729]++;markDirty();}
__CLOVER_71_0.S[1730]++;return _visit;
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[402]++;
__CLOVER_71_0.S[1731]++;if ((((_visit == null && cycle != null) && (++__CLOVER_71_0.CT[325] != 0)) || (++__CLOVER_71_0.CF[325] == 0))){
{
__CLOVER_71_0.S[1732]++;_visit = createVisit(cycle);
// Now that a visit object exists, we need to force the creation
// of a HttpSession.
__CLOVER_71_0.S[1733]++;cycle.getRequestContext().createSession();
__CLOVER_71_0.S[1734]++;setStateful();
}}
__CLOVER_71_0.S[1735]++;if ((((_visit != null) && (++__CLOVER_71_0.CT[326] != 0)) || (++__CLOVER_71_0.CF[326] == 0))){
__CLOVER_71_0.S[1736]++;markDirty();}
__CLOVER_71_0.S[1737]++;return _visit;
} finally { }}
/**
* Updates the visit object and sets the {@link #isDirty() dirty flag}.
*/
public void setVisit(Object value)
{try { __CLOVER_71_0.M[403]++;
__CLOVER_71_0.S[1738]++;_visit = value;
__CLOVER_71_0.S[1739]++;markDirty();
} finally { }}
public boolean getHasVisit()
{try { __CLOVER_71_0.M[404]++;
__CLOVER_71_0.S[1740]++;return _visit != null;
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[405]++;
__CLOVER_71_0.S[1741]++;String visitClassName;
__CLOVER_71_0.S[1742]++;Class visitClass;
__CLOVER_71_0.S[1743]++;Object result = null;
__CLOVER_71_0.S[1744]++;visitClassName = getPropertySource().getPropertyValue(VISIT_CLASS_PROPERTY_NAME);
__CLOVER_71_0.S[1745]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[327] != 0)) || (++__CLOVER_71_0.CF[327] == 0))){
__CLOVER_71_0.S[1746]++;LOG.debug("Creating visit object as instance of " + visitClassName);}
__CLOVER_71_0.S[1747]++;visitClass = getClassResolver().findClass(visitClassName);
__CLOVER_71_0.S[1748]++;try
{
__CLOVER_71_0.S[1749]++;result = visitClass.newInstance();
}
catch (Throwable t)
{
__CLOVER_71_0.S[1750]++;throw new ApplicationRuntimeException(Tapestry.format(
"AbstractEngine.unable-to-instantiate-visit",
visitClassName), t);
}
__CLOVER_71_0.S[1751]++;return result;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[406]++;
__CLOVER_71_0.S[1752]++;return _global;
} finally { }}
public IScriptSource getScriptSource()
{try { __CLOVER_71_0.M[407]++;
__CLOVER_71_0.S[1753]++;return _infrastructure.getScriptSource();
} finally { }}
public boolean isStateful()
{try { __CLOVER_71_0.M[408]++;
__CLOVER_71_0.S[1754]++;return _stateful;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[409]++;
__CLOVER_71_0.S[1755]++;_stateful = true;
} finally { }}
/**
* Allows subclasses to include listener methods easily.
*
* @since 1.0.2
*/
public ListenerMap getListeners()
{try { __CLOVER_71_0.M[410]++;
__CLOVER_71_0.S[1756]++;if ((((_listeners == null) && (++__CLOVER_71_0.CT[328] != 0)) || (++__CLOVER_71_0.CF[328] == 0))){
__CLOVER_71_0.S[1757]++;_listeners = new ListenerMap(this);}
__CLOVER_71_0.S[1758]++;return _listeners;
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[411]++;
__CLOVER_71_0.S[1759]++;String location = ex.getRedirectLocation();
__CLOVER_71_0.S[1760]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_71_0.CT[329] != 0)) || (++__CLOVER_71_0.CF[329] == 0))){
__CLOVER_71_0.S[1761]++;LOG.debug("Redirecting to: " + location);}
__CLOVER_71_0.S[1762]++;RedirectAnalyzer analyzer = new RedirectAnalyzer(location);
__CLOVER_71_0.S[1763]++;analyzer.process(cycle);
} finally { }}
/**
* @since 2.0.4
*/
public ComponentMessagesSource getComponentMessagesSource()
{try { __CLOVER_71_0.M[412]++;
__CLOVER_71_0.S[1764]++;return _infrastructure.getComponentMessagesSource();
} finally { }}
/**
* @see Infrastructure#getDataSqueezer()
*/
public DataSqueezer getDataSqueezer()
{try { __CLOVER_71_0.M[413]++;
__CLOVER_71_0.S[1765]++;return _infrastructure.getDataSqueezer();
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[414]++;
__CLOVER_71_0.S[1766]++;if ((((context.getRequest().getAttribute(Tapestry.TAG_SUPPORT_SERVICE_ATTRIBUTE) != null) && (++__CLOVER_71_0.CT[330] != 0)) || (++__CLOVER_71_0.CF[330] == 0))){
__CLOVER_71_0.S[1767]++;return Tapestry.TAGSUPPORT_SERVICE;}
__CLOVER_71_0.S[1768]++;String serviceData = context.getParameter(Tapestry.SERVICE_QUERY_PARAMETER_NAME);
__CLOVER_71_0.S[1769]++;if ((((serviceData == null) && (++__CLOVER_71_0.CT[331] != 0)) || (++__CLOVER_71_0.CF[331] == 0))){
__CLOVER_71_0.S[1770]++;return Tapestry.HOME_SERVICE;}
// The service name is anything before the first slash,
// if there is one.
__CLOVER_71_0.S[1771]++;int slashx = serviceData.indexOf('/');
__CLOVER_71_0.S[1772]++;if ((((slashx < 0) && (++__CLOVER_71_0.CT[332] != 0)) || (++__CLOVER_71_0.CF[332] == 0))){
__CLOVER_71_0.S[1773]++;return serviceData;}
__CLOVER_71_0.S[1774]++;return serviceData.substring(0, slashx);
} finally { }}
/** @since 2.3 */
public IPropertySource getPropertySource()
{try { __CLOVER_71_0.M[415]++;
__CLOVER_71_0.S[1775]++;return _infrastructure.getApplicationPropertySource();
} finally { }}
/** @since 3.0 */
protected String getExceptionPageName()
{try { __CLOVER_71_0.M[416]++;
__CLOVER_71_0.S[1776]++;return EXCEPTION_PAGE;
} finally { }}
/** @since 3.0 */
protected String getStaleLinkPageName()
{try { __CLOVER_71_0.M[417]++;
__CLOVER_71_0.S[1777]++;return STALE_LINK_PAGE;
} finally { }}
/** @since 3.0 */
protected String getStaleSessionPageName()
{try { __CLOVER_71_0.M[418]++;
__CLOVER_71_0.S[1778]++;return STALE_SESSION_PAGE;
} finally { }}
/**
* 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)
{try { __CLOVER_71_0.M[419]++;
__CLOVER_71_0.S[1779]++;String className = getPropertySource().getPropertyValue("org.apache.tapestry.global-class");
__CLOVER_71_0.S[1780]++;if ((((Tapestry.isBlank(className)) && (++__CLOVER_71_0.CT[333] != 0)) || (++__CLOVER_71_0.CF[333] == 0))){
__CLOVER_71_0.S[1781]++;return Collections.synchronizedMap(new HashMap());}
__CLOVER_71_0.S[1782]++;Class globalClass = getClassResolver().findClass(className);
__CLOVER_71_0.S[1783]++;try
{
__CLOVER_71_0.S[1784]++;return globalClass.newInstance();
}
catch (Exception ex)
{
__CLOVER_71_0.S[1785]++;throw new ApplicationRuntimeException(Tapestry.format(
"AbstractEngine.unable-to-instantiate-global",
className), ex);
}
} finally { }}
/** @see Infrastructure#getObjectPool() */
public ObjectPool getPool()
{try { __CLOVER_71_0.M[420]++;
__CLOVER_71_0.S[1786]++;return _infrastructure.getObjectPool();
} finally { }}
/** @see Infrastructure#getComponentClassEnhancer() */
public IComponentClassEnhancer getComponentClassEnhancer()
{try { __CLOVER_71_0.M[421]++;
__CLOVER_71_0.S[1787]++;return _infrastructure.getComponentClassEnhancer();
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[422]++;
__CLOVER_71_0.S[1788]++;return _dirty;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[423]++;
__CLOVER_71_0.S[1789]++;if ((((!_dirty) && (++__CLOVER_71_0.CT[334] != 0)) || (++__CLOVER_71_0.CF[334] == 0))){
__CLOVER_71_0.S[1790]++;LOG.debug("Setting dirty flag.");}
__CLOVER_71_0.S[1791]++;_dirty = true;
} finally { }}
/**
* Clears the dirty flag when a engine is stored into the {@link HttpSession}.
*
* @since 3.0
*/
public void valueBound(HttpSessionBindingEvent arg0)
{try { __CLOVER_71_0.M[424]++;
__CLOVER_71_0.S[1792]++;LOG.debug((((_dirty ) && (++__CLOVER_71_0.CT[335] != 0)) || (++__CLOVER_71_0.CF[335] == 0))? "Clearing dirty flag." : "Dirty flag already cleared.");
__CLOVER_71_0.S[1793]++;_dirty = false;
} finally { }}
/**
* Does nothing.
*
* @since 3.0
*/
public void valueUnbound(HttpSessionBindingEvent arg0)
{try { __CLOVER_71_0.M[425]++;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[426]++;
__CLOVER_71_0.S[1794]++;return DEFAULT_OUTPUT_ENCODING;
} finally { }}
/**
* 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()
{try { __CLOVER_71_0.M[427]++;
__CLOVER_71_0.S[1795]++;IPropertySource source = getPropertySource();
__CLOVER_71_0.S[1796]++;String encoding = source.getPropertyValue(OUTPUT_ENCODING_PROPERTY_NAME);
__CLOVER_71_0.S[1797]++;if ((((encoding == null) && (++__CLOVER_71_0.CT[336] != 0)) || (++__CLOVER_71_0.CF[336] == 0))){
__CLOVER_71_0.S[1798]++;encoding = getDefaultOutputEncoding();}
__CLOVER_71_0.S[1799]++;return encoding;
} finally { }}
}