Java tutorial
/* * 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; } }