Save This Page
Home » cglib-src-2.2 » net.sf.cglib.core » [javadoc | source]
    1   /*
    2    * Copyright 2003,2004 The Apache Software Foundation
    3    *
    4    *  Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    *  Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   package net.sf.cglib.core;
   17   
   18   import java.beans;
   19   import java.lang.reflect;
   20   import java.security.AccessController;
   21   import java.security.PrivilegedAction;
   22   import java.security.ProtectionDomain;
   23   import java.util;
   24   import org.objectweb.asm.Attribute;
   25   import org.objectweb.asm.Type;
   26   
   27   /**
   28    * @version $Id: ReflectUtils.java,v 1.29 2006/02/28 00:30:51 herbyderby Exp $
   29    */
   30   public class ReflectUtils {
   31       private ReflectUtils() { }
   32       
   33       private static final Map primitives = new HashMap(8);
   34       private static final Map transforms = new HashMap(8);
   35       private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader();
   36       private static Method DEFINE_CLASS;
   37       private static final ProtectionDomain PROTECTION_DOMAIN;
   38       
   39       static {
   40           PROTECTION_DOMAIN = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() {
   41               public Object run() {
   42                   return ReflectUtils.class.getProtectionDomain();
   43               }
   44           });
   45           
   46           AccessController.doPrivileged(new PrivilegedAction() {
   47               public Object run() {
   48                   try {
   49                       Class loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
   50                       DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
   51                                                               new Class[]{ String.class,
   52                                                                            byte[].class,
   53                                                                            Integer.TYPE,
   54                                                                            Integer.TYPE,
   55                                                                            ProtectionDomain.class });
   56                       DEFINE_CLASS.setAccessible(true);
   57                   } catch (ClassNotFoundException e) {
   58                       throw new CodeGenerationException(e);
   59                   } catch (NoSuchMethodException e) {
   60                       throw new CodeGenerationException(e);
   61                   }
   62                   return null;
   63               }
   64           });
   65       }
   66           
   67       private static final String[] CGLIB_PACKAGES = {
   68           "java.lang",
   69       };
   70           
   71       static {
   72           primitives.put("byte", Byte.TYPE);
   73           primitives.put("char", Character.TYPE);
   74           primitives.put("double", Double.TYPE);
   75           primitives.put("float", Float.TYPE);
   76           primitives.put("int", Integer.TYPE);
   77           primitives.put("long", Long.TYPE);
   78           primitives.put("short", Short.TYPE);
   79           primitives.put("boolean", Boolean.TYPE);
   80               
   81           transforms.put("byte", "B");
   82           transforms.put("char", "C");
   83           transforms.put("double", "D");
   84           transforms.put("float", "F");
   85           transforms.put("int", "I");
   86           transforms.put("long", "J");
   87           transforms.put("short", "S");
   88           transforms.put("boolean", "Z");
   89       }
   90           
   91       public static Type[] getExceptionTypes(Member member) {
   92           if (member instanceof Method) {
   93               return TypeUtils.getTypes(((Method)member).getExceptionTypes());
   94           } else if (member instanceof Constructor) {
   95               return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
   96           } else {
   97               throw new IllegalArgumentException("Cannot get exception types of a field");
   98           }
   99       }
  100           
  101       public static Signature getSignature(Member member) {
  102           if (member instanceof Method) {
  103               return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
  104           } else if (member instanceof Constructor) {
  105               Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
  106               return new Signature(Constants.CONSTRUCTOR_NAME,
  107                                    Type.getMethodDescriptor(Type.VOID_TYPE, types));
  108                   
  109           } else {
  110               throw new IllegalArgumentException("Cannot get signature of a field");
  111           }
  112       }
  113           
  114       public static Constructor findConstructor(String desc) {
  115           return findConstructor(desc, defaultLoader);
  116       }
  117           
  118       public static Constructor findConstructor(String desc, ClassLoader loader) {
  119           try {
  120               int lparen = desc.indexOf('(');
  121               String className = desc.substring(0, lparen).trim();
  122               return getClass(className, loader).getConstructor(parseTypes(desc, loader));
  123           } catch (ClassNotFoundException e) {
  124               throw new CodeGenerationException(e);
  125           } catch (NoSuchMethodException e) {
  126               throw new CodeGenerationException(e);
  127           }
  128       }
  129           
  130       public static Method findMethod(String desc) {
  131           return findMethod(desc, defaultLoader);
  132       }
  133           
  134       public static Method findMethod(String desc, ClassLoader loader) {
  135           try {
  136               int lparen = desc.indexOf('(');
  137               int dot = desc.lastIndexOf('.', lparen);
  138               String className = desc.substring(0, dot).trim();
  139               String methodName = desc.substring(dot + 1, lparen).trim();
  140               return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
  141           } catch (ClassNotFoundException e) {
  142               throw new CodeGenerationException(e);
  143           } catch (NoSuchMethodException e) {
  144               throw new CodeGenerationException(e);
  145           }
  146       }
  147           
  148       private static Class[] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException {
  149           int lparen = desc.indexOf('(');
  150           int rparen = desc.indexOf(')', lparen);
  151           List params = new ArrayList();
  152           int start = lparen + 1;
  153           for (;;) {
  154               int comma = desc.indexOf(',', start);
  155               if (comma < 0) {
  156                   break;
  157               }
  158               params.add(desc.substring(start, comma).trim());
  159               start = comma + 1;
  160           }
  161           if (start < rparen) {
  162               params.add(desc.substring(start, rparen).trim());
  163           }
  164           Class[] types = new Class[params.size()];
  165           for (int i = 0; i < types.length; i++) {
  166               types[i] = getClass((String)params.get(i), loader);
  167           }
  168           return types;
  169       }
  170           
  171       private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException {
  172           return getClass(className, loader, CGLIB_PACKAGES);
  173       }
  174           
  175       private static Class getClass(String className, ClassLoader loader, String[] packages) throws ClassNotFoundException {
  176           String save = className;
  177           int dimensions = 0;
  178           int index = 0;
  179           while ((index = className.indexOf("[]", index) + 1) > 0) {
  180               dimensions++;
  181           }
  182           StringBuffer brackets = new StringBuffer(className.length() - dimensions);
  183           for (int i = 0; i < dimensions; i++) {
  184               brackets.append('[');
  185           }
  186           className = className.substring(0, className.length() - 2 * dimensions);
  187               
  188           String prefix = (dimensions > 0) ? brackets + "L" : "";
  189           String suffix = (dimensions > 0) ? ";" : "";
  190           try {
  191               return Class.forName(prefix + className + suffix, false, loader);
  192           } catch (ClassNotFoundException ignore) { }
  193           for (int i = 0; i < packages.length; i++) {
  194               try {
  195                   return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
  196               } catch (ClassNotFoundException ignore) { }
  197           }
  198           if (dimensions == 0) {
  199               Class c = (Class)primitives.get(className);
  200               if (c != null) {
  201                   return c;
  202               }
  203           } else {
  204               String transform = (String)transforms.get(className);
  205               if (transform != null) {
  206                   try {
  207                       return Class.forName(brackets + transform, false, loader);
  208                   } catch (ClassNotFoundException ignore) { }
  209               }
  210           }
  211           throw new ClassNotFoundException(save);
  212       }
  213           
  214           
  215       public static Object newInstance(Class type) {
  216           return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
  217       }
  218           
  219       public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
  220           return newInstance(getConstructor(type, parameterTypes), args);
  221       }
  222           
  223       public static Object newInstance(final Constructor cstruct, final Object[] args) {
  224               
  225           boolean flag = cstruct.isAccessible();
  226           try {
  227               cstruct.setAccessible(true);
  228               Object result = cstruct.newInstance(args);
  229               return result;
  230           } catch (InstantiationException e) {
  231               throw new CodeGenerationException(e);
  232           } catch (IllegalAccessException e) {
  233               throw new CodeGenerationException(e);
  234           } catch (InvocationTargetException e) {
  235               throw new CodeGenerationException(e.getTargetException());
  236           } finally {
  237               cstruct.setAccessible(flag);
  238           }
  239                   
  240       }
  241           
  242       public static Constructor getConstructor(Class type, Class[] parameterTypes) {
  243           try {
  244               Constructor constructor = type.getDeclaredConstructor(parameterTypes);
  245               constructor.setAccessible(true);
  246               return constructor;
  247           } catch (NoSuchMethodException e) {
  248               throw new CodeGenerationException(e);
  249           }
  250       }
  251   
  252       public static String[] getNames(Class[] classes)
  253       {
  254           if (classes == null)
  255               return null;
  256           String[] names = new String[classes.length];
  257           for (int i = 0; i < names.length; i++) {
  258               names[i] = classes[i].getName();
  259           }
  260           return names;
  261       }
  262           
  263       public static Class[] getClasses(Object[] objects) {
  264           Class[] classes = new Class[objects.length];
  265           for (int i = 0; i < objects.length; i++) {
  266               classes[i] = objects[i].getClass();
  267           }
  268           return classes;
  269       }
  270           
  271       public static Method findNewInstance(Class iface) {
  272           Method m = findInterfaceMethod(iface);
  273           if (!m.getName().equals("newInstance")) {
  274               throw new IllegalArgumentException(iface + " missing newInstance method");
  275           }
  276           return m;
  277       }
  278   
  279       public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) {
  280           Set methods = new HashSet();
  281           for (int i = 0; i < properties.length; i++) {
  282               PropertyDescriptor pd = properties[i];
  283               if (read) {
  284                   methods.add(pd.getReadMethod());
  285               }
  286               if (write) {
  287                   methods.add(pd.getWriteMethod());
  288               }
  289           }
  290           methods.remove(null);
  291           return (Method[])methods.toArray(new Method[methods.size()]);
  292       }
  293           
  294       public static PropertyDescriptor[] getBeanProperties(Class type) {
  295           return getPropertiesHelper(type, true, true);
  296       }
  297           
  298       public static PropertyDescriptor[] getBeanGetters(Class type) {
  299           return getPropertiesHelper(type, true, false);
  300       }
  301           
  302       public static PropertyDescriptor[] getBeanSetters(Class type) {
  303           return getPropertiesHelper(type, false, true);
  304       }
  305           
  306       private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
  307           try {
  308               BeanInfo info = Introspector.getBeanInfo(type, Object.class);
  309               PropertyDescriptor[] all = info.getPropertyDescriptors();
  310               if (read && write) {
  311                   return all;
  312               }
  313               List properties = new ArrayList(all.length);
  314               for (int i = 0; i < all.length; i++) {
  315                   PropertyDescriptor pd = all[i];
  316                   if ((read && pd.getReadMethod() != null) ||
  317                       (write && pd.getWriteMethod() != null)) {
  318                       properties.add(pd);
  319                   }
  320               }
  321               return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]);
  322           } catch (IntrospectionException e) {
  323               throw new CodeGenerationException(e);
  324           }
  325       }
  326           
  327           
  328           
  329       public static Method findDeclaredMethod(final Class type,
  330                                               final String methodName, final Class[] parameterTypes)
  331       throws NoSuchMethodException {
  332                           
  333           Class cl = type;
  334           while (cl != null) {
  335               try {
  336                   return cl.getDeclaredMethod(methodName, parameterTypes);
  337               } catch (NoSuchMethodException e) {
  338                   cl = cl.getSuperclass();
  339               }
  340           }
  341           throw new NoSuchMethodException(methodName);
  342               
  343       }
  344           
  345       public static List addAllMethods(final Class type, final List list) {
  346               
  347               
  348           list.addAll(java.util.Arrays.asList(type.getDeclaredMethods()));
  349           Class superclass = type.getSuperclass();
  350           if (superclass != null) {
  351               addAllMethods(superclass, list);
  352           }
  353           Class[] interfaces = type.getInterfaces();
  354           for (int i = 0; i < interfaces.length; i++) {
  355               addAllMethods(interfaces[i], list);
  356           }
  357               
  358           return list;
  359       }
  360           
  361       public static List addAllInterfaces(Class type, List list) {
  362           Class superclass = type.getSuperclass();
  363           if (superclass != null) {
  364               list.addAll(Arrays.asList(type.getInterfaces()));
  365               addAllInterfaces(superclass, list);
  366           }
  367           return list;
  368       }
  369           
  370           
  371       public static Method findInterfaceMethod(Class iface) {
  372           if (!iface.isInterface()) {
  373               throw new IllegalArgumentException(iface + " is not an interface");
  374           }
  375           Method[] methods = iface.getDeclaredMethods();
  376           if (methods.length != 1) {
  377               throw new IllegalArgumentException("expecting exactly 1 method in " + iface);
  378           }
  379           return methods[0];
  380       }
  381           
  382       public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
  383           Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
  384           return (Class)DEFINE_CLASS.invoke(loader, args);
  385       }
  386           
  387       public static int findPackageProtected(Class[] classes) {
  388           for (int i = 0; i < classes.length; i++) {
  389               if (!Modifier.isPublic(classes[i].getModifiers())) {
  390                   return i;
  391               }
  392           }
  393           return 0;
  394       }
  395   
  396       public static MethodInfo getMethodInfo(final Member member, final int modifiers) {
  397           final Signature sig = getSignature(member);
  398           return new MethodInfo() {
  399               private ClassInfo ci;
  400               public ClassInfo getClassInfo() {
  401                   if (ci == null)
  402                       ci = ReflectUtils.getClassInfo(member.getDeclaringClass());
  403                   return ci;
  404               }
  405               public int getModifiers() {
  406                   return modifiers;
  407               }
  408               public Signature getSignature() {
  409                   return sig;
  410               }
  411               public Type[] getExceptionTypes() {
  412                   return ReflectUtils.getExceptionTypes(member);
  413               }
  414               public Attribute getAttribute() {
  415                   return null;
  416               }
  417           };
  418       }
  419   
  420       public static MethodInfo getMethodInfo(Member member) {
  421           return getMethodInfo(member, member.getModifiers());
  422       }
  423   
  424       public static ClassInfo getClassInfo(final Class clazz) {
  425           final Type type = Type.getType(clazz);
  426           final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass());
  427           return new ClassInfo() {
  428               public Type getType() {
  429                   return type;
  430               }
  431               public Type getSuperType() {
  432                   return sc;
  433               }
  434               public Type[] getInterfaces() {
  435                   return TypeUtils.getTypes(clazz.getInterfaces());
  436               }
  437               public int getModifiers() {
  438                   return clazz.getModifiers();
  439               }
  440           };
  441       }
  442   
  443       // used by MethodInterceptorGenerated generated code
  444       public static Method[] findMethods(String[] namesAndDescriptors, Method[] methods)
  445       {
  446           Map map = new HashMap();
  447           for (int i = 0; i < methods.length; i++) {
  448               Method method = methods[i];
  449               map.put(method.getName() + Type.getMethodDescriptor(method), method);
  450           }
  451           Method[] result = new Method[namesAndDescriptors.length / 2];
  452           for (int i = 0; i < result.length; i++) {
  453               result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]);
  454               if (result[i] == null) {
  455                   // TODO: error?
  456               }
  457           }
  458           return result;
  459       }
  460   }

Save This Page
Home » cglib-src-2.2 » net.sf.cglib.core » [javadoc | source]