Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2004-2010 Oracle Corporation. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: Kohsuke Kawaguchi /
  
 
 package org.kohsuke.stapler;
 
 import  org.objectweb.asm.ClassReader;
 import  org.objectweb.asm.Label;
 import  org.objectweb.asm.MethodVisitor;
 import  org.objectweb.asm.Type;
 import  org.objectweb.asm.commons.EmptyVisitor;
 
 import java.net.URL;
 import java.util.List;
 
 import static java.util.logging.Level.FINE;
 import static java.util.logging.Level.WARNING;

Reflection information of a Class.

Author(s):
Kohsuke Kawaguchi
 
 public final class ClassDescriptor {
     public final Class clazz;
     public final FunctionList methods;
     public final Field[] fields;

    

Parameters:
clazz The class to build a descriptor around.
wrappers Optional wrapper duck-typing classes. Static methods on this class that has the first parameter as 'clazz' will be handled as if it's instance methods on 'clazz'. Useful for adding view/controller methods on model classes.
 
     public ClassDescriptor(Class clazzClass... wrappers) {
         this. = clazz;
         this. = clazz.getFields();
 
         // instance methods
         List<Functionfunctions = new ArrayList<Function>();
         for (Method m : clazz.getMethods()) {
             functions.add(new Function.InstanceFunction(m).protectBy(m));
         }
         if(wrappers!=null) {
             for (Class w : wrappers) {
                 for (Method m : w.getMethods()) {
                     if(!Modifier.isStatic(m.getModifiers()))
                         continue;
                     Class<?>[] p = m.getParameterTypes();
                     if(p.length==0)
                         continue;
                     if(p[0].isAssignableFrom(clazz))
                         continue;
                     functions.add(new Function.StaticFunction(m).protectBy(m));
                 }
             }
         }
         this. = new FunctionList(functions);
     }

    
Loads the list of parameter names of the given method, by using a stapler-specific way of getting it.

This is not the best place to expose this, but for now this would do.

 
     public static String[] loadParameterNames(Method m) {
         if(cpn!=null)   return cpn.value();
 
         // debug information, if present, is more trustworthy
         try {
             String[] n = ASM.loadParametersFromAsm(m);
             if (n!=null)    return n;
         } catch (LinkageError e) {
            .log("Incompatible ASM"e);
        } catch (IOException e) {
            .log("Failed to load a class file"e);
        }
        // otherwise check the .stapler file
        Class<?> c = m.getDeclaringClass();
        URL url = c.getClassLoader().getResource(
                    c.getName().replace('.''/').replace('$','/') + '/' + m.getName() + ".stapler");
        if(url!=null) {
            try {
                return IOUtils.toString(url.openStream()).split(",");
            } catch (IOException e) {
                .log("Failed to load "+url,e);
                return ;
            }
        }
        // couldn't find it
        return ;
    }

    
Loads the list of parameter names of the given method, by using a stapler-specific way of getting it.

This is not the best place to expose this, but for now this would do.

    public static String[] loadParameterNames(Constructor<?> m) {
        if(cpn!=null)   return cpn.value();
        // debug information, if present, is more trustworthy
        try {
            String[] n = ASM.loadParametersFromAsm(m);
            if (n!=null)    return n;
        } catch (LinkageError e) {
            .log("Incompatible ASM"e);
        } catch (IOException e) {
            .log("Failed to load a class file"e);
        }
        // couldn't find it
        return ;
    }

    
Isolate the ASM dependency to its own class, as otherwise this seems to cause linkage error on the whole ClassDescriptor.
    private static class ASM {
        
Try to load parameter names from the debug info by using ASM.
        private static String[] loadParametersFromAsm(final Method mthrows IOException {
            final String[] paramNames = new String[m.getParameterTypes().length];
            if (paramNames.length==0) return paramNames;
            Class<?> c = m.getDeclaringClass();
            URL clazz = c.getClassLoader().getResource(c.getName().replace('.''/') + ".class");
            if (clazz==null)    return null;
            final TreeMap<Integer,StringlocalVars = new TreeMap<Integer,String>();
            ClassReader r = new ClassReader(clazz.openStream());
            r.accept(new EmptyVisitor() {
                final String md = Type.getMethodDescriptor(m);
                // First localVariable is "this" for non-static method
                final int limit = (m.getModifiers() & .) != 0 ? 0 : 1;
                @Override public MethodVisitor visitMethod(int accessString methodNameString descString signatureString[] exceptions) {
                    if (methodName.equals(m.getName()) && desc.equals())
                        return new EmptyVisitor() {
                            @Override public void visitLocalVariable(String nameString descString signature, Label start, Label endint index) {
                                if (index >= )
                                    localVars.put(indexname);
                            }
                        };
                    else
                        return null// ignore this method
                }
            }, false);
            // Indexes may not be sequential, but first set of local variables are method params
            int i = 0;
            for (String s : localVars.values()) {
                paramNames[i] = s;
                if (++i == paramNames.lengthreturn paramNames;
            }
            return null// Not enough data found to fill array
        }

        
Try to load parameter names from the debug info by using ASM.
        private static String[] loadParametersFromAsm(final Constructor mthrows IOException {
            final String[] paramNames = new String[m.getParameterTypes().length];
            if (paramNames.length==0) return paramNames;
            Class<?> c = m.getDeclaringClass();
            URL clazz = c.getClassLoader().getResource(c.getName().replace('.''/') + ".class");
            if (clazz==null)    return null;
            final TreeMap<Integer,StringlocalVars = new TreeMap<Integer,String>();
            ClassReader r = new ClassReader(clazz.openStream());
            r.accept(new EmptyVisitor() {
                final String md = getConstructorDescriptor(m);
                public MethodVisitor visitMethod(int accessString methodNameString descString signatureString[] exceptions) {
                    if (methodName.equals("<init>") && desc.equals())
                        return new EmptyVisitor() {
                            @Override public void visitLocalVariable(String nameString descString signature, Label start, Label endint index) {
                                if (index>0)   // 0 is 'this'
                                    localVars.put(indexname);
                            }
                        };
                    else
                        return null// ignore this method
                }
            }, false);
            // Indexes may not be sequential, but first set of local variables are method params
            int i = 0;
            for (String s : localVars.values()) {
                paramNames[i] = s;
                if (++i == paramNames.lengthreturn paramNames;
            }
            return null// Not enough data found to fill array
        }
        private static String getConstructorDescriptor(Constructor c) {
            StringBuilder buf = new StringBuilder("(");
            for (Class p : c.getParameterTypes())
                buf.append(Type.getDescriptor(p));
            return buf.append(")V").toString();
        }
    }
    private static final Logger LOGGER = Logger.getLogger(ClassDescriptor.class.getName());
    private static final String[] EMPTY_ARRAY = new String[0];
New to GrepCode? Check out our FAQ X