View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.orchestra.dynaForm.metadata.impl.ejb;
20  
21  import org.apache.bcel.Repository;
22  import org.apache.bcel.classfile.JavaClass;
23  import org.apache.bcel.generic.ArrayType;
24  import org.apache.bcel.generic.BasicType;
25  import org.apache.bcel.generic.ObjectType;
26  import org.apache.bcel.generic.Type;
27  import org.apache.myfaces.orchestra.dynaForm.lib.DynaFormException;
28  
29  import java.lang.reflect.Array;
30  import java.lang.reflect.Field;
31  import java.lang.reflect.Method;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  /**
36   * Reimplement the reflection facilities provided by Class.class,
37   * but preserving the order in which the properties exist within
38   * the .class file.
39   * <p>
40   * Presumably the field order in the .class file is the same as the order they are
41   * declared within the source file. And presumably the code author arranged
42   * those in some logical order.
43   * <p>
44   * This class uses the BCEL library to inspect the class data.
45   */
46  public class BcelHelper implements ClassHelper
47  {
48      /**
49       * Return a list of all the static and non-static fields of the specified
50       * class, regardless of their accessability.
51       * <p>
52       * The array order matches the order in which the fields were declared within
53       * the original source file.
54       */
55      public Field[] getFields(Class<?> clazz)
56      {
57          JavaClass javaClass = Repository.lookupClass(clazz);
58          org.apache.bcel.classfile.Field[] fields = javaClass.getFields();
59  
60          List<Field> ret = new ArrayList<Field>(fields.length);
61          for (org.apache.bcel.classfile.Field field : fields)
62          {
63              try
64              {
65                  ret.add(clazz.getDeclaredField(field.getName()));
66              }
67              catch (SecurityException e)
68              {
69                  throw new DynaFormException(e);
70              }
71              catch (NoSuchFieldException e)
72              {
73                  throw new DynaFormException(e);
74              }
75          }
76          return ret.toArray(new Field[ret.size()]);
77      }
78  
79      /**
80       * Return a list of all the get*, set* and is* method on the specified class,
81       * regardless of their accessability.
82       * <p>
83       * The array order matches the order in which the methods were declared within
84       * the original source file.
85       */
86      public Method[] getMethods(Class<?> clazz)
87      {
88          JavaClass javaClass = Repository.lookupClass(clazz);
89          org.apache.bcel.classfile.Method[] methods = javaClass.getMethods();
90  
91          List<Method> ret = new ArrayList<Method>(methods.length);
92          for (org.apache.bcel.classfile.Method method : methods)
93          {
94              String methodName = method.getName();
95              if (!methodName.startsWith("set") && !methodName.startsWith("get") && !methodName.startsWith("is"))
96              {
97                  continue;
98              }
99  
100             Type[] types = method.getArgumentTypes();
101             Class<?>[] args = new Class[types.length];
102             for (int i = 0; i < types.length; i++)
103             {
104                 args[i] = type2Class(types[i]);
105             }
106 
107             try
108             {
109                 ret.add(clazz.getDeclaredMethod(methodName, args));
110             }
111             catch (SecurityException e)
112             {
113                 throw new DynaFormException(e);
114             }
115             catch (NoSuchMethodException e)
116             {
117                 throw new DynaFormException(e);
118             }
119         }
120         return ret.toArray(new Method[ret.size()]);
121     }
122 
123     protected Class<?> type2Class(Type type)
124     {
125         if (type instanceof BasicType)
126         {
127             BasicType basicType = (BasicType) type;
128             if (basicType.getType() == BasicType.BOOLEAN.getType())
129             {
130                 return boolean.class;
131             }
132             else if (basicType.getType() == BasicType.BYTE.getType())
133             {
134                 return byte.class;
135             }
136             else if (basicType.getType() == BasicType.CHAR.getType())
137             {
138                 return char.class;
139             }
140             else if (basicType.getType() == BasicType.DOUBLE.getType())
141             {
142                 return double.class;
143             }
144             else if (basicType.getType() == BasicType.FLOAT.getType())
145             {
146                 return float.class;
147             }
148             else if (basicType.getType() == BasicType.INT.getType())
149             {
150                 return int.class;
151             }
152             else if (basicType.getType() == BasicType.LONG.getType())
153             {
154                 return long.class;
155             }
156             else if (basicType.getType() == BasicType.SHORT.getType())
157             {
158                 return short.class;
159             }
160             else if (basicType.getType() == BasicType.STRING.getType())
161             {
162                 return String.class;
163             }
164             else if (basicType.getType() == BasicType.VOID.getType())
165             {
166                 return void.class;
167             }
168             throw new IllegalArgumentException("dont know how to map " + basicType);
169         }
170         else if (type instanceof ObjectType)
171         {
172             ObjectType objectType = (ObjectType) type;
173             try
174             {
175                 return Class.forName(objectType.getClassName());
176             }
177             catch (ClassNotFoundException e)
178             {
179                 throw new DynaFormException(e);
180             }
181         }
182         else if (type instanceof ArrayType)
183         {
184             Class<?> elementType = type2Class(((ArrayType) type).getElementType());
185             return Array.newInstance(elementType, 0).getClass();
186         }
187 
188         throw new IllegalArgumentException("unkown type " + type);
189     }
190 
191 }