| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.axis.utils; |
| |
| import org.apache.axis.AxisFault; |
| import org.apache.axis.Constants; |
| import org.apache.axis.InternalException; |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.description.FieldDesc; |
| import org.apache.axis.description.TypeDesc; |
| import org.apache.commons.logging.Log; |
| |
| import java.beans.Introspector; |
| import java.beans.PropertyDescriptor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.ArrayList; |
| import java.util.Vector; |
| |
| public class BeanUtils { |
| |
| public static final Object[] noArgs = new Object[] {}; |
| protected static Log log = |
| LogFactory.getLog(BeanUtils.class.getName()); |
| |
| /** |
| * Create a BeanPropertyDescriptor array for the indicated class. |
| * @param javaType |
| * @return an ordered array of properties |
| */ |
| public static BeanPropertyDescriptor[] getPd(Class javaType) { |
| return getPd(javaType, null); |
| } |
| |
| /** |
| * Create a BeanPropertyDescriptor array for the indicated class. |
| * @param javaType |
| * @param typeDesc |
| * @return an ordered array of properties |
| */ |
| public static BeanPropertyDescriptor[] getPd(Class javaType, TypeDesc typeDesc) { |
| BeanPropertyDescriptor[] pd; |
| try { |
| final Class secJavaType = javaType; |
| |
| // Need doPrivileged access to do introspection. |
| PropertyDescriptor[] rawPd = getPropertyDescriptors(secJavaType); |
| pd = processPropertyDescriptors(rawPd,javaType,typeDesc); |
| } catch (Exception e) { |
| // this should never happen |
| throw new InternalException(e); |
| } |
| return pd; |
| } |
| |
| private static PropertyDescriptor[] getPropertyDescriptors(final Class secJavaType) { |
| return (PropertyDescriptor[])AccessController.doPrivileged( |
| new PrivilegedAction() { |
| public Object run() { |
| PropertyDescriptor[] result = null; |
| // START FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937 |
| try { |
| // privileged code goes here |
| if (AxisFault.class.isAssignableFrom(secJavaType)) { |
| // Don't include AxisFault data |
| result = Introspector. |
| getBeanInfo(secJavaType,AxisFault.class). |
| getPropertyDescriptors(); |
| } else if (Throwable.class != secJavaType && Throwable.class.isAssignableFrom(secJavaType)) { |
| // Don't include Throwable data |
| result = Introspector. |
| getBeanInfo(secJavaType,Throwable.class). |
| getPropertyDescriptors(); |
| } else { |
| // privileged code goes here |
| result = Introspector. |
| getBeanInfo(secJavaType). |
| getPropertyDescriptors(); |
| } |
| // END FIX http://nagoya.apache.org/bugzilla/showattachment.cgi?attach_id=4937 |
| } catch (java.beans.IntrospectionException Iie) { |
| } |
| return result; |
| } |
| }); |
| } |
| |
| /** |
| * Return a list of properties in the bean which should be attributes |
| */ |
| public static Vector getBeanAttributes(Class javaType, TypeDesc typeDesc) { |
| Vector ret = new Vector(); |
| |
| if (typeDesc == null) { |
| // !!! Support old-style beanAttributeNames for now |
| |
| // See if this object defined the 'getAttributeElements' function |
| // which returns a Vector of property names that are attributes |
| try { |
| Method getAttributeElements = |
| javaType.getMethod("getAttributeElements", |
| new Class [] {}); |
| // get string array |
| String[] array = (String[])getAttributeElements.invoke(null, noArgs); |
| |
| // convert it to a Vector |
| ret = new Vector(array.length); |
| for (int i = 0; i < array.length; i++) { |
| ret.add(array[i]); |
| } |
| } catch (Exception e) { |
| ret.clear(); |
| } |
| } else { |
| FieldDesc [] fields = typeDesc.getFields(); |
| if (fields != null) { |
| for (int i = 0; i < fields.length; i++) { |
| FieldDesc field = fields[i]; |
| if (!field.isElement()) { |
| ret.add(field.getFieldName()); |
| } |
| } |
| } |
| } |
| |
| return ret; |
| } |
| /** |
| * This method attempts to sort the property descriptors using |
| * the typeDesc and order defined in the class. |
| * |
| * This routine also looks for set(i, type) and get(i) methods and adjusts the |
| * property to use these methods instead. These methods are generated by the |
| * emitter for "collection" of properties (i.e. maxOccurs="unbounded" on an element). |
| * JAX-RPC is silent on this issue, but web services depend on this kind of behaviour. |
| * The method signatures were chosen to match bean indexed properties. |
| */ |
| public static BeanPropertyDescriptor[] processPropertyDescriptors( |
| PropertyDescriptor[] rawPd, Class cls) { |
| return processPropertyDescriptors(rawPd, cls, null); |
| } |
| |
| public static BeanPropertyDescriptor[] processPropertyDescriptors( |
| PropertyDescriptor[] rawPd, Class cls, TypeDesc typeDesc) { |
| |
| // Create a copy of the rawPd called myPd |
| BeanPropertyDescriptor[] myPd = new BeanPropertyDescriptor[rawPd.length]; |
| |
| ArrayList pd = new ArrayList(); |
| |
| try { |
| for (int i=0; i < rawPd.length; i++) { |
| // Skip the special "any" field |
| if (rawPd[i].getName().equals(Constants.ANYCONTENT)) |
| continue; |
| pd.add(new BeanPropertyDescriptor(rawPd[i])); |
| } |
| |
| // Now look for public fields |
| Field fields[] = cls.getFields(); |
| if (fields != null && fields.length > 0) { |
| // See if the field is in the list of properties |
| // add it if not. |
| for (int i=0; i < fields.length; i++) { |
| Field f = fields[i]; |
| // skip if field come from a java.* or javax.* package |
| // WARNING: Is this going to make bad things happen for |
| // users JavaBeans? Do they WANT these fields serialzed? |
| String clsName = f.getDeclaringClass().getName(); |
| if (clsName.startsWith("java.") || |
| clsName.startsWith("javax.")) { |
| continue; |
| } |
| // skip field if it is final, transient, or static |
| if (!(Modifier.isStatic(f.getModifiers()) || |
| Modifier.isFinal(f.getModifiers()) || |
| Modifier.isTransient(f.getModifiers()))) { |
| String fName = f.getName(); |
| boolean found = false; |
| for (int j=0; j< rawPd.length && !found; j++) { |
| String pName = |
| ((BeanPropertyDescriptor)pd.get(j)).getName(); |
| if (pName.length() == fName.length() && |
| pName.substring(0,1).equalsIgnoreCase( |
| fName.substring(0,1))) { |
| |
| found = pName.length() == 1 || |
| pName.substring(1).equals(fName.substring(1)); |
| } |
| } |
| |
| if (!found) { |
| pd.add(new FieldPropertyDescriptor(f.getName(), f)); |
| } |
| } |
| } |
| } |
| |
| // If typeDesc meta data exists, re-order according to the fields |
| if (typeDesc != null && |
| typeDesc.getFields(true) != null) { |
| ArrayList ordered = new ArrayList(); |
| // Add the TypeDesc elements first |
| FieldDesc[] fds = typeDesc.getFields(true); |
| for (int i=0; i<fds.length; i++) { |
| FieldDesc field = fds[i]; |
| if (field.isElement()) { |
| boolean found = false; |
| for (int j=0; |
| j<pd.size() && !found; |
| j++) { |
| if (field.getFieldName().equals( |
| ((BeanPropertyDescriptor)pd.get(j)).getName())) { |
| ordered.add(pd.remove(j)); |
| found = true; |
| } |
| } |
| } |
| } |
| // Add the remaining elements |
| while (pd.size() > 0) { |
| ordered.add(pd.remove(0)); |
| } |
| // Use the ordered list |
| pd = ordered; |
| } |
| |
| myPd = new BeanPropertyDescriptor[pd.size()]; |
| for (int i=0; i <pd.size(); i++) { |
| myPd[i] = (BeanPropertyDescriptor) pd.get(i); |
| } |
| } catch (Exception e) { |
| log.error(Messages.getMessage("badPropertyDesc00", |
| cls.getName()), e); |
| throw new InternalException(e); |
| } |
| |
| return myPd; |
| } |
| |
| public static BeanPropertyDescriptor getAnyContentPD(Class javaType) { |
| PropertyDescriptor [] pds = getPropertyDescriptors(javaType); |
| return getSpecificPD(pds, Constants.ANYCONTENT); |
| } |
| |
| public static BeanPropertyDescriptor getSpecificPD(PropertyDescriptor[] pds, |
| String name) { |
| for (int i = 0; i < pds.length; i++) { |
| PropertyDescriptor pd = pds[i]; |
| if (pd.getName().equals(name)) |
| return new BeanPropertyDescriptor(pd); |
| } |
| return null; |
| } |
| |
| public static BeanPropertyDescriptor getSpecificPD(BeanPropertyDescriptor[] pds, |
| String name) { |
| for (int i = 0; i < pds.length; i++) { |
| BeanPropertyDescriptor pd = pds[i]; |
| if (pd.getName().equals(name)) |
| return pd; |
| } |
| return null; |
| } |
| } |