Java/Reflection/Class Method Field Name
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Create a new instance given a class name
- 2 Create a unique hash for Constructor and method
- 3 Format a string buffer containing the Class, Interfaces, CodeSource, and ClassLoader information for the given object clazz.
- 4 Get non Package Qualified Name
- 5 Get the short name of the specified class by striping off the package name.
- 6 Load a class given its name.
- 7 Returns an instance of the given class name, by calling the default constructor.
- 8 Returns the name of a class without the package name
- 9 Returns the package portion of the specified class
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;
}
}