Java/Reflection/Class Method Field Name

Материал из Java эксперт
Версия от 18:01, 31 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Create a new instance given a class name

 
/*
 * 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.
 */
import java.net.MalformedURLException;
import java.net.URL;
/**
 * A collection of class management utility methods.
 *
 * @version $Id: ClassUtils.java 587751 2007-10-24 02:41:36Z vgritsenko $
 */
public class ClassUtils {
    /**
     * Create a new instance given a class name
     *
     * @param className A class name
     * @return A new instance
     * @exception Exception If an instantiation error occurs
     */
    public static Object newInstance(String className) throws Exception {
        return loadClass(className).newInstance();
    }
    /**
     * Load a class given its name.
     * BL: We wan"t to use a known ClassLoader--hopefully the heirarchy
     *     is set correctly.
     *
     * @param className A class name
     * @return The class pointed to by <code>className</code>
     * @exception ClassNotFoundException If a loading error occurs
     */
    public static Class loadClass(String className) throws ClassNotFoundException {
        return getClassLoader().loadClass(className);
    }
    /**
     * Return a resource URL.
     * BL: if this is command line operation, the classloading issues
     *     are more sane.  During servlet execution, we explicitly set
     *     the ClassLoader.
     *
     * @return The context classloader.
     * @exception MalformedURLException If a loading error occurs
     */
    public static URL getResource(String resource) throws MalformedURLException {
        return getClassLoader().getResource(resource);
    }
    /**
     * Return the context classloader.
     * BL: if this is command line operation, the classloading issues
     *     are more sane.  During servlet execution, we explicitly set
     *     the ClassLoader.
     *
     * @return The context classloader.
     */
    public static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
}





Create a unique hash for Constructor and method

 
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
/**
 * Create a unique hash for
 * 
 * @author 
 * @version $Revision: 2787 $
 */
@SuppressWarnings("unchecked")
public class MethodHashing {
  // Constants -----------------------------------------------------
  // Static --------------------------------------------------------
  static Map hashMap = new WeakHashMap();
  public static Method findMethodByHash(Class clazz, long hash) throws Exception {
    Method[] methods = clazz.getDeclaredMethods();
    for (int i = 0; i < methods.length; i++) {
      if (methodHash(methods[i]) == hash)
        return methods[i];
    }
    if (clazz.getSuperclass() != null) {
      return findMethodByHash(clazz.getSuperclass(), hash);
    }
    return null;
  }
  public static Constructor findConstructorByHash(Class clazz, long hash) throws Exception {
    Constructor[] cons = clazz.getDeclaredConstructors();
    for (int i = 0; i < cons.length; i++) {
      if (constructorHash(cons[i]) == hash)
        return cons[i];
    }
    if (clazz.getSuperclass() != null) {
      return findConstructorByHash(clazz.getSuperclass(), hash);
    }
    return null;
  }
  public static long methodHash(Method method) throws Exception {
    Class[] parameterTypes = method.getParameterTypes();
    String methodDesc = method.getName() + "(";
    for (int j = 0; j < parameterTypes.length; j++) {
      methodDesc += getTypeString(parameterTypes[j]);
    }
    methodDesc += ")" + getTypeString(method.getReturnType());
    long hash = 0;
    ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(512);
    MessageDigest messagedigest = MessageDigest.getInstance("SHA");
    DataOutputStream dataoutputstream = new DataOutputStream(new DigestOutputStream(
        bytearrayoutputstream, messagedigest));
    dataoutputstream.writeUTF(methodDesc);
    dataoutputstream.flush();
    byte abyte0[] = messagedigest.digest();
    for (int j = 0; j < Math.min(8, abyte0.length); j++)
      hash += (long) (abyte0[j] & 0xff) << j * 8;
    return hash;
  }
  public static long constructorHash(Constructor method) throws Exception {
    Class[] parameterTypes = method.getParameterTypes();
    String methodDesc = method.getName() + "(";
    for (int j = 0; j < parameterTypes.length; j++) {
      methodDesc += getTypeString(parameterTypes[j]);
    }
    methodDesc += ")";
    long hash = 0;
    ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(512);
    MessageDigest messagedigest = MessageDigest.getInstance("SHA");
    DataOutputStream dataoutputstream = new DataOutputStream(new DigestOutputStream(
        bytearrayoutputstream, messagedigest));
    dataoutputstream.writeUTF(methodDesc);
    dataoutputstream.flush();
    byte abyte0[] = messagedigest.digest();
    for (int j = 0; j < Math.min(8, abyte0.length); j++)
      hash += (long) (abyte0[j] & 0xff) << j * 8;
    return hash;
  }
  /**
   * Calculate method hashes. This algo is taken from RMI.
   * 
   * @param intf
   * @return the map
   */
  public static Map getInterfaceHashes(Class intf) {
    // Create method hashes
    Method[] methods = intf.getDeclaredMethods();
    HashMap map = new HashMap();
    for (int i = 0; i < methods.length; i++) {
      Method method = methods[i];
      try {
        long hash = methodHash(method);
        map.put(method.toString(), new Long(hash));
      } catch (Exception e) {
      }
    }
    return map;
  }
  static String getTypeString(Class cl) {
    if (cl == Byte.TYPE) {
      return "B";
    } else if (cl == Character.TYPE) {
      return "C";
    } else if (cl == Double.TYPE) {
      return "D";
    } else if (cl == Float.TYPE) {
      return "F";
    } else if (cl == Integer.TYPE) {
      return "I";
    } else if (cl == Long.TYPE) {
      return "J";
    } else if (cl == Short.TYPE) {
      return "S";
    } else if (cl == Boolean.TYPE) {
      return "Z";
    } else if (cl == Void.TYPE) {
      return "V";
    } else if (cl.isArray()) {
      return "[" + getTypeString(cl.getComponentType());
    } else {
      return "L" + cl.getName().replace(".", "/") + ";";
    }
  }
  /*
   * The use of hashCode is not enough to differenciate methods we override the
   * hashCode
   * 
   * The hashes are cached in a static for efficiency RO: WeakHashMap needed to
   * support undeploy
   */
  public static long calculateHash(Method method) {
    Map methodHashes = (Map) hashMap.get(method.getDeclaringClass());
    if (methodHashes == null) {
      methodHashes = getInterfaceHashes(method.getDeclaringClass());
      // Copy and add
      WeakHashMap newHashMap = new WeakHashMap();
      newHashMap.putAll(hashMap);
      newHashMap.put(method.getDeclaringClass(), methodHashes);
      hashMap = newHashMap;
    }
    return ((Long) methodHashes.get(method.toString())).longValue();
  }
}





Format a string buffer containing the Class, Interfaces, CodeSource, and ClassLoader information for the given object clazz.

 
import java.lang.reflect.Method;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
public class Main {

  /**
   * Format a string buffer containing the Class, Interfaces, CodeSource, and
   * ClassLoader information for the given object clazz.
   * 
   * @param clazz
   *          the Class
   * @param results -
   *          the buffer to write the info to
   */
  public static void displayClassInfo(Class clazz, StringBuffer results) {
    // Print out some codebase info for the clazz
    ClassLoader cl = clazz.getClassLoader();
    results.append("\n");
    results.append(clazz.getName());
    results.append("(");
    results.append(Integer.toHexString(clazz.hashCode()));
    results.append(").ClassLoader=");
    results.append(cl);
    ClassLoader parent = cl;
    while (parent != null) {
      results.append("\n..");
      results.append(parent);
      URL[] urls = getClassLoaderURLs(parent);
      int length = urls != null ? urls.length : 0;
      for (int u = 0; u < length; u++) {
        results.append("\n....");
        results.append(urls[u]);
      }
      if (parent != null)
        parent = parent.getParent();
    }
    CodeSource clazzCS = clazz.getProtectionDomain().getCodeSource();
    if (clazzCS != null) {
      results.append("\n++++CodeSource: ");
      results.append(clazzCS);
    } else
      results.append("\n++++Null CodeSource");
    results.append("\nImplemented Interfaces:");
    Class[] ifaces = clazz.getInterfaces();
    for (int i = 0; i < ifaces.length; i++) {
      Class iface = ifaces[i];
      results.append("\n++");
      results.append(iface);
      results.append("(");
      results.append(Integer.toHexString(iface.hashCode()));
      results.append(")");
      ClassLoader loader = ifaces[i].getClassLoader();
      results.append("\n++++ClassLoader: ");
      results.append(loader);
      ProtectionDomain pd = ifaces[i].getProtectionDomain();
      CodeSource cs = pd.getCodeSource();
      if (cs != null) {
        results.append("\n++++CodeSource: ");
        results.append(cs);
      } else
        results.append("\n++++Null CodeSource");
    }
  }

  /**
   * Use reflection to access a URL[] getURLs or URL[] getClasspath method so
   * that non-URLClassLoader class loaders, or class loaders that override
   * getURLs to return null or empty, can provide the true classpath info.
   * 
   * @param cl
   * @return the urls
   */
  public static URL[] getClassLoaderURLs(ClassLoader cl) {
    URL[] urls = {};
    try {
      Class returnType = urls.getClass();
      Class[] parameterTypes = {};
      Class clClass = cl.getClass();
      Method getURLs = clClass.getMethod("getURLs", parameterTypes);
      if (returnType.isAssignableFrom(getURLs.getReturnType())) {
        Object[] args = {};
        urls = (URL[]) getURLs.invoke(cl, args);
      }
      if (urls == null || urls.length == 0) {
        Method getCp = clClass.getMethod("getClasspath", parameterTypes);
        if (returnType.isAssignableFrom(getCp.getReturnType())) {
          Object[] args = {};
          urls = (URL[]) getCp.invoke(cl, args);
        }
      }
    } catch (Exception ignore) {
    }
    return urls;
  }
}





