• java常用工具方法2


    /*
     * Copyright 2005 Joe Walker
     *
     * Licensed 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.
     */
    package org.directwebremoting.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    import java.io.Reader;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.URLDecoder;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    import java.util.Set;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import javax.xml.transform.TransformerFactoryConfigurationError;
    
    /**
     * 一些通用的方法
     * Various utilities, mostly to make up for JDK 1.4 functionallity that is not
     * in JDK 1.3
     * @author Joe Walker [joe at getahead dot ltd dot uk]
     */
    public final class LocalUtil
    {
        /**
         * splitInbound() returns the type info in this parameter
         */
        public static final int INBOUND_INDEX_TYPE = 0;
    
        /**
         * splitInbound() returns the value info in this parameter
         */
        public static final int INBOUND_INDEX_VALUE = 1;
    
        /**
         * Prevent instansiation
         */
        private LocalUtil()
        {
        }
    
        /**
         * Replacement for String#replaceAll(String, String) in JDK 1.4+
         * @param text source text
         * @param repl the stuff to get rid of
         * @param with the stuff to replace it with
         * @return replaced text or null if any args are null
         */
        public static String replace(String text, String repl, String with)
        {
            if (text == null || repl == null || with == null || repl.length() == 0)
            {
                return text;
            }
    
            StringBuffer buf = new StringBuffer(text.length());
            int searchFrom = 0;
            while (true)
            {
                int foundAt = text.indexOf(repl, searchFrom);
                if (foundAt == -1)
                {
                    break;
                }
    
                buf.append(text.substring(searchFrom, foundAt)).append(with);
                searchFrom = foundAt + repl.length();
            }
            buf.append(text.substring(searchFrom));
    
            return buf.toString();
        }
    
        /**
         * 判断给定的字符串是否符合 Java 标识符的规范
         * 
         * Determines if the specified string is permissible as a Java identifier.
         * Returns true if the string is non-null, non-zero length with a Java
         * identifier start as the first character and Java identifier parts in all
         * remaining characters.
         * @param test the string to be tested.
         * @return true if the string is a Java identifier, false otherwise.
         * @see java.lang.Character#isJavaIdentifierPart(char)
         * @see java.lang.Character#isJavaIdentifierStart(char)
         */
        public static boolean isJavaIdentifier(String test)
        {
            if (test == null || test.length() == 0)
            {
                return false;
            }
    
            if (!Character.isJavaIdentifierStart(test.charAt(0)) && test.charAt(0) != '_')
            {
                return false;
            }
    
            for (int i = 1; i < test.length(); i++)
            {
                if (!Character.isJavaIdentifierPart(test.charAt(i)) && test.charAt(i) != '_')
                {
                    return false;
                }
            }
    
            return true;
        }
    
        /**
         * Determines if the specified string contains only Unicode letters or
         * digits as defined by {@link Character#isLetterOrDigit(char)}
         * @param test The string to test
         * @return true if the string is non-null, non-empty and contains only
         * characters that are unicode letters or digits
         * @see Character#isLetterOrDigit(char)
         */
        public static boolean isLetterOrDigitOrUnderline(String test)
        {
            if (test == null || test.length() == 0)
            {
                return false;
            }
    
            for (int i = 0; i < test.length(); i++)
            {
                if (!Character.isLetterOrDigit(test.charAt(i)) && test.charAt(i) != '_')
                {
                    return false;
                }
            }
    
            return true;
        }
    
        /**
         * True if c1 is java.lang.Boolean and c2 is boolean, etc.
         * @param c1 the first class to test
         * @param c2 the second class to test
         * @return true if the classes are equivalent
         */
        public static boolean isEquivalent(Class c1, Class c2)
        {
            if (c1 == Boolean.class || c1 == Boolean.TYPE)
            {
                return c2 == Boolean.class || c2 == Boolean.TYPE;
            }
            else if (c1 == Byte.class || c1 == Byte.TYPE)
            {
                return c2 == Byte.class || c2 == Byte.TYPE;
            }
            else if (c1 == Character.class || c1 == Character.TYPE)
            {
                return c2 == Character.class || c2 == Character.TYPE;
            }
            else if (c1 == Short.class || c1 == Short.TYPE)
            {
                return c2 == Short.class || c2 == Short.TYPE;
            }
            else if (c1 == Integer.class || c1 == Integer.TYPE)
            {
                return c2 == Integer.class || c2 == Integer.TYPE;
            }
            else if (c1 == Long.class || c1 == Long.TYPE)
            {
                return c2 == Long.class || c2 == Long.TYPE;
            }
            else if (c1 == Float.class || c1 == Float.TYPE)
            {
                return c2 == Float.class || c2 == Float.TYPE;
            }
            else if (c1 == Double.class || c1 == Double.TYPE)
            {
                return c2 == Double.class || c2 == Double.TYPE;
            }
            else if (c1 == Void.class || c1 == Void.TYPE)
            {
                return c2 == Void.class || c2 == Void.TYPE;
            }
    
            return false;
        }
    
        /**
         * @param type The class to de-primitivize
         * @return The non-privitive version of the class
         */
        public static Class getNonPrimitiveType(Class type)
        {
            if (!type.isPrimitive())
            {
                return type;
            }
            else if (type == Boolean.TYPE)
            {
                return Boolean.class;
            }
            else if (type == Byte.TYPE)
            {
                return Byte.class;
            }
            else if (type == Character.TYPE)
            {
                return Character.class;
            }
            else if (type == Short.TYPE)
            {
                return Short.class;
            }
            else if (type == Integer.TYPE)
            {
                return Integer.class;
            }
            else if (type == Long.TYPE)
            {
                return Long.class;
            }
            else if (type == Float.TYPE)
            {
                return Float.class;
            }
            else if (type == Double.TYPE)
            {
                return Double.class;
            }
            else if (type == Void.TYPE)
            {
                return Void.class;
            }
    
            return null;
        }
    
        /**
         * Add headers to prevent browers and proxies from caching this reply.
         * @param resp The response to add headers to
         */
        public static void addNoCacheHeaders(HttpServletResponse resp)
        {
            // Set standard HTTP/1.1 no-cache headers.
            resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
    
            // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
            resp.addHeader("Cache-Control", "post-check=0, pre-check=0");
    
            // Set standard HTTP/1.0 no-cache header.
            resp.setHeader("Pragma", "no-cache");
    
            // Set to expire far in the past. Prevents caching at the proxy server
            resp.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");
        }
    
        /**
         * Is this class one that we auto fill, so the user can ignore?
         * @param paramType The type to test
         * @return true if the type is a Servlet type
         */
        public static boolean isServletClass(Class paramType)
        {
            return paramType == HttpServletRequest.class ||
                   paramType == HttpServletResponse.class ||
                   paramType == ServletConfig.class ||
                   paramType == ServletContext.class ||
                   paramType == HttpSession.class;
        }
    
        /**
         * URL decode a value. This method gets around the lack of a
         * decode(String, String) method in JDK 1.3.
         * @param value The string to decode
         * @return The decoded string
         */
        public static String decode(String value)
        {
            if (!testedDecoder)
            {
                try
                {
                    decode14 = URLDecoder.class.getMethod("decode", new Class[] { String.class, String.class });
                }
                catch (Exception ex)
                {
                    if (!warn13)
                    {
                        log.warn("URLDecoder.decode(String, String) is not available. Falling back to 1.3 variant.");
                        warn13 = true;
                    }
                }
    
                testedDecoder = true;
            }
    
            if (decode14 != null)
            {
                try
                {
                    return (String) decode14.invoke(null, new Object[] { value, "UTF-8" });
                }
                catch (Exception ex)
                {
                    log.warn("Failed to use JDK 1.4 decoder", ex);
                }
            }
    
            return URLDecoder.decode(value);
        }
    
        /**
         * 用反射给对象设置属性集
         * 
         * Set use reflection to set the setters on the object called by the keys
         * in the params map with the corresponding values
         * @param object The object to setup
         * @param params The settings to use
         * @param ignore List of keys to not warn about if they are not properties
         *               Note only the warning is skipped, we still try the setter
         */
        public static void setParams(Object object, Map params, List ignore)
        {
            for (Iterator it = params.entrySet().iterator(); it.hasNext();)
            {
                Map.Entry entry = (Map.Entry) it.next();
                String key = (String) entry.getKey();
                Object value = entry.getValue();
    
                try
                {
                    setProperty(object, key, value);
                }
                catch (NoSuchMethodException ex)
                {
                    if (ignore != null && !ignore.contains(key))
                    {
                        log.warn("No property '" + key + "' on " + object.getClass().getName());
                    }
                }
                catch (InvocationTargetException ex)
                {
                    log.warn("Error setting " + key + "=" + value + " on " + object.getClass().getName(), ex.getTargetException());
                }
                catch (Exception ex)
                {
                    log.warn("Error setting " + key + "=" + value + " on " + object.getClass().getName(), ex);
                }
            }
        }
    
        /**
         * 用反射给对象设置属性,通过给定的属性名。
         * 
         * Set a property on an object using reflection
         * @param object The object to call the setter on
         * @param key The name of the property to set.
         * @param value The new value to use for the property
         * @throws NoSuchMethodException Passed on from reflection code
         * @throws SecurityException Passed on from reflection code
         * @throws IllegalAccessException Passed on from reflection code
         * @throws IllegalArgumentException Passed on from reflection code
         * @throws InvocationTargetException Passed on from reflection code
         */
        public static void setProperty(Object object, String key, Object value) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
        {
            Class real = object.getClass();
    
            String setterName = "set" + key.substring(0, 1).toUpperCase(Locale.ENGLISH) + key.substring(1);
    
            try
            {
                // Can we work with whatever type we were given?
                Method method = real.getMethod(setterName, new Class[] { value.getClass() });
                method.invoke(object, new Object[] { value });
                return;
            }
            catch (NoSuchMethodException ex)
            {
                // If it is a string then next we try to coerce it to the right type
                // otherwise we give up.
                if (!(value instanceof String))
                {
                    throw ex;
                }
            }
    
            Method[] methods = real.getMethods();
            for (int i = 0; i < methods.length; i++)
            {
                Method setter = methods[i];
    
                if (setter.getName().equals(setterName) && setter.getParameterTypes().length == 1)
                {
                    Class propertyType = setter.getParameterTypes()[0];
                    try
                    {
                        Object param = LocalUtil.simpleConvert((String) value, propertyType);
                        setter.invoke(object, new Object[] { param });
                        return;
                    }
                    catch (IllegalArgumentException ex)
                    {
                        // The conversion failed - it was speculative anyway so we
                        // don't worry now
                    }
                }
            }
    
            throw new NoSuchMethodException("Failed to find a property called: " + key + " on " + object.getClass().getName());
        }
    
        /**
         * Can the type be used in a call to {@link #simpleConvert(String, Class)}?
         * @param paramType The type to test
         * @return true if the type is acceptable to simpleConvert()
         */
        public static boolean isTypeSimplyConvertable(Class paramType)
        {
            return paramType == String.class ||
                paramType == Integer.class ||
                paramType == Integer.TYPE ||
                paramType == Short.class ||
                paramType == Short.TYPE ||
                paramType == Byte.class ||
                paramType == Byte.TYPE ||
                paramType == Long.class ||
                paramType == Long.TYPE ||
                paramType == Float.class ||
                paramType == Float.TYPE ||
                paramType == Double.class ||
                paramType == Double.TYPE ||
                paramType == Character.class ||
                paramType == Character.TYPE ||
                paramType == Boolean.class ||
                paramType == Boolean.TYPE;
        }
    
        /**
         * A very simple conversion function for all the IoC style setup and
         * reflection that we are doing.
         * @param value The value to convert
         * @param paramType The type to convert to. Currently ony primitive types and
         * String are supported.
         * @return The converted object.
         */
        public static Object simpleConvert(String value, Class paramType)
        {
            if (paramType == String.class)
            {
                return value;
            }
    
            if (paramType == Character.class || paramType == Character.TYPE)
            {
                if (value.length() == 1)
                {
                    return new Character(value.charAt(0));
                }
                else
                {
                    throw new IllegalArgumentException("Can't more than one character in string - can't convert to char: '" + value + "'");
                }
            }
    
            String trimValue = value.trim();
    
            if (paramType == Boolean.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Boolean.valueOf(trimValue);
            }
    
            if (paramType == Boolean.TYPE)
            {
                return Boolean.valueOf(trimValue);
            }
    
            if (paramType == Integer.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Integer.valueOf(trimValue);
            }
    
            if (paramType == Integer.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Integer(0);
                }
    
                return Integer.valueOf(trimValue);
            }
    
            if (paramType == Short.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Short.valueOf(trimValue);
            }
    
            if (paramType == Short.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Short((short) 0);
                }
    
                return Short.valueOf(trimValue);
            }
    
            if (paramType == Byte.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Byte.valueOf(trimValue);
            }
    
            if (paramType == Byte.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Byte((byte) 0);
                }
    
                return Byte.valueOf(trimValue);
            }
    
            if (paramType == Long.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Long.valueOf(trimValue);
            }
    
            if (paramType == Long.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Long(0);
                }
    
                return Long.valueOf(trimValue);
            }
    
            if (paramType == Float.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Float.valueOf(trimValue);
            }
    
            if (paramType == Float.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Float(0);
                }
    
                return Float.valueOf(trimValue);
            }
    
            if (paramType == Double.class)
            {
                if (trimValue.length() == 0)
                {
                    return null;
                }
    
                return Double.valueOf(trimValue);
            }
    
            if (paramType == Double.TYPE)
            {
                if (trimValue.length() == 0)
                {
                    return new Double(0);
                }
    
                return Double.valueOf(trimValue);
            }
    
            throw new IllegalArgumentException("Unsupported conversion type: " + paramType.getName());
        }
    
        /**
         * 得到除去包名的类名。
         * 
         * Get the short class name (i.e. without the package part)
         * @param clazz the class to get the short name of
         * @return the class name of the class without the package name
         */
        public static String getShortClassName(Class clazz)
        {
            String className = clazz.getName();
    
            char[] chars = className.toCharArray();
            int lastDot = 0;
            for (int i = 0; i < chars.length; i++)
            {
                if (chars[i] == '.')
                {
                    lastDot = i + 1;
                }
                else if (chars[i] == '$')
                {
                    chars[i] = '.';
                }
            }
    
            // This might come up in scans for locale/charset issues. It's not an
            // issue since we are talking about chars.
            return new String(chars, lastDot, chars.length - lastDot);
        }
    
        /**
         * Is this object property one that we can use in a JSON style or do we need
         * to get fancy. i.e does it contain only letters and numbers with an
         * initial letter.
         * @param name The name to test for JSON compatibility
         * @return true if the name is simple
         */
        public static boolean isSimpleName(String name)
        {
            if (name.length() == 0)
            {
                return false;
            }
    
            if (JavascriptUtil.isReservedWord(name))
            {
                return false;
            }
    
            boolean isSimple = Character.isLetter(name.charAt(0));
            for (int i = 1; isSimple && i < name.length(); i++)
            {
                if (!Character.isLetterOrDigit(name.charAt(i)))
                {
                    isSimple = false;
                }
            }
    
            return isSimple;
        }
    
        /**
         * Utility to essentially do Class forName and allow configurable
         * Classloaders.
         * <p>The initial implementation makes use of the context classloader for
         * the current thread.
         * @param className The class to create
         * @return The class if it is safe or null otherwise.
         * @throws ClassNotFoundException If <code>className</code> is not valid
         */
        public static Class classForName(String className) throws ClassNotFoundException
        {
            // Class.forName(className);
            return Thread.currentThread().getContextClassLoader().loadClass(className);
        }
    
        /**
         * Calling methods using reflection is useful for graceful fallback - this
         * is a helper method to make this easy
         * @param object The object to use as 'this'
         * @param method The method to call, can be null in which case null is returned
         * @param params The parameters to pass to the reflection call
         * @return The results of calling method.invoke() or null
         * @throws IllegalStateException If anything goes wrong
         */
        public static Object invoke(Object object, Method method, Object[] params) throws IllegalStateException
        {
            Object reply = null;
            if (method != null)
            {
                try
                {
                    reply = method.invoke(object, params);
                }
                catch (InvocationTargetException ex)
                {
                    throw new IllegalStateException("InvocationTargetException calling " + method.getName() + ": " + ex.getTargetException().toString());
                }
                catch (Exception ex)
                {
                    throw new IllegalStateException("Reflection error calling " + method.getName() + ": " + ex.toString());
                }
            }
    
            return reply;
        }
    
        /**
         * Utility to essentially do Class forName with the assumption that the
         * environment expects failures for missing jar files and can carry on if
         * this process fails.
         * @param name The name for debugging purposes
         * @param className The class to create
         * @param impl The implementation class - what should className do?
         * @return The class if it is safe or null otherwise.
         */
        public static Class classForName(String name, String className, Class impl)
        {
            Class clazz;
    
            try
            {
                clazz = classForName(className);
            }
            catch (ClassNotFoundException ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to ClassNotFoundException on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
            catch (NoClassDefFoundError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to NoClassDefFoundError on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
            catch (TransformerFactoryConfigurationError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to TransformerFactoryConfigurationError on " + className + ". Cause: " + ex.getMessage());
                log.debug("Maybe you need to add xalan.jar to your webserver?");
                return null;
            }
    
            // Check it is of the right type
            if (!impl.isAssignableFrom(clazz))
            {
                log.error("Class '" + clazz.getName() + "' does not implement '" + impl.getName() + "'.");
                return null;
            }
    
            // Check we can create it
            try
            {
                clazz.newInstance();
            }
            catch (InstantiationException ex)
            {
                log.error("InstantiationException for '" + name + "' failed:", ex);
                return null;
            }
            catch (IllegalAccessException ex)
            {
                log.error("IllegalAccessException for '" + name + "' failed:", ex);
                return null;
            }
            catch (NoClassDefFoundError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to NoClassDefFoundError on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
            catch (TransformerFactoryConfigurationError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to TransformerFactoryConfigurationError on " + className + ". Cause: " + ex.getMessage());
                log.debug("Maybe you need to add xalan.jar to your webserver?");
                return null;
            }
            catch (Exception ex)
            {
                // For some reason we can't catch this?
                if (ex instanceof ClassNotFoundException)
                {
                    // We expect this sometimes, hence debug
                    log.debug("Skipping '" + name + "' due to ClassNotFoundException on " + className + ". Cause: " + ex.getMessage());
                    return null;
                }
                else
                {
                    log.error("Failed to load '" + name + "' (" + className + ")", ex);
                    return null;
                }
            }
    
            return clazz;
        }
    
        /**
         * Utility to essentially do Class forName and newInstance with the
         * assumption that the environment expects failures for missing jar files
         * and can carry on if this process fails.
         * @param name The name for debugging purposes
         * @param className The class to create
         * @param impl The implementation class - what should className do?
         * @return The new instance if it is safe or null otherwise.
         */
        public static Object classNewInstance(String name, String className, Class impl)
        {
            Class clazz;
    
            try
            {
                clazz = LocalUtil.classForName(className);
            }
            catch (ClassNotFoundException ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to ClassNotFoundException on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
            catch (NoClassDefFoundError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to NoClassDefFoundError on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
            catch (TransformerFactoryConfigurationError ex)
            {
                // We expect this sometimes, hence debug
                log.debug("Skipping '" + name + "' due to TransformerFactoryConfigurationError on " + className + ". Cause: " + ex.getMessage());
                return null;
            }
    
            // Check it is of the right type
            if (!impl.isAssignableFrom(clazz))
            {
                log.error("Class '" + clazz.getName() + "' does not implement '" + impl.getName() + "'.");
                return null;
            }
    
            // Check we can create it
            try
            {
                return clazz.newInstance();
            }
            catch (InstantiationException ex)
            {
                log.error("InstantiationException for '" + name + "' failed:", ex);
                return null;
            }
            catch (IllegalAccessException ex)
            {
                log.error("IllegalAccessException for '" + name + "' failed:", ex);
                return null;
            }
            catch (TransformerFactoryConfigurationError ex)
            {
                log.error("TransformerFactoryConfigurationError for '" + name + "' failed:", ex);
                return null;
            }
            catch (Exception ex)
            {
                log.error("Failed to load creator '" + name + "', classname=" + className + ": ", ex);
                return null;
            }
        }
    
        /**
         * InputStream closer that can cope if the input stream is null.
         * If anything goes wrong, the errors are logged and ignored.
         * @param in The resource to close
         */
        public static void close(InputStream in)
        {
            if (in == null)
            {
                return;
            }
    
            try
            {
                in.close();
            }
            catch (IOException ex)
            {
                log.warn(ex.getMessage(), ex);
            }
        }
    
        /**
         * InputStream closer that can cope if the input stream is null.
         * If anything goes wrong, the errors are logged and ignored.
         * @param in The resource to close
         */
        public static void close(Reader in)
        {
            if (in == null)
            {
                return;
            }
    
            try
            {
                in.close();
            }
            catch (IOException ex)
            {
                log.warn(ex.getMessage(), ex);
            }
        }
    
        /**
         * InputStream closer that can cope if the input stream is null.
         * If anything goes wrong, the errors are logged and ignored.
         * @param in The resource to close
         */
        public static void close(RandomAccessFile in)
        {
            if (in == null)
            {
                return;
            }
    
            try
            {
                in.close();
            }
            catch (IOException ex)
            {
                log.warn(ex.getMessage(), ex);
            }
        }
    
        /**
         * Return a List of superclasses for the given class.
         * @param clazz the class to look up
         * @return the List of superclasses in order going up from this one
         */
        public static List getAllSuperclasses(Class clazz)
        {
            List classes = new ArrayList();
    
            Class superclass = clazz.getSuperclass();
            while (superclass != null)
            {
                classes.add(superclass);
                superclass = superclass.getSuperclass();
            }
    
            return classes;
        }
    
        /**
         * Return a list of all fields (whatever access status, and on whatever
         * superclass they were defined) that can be found on this class.
         * <p>This is like a union of {@link Class#getDeclaredFields()} which
         * ignores and superclasses, and {@link Class#getFields()} which ignored
         * non-pubic fields
         * @param clazz The class to introspect
         * @return The complete list of fields
         */
        public static Field[] getAllFields(Class clazz)
        {
            List classes = getAllSuperclasses(clazz);
            classes.add(clazz);
            return getAllFields(classes);
        }
    
        /**
         * As {@link #getAllFields(Class)} but acts on a list of {@link Class}s and
         * uses only {@link Class#getDeclaredFields()}.
         * @param classes The list of classes to reflect on
         * @return The complete list of fields
         */
        private static Field[] getAllFields(List classes)
        {
            Set fields = new HashSet();
            for (Iterator it = classes.iterator(); it.hasNext();)
            {
                Class clazz = (Class) it.next();
                fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            }
    
            return (Field[]) fields.toArray(new Field[fields.size()]);
        }
    
        /**
         * The log stream
         */
        private static final Logger log = Logger.getLogger(LocalUtil.class);
    
        /**
         * Have we given a warning about URLDecoder.decode() in jdk 1.3
         */
        private static boolean warn13 = false;
    
        /**
         * Have we tested for the correct URLDecoder.decode()
         */
        private static boolean testedDecoder = false;
    
        /**
         * Are we using the jdk 1.4 version of URLDecoder.decode()
         */
        private static Method decode14 = null;
    }
  • 相关阅读:
    win10 自定义开机启动项
    面试题(武汉)医疗实施工程师sql
    App逆向相关 | App逆向
    openid 客户端认证方法(Client Authentication methods)简介
    Delphi 连接 Oracle 客户端配置
    转载:VS code【尝试在目标目录创建文件时发生一个错误】解决方案
    转载:Cesium SuperMap问题调研汇总
    转载:通过显式渲染提高Cesium性能
    转载:配置fastjson_safemode
    转载:SuperMap在拥抱开源路上所做的努力
  • 原文地址:https://www.cnblogs.com/langtianya/p/3875133.html
Copyright © 2020-2023  润新知