All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.samskivert.velocity.Application Maven / Gradle / Ivy

There is a newer version: 1.9
Show newest version
//
// $Id$
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001-2011 Michael Bayne, et al.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.samskivert.velocity;

import java.util.Locale;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.velocity.app.Velocity;

import com.samskivert.servlet.HttpErrorException;
import com.samskivert.servlet.IndiscriminateSiteIdentifier;
import com.samskivert.servlet.MessageManager;
import com.samskivert.servlet.RedirectException;
import com.samskivert.servlet.SiteIdentifier;
import com.samskivert.servlet.SiteResourceLoader;
import com.samskivert.servlet.util.ExceptionMap;
import com.samskivert.servlet.util.FriendlyException;
import com.samskivert.servlet.util.RequestUtils;
import com.samskivert.util.StringUtil;

import static com.samskivert.Log.log;

/**
 * The servlet API defines the concept of a web application and associates certain attributes with
 * it like document root and so on. This application class extends that concept by providing a base
 * class that represents the web application. The application class is responsible for initializing
 * services that will be used by the application's logic objects as well as cleaning them up when
 * the application is shut down.
 *
 * 

Error handling
* The application provides a common error handling mechanism. The design is to catch any * exceptions thrown by the logic and to convert them into friendly error messages that are * inserted into the invocation context with the key "error" for easy display in the * resulting web page. * *

The default process of mapping exceptions to friendly error messages is done using the * {@link ExceptionMap} class. This can be replaced by overriding {@link #handleException}. */ public class Application { /** * An initialized application automatically registers itself as a Velocity application * attribute so that it can be retrieved by Velocity plugins using * getApplicationAttribute(VELOCITY_ATTR_KEY). */ public static final String VELOCITY_ATTR_KEY = "!application!"; /** * Performs initializations common to all applications. Applications should override {@link * #willInit} to perform initializations that need to take place before the common * initialization (which includes the creation of the site identifier and message manager) and * should override {@link #didInit} to perform initializations that need to take place after * the common initialization (like passing the application to entities that might turn around * and request a reference to our site identifier). * * @param config the servlet config from which the application will load configuration * information. * @param context the servlet context in which this application is operating. * @param logicPkg the base package for all of the logic implementations for this application. */ public void init (ServletConfig config, ServletContext context, String logicPkg) { // keep this around for later _context = context; // stick ourselves into an application attribute so that we can be accessed by Velocity // plugins Velocity.setApplicationAttribute(VELOCITY_ATTR_KEY, this); // let the derived application do pre-init stuff willInit(config); // remove any trailing dot if (logicPkg.endsWith(".")) { _logicPkg = logicPkg.substring(0, logicPkg.length()-1); } else { _logicPkg = logicPkg; } // create our site identifier _siteIdent = createSiteIdentifier(_context); // create a site resource loader if the user set up the site-specific jar file path String siteJarPath = getInitParameter(config, SITE_JAR_PATH_KEY); if (!StringUtil.isBlank(siteJarPath)) { _siteLoader = new SiteResourceLoader(_siteIdent, siteJarPath); } // instantiate our message manager if the application wants one String bundlePath = getInitParameter(config, MESSAGE_BUNDLE_PATH_KEY); if (!StringUtil.isBlank(bundlePath)) { _msgmgr = createMessageManager(bundlePath); } // if we have a site-specific resource loader, configure the message manager with it, so // that it can load site-specific message resources if (_msgmgr != null && _siteLoader != null) { String siteBundlePath = getInitParameter(config, SITE_MESSAGE_BUNDLE_PATH_KEY); if (!StringUtil.isBlank(siteBundlePath)) { _msgmgr.activateSiteSpecificMessages(siteBundlePath, _siteLoader); } else { log.info("No '" + SITE_MESSAGE_BUNDLE_PATH_KEY + "' specified in servlet " + "configuration. This is required to allow the message manager to load " + "site-specific translation resources."); } } // let the derived application do post-init stuff didInit(config); } /** * Called prior to initializing Velocity to allow the application to specify custom * configuration properties. */ protected void configureVelocity (ServletConfig config, Properties props) { } /** * Looks up an initialization parameter for this application. The default implementation * retrieves the value from the servlet config, but derived classes may wish to get certain * parameters from some other configuration source. */ protected String getInitParameter (ServletConfig config, String key) { return config.getInitParameter(key); } /** * Creates the message manager to be used for this application. */ protected MessageManager createMessageManager (String bundlePath) { return new MessageManager(bundlePath, Locale.getDefault(), _siteIdent); } /** * This should be overridden by the application implementation to invoke any necessary * pre-initialization code. They should be sure to call super.willInit(). */ protected void willInit (ServletConfig config) { } /** * This should be overridden by the application implementation to invoke any necessary * post-initialization code. They should be sure to call super.didInit(). */ protected void didInit (ServletConfig config) { } /** * Allows derived aplication classes to prepare an invocation context prior to the logic class * being invoked. They may wish to add standard tools to the context or do any other * request-invariant preparation. */ protected void prepareContext (InvocationContext ctx) { } /** * Allows derived application classes to check access in a single location prior to resolving * and dispatching a logic class, if they desire access control at this level. Alternatively, * access control can be performed by the logic instance. */ protected void checkAccess (InvocationContext ctx) throws RedirectException, HttpErrorException { } /** * If an exception propagates up from {@link Logic#invoke}, the application is given the chance * to convert a low-level exception into a {@link FriendlyException} or a {@link * RedirectException} which will be handled in the normal way. */ protected Exception translateException (Exception error) { return error; } /** * If a generic exception propagates up from {@link Logic#invoke} and is not otherwise * converted into a friendly or redirect exception, the application will be required to provide * a generic error message to be inserted into the context and should take this opportunity to * log the exception. * *

Note: the string returned by this method will be translated using the * application's message manager before being inserted into the Velocity context. */ protected String handleException (HttpServletRequest req, Logic logic, Exception error) { log.warning(logic + " failed on: " + RequestUtils.reconstructURL(req), error); return ExceptionMap.getMessage(error); } /** * This should be overridden by the application implementation to perform any necessary * cleanup. */ public void shutdown () { } /** * Returns a reference to the servlet context in which this application is operating. */ public ServletContext getServletContext () { return _context; } /** * Returns the message manager in effect for this application, if one is in effect. */ public MessageManager getMessageManager () { return _msgmgr; } /** * Returns the site identifier in effect for figuring out which site through which a user is * making a request. */ public SiteIdentifier getSiteIdentifier () { return _siteIdent; } /** * Returns a reference to the loader used to obtain site-specific resources. This is only valid * if the user specified the site-specific jar file path in the servlet configuration. * * @see #SITE_JAR_PATH_KEY */ public SiteResourceLoader getSiteResourceLoader () { return _siteLoader; } /** * Called to instantiate the site identifier that we'd like to use in this application. This * will be an instance of {@link IndiscriminateSiteIdentifier} unless the derived application * class overrides this method and creates something more to its liking. This will be called * after the application's {@link #init} method has been called. */ protected SiteIdentifier createSiteIdentifier (ServletContext ctx) { return new IndiscriminateSiteIdentifier(); } /** * A convenience function for translating messages. */ public final String translate (InvocationContext ctx, String msg) { return _msgmgr.getMessage(ctx.getRequest(), msg); } /** * A convenience function for translating messages. */ public final String translate (InvocationContext ctx, String msg, Object... args) { return _msgmgr.getMessage(ctx.getRequest(), msg, args); } /** * Given the servlet path (the part of the URI after the context path) this generates the * classname of the logic class that should handle the request. */ protected String generateClass (String path) { // remove the trailing file extension int ldidx = path.lastIndexOf("."); if (ldidx != -1) { path = path.substring(0, ldidx); } // convert slashes to dots path = path.replace('/', '.'); // prepend the base logic package and we're all set return _logicPkg + path; } /** A reference to the servlet context in which this application is operating. */ protected ServletContext _context; /** The prefix that we use to generate fully qualified logic class names. */ protected String _logicPkg; /** A reference to our message manager or null if we have none. */ protected MessageManager _msgmgr; /** A reference to our site identifier. */ protected SiteIdentifier _siteIdent; /** Provides access to site-specific resources. */ protected SiteResourceLoader _siteLoader; /** The servlet parameter key specifying the path to the application's translated message * resources. */ protected static final String MESSAGE_BUNDLE_PATH_KEY = "messages_path"; /** The servlet parameter key specifying the path to the site-specific jar files. */ protected static final String SITE_JAR_PATH_KEY = "site_jar_path"; /** The servlet parameter key specifying the path to the site-specific translated message * resources. */ protected static final String SITE_MESSAGE_BUNDLE_PATH_KEY = "site_messages_path"; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy