View Javadoc

1   package org.codehaus.ivory.serialize;
2   
3   import java.beans.Introspector;
4   import java.beans.PropertyDescriptor;
5   import java.lang.reflect.Method;
6   import java.security.AccessController;
7   import java.security.PrivilegedAction;
8   import java.util.ArrayList;
9   import java.util.Vector;
10  
11  import org.apache.axis.AxisFault;
12  import org.apache.axis.InternalException;
13  import org.apache.axis.description.FieldDesc;
14  import org.apache.axis.description.TypeDesc;
15  import org.apache.axis.utils.BeanPropertyDescriptor;
16  import org.apache.axis.utils.BeanUtils;
17  import org.apache.commons.attributes.Attributes;
18  import org.apache.commons.logging.Log;
19  import org.apache.axis.components.logger.LogFactory;
20  import org.codehaus.ivory.attributes.NonWebMethod;
21  
22  /***
23   * 
24   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
25   * @since May 21, 2003
26   */
27  public class MetaBeanUtils extends BeanUtils
28  {
29  
30      public static final Object[] noArgs = new Object[] {
31      };
32      protected static Log log = LogFactory.getLog(BeanUtils.class.getName());
33  
34      /***
35       * Create a BeanPropertyDescriptor array for the indicated class.
36       * @param javaType
37       * @return an ordered array of properties
38       */
39      public static BeanPropertyDescriptor[] getPd(Class javaType)
40      {
41          return MetaBeanUtils.getPd(javaType, null);
42      }
43  
44      /***
45       * Create a BeanPropertyDescriptor array for the indicated class.
46       * @param javaType
47       * @param typeDesc
48       * @return an ordered array of properties
49       */
50      public static BeanPropertyDescriptor[] getPd(
51          Class javaType,
52          TypeDesc typeDesc)
53      {
54          BeanPropertyDescriptor[] pd;
55          try
56          {
57              final Class secJavaType = javaType;
58  
59              // Need doPrivileged access to do introspection.
60              PropertyDescriptor[] rawPd = MetaBeanUtils.getPropertyDescriptors(secJavaType);
61              pd = MetaBeanUtils.processPropertyDescriptors(rawPd, javaType, typeDesc);
62          }
63          catch (Exception e)
64          {
65              // this should never happen
66              throw new InternalException(e);
67          }
68          return pd;
69      }
70  
71      private static PropertyDescriptor[] getPropertyDescriptors(final Class secJavaType)
72      {
73          return (
74              PropertyDescriptor[]) AccessController
75                  .doPrivileged(new PrivilegedAction()
76          {
77              public Object run()
78              {
79                  PropertyDescriptor[] result = null;
80                  // START FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937
81                  try
82                  {
83                      // privileged code goes here
84                      if (AxisFault.class.isAssignableFrom(secJavaType))
85                      {
86                          // Don't include AxisFault data
87                          result =
88                              Introspector
89                                  .getBeanInfo(secJavaType, AxisFault.class)
90                                  .getPropertyDescriptors();
91                      }
92                      else if (Throwable.class != secJavaType && Throwable.class.isAssignableFrom(secJavaType))
93                      {
94                          // Don't include Throwable data
95                          result =
96                              Introspector
97                                  .getBeanInfo(secJavaType, Throwable.class)
98                                  .getPropertyDescriptors();
99                      }
100                     else
101                     {
102                         // privileged code goes here
103                         result =
104                             Introspector
105                                 .getBeanInfo(secJavaType)
106                                 .getPropertyDescriptors();
107                     }
108                     // END FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937
109                 }
110                 catch (java.beans.IntrospectionException Iie)
111                 {
112                 }
113                 return result;
114             }
115         });
116     }
117 
118     /***
119      * Return a list of properties in the bean which should be attributes
120      */
121     public static Vector getBeanAttributes(Class javaType, TypeDesc typeDesc)
122     {
123         Vector ret = new Vector();
124 
125         if (typeDesc == null)
126         {
127             // !!! Support old-style beanAttributeNames for now
128 
129             // See if this object defined the 'getAttributeElements' function
130             // which returns a Vector of property names that are attributes
131             try
132             {
133                 Method getAttributeElements =
134                     javaType.getMethod("getAttributeElements", new Class[] {
135                 });
136                 // get string array
137                 String[] array =
138                     (String[]) getAttributeElements.invoke(null, noArgs);
139 
140                 // convert it to a Vector
141                 ret = new Vector(array.length);
142                 for (int i = 0; i < array.length; i++)
143                 {
144                     ret.add(array[i]);
145                 }
146             }
147             catch (Exception e)
148             {
149                 ret.clear();
150             }
151         }
152         else
153         {
154             FieldDesc[] fields = typeDesc.getFields();
155             if (fields != null)
156             {
157                 for (int i = 0; i < fields.length; i++)
158                 {
159                     FieldDesc field = fields[i];
160                     if (!field.isElement())
161                     {
162                         ret.add(field.getFieldName());
163                     }
164                 }
165             }
166         }
167 
168         return ret;
169     }
170     /***
171      * This method attempts to sort the property descriptors using
172      * the typeDesc and order defined in the class.
173      *
174      * This routine also looks for set(i, type) and get(i) methods and adjusts the
175      * property to use these methods instead.  These methods are generated by the
176      * emitter for "collection" of properties (i.e. maxOccurs="unbounded" on an element).
177      * JAX-RPC is silent on this issue, but web services depend on this kind of behaviour.
178      * The method signatures were chosen to match bean indexed properties.
179      */
180     public static BeanPropertyDescriptor[] processPropertyDescriptors(
181         PropertyDescriptor[] rawPd,
182         Class cls)
183     {
184         return MetaBeanUtils.processPropertyDescriptors(rawPd, cls, null);
185     }
186 
187     public static BeanPropertyDescriptor[] processPropertyDescriptors(
188         PropertyDescriptor[] rawPd,
189         Class cls,
190         TypeDesc typeDesc)
191     {
192         ArrayList filteredPds = new ArrayList();
193 
194         for (int i = 0; i < rawPd.length; i++)
195         {
196             Method m = rawPd[i].getReadMethod();
197 
198             if (!Attributes.hasAttributeType(m, NonWebMethod.class))
199             {
200                 filteredPds.add(rawPd[i]);
201             }
202             else
203             {
204                 // TODO: How should we log this?
205                 System.out.println("[ivory] skipped method " + m.getName());
206             }
207         }
208 
209         return BeanUtils.processPropertyDescriptors(
210             (PropertyDescriptor[]) filteredPds.toArray( new PropertyDescriptor[0] ),
211             cls,
212             typeDesc);
213     }
214 }