1266 lines
48 KiB
Java
1266 lines
48 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You 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.
|
|
*
|
|
* $Header:$
|
|
*/
|
|
package org.apache.beehive.netui.pageflow.internal;
|
|
|
|
import org.apache.beehive.netui.util.internal.InternalStringBuilder;
|
|
|
|
import org.apache.beehive.netui.pageflow.*;
|
|
import org.apache.beehive.netui.pageflow.config.PageFlowActionMapping;
|
|
import org.apache.beehive.netui.pageflow.config.PageFlowControllerConfig;
|
|
import org.apache.beehive.netui.pageflow.config.PageFlowActionFormBean;
|
|
import org.apache.beehive.netui.pageflow.config.DelegatingActionMapping;
|
|
import org.apache.beehive.netui.pageflow.config.DelegatingExceptionConfig;
|
|
import org.apache.beehive.netui.pageflow.handler.Handlers;
|
|
import org.apache.beehive.netui.pageflow.handler.ReloadableClassHandler;
|
|
import org.apache.beehive.netui.pageflow.handler.StorageHandler;
|
|
import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
|
|
import org.apache.beehive.netui.util.Bundle;
|
|
import org.apache.beehive.netui.util.internal.ServletUtils;
|
|
import org.apache.beehive.netui.util.config.ConfigUtil;
|
|
import org.apache.beehive.netui.util.config.bean.MultipartHandler;
|
|
import org.apache.beehive.netui.util.config.bean.PageFlowConfig;
|
|
import org.apache.beehive.netui.util.logging.Logger;
|
|
import org.apache.struts.Globals;
|
|
import org.apache.struts.util.MessageResources;
|
|
import org.apache.struts.action.*;
|
|
import org.apache.struts.config.ActionConfig;
|
|
import org.apache.struts.config.ControllerConfig;
|
|
import org.apache.struts.config.FormBeanConfig;
|
|
import org.apache.struts.config.ModuleConfig;
|
|
import org.apache.struts.config.MessageResourcesConfig;
|
|
import org.apache.struts.config.ExceptionConfig;
|
|
import org.apache.struts.upload.MultipartRequestWrapper;
|
|
|
|
import javax.servlet.ServletContext;
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.ServletRequest;
|
|
import javax.servlet.ServletResponse;
|
|
import javax.servlet.jsp.JspContext;
|
|
import javax.servlet.jsp.PageContext;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpSession;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
import java.util.Locale;
|
|
|
|
public class InternalUtils
|
|
implements PageFlowConstants, InternalConstants
|
|
{
|
|
private static final Logger _log = Logger.getInstance( InternalUtils.class );
|
|
|
|
private static final String BEA_XMLOBJECT_CLASSNAME = "com.bea.xml.XmlObject";
|
|
private static final String APACHE_XMLOBJECT_CLASSNAME = "org.apache.xmlbeans.XmlObject";
|
|
private static final Class BEA_XMLOBJECT_CLASS = loadClassNonFatal( BEA_XMLOBJECT_CLASSNAME );
|
|
private static final Class APACHE_XMLOBJECT_CLASS = loadClassNonFatal( APACHE_XMLOBJECT_CLASSNAME );
|
|
private static final String LONGLIVED_PAGEFLOWS_ATTR_PREFIX = ATTR_PREFIX + "longLivedPageFlow:";
|
|
private static final String ACTIONOUTPUT_MAP_ATTR = ATTR_PREFIX + "actionOutputs";
|
|
private static final String BINDING_UPDATE_ERRORS_ATTR = ATTR_PREFIX + "bindingUpdateErrors";
|
|
private static final String SHARED_FLOW_CLASSNAME_ATTR = ATTR_PREFIX + "sharedFlowClass";
|
|
private static final String SERVLET_CONTEXT_ATTR = ATTR_PREFIX + "servletContext";
|
|
private static final String AVOID_DIRECT_RESPONSE_OUTPUT_ATTR = ATTR_PREFIX + "_avoidDirectResponseOutput";
|
|
private static final String FORWARDED_FORMBEAN_ATTR = ATTR_PREFIX + "forwardedForm";
|
|
private static final String FORWARDING_MODULE_ATTR = ATTR_PREFIX + "fwdModule";
|
|
private static final String IGNORE_INCLUDE_SERVLET_PATH_ATTR = ATTR_PREFIX + "ignoreIncludeServletPath";
|
|
|
|
|
|
/**
|
|
* If not in production mode, write an error to the response; otherwise, set a response error code.
|
|
*/
|
|
public static void sendDevTimeError( String messageKey, Throwable cause, int productionTimeErrorCode,
|
|
ServletRequest request, ServletResponse response,
|
|
ServletContext servletContext, Object[] messageArgs )
|
|
throws IOException
|
|
{
|
|
sendDevTimeError( messageKey, messageArgs, cause, productionTimeErrorCode, request, response, servletContext );
|
|
}
|
|
|
|
/**
|
|
* If not in production mode, write an error to the response; otherwise, set a response error code.
|
|
* @deprecated Use {@link #sendDevTimeError(String, Throwable, int, ServletRequest, ServletResponse, ServletContext, Object[])}
|
|
*/
|
|
public static void sendDevTimeError( String messageKey, Object[] messageArgs, Throwable cause,
|
|
int productionTimeErrorCode, ServletRequest request,
|
|
ServletResponse response, ServletContext servletContext )
|
|
throws IOException
|
|
{
|
|
boolean prodMode = AdapterManager.getServletContainerAdapter( servletContext ).isInProductionMode();
|
|
boolean avoidDirectResponseOutput = avoidDirectResponseOutput( request );
|
|
|
|
if ( prodMode && ! avoidDirectResponseOutput && response instanceof HttpServletResponse )
|
|
{
|
|
if ( _log.isErrorEnabled() )
|
|
{
|
|
_log.error( "Error (message key " + messageKey + ") occurred. Response error was set to "
|
|
+ productionTimeErrorCode, cause );
|
|
}
|
|
|
|
( ( HttpServletResponse ) response ).sendError( productionTimeErrorCode );
|
|
}
|
|
else
|
|
{
|
|
sendError( messageKey, messageArgs, request, response, cause, prodMode || avoidDirectResponseOutput );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write an error to the response.
|
|
*/
|
|
public static void sendError( String messageKey, Throwable cause, ServletRequest request,
|
|
HttpServletResponse response, Object[] messageArgs )
|
|
throws IOException
|
|
{
|
|
// TODO: the following null check will be unnecessary once the deprecated
|
|
// FlowController.sendError(String, HttpServletResponse) is removed.
|
|
boolean avoidDirectResponseOutput = request != null ? avoidDirectResponseOutput( request ) : false;
|
|
sendError( messageKey, messageArgs, request, response, cause, avoidDirectResponseOutput );
|
|
}
|
|
|
|
/**
|
|
* Write an error to the response.
|
|
*/
|
|
public static void sendError( String messageKey, Object[] messageArgs, ServletRequest request,
|
|
ServletResponse response, Throwable cause, boolean avoidDirectResponseOutput )
|
|
throws IOException
|
|
{
|
|
assert messageArgs.length == 0 || ! ( messageArgs[0] instanceof Object[] )
|
|
: "Object[] passed to sendError; this is probably a mistaken use of varargs";
|
|
|
|
// request may be null because of deprecated FlowController.sendError().
|
|
if ( request != null && avoidDirectResponseOutput )
|
|
{
|
|
String baseMessage = Bundle.getString( messageKey + "_Message", messageArgs );
|
|
throw new ResponseOutputException( baseMessage, cause );
|
|
}
|
|
|
|
// Filter the message args to prevent cross-site scripting (XSS) attacks (e.g., if one of the args is something
|
|
// that ultimately came from the user request, and it contains something like <script>[some sscript]</script>.
|
|
for (int i = 0; i < messageArgs.length; i++) {
|
|
Object messageArg = messageArgs[i];
|
|
messageArgs[i] = messageArg != null ? filterValue(messageArg.toString()) : null;
|
|
}
|
|
|
|
String html = Bundle.getString( messageKey + "_Page", messageArgs );
|
|
response.setContentType( "text/html;charset=UTF-8" );
|
|
response.getWriter().println(html);
|
|
ServletUtils.preventCache( response );
|
|
}
|
|
|
|
/**
|
|
* Filter output to prevent cross-site scripting (XSS) attacks.
|
|
*/
|
|
private static String filterValue(String value)
|
|
throws IOException {
|
|
InternalStringBuilder result = new InternalStringBuilder(value.length());
|
|
|
|
for (int i = 0; i < value.length(); ++i) {
|
|
char c = value.charAt(i);
|
|
switch (c) {
|
|
case '<':
|
|
result.append("<");
|
|
break;
|
|
case '>':
|
|
result.append(">");
|
|
break;
|
|
case '&':
|
|
result.append("&");
|
|
break;
|
|
default:
|
|
result.append(c);
|
|
}
|
|
}
|
|
|
|
return result.toString();
|
|
}
|
|
|
|
/**
|
|
* We unwrap two special form types: XmlBeanActionForm and AnyBeanActionForm.
|
|
*/
|
|
// TODO: make this pluggable
|
|
public static Object unwrapFormBean( ActionForm form )
|
|
{
|
|
if ( form == null ) return null;
|
|
|
|
if ( form instanceof AnyBeanActionForm )
|
|
{
|
|
return ( ( AnyBeanActionForm ) form ).getBean();
|
|
}
|
|
|
|
return form;
|
|
}
|
|
|
|
public static ActionForm wrapFormBean( Object formBean )
|
|
{
|
|
if ( formBean == null ) return null;
|
|
|
|
if ( formBean instanceof ActionForm )
|
|
{
|
|
return ( ActionForm ) formBean;
|
|
}
|
|
else
|
|
{
|
|
Class formClass = formBean.getClass();
|
|
|
|
if ( BEA_XMLOBJECT_CLASS != null && BEA_XMLOBJECT_CLASS.isAssignableFrom( formClass ) )
|
|
{
|
|
return new XmlBeanActionForm( formBean );
|
|
}
|
|
else if ( APACHE_XMLOBJECT_CLASS != null && APACHE_XMLOBJECT_CLASS.isAssignableFrom( formClass ) )
|
|
{
|
|
return new XmlBeanActionForm( formBean );
|
|
}
|
|
|
|
return new AnyBeanActionForm( formBean );
|
|
}
|
|
}
|
|
|
|
private static Class loadClassNonFatal( String className )
|
|
{
|
|
try
|
|
{
|
|
return Class.forName( className );
|
|
}
|
|
catch ( ClassNotFoundException e )
|
|
{
|
|
// Not fatal -- we don't require this to be there. Only if the user wants to use it.
|
|
|
|
if ( _log.isDebugEnabled() )
|
|
{
|
|
_log.debug( "Could not load class " + className );
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get a Method in a Class.
|
|
*
|
|
* @param parentClass the Class in which to find the Method.
|
|
* @param methodName the name of the Method.
|
|
* @param signature the argument types for the Method.
|
|
* @return the Method with the given name and signature, or <code>null</code> if the method does not exist.
|
|
*/
|
|
public static Method lookupMethod( Class parentClass, String methodName, Class[] signature )
|
|
{
|
|
try
|
|
{
|
|
return parentClass.getDeclaredMethod( methodName, signature );
|
|
}
|
|
catch ( NoSuchMethodException e )
|
|
{
|
|
Class superClass = parentClass.getSuperclass();
|
|
return superClass != null ? lookupMethod( superClass, methodName, signature ) : null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a Field in a Class.
|
|
*
|
|
* @param parentClass the Class in which to find the Field.
|
|
* @param fieldName the name of the Field.
|
|
* @return the Field with the given name, or <code>null</code> if the field does not exist.
|
|
*/
|
|
public static Field lookupField( Class parentClass, String fieldName )
|
|
{
|
|
try {
|
|
return parentClass.getDeclaredField( fieldName );
|
|
}
|
|
catch ( NoSuchFieldException e ) {
|
|
Class superClass = parentClass.getSuperclass();
|
|
return superClass != null ? lookupField( superClass, fieldName ) : null;
|
|
}
|
|
}
|
|
|
|
public static String getFlowControllerClassName( String modulePath, ServletRequest request, ServletContext context )
|
|
{
|
|
//
|
|
// We're going to look in the struts config to get the PageFlowController class.
|
|
//
|
|
ModuleConfig mc = ensureModuleConfig( modulePath, context );
|
|
return mc != null ? getFlowControllerClassName( mc ) : null;
|
|
}
|
|
|
|
public static String getFlowControllerClassName( ModuleConfig mc )
|
|
{
|
|
ControllerConfig cc = mc.getControllerConfig();
|
|
return cc instanceof PageFlowControllerConfig ? ( ( PageFlowControllerConfig ) cc ).getControllerClass() : null;
|
|
}
|
|
|
|
/**
|
|
* Tell whether the given module is a long-lived page flow.
|
|
*/
|
|
public static boolean isLongLived( ModuleConfig moduleConfig )
|
|
{
|
|
ControllerConfig cc = moduleConfig.getControllerConfig();
|
|
|
|
if ( cc instanceof PageFlowControllerConfig )
|
|
{
|
|
return ( ( PageFlowControllerConfig ) cc ).isLongLivedPageFlow();
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tell whether the given module is a nested page flow.
|
|
*/
|
|
public static boolean isNestable( ModuleConfig moduleConfig )
|
|
{
|
|
ControllerConfig cc = moduleConfig.getControllerConfig();
|
|
return cc instanceof PageFlowControllerConfig && ( ( PageFlowControllerConfig ) cc ).isNestedPageFlow();
|
|
}
|
|
|
|
public static String getLongLivedFlowAttr( String modulePath )
|
|
{
|
|
return LONGLIVED_PAGEFLOWS_ATTR_PREFIX + modulePath;
|
|
}
|
|
|
|
public static void setCurrentPageFlow( PageFlowController jpf, HttpServletRequest request,
|
|
ServletContext servletContext )
|
|
{
|
|
setCurrentActionResolver( jpf, request, servletContext );
|
|
}
|
|
|
|
public static void removeCurrentPageFlow( HttpServletRequest request, ServletContext servletContext )
|
|
{
|
|
StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
|
|
HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
|
|
RequestContext rc = new RequestContext( unwrappedRequest, null );
|
|
String currentJpfAttrName = ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
|
|
String currentLongLivedAttrName =
|
|
ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
|
|
|
|
sh.removeAttribute( rc, currentJpfAttrName );
|
|
sh.removeAttribute( rc, currentLongLivedAttrName );
|
|
}
|
|
|
|
public static void removeCurrentFacesBackingBean( HttpServletRequest request, ServletContext servletContext )
|
|
{
|
|
StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
|
|
HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
|
|
RequestContext rc = new RequestContext( unwrappedRequest, null );
|
|
String attrName = ScopedServletUtils.getScopedSessionAttrName( FACES_BACKING_ATTR, unwrappedRequest );
|
|
|
|
sh.removeAttribute( rc, attrName );
|
|
}
|
|
|
|
public static String getDecodedURI( HttpServletRequest request )
|
|
{
|
|
return request.getContextPath() + getDecodedServletPath( request );
|
|
}
|
|
|
|
public static String getDecodedServletPath( HttpServletRequest request )
|
|
{
|
|
if ( ignoreIncludeServletPath( request ) ) return request.getServletPath();
|
|
|
|
String servletIncludePath = ( String ) request.getAttribute( RequestProcessor.INCLUDE_SERVLET_PATH );
|
|
return servletIncludePath != null ? servletIncludePath : request.getServletPath();
|
|
}
|
|
|
|
public static void addActionOutputs( Map toAdd, ServletRequest request, boolean overwrite )
|
|
{
|
|
if ( toAdd != null )
|
|
{
|
|
Map map = getActionOutputMap( request, true );
|
|
|
|
for ( Iterator i = toAdd.entrySet().iterator(); i.hasNext(); )
|
|
{
|
|
Map.Entry entry = ( Map.Entry ) i.next();
|
|
String name = ( String ) entry.getKey();
|
|
boolean alreadyExists = map.containsKey( name );
|
|
|
|
if ( overwrite || ! alreadyExists )
|
|
{
|
|
if ( alreadyExists )
|
|
{
|
|
if ( _log.isWarnEnabled() )
|
|
{
|
|
_log.warn( "Overwriting action output \"" + name + "\"." );
|
|
}
|
|
}
|
|
|
|
map.put( name, entry.getValue() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void addActionError( String propertyName, ActionMessage error, ServletRequest request )
|
|
{
|
|
ActionMessages errors = ( ActionMessages ) request.getAttribute( Globals.ERROR_KEY );
|
|
if ( errors == null ) request.setAttribute( Globals.ERROR_KEY, errors = new ActionMessages() );
|
|
errors.add( propertyName, error );
|
|
}
|
|
|
|
public static Object newReloadableInstance( String className, ServletContext servletContext )
|
|
throws ClassNotFoundException, InstantiationException, IllegalAccessException
|
|
{
|
|
return getReloadableClass( className, servletContext ).newInstance();
|
|
}
|
|
|
|
public static Class getReloadableClass( String className, ServletContext servletContext )
|
|
throws ClassNotFoundException
|
|
{
|
|
ReloadableClassHandler handler = Handlers.get( servletContext ).getReloadableClassHandler();
|
|
return handler.loadClass( className );
|
|
}
|
|
|
|
public static Map getActionOutputMap( ServletRequest request, boolean createIfNotExist )
|
|
{
|
|
Map map = ( Map ) request.getAttribute( ACTIONOUTPUT_MAP_ATTR );
|
|
|
|
if ( map == null && createIfNotExist )
|
|
{
|
|
map = new HashMap();
|
|
request.setAttribute( ACTIONOUTPUT_MAP_ATTR, map );
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
public static Map getPageInputMap( ServletRequest request, ServletContext servletContext )
|
|
{
|
|
Map actionOutputsFromPageFlow = getActionOutputMap( request, false );
|
|
if ( actionOutputsFromPageFlow != null ) return actionOutputsFromPageFlow;
|
|
FacesBackingBean fbb = getFacesBackingBean( request, servletContext );
|
|
return fbb != null ? fbb.getPageInputMap() : null;
|
|
}
|
|
|
|
public static Map getPageInputMap( ServletRequest request )
|
|
{
|
|
Map actionOutputsFromPageFlow = getActionOutputMap( request, false );
|
|
if ( actionOutputsFromPageFlow != null ) return actionOutputsFromPageFlow;
|
|
FacesBackingBean fbb = getFacesBackingBean( request, getServletContext( request ) );
|
|
return fbb != null ? fbb.getPageInputMap() : null;
|
|
}
|
|
|
|
/**
|
|
* Get the Struts ModuleConfig for the given module path.
|
|
*/
|
|
public static ModuleConfig getModuleConfig( String modulePath, ServletContext context )
|
|
{
|
|
return ( ModuleConfig ) context.getAttribute( Globals.MODULE_KEY + modulePath );
|
|
}
|
|
|
|
/**
|
|
* Get the Struts ModuleConfig for the given module path. If there is none registered,
|
|
* and if it is possible to register one automatically, do so.
|
|
*/
|
|
public static ModuleConfig ensureModuleConfig( String modulePath, ServletContext context )
|
|
{
|
|
try
|
|
{
|
|
ModuleConfig ret = getModuleConfig( modulePath, context );
|
|
|
|
if ( ret != null )
|
|
{
|
|
return ret;
|
|
}
|
|
else
|
|
{
|
|
ActionServlet as = getActionServlet( context );
|
|
|
|
if ( as instanceof AutoRegisterActionServlet )
|
|
{
|
|
return ( ( AutoRegisterActionServlet ) as ).ensureModuleRegistered( modulePath );
|
|
}
|
|
}
|
|
}
|
|
catch ( IOException e )
|
|
{
|
|
_log.error( "Error while registering Struts module " + modulePath, e );
|
|
}
|
|
catch ( ServletException e )
|
|
{
|
|
_log.error( "Error while registering Struts module " + modulePath, e );
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Initialize delegating action configs and exception configs for a Struts module that should delegate
|
|
* to one generated from a superclass.
|
|
*/
|
|
public static void initDelegatingConfigs(ModuleConfig moduleConfig, ServletContext servletContext)
|
|
{
|
|
ActionConfig[] actionConfigs = moduleConfig.findActionConfigs();
|
|
|
|
// Initialize action configs.
|
|
for (int i = 0; i < actionConfigs.length; i++) {
|
|
ActionConfig actionConfig = actionConfigs[i];
|
|
if (actionConfig instanceof DelegatingActionMapping) {
|
|
((DelegatingActionMapping) actionConfig).init(servletContext);
|
|
} else {
|
|
// Initialize action-level exception configs.
|
|
ExceptionConfig[] exceptionConfigs = actionConfig.findExceptionConfigs();
|
|
for (int j = 0; j < exceptionConfigs.length; j++) {
|
|
ExceptionConfig exceptionConfig = exceptionConfigs[j];
|
|
if (exceptionConfig instanceof DelegatingExceptionConfig) {
|
|
((DelegatingExceptionConfig) exceptionConfig).init(servletContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize module-level exception configs.
|
|
ExceptionConfig[] exceptionConfigs = moduleConfig.findExceptionConfigs();
|
|
for (int i = 0; i < exceptionConfigs.length; i++) {
|
|
ExceptionConfig exceptionConfig = exceptionConfigs[i];
|
|
if (exceptionConfig instanceof DelegatingExceptionConfig) {
|
|
((DelegatingExceptionConfig) exceptionConfig).init(servletContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the current ActionServlet.
|
|
*
|
|
* @param context the current ServletContext
|
|
* @return the ActionServlet that is stored as an attribute in the ServletContext
|
|
*/
|
|
public static ActionServlet getActionServlet( ServletContext context )
|
|
{
|
|
if ( context == null ) return null;
|
|
return ( ActionServlet ) context.getAttribute( Globals.ACTION_SERVLET_KEY );
|
|
}
|
|
|
|
/**
|
|
* Add a BindingUpdateError to the request.
|
|
*
|
|
* @param request the current ServletRequest.
|
|
* @param expression the expression associated with this error.
|
|
* @param message the error message.
|
|
* @param cause the Throwable that caused the error.
|
|
*/
|
|
public static void addBindingUpdateError( ServletRequest request, String expression, String message, Throwable cause )
|
|
{
|
|
Map errors = ( Map ) request.getAttribute( BINDING_UPDATE_ERRORS_ATTR );
|
|
|
|
if ( errors == null )
|
|
{
|
|
errors = new LinkedHashMap();
|
|
request.setAttribute( BINDING_UPDATE_ERRORS_ATTR, errors );
|
|
}
|
|
|
|
errors.put( expression, new BindingUpdateError( expression, message, cause ) );
|
|
}
|
|
|
|
/**
|
|
* Get a map of BindingUpdateErrors stored in the request.
|
|
*
|
|
* @return a Map of expression (String) -> BindingUpdateError.
|
|
*/
|
|
public static Map getBindingUpdateErrors( ServletRequest request )
|
|
{
|
|
return ( Map ) request.getAttribute( BINDING_UPDATE_ERRORS_ATTR );
|
|
}
|
|
|
|
public static void setCurrentModule( ModuleConfig mc, ServletRequest request )
|
|
{
|
|
request.setAttribute( Globals.MODULE_KEY, mc );
|
|
}
|
|
|
|
public static ActionForm createActionForm( ActionMapping mapping, ModuleConfig moduleConfig,
|
|
ActionServlet actionServlet, ServletContext servletContext )
|
|
{
|
|
String formName = mapping.getName();
|
|
if ( formName == null ) return null;
|
|
FormBeanConfig config = moduleConfig.findFormBeanConfig( formName );
|
|
if ( config == null ) return null;
|
|
|
|
try
|
|
{
|
|
ActionForm bean;
|
|
|
|
if ( config.getDynamic() )
|
|
{
|
|
if ( _log.isDebugEnabled() )
|
|
{
|
|
_log.debug( "Creating new DynaActionForm instance of type " + config.getType() );
|
|
}
|
|
|
|
DynaActionFormClass dynaClass = DynaActionFormClass.createDynaActionFormClass( config );
|
|
bean = ( ActionForm ) dynaClass.newInstance();
|
|
( ( DynaActionForm ) bean ).initialize( mapping );
|
|
}
|
|
else
|
|
{
|
|
if ( _log.isDebugEnabled() )
|
|
{
|
|
_log.debug( "Creating new ActionForm instance of type " + config.getType() );
|
|
}
|
|
|
|
bean = ( ActionForm ) newReloadableInstance( config.getType(), servletContext );
|
|
}
|
|
|
|
bean.setServlet( actionServlet );
|
|
return bean;
|
|
}
|
|
catch ( Exception e )
|
|
{
|
|
if ( _log.isErrorEnabled() )
|
|
{
|
|
_log.error( "Error creating action form of type " + config.getType(), e );
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the given form in either the request or session, as appropriate, so Struts/NetUI
|
|
* tags will have access to it.
|
|
*/
|
|
public static void setFormInScope( String formName, ActionForm form, ActionMapping mapping,
|
|
HttpServletRequest request, boolean overwrite )
|
|
{
|
|
if ( formName != null && form != null )
|
|
{
|
|
if ( isSessionScope( mapping ) )
|
|
{
|
|
HttpSession session = request.getSession();
|
|
|
|
if ( overwrite || session.getAttribute( formName ) == null )
|
|
{
|
|
session.setAttribute( formName, form );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( overwrite || request.getAttribute( formName ) == null )
|
|
{
|
|
request.setAttribute( formName, form );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static boolean isSessionScope( ActionMapping mapping )
|
|
{
|
|
return ( mapping.getScope() == null || mapping.getScope().equals( "session" ) );
|
|
}
|
|
|
|
public static ActionForm getFormBean( ActionMapping mapping, ServletRequest request )
|
|
{
|
|
String formBeanName = mapping.getAttribute();
|
|
|
|
if ( formBeanName != null )
|
|
{
|
|
if ( isSessionScope( mapping ) )
|
|
{
|
|
HttpSession session = getHttpSession( request, false );
|
|
return session != null ? ( ActionForm ) session.getAttribute( formBeanName ) : null;
|
|
}
|
|
else
|
|
{
|
|
return ( ActionForm ) request.getAttribute( formBeanName );
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Set the current {@link ActionResolver} (or {@link PageFlowController}) in the user session.
|
|
*
|
|
* @param resolver the {@link ActionResolver} to set as the current one in the user session.
|
|
* @deprecated Will be removed in the next version.
|
|
*/
|
|
public static void setCurrentActionResolver( ActionResolver resolver, HttpServletRequest request,
|
|
ServletContext servletContext )
|
|
{
|
|
StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
|
|
HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
|
|
RequestContext rc = new RequestContext( unwrappedRequest, null );
|
|
String currentJpfAttrName =
|
|
ScopedServletUtils.getScopedSessionAttrName( CURRENT_JPF_ATTR, unwrappedRequest );
|
|
String currentLongLivedJpfAttrName =
|
|
ScopedServletUtils.getScopedSessionAttrName( CURRENT_LONGLIVED_ATTR, unwrappedRequest );
|
|
|
|
//
|
|
// This case occurs when the previous page flow is no longer active and there is no new page flow
|
|
//
|
|
if ( resolver == null )
|
|
{
|
|
sh.removeAttribute( rc, currentJpfAttrName );
|
|
sh.removeAttribute( rc, currentLongLivedJpfAttrName );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If this is a long-lived page flow, also store the instance in an attribute that never goes away.
|
|
//
|
|
if ( resolver.isPageFlow() && isLongLived( ( ( PageFlowController ) resolver ).theModuleConfig() ) )
|
|
{
|
|
String longLivedAttrName = getLongLivedFlowAttr( resolver.getModulePath() );
|
|
longLivedAttrName = ScopedServletUtils.getScopedSessionAttrName( longLivedAttrName, unwrappedRequest );
|
|
|
|
// Only set this attribute if it's not already there. We want to avoid our onDestroy() callback that's
|
|
// invoked when the page flow's session attribute is unbound.
|
|
if ( sh.getAttribute( rc, longLivedAttrName ) != resolver )
|
|
{
|
|
sh.setAttribute( rc, longLivedAttrName, resolver );
|
|
}
|
|
|
|
sh.setAttribute( rc, currentLongLivedJpfAttrName, resolver.getModulePath() );
|
|
sh.removeAttribute( rc, currentJpfAttrName );
|
|
}
|
|
//
|
|
// Default case for removing a previous page flow in the presence of a new page flow.
|
|
//
|
|
else
|
|
{
|
|
sh.setAttribute( rc, currentJpfAttrName, resolver );
|
|
sh.removeAttribute( rc, currentLongLivedJpfAttrName );
|
|
}
|
|
}
|
|
|
|
public static boolean isSharedFlowModule( ModuleConfig mc )
|
|
{
|
|
ControllerConfig cc = mc.getControllerConfig();
|
|
return cc instanceof PageFlowControllerConfig && ( ( PageFlowControllerConfig ) cc ).isSharedFlow();
|
|
}
|
|
|
|
|
|
public static FacesBackingBean getFacesBackingBean( ServletRequest request, ServletContext servletContext )
|
|
{
|
|
if ( request instanceof HttpServletRequest )
|
|
{
|
|
StorageHandler sh = Handlers.get( servletContext ).getStorageHandler();
|
|
HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( ( HttpServletRequest ) request );
|
|
RequestContext rc = new RequestContext( unwrappedRequest, null );
|
|
String attrName = ScopedServletUtils.getScopedSessionAttrName( FACES_BACKING_ATTR, unwrappedRequest );
|
|
return ( FacesBackingBean ) sh.getAttribute( rc, attrName );
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
}
|
|
|
|
public static boolean isMultipartHandlingEnabled( ServletRequest request )
|
|
{
|
|
ModuleConfig moduleConfig = ( ModuleConfig ) request.getAttribute( Globals.MODULE_KEY );
|
|
return moduleConfig.getControllerConfig().getMultipartClass() != null;
|
|
}
|
|
|
|
public static MultipartHandler getMultipartHandlerType()
|
|
{
|
|
PageFlowConfig pfConfig = ConfigUtil.getConfig().getPageFlowConfig();
|
|
return pfConfig != null ? pfConfig.getMultipartHandler() : null;
|
|
}
|
|
|
|
public static void setServletContext( ServletRequest request, ServletContext servletContext )
|
|
{
|
|
ScopedServletUtils.getOuterServletRequest( request ).setAttribute( SERVLET_CONTEXT_ATTR, servletContext );
|
|
}
|
|
|
|
public static ServletContext getServletContext( ServletRequest req )
|
|
{
|
|
HttpSession session = getHttpSession( req, false );
|
|
return session != null
|
|
? session.getServletContext()
|
|
: ( ServletContext ) ScopedServletUtils.getOuterServletRequest( req ).getAttribute( SERVLET_CONTEXT_ATTR );
|
|
}
|
|
|
|
public static HttpSession getHttpSession( ServletRequest request, boolean create )
|
|
{
|
|
if ( ! ( request instanceof HttpServletRequest ) ) return null;
|
|
return ( ( HttpServletRequest ) request ).getSession( create );
|
|
}
|
|
|
|
public static String createActionPath( ServletRequest request, String qualifiedAction )
|
|
{
|
|
ModuleConfig appConfig = ( ModuleConfig ) request.getAttribute( Globals.MODULE_KEY );
|
|
|
|
if ( appConfig != null )
|
|
{
|
|
InternalStringBuilder value = new InternalStringBuilder( qualifiedAction.length() + 16 );
|
|
value.append( appConfig.getPrefix() );
|
|
value.append( qualifiedAction );
|
|
return value.toString();
|
|
}
|
|
|
|
return qualifiedAction;
|
|
}
|
|
|
|
public static String qualifyAction( ServletContext servletContext, String action )
|
|
{
|
|
assert action != null;
|
|
InternalStringBuilder sb = null;
|
|
|
|
String queryString = null;
|
|
int question = action.indexOf( '?' );
|
|
if ( question >= 0 ) queryString = action.substring( question );
|
|
|
|
String actionMapping = getActionMappingName( action );
|
|
sb = new InternalStringBuilder( action.length() + ACTION_EXTENSION_LEN + 1 );
|
|
sb.append( actionMapping );
|
|
sb.append( ACTION_EXTENSION );
|
|
if ( queryString != null ) sb.append( queryString );
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Return the form action converted into an action mapping path. The
|
|
* value of the <code>action</code> property is manipulated as follows in
|
|
* computing the name of the requested mapping:
|
|
* <ul>
|
|
* <li>Any filename extension is removed (on the theory that extension
|
|
* mapping is being used to select the controller servlet).</li>
|
|
* <li>If the resulting value does not start with a slash, then a
|
|
* slash is prepended.</li>
|
|
* </ul>
|
|
*
|
|
* @param action the action name to be converted.
|
|
* @return an action path, suitable for lookup in the Struts configuration file.
|
|
*/
|
|
public static String getActionMappingName( String action )
|
|
{
|
|
return getCleanActionName( action, true );
|
|
}
|
|
|
|
public static String getCleanActionName( String action, boolean prependSlash )
|
|
{
|
|
int question = action.indexOf( '?' );
|
|
if ( question >= 0 )
|
|
{
|
|
action = action.substring( 0, question );
|
|
}
|
|
|
|
if ( action.endsWith( ACTION_EXTENSION ) )
|
|
{
|
|
action = action.substring( 0, action.length() - ACTION_EXTENSION_LEN );
|
|
}
|
|
|
|
if ( action.charAt( 0 ) == '/' )
|
|
{
|
|
if ( ! prependSlash ) action = action.substring( 1 );
|
|
}
|
|
else
|
|
{
|
|
if ( prependSlash ) action = '/' + action;
|
|
}
|
|
|
|
return action;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a parameter to the given URL. Assumes there is no trailing
|
|
* anchor/fragment indicated with a '#'.
|
|
*
|
|
* @param url the URL to which to append.
|
|
* @param paramName the name of the parameter to add.
|
|
* @param paramVal the value of the parameter to add.
|
|
* @return the URL, with the given parameter added.
|
|
*/
|
|
public static String addParam( String url, String paramName, String paramVal )
|
|
{
|
|
return url + ( url.indexOf( '?' ) != -1 ? '&' : '?' ) + paramName + '=' + paramVal;
|
|
}
|
|
|
|
public static String getActionName( ActionMapping mapping )
|
|
{
|
|
if ( mapping == null ) return null;
|
|
|
|
String actionName = mapping.getPath();
|
|
if ( actionName.charAt( 0 ) == '/' ) actionName = actionName.substring( 1 );
|
|
|
|
//
|
|
// Look to see if we need are in a disambiguated action, i.e., one whose name is qualified
|
|
// by the form. If so, we need to restore the unqualified action name.
|
|
//
|
|
if ( mapping instanceof PageFlowActionMapping )
|
|
{
|
|
String unqualifiedAction = ( ( PageFlowActionMapping ) mapping ).getUnqualifiedActionName();
|
|
if ( unqualifiedAction != null ) actionName = unqualifiedAction;
|
|
}
|
|
|
|
return actionName;
|
|
}
|
|
|
|
public static ActionMapping getCurrentActionMapping( ServletRequest request )
|
|
{
|
|
return ( ActionMapping ) request.getAttribute( Globals.MAPPING_KEY );
|
|
}
|
|
|
|
public static ActionForm getCurrentActionForm( ServletRequest request )
|
|
{
|
|
ActionMapping mapping = getCurrentActionMapping( request );
|
|
String attribute = mapping != null ? mapping.getAttribute() : null;
|
|
if ( attribute == null ) return null;
|
|
|
|
if ( "request".equals( mapping.getScope() ) )
|
|
{
|
|
return ( ActionForm ) request.getAttribute( attribute );
|
|
}
|
|
else
|
|
{
|
|
HttpSession session = getHttpSession( request, false );
|
|
return session != null ? ( ActionForm ) session.getAttribute( attribute ) : null;
|
|
}
|
|
}
|
|
|
|
public static boolean sessionExpired( ServletRequest servletRequest )
|
|
{
|
|
if ( servletRequest instanceof HttpServletRequest )
|
|
{
|
|
HttpServletRequest request = ( HttpServletRequest ) servletRequest;
|
|
String requestedSessionID = request.getRequestedSessionId();
|
|
|
|
if ( requestedSessionID != null )
|
|
{
|
|
HttpSession session = request.getSession( false );
|
|
return session == null || ! requestedSessionID.equals( session.getId() );
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void throwPageFlowException( PageFlowException ex )
|
|
{
|
|
throwPageFlowException( ex, null );
|
|
}
|
|
|
|
public static void throwPageFlowException( PageFlowException effect, ServletRequest request )
|
|
throws PageFlowException
|
|
{
|
|
if ( request != null && effect.causeMayBeSessionExpiration() && sessionExpired( request ) )
|
|
{
|
|
PageFlowConfig pfc = ConfigUtil.getConfig().getPageFlowConfig();
|
|
if ( pfc == null || pfc.isThrowSessionExpiredException() )
|
|
{
|
|
throw new SessionExpiredException( effect );
|
|
}
|
|
}
|
|
|
|
throw effect;
|
|
}
|
|
|
|
/**
|
|
* Get the Struts ActionConfig for the given action config path and module path.
|
|
*/
|
|
public static ActionConfig findActionConfig( String actionConfigPath, String modulePath, ServletContext context )
|
|
{
|
|
ModuleConfig moduleConfig = getModuleConfig( modulePath, context );
|
|
assert moduleConfig != null;
|
|
return moduleConfig.findActionConfig( actionConfigPath );
|
|
}
|
|
|
|
/**
|
|
* Get the Struts ActionMapping path from the ActionMapping that is in the request under the key
|
|
* Globals.MAPPING_KEY.
|
|
*
|
|
* @return the path for the ActionMapping, as found with ActionMapping.getPath()
|
|
*/
|
|
public static String getActionMappingPath( ServletRequest request )
|
|
{
|
|
ActionMapping actionMapping = ( ActionMapping ) request.getAttribute( Globals.MAPPING_KEY );
|
|
return actionMapping != null ? actionMapping.getPath() : null;
|
|
}
|
|
|
|
/**
|
|
* Gets the Struts module path from the input request. If a ModuleConfig
|
|
* object has been populated into the request it is used to get the module prefix,
|
|
* otherwise getModulePath is called, which derives the module path from
|
|
* the request URI.
|
|
*/
|
|
public static String getModulePathFromReqAttr( HttpServletRequest request )
|
|
{
|
|
//
|
|
// If a config was in the request, use its associated prefix; otherwise, fall back to the URI.
|
|
//
|
|
ModuleConfig config = ( ModuleConfig ) request.getAttribute( Globals.MODULE_KEY );
|
|
return config != null ? config.getPrefix() : PageFlowUtils.getModulePath( request );
|
|
}
|
|
|
|
/**
|
|
* Set the forwarded form. This overrides the auto-generated form created by processActionForm
|
|
* and populated by processPopulate (in PageFlowRequestProcessor).
|
|
*/
|
|
public static void setForwardedFormBean( ServletRequest request, ActionForm form )
|
|
{
|
|
if ( form == null )
|
|
{
|
|
request.removeAttribute( FORWARDED_FORMBEAN_ATTR );
|
|
}
|
|
else
|
|
{
|
|
request.setAttribute( FORWARDED_FORMBEAN_ATTR, form );
|
|
}
|
|
}
|
|
|
|
public static ActionForm getForwardedFormBean( ServletRequest request, boolean removeFromRequest )
|
|
{
|
|
ActionForm form = ( ActionForm ) request.getAttribute( FORWARDED_FORMBEAN_ATTR );
|
|
if ( removeFromRequest ) request.removeAttribute( FORWARDED_FORMBEAN_ATTR );
|
|
return form;
|
|
}
|
|
|
|
/**
|
|
* Tell whether a special request attribute was set, indicating that we should avoid writing to the response (or
|
|
* setting response error codes).
|
|
*/
|
|
public static boolean avoidDirectResponseOutput( ServletRequest request )
|
|
{
|
|
Boolean avoid = ( Boolean ) request.getAttribute( AVOID_DIRECT_RESPONSE_OUTPUT_ATTR );
|
|
return avoid != null && avoid.booleanValue();
|
|
}
|
|
|
|
/**
|
|
* Set a special request attribute to indicate that we should avoid writing to the response (or
|
|
* setting response error codes).
|
|
*/
|
|
public static void setAvoidDirectResponseOutput( ServletRequest request )
|
|
{
|
|
request.setAttribute( AVOID_DIRECT_RESPONSE_OUTPUT_ATTR, Boolean.TRUE );
|
|
}
|
|
|
|
/**
|
|
* Set the module prefix for the ModuleConfig that is performing a forward in this request.
|
|
*/
|
|
public static void setForwardingModule( ServletRequest request, String modulePrefix )
|
|
{
|
|
request.setAttribute( FORWARDING_MODULE_ATTR, modulePrefix );
|
|
}
|
|
|
|
/**
|
|
* Set the module prefix for the ModuleConfig that is performing a forward in this request.
|
|
*/
|
|
public static String getForwardingModule( ServletRequest request )
|
|
{
|
|
return ( String ) request.getAttribute( FORWARDING_MODULE_ATTR );
|
|
}
|
|
|
|
public static String getFormBeanType( FormBeanConfig formBeanConfig )
|
|
{
|
|
String formBeanType = null;
|
|
|
|
// First, try to read the form bean type from our custom property, which supports the any-bean feature.
|
|
if ( formBeanConfig instanceof PageFlowActionFormBean )
|
|
{
|
|
formBeanType = ( ( PageFlowActionFormBean ) formBeanConfig ).getActualType();
|
|
}
|
|
|
|
// If we didn't find it there, this is a normal Struts ActionForm. Just get it from the type attr.
|
|
if ( formBeanType == null ) formBeanType = formBeanConfig.getType();
|
|
|
|
return formBeanType;
|
|
}
|
|
|
|
/**
|
|
* Tell {@link #getDecodedServletPath} (and all that call it) to ignore the attribute that specifies the Servlet
|
|
* Include path, which is set when a Servlet include is done through RequestDispatcher. Normally,
|
|
* getDecodedServletPath tries the Servlet Include path before falling back to getServletPath() on the request.
|
|
* Note that this is basically a stack of instructions to ignore the include path, and this method expects each
|
|
* call with <code>ignore</code>==<code>true</code> to be balanced by a call with
|
|
* <code>ignore</code>==<code>false</code>.
|
|
*/
|
|
public static void setIgnoreIncludeServletPath( ServletRequest request, boolean ignore )
|
|
{
|
|
Integer depth = ( Integer ) request.getAttribute( IGNORE_INCLUDE_SERVLET_PATH_ATTR );
|
|
|
|
if ( ignore )
|
|
{
|
|
if ( depth == null ) depth = new Integer( 0 );
|
|
request.setAttribute( IGNORE_INCLUDE_SERVLET_PATH_ATTR, new Integer( depth.intValue() + 1 ) );
|
|
}
|
|
else
|
|
{
|
|
assert depth != null : "call to setIgnoreIncludeServletPath() was imbalanced";
|
|
depth = new Integer( depth.intValue() - 1 );
|
|
|
|
if ( depth.intValue() == 0 )
|
|
{
|
|
request.removeAttribute( IGNORE_INCLUDE_SERVLET_PATH_ATTR );
|
|
}
|
|
else
|
|
{
|
|
request.setAttribute( IGNORE_INCLUDE_SERVLET_PATH_ATTR, depth );
|
|
}
|
|
}
|
|
}
|
|
|
|
public static boolean ignoreIncludeServletPath( ServletRequest request )
|
|
{
|
|
return request.getAttribute( IGNORE_INCLUDE_SERVLET_PATH_ATTR ) != null;
|
|
}
|
|
|
|
/**
|
|
* If the given request is a MultipartRequestWrapper (Struts class that doesn't extend
|
|
* HttpServletRequestWrapper), return the wrapped request; otherwise, return the given request.
|
|
*/
|
|
public static ServletRequest unwrapMultipart( ServletRequest request )
|
|
{
|
|
if ( request instanceof MultipartRequestWrapper )
|
|
{
|
|
request = ( ( MultipartRequestWrapper ) request ).getRequest();
|
|
}
|
|
|
|
return request;
|
|
}
|
|
|
|
/**
|
|
* Set the given Struts module in the request, and expose its set of MessageResources as request attributes.
|
|
*
|
|
* @param prefix the prefix of the desired module.
|
|
* @param request the current HttpServletRequest.
|
|
* @param servletContext the current ServletContext.
|
|
* @return the selected ModuleConfig, or <code>null</code> if there is none for the given module prefix.
|
|
*/
|
|
public static ModuleConfig selectModule( String prefix, HttpServletRequest request, ServletContext servletContext )
|
|
{
|
|
ModuleConfig moduleConfig = getModuleConfig( prefix, servletContext );
|
|
|
|
if ( moduleConfig == null )
|
|
{
|
|
request.removeAttribute( Globals.MODULE_KEY );
|
|
return null;
|
|
}
|
|
|
|
// If this module came from an abstract page flow controller class, don't select it.
|
|
ControllerConfig cc = moduleConfig.getControllerConfig();
|
|
if (cc instanceof PageFlowControllerConfig && ((PageFlowControllerConfig) cc).isAbstract()) {
|
|
return moduleConfig;
|
|
}
|
|
|
|
// Just return it if it's already registered.
|
|
if ( request.getAttribute( Globals.MODULE_KEY ) == moduleConfig ) return moduleConfig;
|
|
request.setAttribute( Globals.MODULE_KEY, moduleConfig );
|
|
|
|
MessageResourcesConfig[] mrConfig = moduleConfig.findMessageResourcesConfigs();
|
|
Object formBean = unwrapFormBean( getCurrentActionForm( request ) );
|
|
|
|
for ( int i = 0; i < mrConfig.length; i++ )
|
|
{
|
|
String key = mrConfig[i].getKey();
|
|
MessageResources resources = ( MessageResources ) servletContext.getAttribute( key + prefix );
|
|
|
|
if ( resources != null )
|
|
{
|
|
if ( ! ( resources instanceof ExpressionAwareMessageResources ) )
|
|
{
|
|
resources = new ExpressionAwareMessageResources( resources, formBean, request, servletContext );
|
|
}
|
|
|
|
request.setAttribute( key, resources );
|
|
}
|
|
else
|
|
{
|
|
request.removeAttribute( key );
|
|
}
|
|
}
|
|
|
|
return moduleConfig;
|
|
}
|
|
|
|
public static MessageResources getMessageResources( String bundleName, ServletRequest request,
|
|
ServletContext servletContext )
|
|
{
|
|
MessageResources resources = (MessageResources) request.getAttribute(bundleName);
|
|
|
|
if ( resources == null )
|
|
{
|
|
String qualified = getQualifiedBundleName(bundleName, request);
|
|
resources = (MessageResources) servletContext.getAttribute(qualified);
|
|
}
|
|
|
|
// If we can't find resources with this name, try them at the root (unqualified).
|
|
if ( resources == null ) resources = (MessageResources) servletContext.getAttribute(bundleName);
|
|
|
|
return resources;
|
|
}
|
|
|
|
/**
|
|
* Qualify the given bundle name with the current module path to return a full bundle name.
|
|
*
|
|
* @return the qualified Bundle name
|
|
*/
|
|
public static String getQualifiedBundleName( String bundleName, ServletRequest request )
|
|
{
|
|
if ( bundleName != null )
|
|
{
|
|
if ( bundleName.indexOf( '/' ) == -1 )
|
|
{
|
|
ModuleConfig mc = ( ModuleConfig ) request.getAttribute( Globals.MODULE_KEY );
|
|
|
|
// Note that we don't append the module path for the root module.
|
|
if ( mc != null && mc.getPrefix() != null && mc.getPrefix().length() > 1 )
|
|
{
|
|
bundleName += mc.getPrefix();
|
|
}
|
|
}
|
|
else if ( bundleName.endsWith( "/" ) )
|
|
{
|
|
// Special handling for bundles referring to the root module -- they should not have
|
|
// the module path ("/") at the end.
|
|
bundleName = bundleName.substring( 0, bundleName.length() - 1 );
|
|
}
|
|
}
|
|
|
|
return bundleName;
|
|
}
|
|
|
|
public static Locale lookupLocale(JspContext jspContext) {
|
|
assert jspContext instanceof PageContext : "Found JspContext of type \"" + (jspContext != null ? jspContext.getClass().getName() : "null") + "\"";
|
|
return lookupLocale(((PageContext)jspContext).getRequest());
|
|
}
|
|
|
|
public static Locale lookupLocale(ServletRequest request) {
|
|
assert request instanceof HttpServletRequest : "Found servlet request of type \"" + (request != null ? request.getClass().getName() : "null") + "\"";
|
|
|
|
Locale locale = null;
|
|
HttpServletRequest httpServletRequest = (HttpServletRequest)request;
|
|
HttpSession session = httpServletRequest.getSession(false);
|
|
if(session != null)
|
|
locale = (Locale)session.getAttribute(Globals.LOCALE_KEY);
|
|
|
|
if(locale == null)
|
|
locale = request.getLocale();
|
|
|
|
return locale;
|
|
}
|
|
|
|
}
|