xworkconverter.java

来自「在Struts2中的jar包xwork的源代码.版本为2.0.7」· Java 代码 · 共 840 行 · 第 1/3 页

JAVA
840
字号
/* * Copyright (c) 2002-2006 by OpenSymphony * All rights reserved. */package com.opensymphony.xwork2.util;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Member;import java.lang.reflect.Method;import java.lang.annotation.Annotation;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Properties;import ognl.DefaultTypeConverter;import ognl.OgnlRuntime;import ognl.TypeConverter;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import com.opensymphony.xwork2.inject.Inject;import com.opensymphony.xwork2.util.FileManager;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ObjectFactory;import com.opensymphony.xwork2.XWorkMessages;import com.opensymphony.xwork2.conversion.annotations.Conversion;import com.opensymphony.xwork2.conversion.annotations.TypeConversion;import com.opensymphony.xwork2.conversion.annotations.ConversionType;import com.opensymphony.xwork2.conversion.annotations.ConversionRule;/** * XWorkConverter is a singleton used by many of the WebWork's Ognl extention points, * such as InstantiatingNullHandler, XWorkListPropertyAccessor etc to do object  * conversion. *  * <!-- START SNIPPET: javadoc --> * * Type conversion is great for situations where you need to turn a String in to a more complex object. Because the web * is type-agnostic (everything is a string in HTTP), WebWork's type conversion features are very useful. For instance, * if you were prompting a user to enter in coordinates in the form of a string (such as "3, 22"), you could have * WebWork do the conversion both from String to Point and from Point to String. * * <p/> Using this "point" example, if your action (or another compound object in which you are setting properties on) * has a corresponding ClassName-conversion.properties file, WebWork will use the configured type converters for * conversion to and from strings. So turning "3, 22" in to new Point(3, 22) is done by merely adding the following * entry to <b>ClassName-conversion.properties</b> (Note that the PointConverter should impl the ognl.TypeConverter * interface): * * <p/><b>point = com.acme.PointConverter</b> * * <p/> Your type converter should be sure to check what class type it is being requested to convert. Because it is used * for both to and from strings, you will need to split the conversion method in to two parts: one that turns Strings in * to Points, and one that turns Points in to Strings. * * <p/> After this is done, you can now reference your point (using &lt;ww:property value="post"/&gt; in JSP or ${point} * in FreeMarker) and it will be printed as "3, 22" again. As such, if you submit this back to an action, it will be * converted back to a Point once again. * * <p/> In some situations you may wish to apply a type converter globally. This can be done by editing the file * <b>xwork-conversion.properties</b> in the root of your class path (typically WEB-INF/classes) and providing a * property in the form of the class name of the object you wish to convert on the left hand side and the class name of * the type converter on the right hand side. For example, providing a type converter for all Point objects would mean * adding the following entry: * * <p/><b>com.acme.Point = com.acme.PointConverter</b> * * <!-- END SNIPPET: javadoc --> * * <p/> * * <!-- START SNIPPET: i18n-note --> * * Type conversion should not be used as a substitute for i18n. It is not recommended to use this feature to print out * properly formatted dates. Rather, you should use the i18n features of WebWork (and consult the JavaDocs for JDK's * MessageFormat object) to see how a properly formatted date should be displayed. * * <!-- END SNIPPET: i18n-note --> * * <p/> * * <!-- START SNIPPET: error-reporting --> * * Any error that occurs during type conversion may or may not wish to be reported. For example, reporting that the * input "abc" could not be converted to a number might be important. On the other hand, reporting that an empty string, * "", cannot be converted to a number might not be important - especially in a web environment where it is hard to * distinguish between a user not entering a value vs. entering a blank value. * * <p/> By default, all conversion errors are reported using the generic i18n key <b>xwork.default.invalid.fieldvalue</b>, * which you can override (the default text is <i>Invalid field value for field "xxx"</i>, where xxx is the field name) * in your global i18n resource bundle. * * <p/>However, sometimes you may wish to override this message on a per-field basis. You can do this by adding an i18n * key associated with just your action (Action.properties) using the pattern <b>invalid.fieldvalue.xxx</b>, where xxx * is the field name. * * <p/>It is important to know that none of these errors are actually reported directly. Rather, they are added to a map * called <i>conversionErrors</i> in the ActionContext. There are several ways this map can then be accessed and the * errors can be reported accordingly. * * <!-- END SNIPPET: error-reporting --> * * @author <a href="mailto:plightbo@gmail.com">Pat Lightbody</a> * @author Rainer Hermanns * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a> * @author tm_jee *  * @version $Date: 2007-07-16 17:32:09 +0200 (Mo, 16 Jul 2007) $ $Id: XWorkConverter.java 1548 2007-07-16 15:32:09Z rainerh $ *  * @see XWorkBasicConverter */public class XWorkConverter extends DefaultTypeConverter {    private static XWorkConverter instance;    protected static final Log LOG = LogFactory.getLog(XWorkConverter.class);    public static final String REPORT_CONVERSION_ERRORS = "report.conversion.errors";    public static final String CONVERSION_PROPERTY_FULLNAME = "conversion.property.fullName";    public static final String CONVERSION_ERROR_PROPERTY_PREFIX = "invalid.fieldvalue.";    public static final String CONVERSION_COLLECTION_PREFIX = "Collection_";    public static final String LAST_BEAN_CLASS_ACCESSED = "last.bean.accessed";    public static final String LAST_BEAN_PROPERTY_ACCESSED = "last.property.accessed";    /**     * Target class conversion Mappings.      * <pre>     * Map<Class, Map<String, Object>>     *  - Class -> convert to class     *  - Map<String, Object>     *    - String -> property name      *                eg. Element_property, property etc.     *    - Object -> String to represent properties      *                eg. value part of      *                    KeyProperty_property=id     *             -> TypeConverter to represent an Ognl TypeConverter     *                eg. value part of      *                    property=foo.bar.MyConverter     *             -> Class to represent a class     *                eg. value part of      *                    Element_property=foo.bar.MyObject     * </pre>                    */    protected HashMap<Class,Map<String,Object>> mappings = new HashMap<Class,Map<String,Object>>(); // action 			        /**     * Unavailable target class conversion mappings, serves as a simple cache.     */    protected HashSet<Class> noMapping = new HashSet<Class>(); // action        /**     * Record class and its type converter mapping.     * <pre>     * - String - classname as String     * - TypeConverter - instance of TypeConverter     * </pre>     */    protected HashMap<String, TypeConverter> defaultMappings = new HashMap<String, TypeConverter>();  // non-action (eg. returned value)        /**     * Record classes that doesn't have conversion mapping defined.     * <pre>     * - String -> classname as String     * </pre>     */    protected HashSet<String> unknownMappings = new HashSet<String>(); 	// non-action (eg. returned value)        protected TypeConverter defaultTypeConverter = new XWorkBasicConverter();    protected ObjectTypeDeterminer objectTypeDeterminer = null;    protected XWorkConverter() {        try {            // note: this file is deprecated            loadConversionProperties("xwork-default-conversion.properties");        } catch (Exception e) {        }        try {            loadConversionProperties("xwork-conversion.properties");        } catch (Exception e) {        }    }    public static String getConversionErrorMessage(String propertyName, ValueStack stack) {        String defaultMessage = LocalizedTextUtil.findDefaultText(XWorkMessages.DEFAULT_INVALID_FIELDVALUE,                ActionContext.getContext().getLocale(),                new Object[]{                        propertyName                });        String getTextExpression = "getText('" + CONVERSION_ERROR_PROPERTY_PREFIX + propertyName + "','" + defaultMessage + "')";        String message = (String) stack.findValue(getTextExpression);        if (message == null) {            message = defaultMessage;        }        return message;    }    public static XWorkConverter getInstance() {         if (instance == null) {             instance = new XWorkConverter();         }         return instance;     }        @Inject    public static void setInstance(XWorkConverter instance) {        XWorkConverter.instance = instance;    }    public static String buildConverterFilename(Class clazz) {        String className = clazz.getName();        String resource = className.replace('.', '/') + "-conversion.properties";        return resource;    }    public static void resetInstance() {        instance = null;    }    public void setDefaultConverter(TypeConverter defaultTypeConverter) {        this.defaultTypeConverter = defaultTypeConverter;    }    public Object convertValue(Map map, Object o, Class aClass) {        return convertValue(map, null, null, null, o, aClass);    }    /**     * Convert value from one form to another.     * Minimum requirement of arguments:     * <ul>     * 		<li>supplying context, toClass and value</li>     * 		<li>supplying context, target and value.</li>     * </ul>     *      * @see ognl.TypeConverter#convertValue(java.util.Map, java.lang.Object, java.lang.reflect.Member, java.lang.String, java.lang.Object, java.lang.Class)     */    public Object convertValue(Map context, Object target, Member member, String property, Object value, Class toClass) {        //        // Process the conversion using the default mappings, if one exists        //        TypeConverter tc = null;        if ((value != null) && (toClass == value.getClass())) {            return value;        }        // allow this method to be called without any context        // i.e. it can be called with as little as "Object value" and "Class toClass"        if (target != null) {            Class clazz = target.getClass();            Object[] classProp = null;            // this is to handle weird issues with setValue with a different type            if ((target instanceof CompoundRoot) && (context != null)) {                classProp = getClassProperty(context);            }            if (classProp != null) {                clazz = (Class) classProp[0];                property = (String) classProp[1];            }            tc = (TypeConverter) getConverter(clazz, property);                        if (LOG.isDebugEnabled())                LOG.debug("field-level type converter for property ["+property+"] = "+(tc==null?"none found":tc));        }        

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?