View Javadoc
1 /* 2 * Copyright (C) 2002 Carsten Krebs (Team-Konzept GmbH & Co.KG) 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 package com.teamkonzept.dom4jb.beans; 19 20 import java.beans.BeanInfo; 21 import java.beans.IntrospectionException; 22 import java.beans.PropertyDescriptor; 23 import java.lang.reflect.Method; 24 import java.util.ArrayList; 25 import java.util.HashMap; 26 import java.util.HashSet; 27 import java.util.Iterator; 28 import java.util.LinkedList; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 import java.util.WeakHashMap; 33 34 import com.teamkonzept.dom4jb.schema.DataDescriptor; 35 import com.teamkonzept.dom4jb.schema.ElementDescriptor; 36 import com.teamkonzept.dom4jb.schema.GroupDescriptor; 37 import com.teamkonzept.dom4jb.schema.Sequence; 38 39 public class Introspector { 40 41 private static final String XML_BEAN_INFO = "XMLBeanInfo"; 42 43 private static final Map infoCache = new WeakHashMap(); 44 private static final List searchPackages = new ArrayList(); 45 46 static { 47 searchPackages.add("com.teamkonzept.dom4jb.beans.infos"); 48 } 49 50 public static XMLBeanInfo getBeanInfo(final Class beanClass) 51 throws IntrospectionException { 52 53 XMLBeanInfo info = (XMLBeanInfo) infoCache.get(beanClass); 54 if (info != null) { 55 return info; 56 } 57 58 final String[] names = getBeanInfoNames(beanClass); 59 for (int i = 0; i < names.length; i++) { 60 try { 61 final Class beanInfoClass = Class.forName(names[i]); 62 info = (XMLBeanInfo) beanInfoClass.newInstance(); 63 put(beanClass, info); 64 return info; 65 } catch (ClassNotFoundException e) { 66 /* NOP */ 67 } catch (InstantiationException e) { 68 /* NOP */ 69 } catch (IllegalAccessException e) { 70 /* NOP */ 71 } catch (NoClassDefFoundError e) { 72 /* NOP */ 73 } 74 75 } 76 77 return buildBeanInfo(beanClass, new HashSet()); 78 } 79 80 public static XMLBeanInfo getBeanInfo(final Class beanClass, 81 final Set defined) 82 throws IntrospectionException { 83 84 XMLBeanInfo info = (XMLBeanInfo) infoCache.get(beanClass); 85 if (info != null) { 86 return info; 87 } 88 89 final String[] names = getBeanInfoNames(beanClass); 90 for (int i = 0; i < names.length; i++) { 91 try { 92 final Class beanInfoClass = Class.forName(names[i]); 93 info = (XMLBeanInfo) beanInfoClass.newInstance(); 94 put(beanClass, info); 95 extend(beanClass, defined); 96 return info; 97 } catch (ClassNotFoundException e) { 98 /* NOP */ 99 } catch (InstantiationException e) { 100 /* NOP */ 101 } catch (IllegalAccessException e) { 102 /* NOP */ 103 } 104 } 105 106 return buildBeanInfo(beanClass, defined); 107 } 108 109 public static XMLBeanInfo buildBeanInfo(final Class beanClass, 110 final Set defined) 111 throws IntrospectionException { 112 113 final LinkedList content = new LinkedList(); 114 final LinkedList attributes = new LinkedList(); 115 116 final BeanInfo beanInfo = 117 java.beans.Introspector.getBeanInfo( 118 beanClass, 119 java.beans.Introspector.IGNORE_ALL_BEANINFO); 120 121 final PropertyDescriptor[] properties = 122 beanInfo.getPropertyDescriptors(); 123 final HashMap propertySet = new HashMap(properties.length); 124 for (int i = 0; i < properties.length; i++) { 125 final Method readMethod = properties[i].getReadMethod(); 126 if (readMethod == null) { 127 continue; 128 } 129 if (readMethod.getDeclaringClass() != beanClass) { 130 continue; 131 } 132 133 // propertySet.put( readMethod, properties[i] ); 134 propertySet.put(properties[i].getName(), properties[i]); 135 } 136 137 // 138 // remove all superclass properties 139 // 140 final Class superclass = beanClass.getSuperclass(); 141 if (superclass != null && !defined.contains(superclass)) { 142 143 final BeanInfo superclassInfo = 144 java.beans.Introspector.getBeanInfo( 145 superclass, 146 java.beans.Introspector.IGNORE_ALL_BEANINFO); 147 final PropertyDescriptor[] superclassProperties = 148 superclassInfo.getPropertyDescriptors(); 149 150 for (int i = 0; i < superclassProperties.length; i++) { 151 propertySet.remove(superclassProperties[i].getName()); 152 } 153 154 // add xml-bean-info for superclass 155 final XMLBeanInfo superclassXMLInfo = 156 getBeanInfo(superclass, defined); 157 158 // add content descriptors 159 final GroupDescriptor contentGroup = 160 superclassXMLInfo.getContentDescriptors(); 161 if (contentGroup != null && !contentGroup.isEmpty()) { 162 content.add(contentGroup); 163 } 164 165 // add attribute descriptors 166 final GroupDescriptor attributeGroup = 167 superclassXMLInfo.getAttributeDescriptors(); 168 if (attributeGroup != null && !attributeGroup.isEmpty()) { 169 attributes.add(attributeGroup); 170 } 171 extend(superclass, defined); 172 } 173 174 // 175 // remove all interface properties 176 // 177 final Class[] interfaces = beanClass.getInterfaces(); 178 for (int i = 0; i < interfaces.length; i++) { 179 180 if (defined.contains(interfaces[i])) { 181 continue; 182 } 183 184 final BeanInfo interfaceInfo = 185 java.beans.Introspector.getBeanInfo( 186 interfaces[i], 187 java.beans.Introspector.IGNORE_ALL_BEANINFO); 188 final PropertyDescriptor[] interfaceProperties = 189 interfaceInfo.getPropertyDescriptors(); 190 191 if (interfaceProperties != null) { 192 for (int j = 0; j < interfaceProperties.length; j++) { 193 propertySet.remove(interfaceProperties[j].getName()); 194 } 195 196 // add xml-bean-info for interface[i] 197 final XMLBeanInfo interfaceXMLInfo = 198 getBeanInfo(interfaces[i], defined); 199 200 // add content descriptors 201 final GroupDescriptor contentGroup = 202 interfaceXMLInfo.getContentDescriptors(); 203 if (contentGroup != null && !contentGroup.isEmpty()) { 204 content.add(contentGroup); 205 } 206 207 // add attribute descriptors 208 final GroupDescriptor attributeGroup = 209 interfaceXMLInfo.getAttributeDescriptors(); 210 if (attributeGroup != null && !attributeGroup.isEmpty()) { 211 attributes.add(attributeGroup); 212 } 213 } 214 // extends the set of defined interfaces an superclasses 215 extend(interfaces[i], defined); 216 } 217 218 // add rest of properties as element-content 219 final Iterator ownProperties = propertySet.values().iterator(); 220 while (ownProperties.hasNext()) { 221 final PropertyDescriptor property = 222 (PropertyDescriptor) ownProperties.next(); 223 224 content.add(new ElementDescriptor(property)); 225 } 226 227 final XMLBeanInfo info = new ElementInfo(content, attributes); 228 put(beanClass, info); 229 230 return info; 231 } 232 233 public static void extend(final Class beanClass, final Set defined) { 234 defined.add(beanClass); 235 236 final Class[] interfaces = beanClass.getInterfaces(); 237 for (int i = 0; i < interfaces.length; i++) { 238 if (defined.contains(interfaces[i])) { 239 // extends the set of defined interfaces an superclasses 240 extend(interfaces[i], defined); 241 } else { 242 defined.add(interfaces[i]); 243 } 244 } 245 } 246 247 protected static String getBaseName(final Class beanClass) { 248 final String fullName = beanClass.getName(); 249 final int idx = fullName.lastIndexOf('.'); 250 return (idx < 0 ? fullName : fullName.substring(idx + 1)); 251 } 252 253 protected static String getBeanInfoName(final String packageName, 254 final String className) { 255 final StringBuffer name; 256 if (packageName == null || packageName.length() <= 0) { 257 name = new StringBuffer(className); 258 } else { 259 name = new StringBuffer(packageName); 260 name.append('.'); 261 name.append(className); 262 } 263 name.append(XML_BEAN_INFO); 264 return name.toString(); 265 } 266 267 protected static final String[] getBeanInfoNames(final Class beanClass) { 268 final String[] names = new String[searchPackages.size() + 1]; 269 270 final String className = getBaseName(beanClass); 271 final Iterator packages = searchPackages.iterator(); 272 final Package pack = beanClass.getPackage(); 273 String packageName = (pack != null ? pack.getName() : null); 274 int i = 0; 275 do { 276 names[i++] = getBeanInfoName(packageName, className); 277 278 if (packages.hasNext()) { 279 packageName = (String) packages.next(); 280 } 281 } while (i < names.length); 282 283 return names; 284 } 285 286 public static void put(final Class beanClass, final XMLBeanInfo info) { 287 synchronized (infoCache) { 288 infoCache.put(beanClass, info); 289 } 290 } 291 292 public static void addSearchPath(final String path) { 293 if (!searchPackages.contains(path)) { 294 searchPackages.add(path); 295 } 296 } 297 298 public static void clearCache() { 299 synchronized (infoCache) { 300 infoCache.clear(); 301 } 302 } 303 } 304 305 final class ElementInfo implements XMLBeanInfo { 306 307 private final GroupDescriptor content; 308 private final GroupDescriptor attributes; 309 310 public ElementInfo() { 311 this.content = GroupDescriptor.EMPTY_DESCRIPTOR; 312 this.attributes = GroupDescriptor.EMPTY_DESCRIPTOR; 313 } 314 315 public ElementInfo(final List content, final List attributes) { 316 this.content = new Sequence(content); 317 this.attributes = new Sequence(attributes); 318 } 319 320 /*** 321 * Liefert alle direketen Content-Deskriptoren der Klasse 322 */ 323 public GroupDescriptor getContentDescriptors() { 324 return this.content; 325 } 326 327 /*** 328 * Liefert alle Attribut-Deskriptoren der Klasse 329 */ 330 public GroupDescriptor getAttributeDescriptors() { 331 return this.attributes; 332 } 333 334 /*** 335 * Liefert den DataDescriptor, zur Konvertierung der Bean 336 * in ihre entsprechende String-Repräsentation 337 */ 338 public DataDescriptor getDataDescriptor() { 339 return DataDescriptor.STRING; 340 } 341 342 /*** 343 * Liefert den Namen des Elementes, falls dieser nicht explizit angegeben 344 * wurde 345 */ 346 public String getItemName() { 347 return "item"; 348 } 349 }

This page was automatically generated by Maven