KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > utils > BeanUtils


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55 package org.jboss.axis.utils;
56
57 import org.jboss.axis.AxisFault;
58 import org.jboss.axis.Constants;
59 import org.jboss.axis.InternalException;
60 import org.jboss.axis.description.FieldDesc;
61 import org.jboss.axis.description.TypeDesc;
62 import org.jboss.logging.Logger;
63
64 import java.beans.Introspector JavaDoc;
65 import java.beans.PropertyDescriptor JavaDoc;
66 import java.lang.reflect.Field JavaDoc;
67 import java.lang.reflect.Method JavaDoc;
68 import java.lang.reflect.Modifier JavaDoc;
69 import java.security.AccessController JavaDoc;
70 import java.security.PrivilegedAction JavaDoc;
71 import java.util.ArrayList JavaDoc;
72 import java.util.Arrays JavaDoc;
73 import java.util.List JavaDoc;
74 import java.util.Vector JavaDoc;
75
76 public class BeanUtils
77 {
78
79    public static final Object JavaDoc[] noArgs = new Object JavaDoc[]{};
80    private static Logger log = Logger.getLogger(BeanUtils.class.getName());
81
82    /**
83     * Create a BeanPropertyDescriptor array for the indicated class.
84     *
85     * @param javaType
86     * @return an ordered array of properties
87     */

88    public static BeanPropertyDescriptor[] getPd(Class JavaDoc javaType)
89    {
90       return getPd(javaType, null);
91    }
92
93    /**
94     * Create a BeanPropertyDescriptor array for the indicated class.
95     *
96     * @param javaType
97     * @param typeDesc
98     * @return an ordered array of properties
99     */

100    public static BeanPropertyDescriptor[] getPd(Class JavaDoc javaType, TypeDesc typeDesc)
101    {
102       BeanPropertyDescriptor[] pd;
103       try
104       {
105          final Class JavaDoc secJavaType = javaType;
106
107          // Need doPrivileged access to do introspection.
108
PropertyDescriptor JavaDoc[] rawPd = getPropertyDescriptors(secJavaType);
109          pd = processPropertyDescriptors(rawPd, javaType, typeDesc);
110       }
111       catch (Exception JavaDoc e)
112       {
113          // this should never happen
114
throw new InternalException(e);
115       }
116       return pd;
117    }
118
119    private static PropertyDescriptor JavaDoc[] getPropertyDescriptors(final Class JavaDoc secJavaType)
120    {
121       return (PropertyDescriptor JavaDoc[])AccessController.doPrivileged(new PrivilegedAction JavaDoc()
122       {
123          public Object JavaDoc run()
124          {
125             PropertyDescriptor JavaDoc[] result = null;
126             // START FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937
127
try
128             {
129                // privileged code goes here
130
boolean isAxisFault = AxisFault.class.isAssignableFrom(secJavaType);
131                boolean isThrowable = Throwable JavaDoc.class.isAssignableFrom(secJavaType);
132
133                if (isAxisFault)
134                {
135                   // Don't include AxisFault data
136
result = Introspector.
137                           getBeanInfo(secJavaType, AxisFault.class).
138                           getPropertyDescriptors();
139                }
140                else if (isThrowable)
141                {
142                   // Don't include Throwable data
143
result = Introspector.
144                           getBeanInfo(secJavaType, Throwable JavaDoc.class).
145                           getPropertyDescriptors();
146                }
147                else
148                {
149                   // privileged code goes here
150
result = Introspector.
151                           getBeanInfo(secJavaType).
152                           getPropertyDescriptors();
153                }
154
155                // Include the message property
156
if (isThrowable)
157                {
158                   List JavaDoc bpList = new ArrayList JavaDoc();
159                   bpList.add(new PropertyDescriptor JavaDoc("message", Throwable JavaDoc.class, "getMessage", null));
160                   bpList.addAll(Arrays.asList(result));
161                   result = new PropertyDescriptor JavaDoc[bpList.size()];
162                   bpList.toArray(result);
163                }
164             }
165             catch (java.beans.IntrospectionException JavaDoc Iie)
166             {
167             }
168             // END FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937
169

170             return result;
171          }
172       });
173    }
174
175    /**
176     * Return a list of properties in the bean which should be attributes
177     */

178    public static Vector JavaDoc getBeanAttributes(Class JavaDoc javaType, TypeDesc typeDesc)
179    {
180       Vector JavaDoc ret = new Vector JavaDoc();
181
182       if (typeDesc == null)
183       {
184          // !!! Support old-style beanAttributeNames for now
185

186          // See if this object defined the 'getAttributeElements' function
187
// which returns a Vector of property names that are attributes
188
try
189          {
190             Method JavaDoc getAttributeElements =
191                     javaType.getMethod("getAttributeElements",
192                             new Class JavaDoc[]{});
193             // get string array
194
String JavaDoc[] array = (String JavaDoc[])getAttributeElements.invoke(null, noArgs);
195
196             // convert it to a Vector
197
ret = new Vector JavaDoc(array.length);
198             for (int i = 0; i < array.length; i++)
199             {
200                ret.add(array[i]);
201             }
202          }
203          catch (Exception JavaDoc e)
204          {
205             ret.clear();
206          }
207       }
208       else
209       {
210          FieldDesc[] fields = typeDesc.getFields();
211          if (fields != null)
212          {
213             for (int i = 0; i < fields.length; i++)
214             {
215                FieldDesc field = fields[i];
216                if (!field.isElement())
217                {
218                   ret.add(field.getFieldName());
219                }
220             }
221          }
222       }
223
224       return ret;
225    }
226
227    /**
228     * This method attempts to sort the property descriptors using
229     * the typeDesc and order defined in the class.
230     * <p/>
231     * This routine also looks for set(i, type) and get(i) methods and adjusts the
232     * property to use these methods instead. These methods are generated by the
233     * emitter for "collection" of properties (i.e. maxOccurs="unbounded" on an element).
234     * JAX-RPC is silent on this issue, but web services depend on this kind of behaviour.
235     * The method signatures were chosen to match bean indexed properties.
236     */

237    public static BeanPropertyDescriptor[] processPropertyDescriptors(PropertyDescriptor JavaDoc[] rawPd, Class JavaDoc cls)
238    {
239       return processPropertyDescriptors(rawPd, cls, null);
240    }
241
242    public static BeanPropertyDescriptor[] processPropertyDescriptors(PropertyDescriptor JavaDoc[] rawPd, Class JavaDoc cls, TypeDesc typeDesc)
243    {
244
245       // Create a copy of the rawPd called myPd
246
BeanPropertyDescriptor[] myPd = new BeanPropertyDescriptor[rawPd.length];
247
248       ArrayList JavaDoc pd = new ArrayList JavaDoc();
249
250       try
251       {
252          for (int i = 0; i < rawPd.length; i++)
253          {
254             // Skip the special "any" field
255
if (rawPd[i].getName().equals(Constants.ANYCONTENT))
256                continue;
257             pd.add(new BeanPropertyDescriptor(rawPd[i]));
258          }
259
260          // Now look for public fields
261
Field JavaDoc fields[] = cls.getFields();
262          if (fields != null && fields.length > 0)
263          {
264             // See if the field is in the list of properties
265
// add it if not.
266
for (int i = 0; i < fields.length; i++)
267             {
268                Field JavaDoc f = fields[i];
269                // skip if field come from a java.* or javax.* package
270
// WARNING: Is this going to make bad things happen for
271
// users JavaBeans? Do they WANT these fields serialzed?
272
String JavaDoc clsName = f.getDeclaringClass().getName();
273                if (clsName.startsWith("java.") ||
274                        clsName.startsWith("javax."))
275                {
276                   continue;
277                }
278                // skip field if it is final, transient, or static
279
if (!(Modifier.isStatic(f.getModifiers()) ||
280                        Modifier.isFinal(f.getModifiers()) ||
281                        Modifier.isTransient(f.getModifiers())))
282                {
283                   String JavaDoc fName = f.getName();
284                   boolean found = false;
285                   for (int j = 0; j < rawPd.length && !found; j++)
286                   {
287                      String JavaDoc pName =
288                              ((BeanPropertyDescriptor)pd.get(j)).getName();
289                      if (pName.length() == fName.length() &&
290                              pName.substring(0, 1).equalsIgnoreCase(fName.substring(0, 1)))
291                      {
292
293                         found = pName.length() == 1 ||
294                                 pName.substring(1).equals(fName.substring(1));
295                      }
296                   }
297
298                   if (!found)
299                   {
300                      pd.add(new FieldPropertyDescriptor(f.getName(), f));
301                   }
302                }
303             }
304          }
305
306          // If typeDesc meta data exists, re-order according to the fields
307
if (typeDesc != null &&
308                  typeDesc.getFields(true) != null)
309          {
310             ArrayList JavaDoc ordered = new ArrayList JavaDoc();
311             // Add the TypeDesc elements first
312
FieldDesc[] fds = typeDesc.getFields(true);
313             for (int i = 0; i < fds.length; i++)
314             {
315                FieldDesc field = fds[i];
316                if (field.isElement())
317                {
318                   boolean found = false;
319                   for (int j = 0;
320                        j < pd.size() && !found;
321                        j++)
322                   {
323                      if (field.getFieldName().equals(((BeanPropertyDescriptor)pd.get(j)).getName()))
324                      {
325                         ordered.add(pd.remove(j));
326                         found = true;
327                      }
328                   }
329                }
330             }
331             // Add the remaining elements
332
while (pd.size() > 0)
333             {
334                ordered.add(pd.remove(0));
335             }
336             // Use the ordered list
337
pd = ordered;
338          }
339
340          myPd = new BeanPropertyDescriptor[pd.size()];
341          for (int i = 0; i < pd.size(); i++)
342          {
343             myPd[i] = (BeanPropertyDescriptor)pd.get(i);
344          }
345       }
346       catch (Exception JavaDoc e)
347       {
348          log.error(Messages.getMessage("badPropertyDesc00",
349                  cls.getName()), e);
350          throw new InternalException(e);
351       }
352
353       return myPd;
354    }
355
356    public static BeanPropertyDescriptor getAnyContentPD(Class JavaDoc javaType)
357    {
358       PropertyDescriptor JavaDoc[] pds = getPropertyDescriptors(javaType);
359       for (int i = 0; i < pds.length; i++)
360       {
361          PropertyDescriptor JavaDoc pd = pds[i];
362          if (pd.getName().equals(Constants.ANYCONTENT))
363             return new BeanPropertyDescriptor(pd);
364       }
365       return null;
366    }
367 }
368
Popular Tags