Get non Package Qualified Name

 


public class Utils {
  public static String nonPackageQualifiedName( final Class<?> clazz ) {
      String name = clazz.getName();
      return name.substring(name.lastIndexOf(".") + 1);
  }

}





Get the short name of the specified class by striping off the package name.

 
import java.lang.reflect.Method;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
public class Main {
  /** The string used to separator packages */
  public static final String PACKAGE_SEPARATOR = ".";
  /**
   * Get the short name of the specified class by striping off the package name.
   * 
   * @param classname
   *          Class name.
   * @return Short class name.
   */
  public static String stripPackageName(final String classname) {
    int idx = classname.lastIndexOf(PACKAGE_SEPARATOR);
    if (idx != -1)
      return classname.substring(idx + 1, classname.length());
    return classname;
  }
}





Load a class given its name.

 
/*
 * 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.
 */
import java.net.MalformedURLException;
import java.net.URL;
/**
 * A collection of class management utility methods.
 *
 * @version $Id: ClassUtils.java 587751 2007-10-24 02:41:36Z vgritsenko $
 */
public class ClassUtils {

    /**
     * Load a class given its name.
     * BL: We wan"t to use a known ClassLoader--hopefully the heirarchy
     *     is set correctly.
     *
     * @param className A class name
     * @return The class pointed to by <code>className</code>
     * @exception ClassNotFoundException If a loading error occurs
     */
    public static Class loadClass(String className) throws ClassNotFoundException {
        return getClassLoader().loadClass(className);
    }
    /**
     * Return a resource URL.
     * BL: if this is command line operation, the classloading issues
     *     are more sane.  During servlet execution, we explicitly set
     *     the ClassLoader.
     *
     * @return The context classloader.
     * @exception MalformedURLException If a loading error occurs
     */
    public static URL getResource(String resource) throws MalformedURLException {
        return getClassLoader().getResource(resource);
    }
    /**
     * Return the context classloader.
     * BL: if this is command line operation, the classloading issues
     *     are more sane.  During servlet execution, we explicitly set
     *     the ClassLoader.
     *
     * @return The context classloader.
     */
    public static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
}





Returns an instance of the given class name, by calling the default constructor.

 
/*
 * $Id: ClassUtil.java 709153 2008-10-30 12:54:10Z apetrelli $
 *
 * 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.
 */

/**
 * Utilities to work with dynamic class loading and instantiation.
 *
 * @version $Rev: 709153 $ $Date: 2008-10-30 13:54:10 +0100 (Thu, 30 Oct 2008) $
 * @since 2.0.7
 */
public class Main {
  /**
   * Returns an instance of the given class name, by calling the default
   * constructor.
   *
   * @param className The class name to load and to instantiate.
   * @param returnNull If <code>true</code>, if the class is not found it
   * returns <code>true</code>, otherwise it throws a
   * <code>TilesException</code>.
   * @return The new instance of the class name.
   * @throws CannotInstantiateObjectException If something goes wrong during instantiation.
   * @since 2.0.7
   */
  public static Object instantiate(String className, boolean returnNull) {
      ClassLoader original = Thread.currentThread().getContextClassLoader();
      if (original == null) {
          Thread.currentThread().setContextClassLoader(Main.class.getClassLoader());
      }
      try {
          Class<?> namedClass = Class.forName(className);
          return namedClass.newInstance();
      } catch (ClassNotFoundException e) {
          if (returnNull) {
              return null;
          }
          throw new RuntimeException(
                  "Unable to resolve factory class: "" + className + """, e);
      } catch (IllegalAccessException e) {
          throw new RuntimeException(
                  "Unable to access factory class: "" + className + """, e);
      } catch (InstantiationException e) {
          throw new RuntimeException(
                  "Unable to instantiate factory class: ""
                          + className
                          + "". Make sure that this class has a default constructor",
                  e);
      } finally {
          // If the original context classloader of the current thread was
          // null, it must be reset.
          if (original == null) {
              Thread.currentThread().setContextClassLoader(null);
          }
      }
  }
}





Returns the name of a class without the package name

 
public class Utils {
  /**
   * Returns the name of a class without the package name.  For example: if
   * input = "java.lang.Object" , then output = "Object".
   * @param fully qualified classname
   * @return the unqualified classname 
   */
  public static String getShortClassName(final String className) {
      if (className != null) {
          final int index = className.lastIndexOf(".");
          return className.substring(index + 1);
      }
      return null;
  }
}





Returns the package portion of the specified class

 
public class Utils {
  /**
   * Returns the package portion of the specified class
   * @param className the name of the class from which to extract the package
   * @return package portion of the specified class
   */
  public static String getPackageName(final String className) {
      if (className != null) {
          final int index = className.lastIndexOf(".");
          return ((index != -1) ? className.substring(0, index) : ""); // NOI18N
      }
      return null;
  }
}