Canned the long unsupported webmacro stuff.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@1399 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -83,14 +83,6 @@
|
||||
<available property="jakarta.velocity.present"
|
||||
classname="org.apache.velocity.Template" classpathref="classpath"/>
|
||||
<echo message="Velocity: ${jakarta.velocity.present}"/>
|
||||
|
||||
<echo message=""/>
|
||||
<echo message="-----------------------------------"/>
|
||||
<echo message="WebMacro - http://www.webmacro.org/"/>
|
||||
<echo message="-----------------------------------"/>
|
||||
<available property="webmacro.present"
|
||||
classname="org.webmacro.Template" classpathref="classpath"/>
|
||||
<echo message="WebMacro: ${webmacro.present}"/>
|
||||
</target>
|
||||
|
||||
<!-- combines package availability into build controls -->
|
||||
@@ -153,16 +145,6 @@
|
||||
</condition>
|
||||
<echo message="com.samskivert.velocity: ${build.velocity}"/>
|
||||
|
||||
<condition property="build.webmacro">
|
||||
<and>
|
||||
<isset property="build.servlet"/>
|
||||
<isset property="build.util"/>
|
||||
<isset property="servlet2.2.present"/>
|
||||
<isset property="webmacro.present"/>
|
||||
</and>
|
||||
</condition>
|
||||
<echo message="com.samskivert.webmacro: ${build.webmacro}"/>
|
||||
|
||||
<condition property="build.xml">
|
||||
<and>
|
||||
<isset property="build.io"/>
|
||||
@@ -205,7 +187,6 @@
|
||||
<exclude name="com/samskivert/test/**" unless="build.test"/>
|
||||
<exclude name="com/samskivert/util/**" unless="build.util"/>
|
||||
<exclude name="com/samskivert/velocity/**" unless="build.velocity"/>
|
||||
<exclude name="com/samskivert/webmacro/**" unless="build.webmacro"/>
|
||||
<exclude name="com/samskivert/xml/**" unless="build.xml"/>
|
||||
</javac>
|
||||
</target>
|
||||
@@ -227,7 +208,6 @@
|
||||
<exclude name="com/samskivert/test/**" unless="build.test"/>
|
||||
<exclude name="com/samskivert/util/**" unless="build.util"/>
|
||||
<exclude name="com/samskivert/velocity/**" unless="build.velocity"/>
|
||||
<exclude name="com/samskivert/webmacro/**" unless="build.webmacro"/>
|
||||
<exclude name="com/samskivert/xml/**" unless="build.xml"/>
|
||||
</packageset>
|
||||
<bottom>Copyright © 2000-${year} ${copyright.holder}.
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
//
|
||||
// $Id: Application.java,v 1.4 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import org.webmacro.servlet.WebContext;
|
||||
|
||||
import com.samskivert.servlet.MessageManager;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public class Application
|
||||
{
|
||||
/**
|
||||
* This should be overridden by the application implementation to
|
||||
* perform any necessary initialization.
|
||||
*/
|
||||
public void init (ServletContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by the application implementation to
|
||||
* perform any necessary cleanup.
|
||||
*/
|
||||
public void shutdown ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message manager in effect for this application, if one
|
||||
* is in effect.
|
||||
*/
|
||||
public MessageManager getMessageManager ()
|
||||
{
|
||||
return _msgmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* If an application wishes to make use of the translation facilities
|
||||
* provided by the message manager, it need only provide the path to
|
||||
* its message resource bundle via this member function. Using a
|
||||
* message manager allows framework components like the
|
||||
* <code>MsgTool</code> to make use of the application's message
|
||||
* bundles.
|
||||
*/
|
||||
protected String getMessageBundlePath ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for translating messages.
|
||||
*/
|
||||
public final String translate (WebContext ctx, String msg)
|
||||
{
|
||||
return _msgmgr.getMessage(ctx.getRequest(), msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for translating messages.
|
||||
*/
|
||||
public final String translate (WebContext ctx, String msg, Object arg)
|
||||
{
|
||||
return _msgmgr.getMessage(ctx.getRequest(), msg,
|
||||
new Object[]{ arg });
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for translating messages.
|
||||
*/
|
||||
public final String translate (WebContext ctx, String msg,
|
||||
Object arg1, Object arg2)
|
||||
{
|
||||
return _msgmgr.getMessage(ctx.getRequest(), msg,
|
||||
new Object[]{ arg1, arg2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for translating messages.
|
||||
*/
|
||||
public final String translate (WebContext ctx, String msg,
|
||||
Object arg1, Object arg2, Object arg3)
|
||||
{
|
||||
return _msgmgr.getMessage(ctx.getRequest(), msg,
|
||||
new Object[]{ arg1, arg2, arg3 });
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for translating messages.
|
||||
*/
|
||||
public final String translate (WebContext ctx, String msg,
|
||||
Object[] args)
|
||||
{
|
||||
return _msgmgr.getMessage(ctx.getRequest(), msg, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs initializations common to all applications. We could put
|
||||
* this in init() and require application derived classes to call
|
||||
* super.init() but people would forget to do so and be confused.
|
||||
*
|
||||
* <p> The default application implementation takes the base URI and
|
||||
* base package as defined in the application declaration in the
|
||||
* servlet configuration and uses those to determine whether or not a
|
||||
* given URI maps to this application.
|
||||
*/
|
||||
public void preInit (String baseURI, String basePkg)
|
||||
{
|
||||
// remove any trailing slash
|
||||
if (baseURI.endsWith("/")) {
|
||||
_baseURI = baseURI.substring(0, baseURI.length()-1);
|
||||
} else {
|
||||
_baseURI = baseURI;
|
||||
}
|
||||
|
||||
// remove any trailing dot
|
||||
if (basePkg.endsWith(".")) {
|
||||
_basePkg = basePkg.substring(0, basePkg.length()-1);
|
||||
} else {
|
||||
_basePkg = basePkg;
|
||||
}
|
||||
|
||||
// instantiate our message manager if the application wants one
|
||||
String bpath = getMessageBundlePath();
|
||||
if (bpath != null) {
|
||||
_msgmgr = new MessageManager(bpath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied URI should be handled by this
|
||||
* application.
|
||||
*/
|
||||
public boolean matches (String uri)
|
||||
{
|
||||
return uri.startsWith(_baseURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a request URI this generates the classname of the logic class
|
||||
* that should handle the request.
|
||||
*/
|
||||
public String generateClass (String uri)
|
||||
{
|
||||
// remove the base URI
|
||||
uri = uri.substring(_baseURI.length());
|
||||
// convert slashes to dots
|
||||
uri = StringUtil.replace(uri, "/", ".");
|
||||
// remove the trailing file extension
|
||||
uri = uri.substring(0, uri.length() - FILE_EXTENSION.length());
|
||||
// prepend the base package and we're all set
|
||||
return _basePkg + uri;
|
||||
}
|
||||
|
||||
protected String _baseURI;
|
||||
protected String _basePkg;
|
||||
protected MessageManager _msgmgr;
|
||||
|
||||
/**
|
||||
* This is the default file extension.
|
||||
*/
|
||||
protected static final String FILE_EXTENSION = ".wm";
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
//
|
||||
// $Id: DataValidationException.java,v 1.2 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
/**
|
||||
* A data validation exception is thrown when a value supplied in a form
|
||||
* element is not valid. The servlet framework will substitute the message
|
||||
* assosciated with this exception into the context with the key
|
||||
* <code>"invalid_data"</code>. Templates should be structured so that
|
||||
* this is reported to the user along with the filled out form field for
|
||||
* their editing and resubmitting pleasures.
|
||||
*/
|
||||
public class DataValidationException extends FriendlyException
|
||||
{
|
||||
public DataValidationException (String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,424 +0,0 @@
|
||||
//
|
||||
// $Id: DispatcherServlet.java,v 1.13 2002/04/01 01:57:31 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.webmacro.*;
|
||||
import org.webmacro.servlet.HandlerException;
|
||||
import org.webmacro.servlet.WMServlet;
|
||||
import org.webmacro.servlet.WebContext;
|
||||
|
||||
import com.samskivert.Log;
|
||||
import com.samskivert.servlet.MessageManager;
|
||||
import com.samskivert.servlet.RedirectException;
|
||||
import com.samskivert.util.ConfigUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* The dispatcher servlet builds upon WebMacro's architecture. It does so
|
||||
* in the following ways:
|
||||
*
|
||||
* <ul>
|
||||
* <li> It defines the notion of a logic object which populates the
|
||||
* context with data to be used to satisfy a particular request. The logic
|
||||
* is not a servlet and is therefore limited in what it can do while
|
||||
* populating data. Experience dictates that ultimate flexibility leads to
|
||||
* bad design decisions and that this is a place where that sort of thing
|
||||
* can be comfortably nipped in the bud. <br><br>
|
||||
*
|
||||
* <li> It allows .wm files to be referenced directly in the URL while
|
||||
* maintaining the ability to choose a cobranded template based. The URI
|
||||
* is mapped to a servlet based on some simple mapping rules. This
|
||||
* provides template designers with a clearer understanding of the
|
||||
* structure of a web application as well as with an easy way to test
|
||||
* their templates in the absence of an associated servlet. <br><br>
|
||||
*
|
||||
* <li> It provides a common error handling paradigm that simplifies the
|
||||
* task of authoring web applications.
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>URI to servlet mapping</b><br>
|
||||
* The mapping process allows the webmacro framework to be invoked for all
|
||||
* requests ending in a particular file extension (usually
|
||||
* <code>.wm</code>). It is necessary to instruct your servlet engine of
|
||||
* choice to invoke the <code>Dispatcher</code> servlet for all requests
|
||||
* ending in that extension. For Apache/JServ this looks something like
|
||||
* this:
|
||||
*
|
||||
* <pre>
|
||||
* ApJServAction .wm /servlets/com.samskivert.webmacro.Dispatcher
|
||||
* </pre>
|
||||
*
|
||||
* The request URI then defines the path of the webmacro template that
|
||||
* will be used to satisfy the request. To understand how code is selected
|
||||
* to go along with the request, let's look at an example. Consider the
|
||||
* following configuration:
|
||||
*
|
||||
* <pre>
|
||||
* applications=whowhere
|
||||
* whowhere.base_uri=/whowhere
|
||||
* whowhere.base_pkg=whowhere.logic
|
||||
* </pre>
|
||||
*
|
||||
* This defines an application identified as <code>whowhere</code>. An
|
||||
* application is defined by three parameters, the application identifier,
|
||||
* the <code>base_uri</code>, and the <code>base_pkg</code>. The
|
||||
* <code>base_uri</code> defines the prefix shared by all pages served by
|
||||
* the application and which serves to identify which application to
|
||||
* invoke when processing a request. The <code>base_pkg</code> is used to
|
||||
* construct the logic classname based on the URI and the
|
||||
* <code>base_uri</code> parameter.
|
||||
*
|
||||
* <p> Now let's look at a sample request to determine how the logic
|
||||
* classname is resolved. Consider the following request URI:
|
||||
*
|
||||
* <pre>
|
||||
* /whowhere/view/trips.wm
|
||||
* </pre>
|
||||
*
|
||||
* It begins with <code>/whowhere</code> which tells the dispatcher that
|
||||
* it's part of the <code>whowhere</code> application. That application's
|
||||
* <code>base_uri</code> is then stripped from the URI leaving
|
||||
* <code>/view/trips.wm</code>. The slashes are converted into periods to
|
||||
* map directories to packages, giving us <code>view.trips.wm</code>.
|
||||
* Finally, the <code>base_pkg</code> is prepended and the trailing
|
||||
* <code>.wm</code> extension removed.
|
||||
*
|
||||
* <p> Thus the class invoked to populate the context for this request is
|
||||
* <code>whowhere.servlets.view.trips</code> (note that the classname
|
||||
* <em>is</em> lowercase which is an intentional choice in resolving
|
||||
* conflicting recommendations that classnames should always start with a
|
||||
* capital letter and URLs should always be lowercase).
|
||||
*
|
||||
* <p> The template used to generate the result is loaded based on the
|
||||
* full URI, essentially with a call to
|
||||
* <code>getTemplate("/whowhere/view/trips.wm")</code> in this example.
|
||||
* This is the place where more sophisticated cobranding support could be
|
||||
* inserted in the future (ie. if I ever want to use this to develop a
|
||||
* cobranded web site).
|
||||
*
|
||||
* <p><b>Error handling</b><br>
|
||||
* The dispatcher servlet 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 web
|
||||
* context with the key <code>"error"</code> for easy display in the
|
||||
* resulting web page.
|
||||
*
|
||||
* <p> The process of mapping exceptions to friendly error messages is
|
||||
* done using the <code>ExceptionMap</code> class. Consult its
|
||||
* documentation for an explanation of how it works.
|
||||
*
|
||||
* @see Logic
|
||||
* @see ExceptionMap
|
||||
*/
|
||||
public class DispatcherServlet extends WMServlet
|
||||
{
|
||||
public void start ()
|
||||
throws ServletException
|
||||
{
|
||||
// Log.info("Initializing dispatcher servlet.");
|
||||
|
||||
// first load the properties file
|
||||
Properties props = null;
|
||||
try {
|
||||
// load up our configuration
|
||||
ClassLoader cld = DispatcherServlet.class.getClassLoader();
|
||||
props = ConfigUtil.loadProperties("dispatcher.properties", cld);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Failure trying to load 'dispatcher.properties': " +
|
||||
ioe);
|
||||
}
|
||||
|
||||
if (props == null) {
|
||||
Log.warning("Unable to load properties for dispatcher servlet.");
|
||||
Log.warning("Make sure 'dispatcher.properties' file exists " +
|
||||
"somewhere in your classpath.");
|
||||
props = new Properties();
|
||||
}
|
||||
|
||||
// now parse the configuration
|
||||
String apps = props.getProperty("applications");
|
||||
if (apps != null) {
|
||||
StringTokenizer tok = new StringTokenizer(apps);
|
||||
while (tok.hasMoreTokens()) {
|
||||
String appid = tok.nextToken();
|
||||
String baseURI = props.getProperty(appid + ".base_uri");
|
||||
String basePkg = props.getProperty(appid + ".base_pkg");
|
||||
String appcl = props.getProperty(appid + ".application");
|
||||
|
||||
// make sure we're not missing anything
|
||||
if (baseURI == null) {
|
||||
Log.warning("Application '" + appid + "' missing " +
|
||||
"base_uri specification.");
|
||||
continue;
|
||||
}
|
||||
if (basePkg == null) {
|
||||
Log.warning("Application '" + appid + "' missing " +
|
||||
"base_pkg specification.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// instantiate the specified application class
|
||||
Application app;
|
||||
|
||||
try {
|
||||
// if a custom application class was specified,
|
||||
// instantiate one of those. otherwise use the default
|
||||
if (appcl != null) {
|
||||
Class appclass = Class.forName(appcl);
|
||||
app = (Application)appclass.newInstance();
|
||||
} else {
|
||||
app = new Application();
|
||||
}
|
||||
|
||||
// now initialize the applicaiton
|
||||
app.preInit(baseURI, basePkg);
|
||||
app.init(getServletContext());
|
||||
|
||||
// finally add it to our list
|
||||
_apps.add(app);
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.warning("Error instantiating custom application " +
|
||||
"[class=" + appcl + "].");
|
||||
Log.logStackTrace(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop ()
|
||||
{
|
||||
// shutdown our applications
|
||||
for (int i = 0; i < _apps.size(); i++) {
|
||||
Application app = (Application)_apps.get(i);
|
||||
app.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public Template handle (WebContext ctx) throws HandlerException
|
||||
{
|
||||
// first we select the template
|
||||
Template tmpl;
|
||||
try {
|
||||
tmpl = selectTemplate(ctx);
|
||||
} catch (ResourceException e) {
|
||||
throw new HandlerException("Unable to load template: " + e);
|
||||
}
|
||||
|
||||
// assume an HTML response unless otherwise massaged by the logic
|
||||
ctx.getResponse().setContentType("text/html");
|
||||
|
||||
// select the proper application for the request
|
||||
String path = cleanupURI(ctx.getRequest().getRequestURI());
|
||||
Application app = selectApplication(path);
|
||||
String errmsg = null;
|
||||
|
||||
try {
|
||||
// if we don't have a matching app, we'll just execute the
|
||||
// template as is without first invoking a logic object
|
||||
if (app != null) {
|
||||
// insert the application into the web context in case the
|
||||
// logic or a tool wishes to make use of it
|
||||
ctx.put(APPLICATION_KEY, app);
|
||||
|
||||
// resolve the appropriate logic class for this URI and
|
||||
// execute it if it exists
|
||||
Logic logic = resolveLogic(app, path);
|
||||
if (logic != null) {
|
||||
logic.invoke(app, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (RedirectException re) {
|
||||
try {
|
||||
ctx.getResponse().sendRedirect(re.getRedirectURL());
|
||||
return null;
|
||||
} catch (IOException ioe) {
|
||||
throw new HandlerException("Unable to send redirect: " + ioe);
|
||||
}
|
||||
|
||||
} catch (FriendlyException fe) {
|
||||
// grab the error message, we'll deal with it shortly
|
||||
errmsg = fe.getMessage();
|
||||
|
||||
} catch (Exception e) {
|
||||
errmsg = ExceptionMap.getMessage(e);
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
|
||||
// if we have an error message, insert it into the template
|
||||
if (errmsg != null) {
|
||||
// if we have an application, try using it to localize the
|
||||
// error message before we insert it
|
||||
if (app != null) {
|
||||
MessageManager msgmgr = app.getMessageManager();
|
||||
if (msgmgr != null) {
|
||||
errmsg = msgmgr.getMessage(ctx.getRequest(), errmsg);
|
||||
}
|
||||
}
|
||||
ctx.put(ERROR_KEY, errmsg);
|
||||
}
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference to the application that is handling this
|
||||
* request.
|
||||
*
|
||||
* @return The application in effect for this request or null if no
|
||||
* application was selected to handle the request.
|
||||
*/
|
||||
public static Application getApplication (WebContext context)
|
||||
{
|
||||
return (Application)context.get(APPLICATION_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to select the appropriate template for this
|
||||
* request. The default implementation simply loads the template using
|
||||
* WebMacro's default template loading services based on the URI
|
||||
* provided in the request. It is assumed that the document root is
|
||||
* registered in WebMacro's search path.
|
||||
*
|
||||
* @param ctx The context of this request.
|
||||
*
|
||||
* @return The template to be used in generating the response.
|
||||
*/
|
||||
protected Template selectTemplate (WebContext ctx)
|
||||
throws ResourceException
|
||||
{
|
||||
// String path = cleanupURI(ctx.getRequest().getRequestURI());
|
||||
String path = ctx.getRequest().getServletPath();
|
||||
// Log.info("Loading template [path=" + path + "].");
|
||||
return getTemplate(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects and returns the matching application for this request.
|
||||
*
|
||||
* @return the application that should handle this request or null if
|
||||
* no matching application could be found.
|
||||
*/
|
||||
protected Application selectApplication (String path)
|
||||
{
|
||||
// try to locate an application that matches this URI
|
||||
for (int i = 0; i < _apps.size(); i++) {
|
||||
Application app = (Application)_apps.get(i);
|
||||
if (app.matches(path)) {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to select the appropriate logic for this
|
||||
* request URI.
|
||||
*
|
||||
* @return The logic to be used in generating the response or null if
|
||||
* no logic could be matched.
|
||||
*/
|
||||
protected Logic resolveLogic (Application app, String path)
|
||||
{
|
||||
// look for a cached logic instance
|
||||
String lclass = app.generateClass(path);
|
||||
Logic logic = (Logic)_logic.get(lclass);
|
||||
|
||||
if (logic == null) {
|
||||
try {
|
||||
Class pcl = Class.forName(lclass);
|
||||
logic = (Logic)pcl.newInstance();
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.warning("Unable to instantiate logic for " +
|
||||
"matching application [path=" + path +
|
||||
", lclass=" + lclass + ", error=" + t + "].");
|
||||
// use a dummy in it's place so that we don't sit around
|
||||
// all day freaking out about our inability to instantiate
|
||||
// the proper logic class
|
||||
logic = new DummyLogic();
|
||||
}
|
||||
_logic.put(lclass, logic);
|
||||
}
|
||||
|
||||
return logic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because the URI can actually contain the protocol and server name,
|
||||
* though it commonly doesn't, we need to be sure to remove that extra
|
||||
* information before we look at the URI because we only want the path
|
||||
* part of the URI. The JSDK unfortunately doesn't provide an easy
|
||||
* mechanism to request just the path part of the URI.
|
||||
*/
|
||||
protected static String cleanupURI (String uri)
|
||||
{
|
||||
int dsidx = uri.indexOf("//");
|
||||
if (dsidx == -1) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
int sidx = uri.indexOf("/", dsidx + 2);
|
||||
if (sidx == -1) {
|
||||
Log.warning("Malformed URI?! [uri=" + uri + "].");
|
||||
return "/";
|
||||
}
|
||||
|
||||
return uri.substring(sidx);
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
System.out.println(cleanupURI("/whowhere/viewtrip.wm"));
|
||||
System.out.println(cleanupURI("http://samskivert.com/foo/bar/baz.wm"));
|
||||
System.out.println(cleanupURI("http://samskivert.com"));
|
||||
System.out.println(cleanupURI("http://samskivert.com/"));
|
||||
System.out.println(cleanupURI("//samskivert.com/is/this/even/legal"));
|
||||
}
|
||||
|
||||
protected ArrayList _apps = new ArrayList();
|
||||
protected HashMap _logic = new HashMap();
|
||||
|
||||
/** This is the key used in the context for error messages. */
|
||||
protected static final String ERROR_KEY = "error";
|
||||
|
||||
/**
|
||||
* This is the key used to store a reference back to the dispatcher
|
||||
* servlet in our web context.
|
||||
*/
|
||||
protected static final String APPLICATION_KEY = "%_app_%";
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// $Id: DummyLogic.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import org.webmacro.servlet.WebContext;
|
||||
|
||||
/**
|
||||
* The dummy logic is used as a placeholder for URIs that match no normal
|
||||
* logic or for which the matching logic could not be instantiated. It
|
||||
* does nothing.
|
||||
*/
|
||||
public class DummyLogic implements Logic
|
||||
{
|
||||
public void invoke (Application app, WebContext context) throws Exception
|
||||
{
|
||||
// we're such a dummy that we do absolutely nothing.
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
//
|
||||
// $Id: ExceptionMap.java,v 1.5 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.samskivert.Log;
|
||||
import com.samskivert.util.ConfigUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
/**
|
||||
* The exception map is used to map exceptions to error messages based on
|
||||
* a static, server-wide configuration.
|
||||
*
|
||||
* <p>The configuration file is loaded via the classpath. The file should
|
||||
* be named <code>exceptionmap.properties</code> and placed in the
|
||||
* classpath of the JVM in which the servlet is executed. The file should
|
||||
* contain colon-separated mappings from exception classes to friendly
|
||||
* error messages. For example:
|
||||
*
|
||||
* <pre>
|
||||
* # Exception mappings (lines beginning with # are ignored)
|
||||
* com.samskivert.webmacro.FriendlyException: An error occurred while \
|
||||
* processing your request: {m}
|
||||
*
|
||||
* # lines ending with \ are continued on the next line
|
||||
* java.sql.SQLException: The database is currently unavailable. Please \
|
||||
* try your request again later.
|
||||
*
|
||||
* java.lang.Exception: An unexpected error occurred while processing \
|
||||
* your request. Please try again later.
|
||||
* </pre>
|
||||
*
|
||||
* The message associated with the exception will be substituted into the
|
||||
* error string in place of <code>{m}</code>. The exceptions should be
|
||||
* listed in order of most to least specific, as the first mapping for
|
||||
* which the exception to report is an instance of the listed exception
|
||||
* will be used.
|
||||
*
|
||||
* <p><em>Note:</em> These exception mappings are used for all requests
|
||||
* (perhaps some day only for requests associated with a particular
|
||||
* application). Regardless, this error handling mechanism should not be
|
||||
* used for request specific errors. For example, an SQL exception
|
||||
* reporting a duplicate key should probably be caught and reported
|
||||
* specifically by the appropriate populator (it can still leverage the
|
||||
* pattern of inserting the error message into the context as
|
||||
* <code>"error"</code>) rather than relying on the default SQL exception
|
||||
* error message which is not likely to be meaningful for such a
|
||||
* situation.
|
||||
*
|
||||
* @see DispatcherServlet
|
||||
*/
|
||||
public class ExceptionMap
|
||||
{
|
||||
/**
|
||||
* Searches for the <code>exceptionmap.properties</code> file in the
|
||||
* classpath and loads it. If the file could not be found, an error is
|
||||
* reported and a default set of mappings is used.
|
||||
*/
|
||||
public static synchronized void init ()
|
||||
{
|
||||
// only initialize ourselves once
|
||||
if (_keys != null) {
|
||||
return;
|
||||
} else {
|
||||
_keys = new ArrayList();
|
||||
_values = new ArrayList();
|
||||
}
|
||||
|
||||
// first try loading the properties file without a leading slash
|
||||
ClassLoader cld = ExceptionMap.class.getClassLoader();
|
||||
InputStream config = ConfigUtil.getStream(PROPS_NAME, cld);
|
||||
if (config == null) {
|
||||
Log.warning("Unable to load " + PROPS_NAME + " from CLASSPATH.");
|
||||
|
||||
} else {
|
||||
// otherwise process ye old config file.
|
||||
try {
|
||||
// we'll do some serious jiggery pokery to leverage the
|
||||
// parsing implementation provided by
|
||||
// java.util.Properties. god bless method overloading
|
||||
Properties loader = new Properties() {
|
||||
public Object put (Object key, Object value)
|
||||
{
|
||||
_keys.add(key);
|
||||
_values.add(value);
|
||||
return key;
|
||||
}
|
||||
};
|
||||
loader.load(config);
|
||||
|
||||
// now cruise through and resolve the exceptions named as
|
||||
// keys and throw out any that don't appear to exist
|
||||
for (int i = 0; i < _keys.size(); i++) {
|
||||
String exclass = (String)_keys.get(i);
|
||||
try {
|
||||
Class cl = Class.forName(exclass);
|
||||
// replace the string with the class object
|
||||
_keys.set(i, cl);
|
||||
|
||||
} catch (Throwable t) {
|
||||
Log.warning("Unable to resolve exception class. " +
|
||||
"[class=" + exclass +
|
||||
", error=" + t + "].");
|
||||
_keys.remove(i);
|
||||
_values.remove(i);
|
||||
i--; // back on up a notch
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Error reading exception mapping file: " + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the supplied exception in the map and returns the most
|
||||
* specific error message available for exceptions of that class.
|
||||
*
|
||||
* @param ex The exception to resolve into an error message.
|
||||
*
|
||||
* @return The error message to which this exception maps (properly
|
||||
* populated with the message associated with this exception
|
||||
* instance).
|
||||
*/
|
||||
public static String getMessage (Throwable ex)
|
||||
{
|
||||
String msg = DEFAULT_ERROR_MSG;
|
||||
|
||||
for (int i = 0; i < _keys.size(); i++) {
|
||||
Class cl = (Class)_keys.get(i);
|
||||
if (cl.isInstance(ex)) {
|
||||
msg = (String)_values.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtil.replace(msg, MESSAGE_MARKER, ex.getMessage());
|
||||
}
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
ExceptionMap map = new ExceptionMap();
|
||||
System.out.println(map.getMessage(new Exception("Test error")));
|
||||
}
|
||||
|
||||
protected static List _keys;
|
||||
protected static List _values;
|
||||
|
||||
// initialize ourselves
|
||||
static { init(); }
|
||||
|
||||
protected static final String PROPS_NAME = "exceptionmap.properties";
|
||||
protected static final String DEFAULT_ERROR_MSG = "Error: {m}";
|
||||
protected static final String MESSAGE_MARKER = "{m}";
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
//
|
||||
// $Id: FormUtil.java,v 1.6 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import com.samskivert.Log;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import org.webmacro.servlet.WebContext;
|
||||
|
||||
/**
|
||||
* The form util class provides handy functions for doing form-related
|
||||
* stuff.
|
||||
*/
|
||||
public class FormUtil
|
||||
{
|
||||
/**
|
||||
* Fetches the supplied parameter from the request and converts it to
|
||||
* an integer. If the parameter does not exist or is not a well-formed
|
||||
* integer, a data validation exception is thrown with the supplied
|
||||
* message.
|
||||
*/
|
||||
public static int requireIntParameter (WebContext context, String name,
|
||||
String invalidDataMessage)
|
||||
throws DataValidationException
|
||||
{
|
||||
String value = context.getForm(name);
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new DataValidationException(invalidDataMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the supplied parameter from the request. If the parameter
|
||||
* does not exist, a data validation exception is thrown with the
|
||||
* supplied message.
|
||||
*/
|
||||
public static String requireParameter (WebContext context, String name,
|
||||
String missingDataMessage)
|
||||
throws DataValidationException
|
||||
{
|
||||
String value = context.getForm(name);
|
||||
if (StringUtil.blank(value)) {
|
||||
throw new DataValidationException(missingDataMessage);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the supplied parameter from the request and converts it to
|
||||
* a date. The value of the parameter should be a date formatted like
|
||||
* so: 2001-12-25. If the parameter does not exist or is not a
|
||||
* well-formed date, a data validation exception is thrown with the
|
||||
* supplied message.
|
||||
*/
|
||||
public static Date requireDateParameter (WebContext context, String name,
|
||||
String invalidDataMessage)
|
||||
throws DataValidationException
|
||||
{
|
||||
return parseDateParameter(context.getForm(name), invalidDataMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the supplied parameter from the request. If the parameter
|
||||
* does not exist, either null or the empty string will be returned
|
||||
* depending on the value of the <code>returnNull</code> parameter.
|
||||
*/
|
||||
public static String getParameter (WebContext context, String name,
|
||||
boolean returnNull)
|
||||
{
|
||||
String value = context.getForm(name);
|
||||
if (returnNull || !StringUtil.blank(value)) {
|
||||
return value;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the supplied parameter from the request and converts it to
|
||||
* a date. The value of the parameter should be a date formatted like
|
||||
* so: 2001-12-25. If the parameter does not exist, null is
|
||||
* returned. If the parameter is not a well-formed date, a data
|
||||
* validation exception is thrown with the supplied message.
|
||||
*/
|
||||
public static Date getDateParameter (WebContext context, String name,
|
||||
String invalidDataMessage)
|
||||
throws DataValidationException
|
||||
{
|
||||
String value = context.getForm(name);
|
||||
if (StringUtil.blank(value)) {
|
||||
return null;
|
||||
}
|
||||
return parseDateParameter(value, invalidDataMessage);
|
||||
}
|
||||
|
||||
protected static
|
||||
Date parseDateParameter (String value, String invalidDataMessage)
|
||||
throws DataValidationException
|
||||
{
|
||||
Date date = null;
|
||||
|
||||
try {
|
||||
if (value != null) {
|
||||
date = _dparser.parse(value);
|
||||
}
|
||||
} catch (ParseException pe) {
|
||||
// fall through with date == null
|
||||
Log.info("Date parsing failed: " + pe);
|
||||
}
|
||||
|
||||
// freak out if we failed to parse the date for some reason
|
||||
if (date == null) {
|
||||
throw new DataValidationException(invalidDataMessage);
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified parameter is set in the request
|
||||
* context.
|
||||
*
|
||||
* @return true if the specified parameter is set in the request
|
||||
* context, false otherwise.
|
||||
*/
|
||||
public static boolean isSet (WebContext context, String name)
|
||||
{
|
||||
return !StringUtil.blank(context.getForm(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified parameter is equal to the supplied
|
||||
* value. If the parameter is not set in the request context, false is
|
||||
* returned.
|
||||
*
|
||||
* @param context The request context.
|
||||
* @param name The parameter whose value should be compared with the
|
||||
* supplied value.
|
||||
* @param value The value to which the parameter may be equal. This
|
||||
* should not be null.
|
||||
*
|
||||
* @return true if the specified parameter is equal to the supplied
|
||||
* parameter, false otherwise.
|
||||
*/
|
||||
public static boolean equals (WebContext context, String name,
|
||||
String value)
|
||||
{
|
||||
return value.equals(context.getForm(name));
|
||||
}
|
||||
|
||||
/** We use this to parse dates in requireDateParameter(). */
|
||||
protected static SimpleDateFormat _dparser =
|
||||
new SimpleDateFormat("yyyy-MM-dd");
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// $Id: FriendlyException.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
/**
|
||||
* The friendly exception provides a mechanism by which a servlet can
|
||||
* abort its processing and report a human readable error to the servlet
|
||||
* framework that will be inserted into the context in the appropriate
|
||||
* place so that the error message will be displayed to the user. Simply
|
||||
* construct a friendly exception with the desired error message and throw
|
||||
* it during the call to <code>populateContext</code>.
|
||||
*
|
||||
* @see DispatcherServlet
|
||||
*/
|
||||
public class FriendlyException extends Exception
|
||||
{
|
||||
public FriendlyException (String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
//
|
||||
// $Id: Logic.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import org.webmacro.servlet.WebContext;
|
||||
|
||||
/**
|
||||
* The logic class is called upon to populate the WebMacro web context,
|
||||
* prior to invoking a particular WebMacro template upon it to generate a
|
||||
* response page. The logic takes the place of the servlet in the standard
|
||||
* WebMacro architecture and should perform all of the logic involved in
|
||||
* handling a particular request.
|
||||
*
|
||||
* @see DispatcherServlet
|
||||
*/
|
||||
public interface Logic
|
||||
{
|
||||
/**
|
||||
* Perform any necessary computation and populate the context with
|
||||
* data for this request. Any exceptions that are thrown will be
|
||||
* converted into friendly error messages using the exception mapping
|
||||
* services.
|
||||
*
|
||||
* @param app The application that generated this logic instance (used
|
||||
* to access application-wide resources).
|
||||
* @param context The WebMacro context in scope for this request.
|
||||
*
|
||||
* @see ExceptionMap
|
||||
*/
|
||||
public void invoke (Application app, WebContext context) throws Exception;
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
//
|
||||
// $Id: MsgTool.java,v 1.3 2001/08/11 22:43:29 mdb Exp $
|
||||
//
|
||||
// samskivert library - useful routines for java programs
|
||||
// Copyright (C) 2001 Michael Bayne
|
||||
//
|
||||
// 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.webmacro;
|
||||
|
||||
import org.webmacro.*;
|
||||
import org.webmacro.servlet.WebContext;
|
||||
import org.webmacro.util.PropertyObject;
|
||||
import org.webmacro.util.PropertyMethod;
|
||||
|
||||
import com.samskivert.Log;
|
||||
import com.samskivert.servlet.MessageManager;
|
||||
|
||||
/**
|
||||
* The message tool maps a set of appliation messages (translation
|
||||
* strings) into the context so that they are available to templates that
|
||||
* wish to display localized text.
|
||||
*/
|
||||
public class MsgTool implements ContextTool
|
||||
{
|
||||
/**
|
||||
* Loads up the message resources and inserts them into the context.
|
||||
*/
|
||||
public Object init (Context ctx)
|
||||
throws InvalidContextException
|
||||
{
|
||||
try {
|
||||
WebContext wctx = (WebContext)ctx;
|
||||
|
||||
// get a handle on the application in effect for this request
|
||||
Application app = DispatcherServlet.getApplication(wctx);
|
||||
if (app == null) {
|
||||
String err = "No application in effect for this request. " +
|
||||
"Can't resolve messages without an application.";
|
||||
throw new InvalidContextException(err);
|
||||
}
|
||||
|
||||
// get the message manager from the application
|
||||
MessageManager msgmgr = app.getMessageManager();
|
||||
if (msgmgr == null) {
|
||||
String err = "Application did not provide a message " +
|
||||
"manager. Can't resolve messages without one.";
|
||||
throw new InvalidContextException(err);
|
||||
}
|
||||
|
||||
// then create a wrapper that allows webmacro to access it
|
||||
return new Wrapper(msgmgr);
|
||||
|
||||
} catch (ClassCastException cce) {
|
||||
throw new InvalidContextException("MsgTool requires a WebContext");
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy (Object obj)
|
||||
{
|
||||
// nothing to clean up
|
||||
}
|
||||
|
||||
public static class Wrapper implements PropertyObject
|
||||
{
|
||||
public Wrapper (MessageManager msgmgr)
|
||||
{
|
||||
_msgmgr = msgmgr;
|
||||
}
|
||||
|
||||
public Object getProperty (Context context, Object[] names, int offset)
|
||||
throws PropertyException, SecurityException
|
||||
{
|
||||
StringBuffer path = new StringBuffer();
|
||||
boolean bogus = false;
|
||||
int lastidx = names.length-1;
|
||||
WebContext wctx = (WebContext)context;
|
||||
|
||||
// reconstruct the path to the property
|
||||
for (int i = offset; i < names.length; i++) {
|
||||
// separate components with dots
|
||||
if (path.length() > 0) {
|
||||
path.append(".");
|
||||
}
|
||||
|
||||
// each name should either be a PropertyMethod or a string
|
||||
// or an object that can be toString()ed
|
||||
if (names[i] instanceof PropertyMethod) {
|
||||
// make a note to freak out if this is anything but
|
||||
// the last component of the path. we'd freak out now
|
||||
// but we want to reconstruct the path so that we can
|
||||
// report it in the exception that's thrown
|
||||
if (i != lastidx) {
|
||||
bogus = true;
|
||||
}
|
||||
path.append(((PropertyMethod)names[i]).getName());
|
||||
|
||||
} else {
|
||||
path.append(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// do any pending freaking out
|
||||
if (bogus) {
|
||||
throw new PropertyException("Invalid message resource " +
|
||||
"path: " + path);
|
||||
}
|
||||
|
||||
// if the last component is a property method, we want to use
|
||||
// it's arguments when looking up the message
|
||||
if (names[lastidx] instanceof PropertyMethod) {
|
||||
PropertyMethod pm = (PropertyMethod)names[lastidx];
|
||||
// we may cache message formatters later, but for now just
|
||||
// use the static convenience function
|
||||
Object[] args = pm.getArguments(context);
|
||||
return _msgmgr.getMessage(wctx.getRequest(),
|
||||
path.toString(), args);
|
||||
|
||||
} else {
|
||||
// otherwise just look up the path
|
||||
return _msgmgr.getMessage(wctx.getRequest(), path.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setProperty (Context context, Object[] names, int offset,
|
||||
Object value)
|
||||
throws PropertyException, SecurityException
|
||||
{
|
||||
throw new PropertyException("Setting a message resource " +
|
||||
"is not supported!");
|
||||
}
|
||||
|
||||
protected MessageManager _msgmgr;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
$Id: package.html,v 1.2 2001/08/12 01:45:46 mdb Exp $
|
||||
|
||||
samskivert library - useful routines for java programs
|
||||
Copyright (C) 2001 Michael Bayne
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
Provides parts of a simple web application framework built around the
|
||||
WebMacro template engine.
|
||||
|
||||
<p> The web application framework provided by this package is simple
|
||||
and intended for use in small projects with limited scope. It is not
|
||||
intended to be all things, nor to evolve into something that makes
|
||||
toast. It builds upon WebMacro, a template engine whose
|
||||
<a href="http://www.webmacro.org/WebMacroMotivation">philosophies</a>
|
||||
about the separation of markup and code I agree with.
|
||||
|
||||
<p> WebMacro is designed to be used explicitly by servlets in
|
||||
applications where the design is structured around the servlets
|
||||
rather than the pages generated by the servlets. This is in contrast
|
||||
to the JSP approach where the pages themselves dictate the structure
|
||||
of the application and the servlets are automatically generated to
|
||||
conform to that structure. This package provides a means by which to
|
||||
automatically map serlvet-like units of code to templates in a way
|
||||
akin to JSP's approach but without the combination of code and
|
||||
markup.
|
||||
|
||||
<p>I'd document this more, but I'm probably going to start using
|
||||
<a href="http://jakarta.apache.org/turbine/">Turbine</a> and abandon
|
||||
this framework next time I get around to working on web
|
||||
applications.
|
||||
|
||||
<h2>Related Documentation</h2>
|
||||
|
||||
<a href="http://www.webmacro.org/">WebMacro website</a>.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user