/* $$ 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;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.Registry;
import org.apache.hivemind.impl.DefaultClassResolver;
import org.apache.hivemind.impl.RegistryBuilder;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.services.ApplicationGlobals;
import org.apache.tapestry.services.ApplicationInitializer;
import org.apache.tapestry.services.RequestServicer;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.util.exception.ExceptionAnalyzer;
/**
* Links a servlet container with a Tapestry application. The servlet has some
* responsibilities related to bootstrapping the application (in terms of
* logging, reading the {@link ApplicationSpecification specification}, etc.).
* It is also responsible for creating or locating the {@link IEngine} and delegating
* incoming requests to it.
*
* <p>The servlet init parameter
* <code>org.apache.tapestry.specification-path</code>
* should be set to the complete resource path (within the classpath)
* to the application specification, i.e.,
* <code>/com/foo/bar/MyApp.application</code>.
*
* <p>In some servlet containers (notably
* <a href="www.bea.com"/>WebLogic</a>)
* it is necessary to invoke {@link HttpSession#setAttribute(String,Object)}
* in order to force a persistent value to be replicated to the other
* servers in the cluster. Tapestry applications usually only have a single
* persistent value, the {@link IEngine engine}. For persistence to
* work in such an environment, the
* JVM system property <code>org.apache.tapestry.store-engine</code>
* must be set to <code>true</code>. This will force the application
* servlet to restore the engine into the {@link HttpSession} at the
* end of each request cycle.
*
* <p>As of release 1.0.1, it is no longer necessary for a {@link HttpSession}
* to be created on the first request cycle. Instead, the HttpSession is created
* as needed by the {@link IEngine} ... that is, when a visit object is created,
* or when persistent page state is required. Otherwise, for sessionless requests,
* an {@link IEngine} from a {@link Pool} is used. Additional work must be done
* so that the {@link IEngine} can change locale <em>without</em> forcing
* the creation of a session; this involves the servlet and the engine storing
* locale information in a {@link Cookie}.
*
* <p>
* As of release 3.1, this servlet will also create a HiveMind Registry and manage it.
*
* @author Howard Lewis Ship
*
*/
public class ApplicationServlet extends HttpServlet
{public static com.cortexeb.tools.clover.d __CLOVER_3_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(ApplicationServlet.class);
/**
* Name of the cookie written to the client web browser to
* identify the locale.
*
*/
public static final String LOCALE_COOKIE_NAME = "org.apache.tapestry.locale";
/**
* The application specification, which is read once and kept in memory
* thereafter.
*
*/
private IApplicationSpecification _specification;
/**
* Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
*
* @since 1.0.6
*
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{try { __CLOVER_3_0.M[129]++;
__CLOVER_3_0.S[468]++;doService(request, response);
} finally { }}
/**
* @since 2.3
*
*/
private ClassResolver _resolver;
/**
* @since 3.1
*/
private Registry _registry;
/**
* @since 3.1
*/
private RequestServicer _requestServicer;
/**
* Handles the GET and POST requests. Performs the following:
* <ul>
* <li>Construct a {@link RequestContext}
* <li>Invoke {@link #getEngine(RequestContext)} to get or create the {@link IEngine}
* <li>Invoke {@link IEngine#service(RequestContext)} on the application
* </ul>
*/
protected void doService(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{try { __CLOVER_3_0.M[130]++;
__CLOVER_3_0.S[469]++;try
{
__CLOVER_3_0.S[470]++;_requestServicer.service(request, response);
}
catch (ServletException ex)
{
__CLOVER_3_0.S[471]++;log("ServletException", ex);
__CLOVER_3_0.S[472]++;show(ex);
// Rethrow it.
__CLOVER_3_0.S[473]++;throw ex;
}
catch (IOException ex)
{
__CLOVER_3_0.S[474]++;log("IOException", ex);
__CLOVER_3_0.S[475]++;show(ex);
// Rethrow it.
__CLOVER_3_0.S[476]++;throw ex;
}
} finally { }}
protected void show(Exception ex)
{try { __CLOVER_3_0.M[131]++;
__CLOVER_3_0.S[477]++;System.err.println("\n\n**********************************************************\n\n");
__CLOVER_3_0.S[478]++;new ExceptionAnalyzer().reportException(ex, System.err);
__CLOVER_3_0.S[479]++;System.err.println("\n**********************************************************\n");
} finally { }}
/**
* Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
*
*
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{try { __CLOVER_3_0.M[132]++;
__CLOVER_3_0.S[480]++;doService(request, response);
} finally { }}
/**
* Returns the application specification, which is read
* by the {@link #init(ServletConfig)} method.
*
* @deprecated Use {@link RequestContext#getApplicationSpecification()} instead.
*/
public IApplicationSpecification getApplicationSpecification()
{try { __CLOVER_3_0.M[133]++;
__CLOVER_3_0.S[481]++;return _specification;
} finally { }}
/**
* Reads the application specification when the servlet is
* first initialized. All {@link IEngine engine instances}
* will have access to the specification via the servlet.
*
* @see #getApplicationSpecification()
* @see #constructApplicationSpecification()
* @see #createResourceResolver()
*
*/
public void init(ServletConfig config) throws ServletException
{try { __CLOVER_3_0.M[134]++;
__CLOVER_3_0.S[482]++;super.init(config);
__CLOVER_3_0.S[483]++;_resolver = createClassResolver();
__CLOVER_3_0.S[484]++;try
{
__CLOVER_3_0.S[485]++;constructRegistry();
__CLOVER_3_0.S[486]++;initializeApplication();
}
catch (Exception ex)
{
__CLOVER_3_0.S[487]++;show(ex);
__CLOVER_3_0.S[488]++;throw new ServletException(TapestryMessages.servletInitFailure(ex), ex);
}
} finally { }}
/**
* Invoked from {@link #init(ServletConfig)} to create a resource resolver
* for the servlet (which will utlimately be shared and used through the
* application).
*
* <p>This implementation constructs a {@link DefaultResourceResolver}, subclasses
* may provide a different implementation.
*
* @see #getResourceResolver()
* @since 2.3
*
*/
protected ClassResolver createClassResolver() throws ServletException
{try { __CLOVER_3_0.M[135]++;
__CLOVER_3_0.S[489]++;return new DefaultClassResolver();
} finally { }}
/**
* Closes the stream, ignoring any exceptions.
*
*/
protected void close(InputStream stream)
{try { __CLOVER_3_0.M[136]++;
__CLOVER_3_0.S[490]++;try
{
__CLOVER_3_0.S[491]++;if ((((stream != null) && (++__CLOVER_3_0.CT[105] != 0)) || (++__CLOVER_3_0.CF[105] == 0))){
__CLOVER_3_0.S[492]++;stream.close();}
}
catch (IOException ex)
{
// Ignore it.
}
} finally { }}
/**
* Invoked from the {@link IEngine engine}, just prior to starting to
* render a response, when the locale has changed. The servlet writes a
* {@link Cookie} so that, on subsequent request cycles, an engine localized
* to the selected locale is chosen.
*
* <p>At this time, the cookie is <em>not</em> persistent. That may
* change in subsequent releases.
*
* @since 1.0.1
*/
public static void writeLocaleCookie(Locale locale, IEngine engine, RequestContext cycle)
{try { __CLOVER_3_0.M[137]++;
__CLOVER_3_0.S[493]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_3_0.CT[106] != 0)) || (++__CLOVER_3_0.CF[106] == 0))){
__CLOVER_3_0.S[494]++;LOG.debug("Writing locale cookie " + locale);}
__CLOVER_3_0.S[495]++;Cookie cookie = new Cookie(LOCALE_COOKIE_NAME, locale.toString());
__CLOVER_3_0.S[496]++;cookie.setPath(engine.getServletPath());
__CLOVER_3_0.S[497]++;cycle.addCookie(cookie);
} finally { }}
/**
* Returns a resource resolver that can access classes and resources related
* to the current web application context. Relies on
* {@link java.lang.Thread#getContextClassLoader()}, which is set by
* most modern servlet containers.
*
* @since 2.3
*
*/
public ClassResolver getClassResolver()
{try { __CLOVER_3_0.M[138]++;
__CLOVER_3_0.S[498]++;return _resolver;
} finally { }}
/**
* Invoked from {@link #init(ServletConfig)} to construct the Registry to
* be used by the application.
*
* @since 3.1
*/
protected void constructRegistry()
{try { __CLOVER_3_0.M[139]++;
// This will expand in the future.
__CLOVER_3_0.S[499]++;_registry = RegistryBuilder.constructDefaultRegistry();
} finally { }}
/**
* Invoked from {@link #init(ServletConfig)}, after the registry has
* been constructed, to bootstrap the application via the
* <code>tapestry.MasterApplicationInitializer</code> service.
*/
protected void initializeApplication()
{try { __CLOVER_3_0.M[140]++;
__CLOVER_3_0.S[500]++;ApplicationInitializer ai =
(ApplicationInitializer) _registry.getService(
"tapestry.init.MasterInitializer",
ApplicationInitializer.class);
__CLOVER_3_0.S[501]++;ai.initialize(this);
__CLOVER_3_0.S[502]++;_registry.cleanupThread();
// This is temporary, since most of the code still gets the
// specification from the servlet --- in fact, has to downcase
// RequestContext.getServlet() to do so.
__CLOVER_3_0.S[503]++;ApplicationGlobals ag =
(ApplicationGlobals) _registry.getService(
"tapestry.globals.ApplicationGlobals",
ApplicationGlobals.class);
__CLOVER_3_0.S[504]++;_specification = ag.getSpecification();
__CLOVER_3_0.S[505]++;_requestServicer =
(RequestServicer) _registry.getService(
"tapestry.request.RequestServicerPipeline",
RequestServicer.class);
} finally { }}
/**
* Returns the Registry used by the application.
*
* @since 3.1
*/
public Registry getRegistry()
{try { __CLOVER_3_0.M[141]++;
__CLOVER_3_0.S[506]++;return _registry;
} finally { }}
/**
* Shuts down the registry (if it exists).
*
* @since 3.1
*/
public void destroy()
{try { __CLOVER_3_0.M[142]++;
__CLOVER_3_0.S[507]++;if ((((_registry != null) && (++__CLOVER_3_0.CT[107] != 0)) || (++__CLOVER_3_0.CF[107] == 0))){
{
__CLOVER_3_0.S[508]++;_registry.shutdown();
__CLOVER_3_0.S[509]++;_registry = null;
}}
} finally { }}
}