Author: rich
Date: Wed Sep 15 10:04:24 2004
New Revision: 46123
Modified:
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/JpfLanguageConstants.java
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionOutputModel.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/CachedPageFlowInfo.java
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
Log:
- Added a 'required' attribute on @Jpf.ActionOutput, to replace 'nullable'
(deprecated).
- Fixed an NPE that occurred when calling FlowControllerFactory.getPageFlow()
on a page flow class whose Struts module has not yet been registered.
- Re-added some protected methods that were lost when FlowController broke its
inheritance from org.apache.struts.action.Action.
DRT: netui (WinXP)
BB: self (linux)
Modified:
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/JpfLanguageConstants.java
==============================================================================
---
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/JpfLanguageConstants.java
(original)
+++
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/JpfLanguageConstants.java
Wed Sep 15 10:04:24 2004
@@ -123,6 +123,7 @@
public static final String BUNDLE_KEY_ATTR = "bundleKey";
public static final String ACTION_OUTPUTS_ATTR = "actionOutputs";
public static final String NULLABLE_ATTR = "nullable";
+ public static final String REQUIRED_ATTR = "required";
public static final String USE_FORM_BEAN_ATTR = "useFormBean";
public static final String READONLY_ATTR = "readOnly";
public static final String RESTORE_QUERY_STRING_ATTR =
"restoreQueryString";
Modified:
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionOutputModel.java
==============================================================================
---
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionOutputModel.java
(original)
+++
incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/netui/compiler/genmodel/GenActionOutputModel.java
Wed Sep 15 10:04:24 2004
@@ -34,7 +34,12 @@
public GenActionOutputModel( AnnotationMirror annotation, ClassDeclaration
jclass )
{
setName( CompilerUtils.getString( annotation, NAME_ATTR, true ) );
- setNullable( CompilerUtils.getBoolean( annotation, NULLABLE_ATTR,
false ).booleanValue() );
+
+ Boolean required = CompilerUtils.getBoolean( annotation,
REQUIRED_ATTR, true );
+ boolean nullable =
+ required != null ? ! required : CompilerUtils.getBoolean(
annotation, NULLABLE_ATTR, false );
+
+ setNullable( nullable );
//
// Get the base type, and add "[]" to it for arrays.
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java
Wed Sep 15 10:04:24 2004
@@ -24,15 +24,20 @@
import org.apache.beehive.netui.pageflow.internal.InternalUtils;
import org.apache.beehive.netui.pageflow.internal.InternalExpressionUtils;
import org.apache.beehive.netui.pageflow.internal.RequestValues;
-import org.apache.beehive.netui.pageflow.handler.LoginHandler;
+import org.apache.beehive.netui.pageflow.annotations.Jpf;import
org.apache.beehive.netui.pageflow.handler.LoginHandler;
import org.apache.beehive.netui.pageflow.handler.ExceptionsHandler;
import org.apache.beehive.netui.util.cache.ClassLevelCache;
import org.apache.beehive.netui.util.logging.Logger;
import org.apache.struts.Globals;
+import org.apache.struts.util.TokenProcessor;
+import org.apache.struts.util.MessageResources;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionMessages;
import org.apache.struts.config.ActionConfig;
import org.apache.struts.config.ModuleConfig;
@@ -42,6 +47,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.sql.DataSource;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
@@ -67,6 +73,26 @@
private static final String DEFAULT_SIMPLE_ACTION_FORWARD_NAME =
"_defaultForward";
private static final Locale DEFAULT_LOCALE = Locale.getDefault();
private static final ActionForward NULL_ACTION_FORWARD = new
ActionForward();
+ private static final TokenProcessor TOKEN_PROCESSOR =
TokenProcessor.getInstance();
+
+ /**
+ * The system default Locale.
+ *
+ * @deprecated Use [EMAIL PROTECTED] #getDefaultLocale}.
+ */
+ protected static Locale defaultLocale = DEFAULT_LOCALE;
+
+
+ /**
+ * Get the current Struts ActionServlet.
+ *
+ * @deprecated This variable will be removed with no replacement. In most
cases,
+ * [EMAIL PROTECTED] FlowController#getServletContext()} is
sufficient; for other cases, the ActionServlet itself
+ * is in the ServletContext attribute [EMAIL PROTECTED]
Globals#ACTION_SERVLET_KEY}.
+ */
+ protected transient ActionServlet servlet = null;
+
+
static class PerRequestState
@@ -133,6 +159,7 @@
// isn't available to do a lazy initialization.
//
initModuleConfig( servletContext, request );
+ servlet = getServlet();
super.reinitialize( request, response, servletContext );
}
@@ -192,16 +219,6 @@
InternalUtils.sendError( "PageFlow_Custom_Error", request, response,
null, getDisplayName(), errText );
}
- public static Locale retrieveUserLocale( HttpServletRequest request,
String locale )
- {
- if ( locale == null ) locale = Globals.LOCALE_KEY;
- HttpSession session = request.getSession( false );
- Locale userLocale = null;
- if ( session != null ) userLocale = ( Locale ) session.getAttribute(
locale );
- if ( userLocale == null ) userLocale = DEFAULT_LOCALE;
- return userLocale;
- }
-
/**
* Handle the given exception - invoke user code if appropriate and return
a destination URI.
*
@@ -1495,5 +1512,297 @@
return new Forward( DEFAULT_SIMPLE_ACTION_FORWARD_NAME );
}
+
+ /**
+ * Get the system default locale.
+ *
+ * @return the system default locale.
+ */
+ protected static Locale getDefaultLocale()
+ {
+ return defaultLocale;
+ }
+
+
+ /**
+ * Generate a new transaction token, to be used for enforcing a single
request for a particular transaction.
+ * @deprecated Use
+ *
+ * @param request the current request.
+ */
+ protected String generateToken(HttpServletRequest request) {
+ return TOKEN_PROCESSOR.generateToken(request);
+ }
+
+ /**
+ * Return the default data source for the module associated with this page
flow.
+ *
+ * @param request the current request.
+ */
+ protected DataSource getDataSource(HttpServletRequest request) {
+
+ return getDataSource(request, Globals.DATA_SOURCE_KEY);
+
+ }
+
+ /**
+ * Return the specified data source for the current module.
+ *
+ * @param request The servlet request we are processing
+ * @param key The key specified in the
+ * <code><message-resources></code> element for the
+ * requested bundle
+ */
+ protected DataSource getDataSource(HttpServletRequest request, String key)
{
+
+ ModuleConfig moduleConfig = getModuleConfig();
+
+ // Return the requested data source instance
+ return (DataSource) getServletContext().getAttribute( key +
moduleConfig.getPrefix() );
+
+ }
+
+
+ /**
+ * Return the user's currently selected Locale.
+ * @deprecated Use [EMAIL PROTECTED] #getLocale()}.
+ *
+ * @param request the current request.
+ * @return the user's currently selected Locale, stored in the session.
+ */
+ protected Locale getLocale(HttpServletRequest request) {
+
+ HttpSession session = request.getSession();
+ Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
+ return locale != null ? locale : DEFAULT_LOCALE;
+ }
+
+ /**
+ * Return the user's currently selected Locale.
+ *
+ * @return the user's currently selected Locale, stored in the session.
+ */
+ protected Locale getLocale()
+ {
+ Locale locale = (Locale) getSession().getAttribute(Globals.LOCALE_KEY);
+ return locale != null ? locale : DEFAULT_LOCALE;
+ }
+
+ public static Locale retrieveUserLocale( HttpServletRequest request,
String locale )
+ {
+ if ( locale == null ) locale = Globals.LOCALE_KEY;
+ HttpSession session = request.getSession( false );
+ Locale userLocale = null;
+ if ( session != null ) userLocale = ( Locale ) session.getAttribute(
locale );
+ if ( userLocale == null ) userLocale = DEFAULT_LOCALE;
+ return userLocale;
+ }
+
+ /**
+ * Return the message resources for the default module.
+ *
+ * @deprecated This method can only return the resources for the default
+ * module. Use getResources(HttpServletRequest) to get the
+ * resources for the current module.
+ */
+ protected MessageResources getResources() {
+
+ return (MessageResources)
+ getServletContext().getAttribute(Globals.MESSAGES_KEY);
+
+ }
+
+
+ /**
+ * Return the default message resources for the current module.
+ *
+ * @param request The servlet request we are processing
+ */
+ protected MessageResources getResources(HttpServletRequest request) {
+
+ return ((MessageResources) request.getAttribute(Globals.MESSAGES_KEY));
+
+ }
+
+
+
+ /**
+ * Return the specified message resources for the current module.
+ *
+ * @param request the current request.
+ * @param key The bundle key specified in a
+ * [EMAIL PROTECTED] Jpf.MessageResource} annotation.
+ * <code><message-resources></code> element for the
+ * requested bundle
+ *
+ * @since Struts 1.1
+ */
+ protected MessageResources getResources(HttpServletRequest request,
+ String key) {
+
+ return ((MessageResources) getServletContext().getAttribute
+ (key + getModuleConfig().getPrefix()));
+
+ }
+
+ /**
+ * <p>Returns <code>true</code> if the current form's cancel button was
+ * pressed. This method will check if the <code>Globals.CANCEL_KEY</code>
+ * request attribute has been set, which normally occurs if the cancel
+ * button generated by <strong>CancelTag</strong> was pressed by the user
+ * in the current request. If <code>true</code>, validation performed
+ * by an <strong>ActionForm</strong>'s <code>validate()</code> method
+ * will have been skipped by the controller servlet.</p>
+ *
+ * @param request The servlet request we are processing
+ * @see org.apache.struts.taglib.html.CancelTag
+ */
+ protected boolean isCancelled(HttpServletRequest request) {
+
+ return (request.getAttribute(Globals.CANCEL_KEY) != null);
+
+ }
+
+
+ /**
+ * Return <code>true</code> if there is a transaction token stored in
+ * the user's current session, and the value submitted as a request
+ * parameter with this action matches it. Returns <code>false</code>
+ * under any of the following circumstances:
+ * <ul>
+ * <li>No session associated with this request</li>
+ * <li>No transaction token saved in the session</li>
+ * <li>No transaction token included as a request parameter</li>
+ * <li>The included transaction token value does not match the
+ * transaction token in the user's session</li>
+ * </ul>
+ *
+ * @param request The servlet request we are processing
+ */
+ protected boolean isTokenValid(HttpServletRequest request) {
+
+ return TOKEN_PROCESSOR.isTokenValid(request, false);
+
+ }
+
+
+ /**
+ * Return <code>true</code> if there is a transaction token stored in
+ * the user's current session, and the value submitted as a request
+ * parameter with this action matches it. Returns <code>false</code>
+ * <ul>
+ * <li>No session associated with this request</li>
+ * <li>No transaction token saved in the session</li>
+ * <li>No transaction token included as a request parameter</li>
+ * <li>The included transaction token value does not match the
+ * transaction token in the user's session</li>
+ * </ul>
+ *
+ * @param request The servlet request we are processing
+ * @param reset Should we reset the token after checking it?
+ */
+ protected boolean isTokenValid(
+ HttpServletRequest request,
+ boolean reset) {
+
+ return TOKEN_PROCESSOR.isTokenValid(request, reset);
+ }
+
+
+ /**
+ * Reset the saved transaction token in the user's session. This
+ * indicates that transactional token checking will not be needed
+ * on the next request that is submitted.
+ *
+ * @param request The servlet request we are processing
+ */
+ protected void resetToken(HttpServletRequest request) {
+ TOKEN_PROCESSOR.resetToken(request);
+ }
+
+
+ /**
+ * Save the specified error messages keys into the appropriate request
+ * attribute for use by the <html:errors> tag, if any messages
+ * are required. Otherwise, ensure that the request attribute is not
+ * created.
+ *
+ * @param request The servlet request we are processing
+ * @param errors Error messages object
+ */
+ protected void saveErrors(HttpServletRequest request,
+ ActionErrors errors) {
+
+ // Remove any error messages attribute if none are required
+ if (errors == null || errors.isEmpty()) {
+ request.removeAttribute(Globals.ERROR_KEY);
+ return;
+ }
+
+ // Save the error messages we need
+ request.setAttribute(Globals.ERROR_KEY, errors);
+
+ }
+
+
+ /**
+ * Save the specified messages keys into the appropriate request
+ * attribute for use by the <html:messages> tag (if
+ * messages="true" is set), if any messages are required. Otherwise,
+ * ensure that the request attribute is not created.
+ *
+ * @param request The servlet request we are processing
+ * @param messages Messages object
+ * @since Struts 1.1
+ */
+ protected void saveMessages(HttpServletRequest request,
+ ActionMessages messages) {
+
+ // Remove any messages attribute if none are required
+ if (messages == null || messages.isEmpty()) {
+ request.removeAttribute(Globals.MESSAGE_KEY);
+ return;
+ }
+
+ // Save the messages we need
+ request.setAttribute(Globals.MESSAGE_KEY, messages);
+
+ }
+
+
+ /**
+ * Save a new transaction token in the user's current session, creating
+ * a new session if necessary.
+ *
+ * @param request The servlet request we are processing
+ */
+ protected void saveToken(HttpServletRequest request) {
+ TOKEN_PROCESSOR.saveToken(request);
+ }
+
+
+ /**
+ * Set the user's currently selected Locale.
+ * @deprecated Use [EMAIL PROTECTED] #setLocale(java.util.Locale)}.
+ *
+ * @param request The request we are processing
+ * @param locale The user's selected Locale to be set, or null
+ * to select the server's default Locale
+ */
+ protected void setLocale(HttpServletRequest request, Locale locale) {
+
+ HttpSession session = request.getSession();
+ if (locale == null) {
+ locale = defaultLocale;
+ }
+ session.setAttribute(Globals.LOCALE_KEY, locale);
+
+ }
+
+ protected void setLocale( Locale locale )
+ {
+ if ( locale == null ) locale = getDefaultLocale();
+ getSession().setAttribute( Globals.LOCALE_KEY, locale );
+ }
}
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowControllerFactory.java
Wed Sep 15 10:04:24 2004
@@ -25,8 +25,12 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
import org.apache.struts.config.ModuleConfig;
+import org.apache.struts.action.ActionServlet;
+
+import java.io.IOException;
/**
@@ -178,6 +182,37 @@
}
}
+ private static ModuleConfig ensureModule( String modulePath,
HttpServletRequest request,
+ ServletContext servletContext )
+ {
+ ModuleConfig mc = InternalUtils.getModuleConfig( modulePath,
servletContext );
+
+ if ( mc == null )
+ {
+ ActionServlet as = InternalUtils.getActionServlet( servletContext
);
+
+ if ( as instanceof AutoRegisterActionServlet )
+ {
+ AutoRegisterActionServlet das = ( AutoRegisterActionServlet )
as;
+
+ try
+ {
+ return das.ensureModuleRegistered( modulePath, request );
+ }
+ catch ( IOException e )
+ {
+ _log.error( "Could not register Struts module for path " +
modulePath, e );
+ }
+ catch ( ServletException e )
+ {
+ _log.error( "Could not register Struts module for path " +
modulePath, e.getRootCause() );
+ }
+ }
+ }
+
+ return null;
+ }
+
/**
* Get the [EMAIL PROTECTED] PageFlowController} for the given type. The
PageFlowController stack (for
* nesting) will be cleared or pushed, and the new instance will be stored
as the current
@@ -203,10 +238,15 @@
// PageFlowUtils.getCurrentPageFlow again, with the singleton flag.
//
PageFlowController retVal = null;
- String modulePath = PageFlowUtils.getModulePath( request );
- ModuleConfig mc = InternalUtils.getModuleConfig( modulePath,
servletContext );
- boolean createdNew = false;
- assert mc != null : "no module config for page flow class " +
jpfClass.getName();
+ String modulePath = InternalUtils.inferModulePathFromClassName(
jpfClass.getName() );
+ ModuleConfig mc = ensureModule( modulePath, request,
servletContext );
+
+ if ( mc == null )
+ {
+ _log.error( "Struts module " + modulePath + " not found for "
+ jpfClass.getName()
+ + "; cannot create page flow.");
+ return null;
+ }
if ( InternalUtils.isSingleton( mc ) )
{
@@ -233,6 +273,7 @@
// PageFlowController.forwardTo(). Nested page flows can only
self-nest by forwarding to the .jpf URI, not
// indirectly by executing actions on themselves (think about it
-- that would be a disaster).
//
+ boolean createdNew = false;
boolean isNestable = InternalUtils.isNestable( mc );
PageFlowStack pfStack = PageFlowStack.get( request, false );
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.java
Wed Sep 15 10:04:24 2004
@@ -388,6 +388,8 @@
{
String name();
Class type();
+ boolean required() default true;
+ /** @deprecated Use [EMAIL PROTECTED] #required}. **/
boolean nullable() default false;
}
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/CachedPageFlowInfo.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/CachedPageFlowInfo.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/CachedPageFlowInfo.java
Wed Sep 15 10:04:24 2004
@@ -73,17 +73,7 @@
//
// module path
//
- int lastDot = className.lastIndexOf( '.' );
-
- if ( lastDot != -1 )
- {
- className = className.substring( 0, lastDot );
- _modulePath = "/" + className.replace( '.', '/' );
- }
- else
- {
- _modulePath = "";
- }
+ _modulePath = InternalUtils.inferModulePathFromClassName( className );
}
public String getModulePath()
Modified:
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
==============================================================================
---
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
(original)
+++
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/InternalUtils.java
Wed Sep 15 10:04:24 2004
@@ -1003,4 +1003,19 @@
return null;
}
+
+ public static String inferModulePathFromClassName( String className )
+ {
+ int lastDot = className.lastIndexOf( '.' );
+
+ if ( lastDot != -1 )
+ {
+ className = className.substring( 0, lastDot );
+ return '/' + className.replace( '.', '/' );
+ }
+ else
+ {
+ return "";
+ }
+ }
}