1 22 package org.jboss.kernel.plugins.config.xml; 23 24 import java.security.AccessController ; 25 import java.security.PrivilegedExceptionAction ; 26 import java.util.Iterator ; 27 import java.util.Set ; 28 29 import javax.xml.namespace.NamespaceContext ; 30 import javax.xml.namespace.QName ; 31 32 import org.jboss.beans.info.spi.BeanInfo; 33 import org.jboss.beans.info.spi.PropertyInfo; 34 import org.jboss.kernel.plugins.config.Configurator; 35 import org.jboss.kernel.plugins.config.property.PropertyKernelConfig; 36 import org.jboss.kernel.spi.config.KernelConfig; 37 import org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory; 38 import org.jboss.reflect.spi.MethodInfo; 39 import org.jboss.reflect.spi.TypeInfo; 40 import org.jboss.reflect.spi.TypeInfoFactory; 41 import org.jboss.util.propertyeditor.PropertyEditors; 42 import org.jboss.xb.binding.sunday.unmarshalling.DefaultElementHandler; 43 import org.jboss.xb.binding.sunday.unmarshalling.DefaultElementInterceptor; 44 import org.jboss.xb.binding.sunday.unmarshalling.ElementBinding; 45 import org.jboss.xb.binding.sunday.unmarshalling.SchemaBinding; 46 import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingInitializer; 47 import org.jboss.xb.binding.sunday.unmarshalling.TypeBinding; 48 import org.xml.sax.Attributes ; 49 50 56 public class JavaBeanSchemaInitializer implements SchemaBindingInitializer 57 { 58 59 private static final KernelConfig config; 60 61 protected static final TypeInfoFactory typeInfoFactory = new IntrospectionTypeInfoFactory(); 62 63 64 private static final String JAVABEAN_NS = "urn:jboss:javabean:1.0"; 65 66 67 private static final QName javabeanTypeQName = new QName (JAVABEAN_NS, "javabeanType"); 68 69 70 private static final QName propertyTypeQName = new QName (JAVABEAN_NS, "propertyType"); 71 72 73 private static final QName propertyQName = new QName (JAVABEAN_NS, "property"); 74 75 static 76 { 77 try 78 { 79 config = AccessController.doPrivileged(new PrivilegedExceptionAction <KernelConfig>() 80 { 81 public KernelConfig run() throws Exception 82 { 83 return new PropertyKernelConfig(System.getProperties()); 84 } 85 }); 86 } 87 catch (RuntimeException e) 88 { 89 throw e; 90 } 91 catch (Exception e) 92 { 93 throw new RuntimeException ("Error getting configuration", e); 94 } 95 96 PropertyEditors.init(); 97 } 98 99 public SchemaBinding init(SchemaBinding schema) 100 { 101 TypeBinding beanType = schema.getType(javabeanTypeQName); 103 beanType.setHandler(new DefaultElementHandler() 104 { 105 106 public Object startElement(Object parent, QName name, ElementBinding element) 107 { 108 return new Holder(); 109 } 110 111 public void attributes(Object o, QName elementName, ElementBinding element, Attributes attrs, NamespaceContext nsCtx) 112 { 113 Holder holder = (Holder) o; 114 String className = null; 115 for (int i = 0; i < attrs.getLength(); ++i) 116 { 117 String localName = attrs.getLocalName(i); 118 if ("class".equals(localName)) 119 className = attrs.getValue(i); 120 } 121 122 if (className == null) 123 throw new IllegalArgumentException ("No class attribute for " + elementName); 124 125 try 126 { 127 BeanInfo beanInfo = config.getBeanInfo(className, Thread.currentThread().getContextClassLoader()); 128 Object object = Configurator.instantiate(config, beanInfo, null); 129 holder.setValue(object); 130 } 131 catch (RuntimeException e) 132 { 133 throw e; 134 } 135 catch (Error e) 136 { 137 throw e; 138 } 139 catch (Throwable t) 140 { 141 throw new RuntimeException ("Error instantiating class " + className, t); 142 } 143 } 144 145 public Object endElement(Object o, QName qName, ElementBinding element) 146 { 147 Holder holder = (Holder) o; 148 return holder.getValue(); 149 } 150 }); 151 152 beanType.pushInterceptor(propertyQName, new DefaultElementInterceptor() 154 { 155 public void add(Object parent, Object child, QName name) 156 { 157 Holder holder = (Holder) parent; 158 Object parentValue = holder.getValue(); 159 160 Property prop = (Property) child; 161 String property = prop.getProperty(); 162 163 MethodInfo method; 164 Object value = prop.getValue(); 165 try 166 { 167 PropertyInfo info = getProperty(parentValue, property); 168 value = convertValue(info, prop.getType(), value); 169 method = info.getSetter(); 170 method.invoke(parentValue, new Object [] { value }); 171 } 172 catch (RuntimeException e) 173 { 174 throw e; 175 } 176 catch (Error e) 177 { 178 throw e; 179 } 180 catch (Throwable t) 181 { 182 throw new RuntimeException ("Error setting property " + property + " on object" + parentValue + " with value " + value, t); 183 } 184 } 185 }); 186 187 TypeBinding propertyType = schema.getType(propertyTypeQName); 189 propertyType.setHandler(new DefaultElementHandler() 190 { 191 192 public Object startElement(Object parent, QName name, ElementBinding element) 193 { 194 return new Property(); 195 } 196 197 public void attributes(Object o, QName elementName, ElementBinding element, Attributes attrs, NamespaceContext nsCtx) 198 { 199 Property property = (Property) o; 200 for (int i = 0; i < attrs.getLength(); ++i) 201 { 202 String localName = attrs.getLocalName(i); 203 if ("name".equals(localName)) 204 property.setProperty(attrs.getValue(i)); 205 else if ("class".equals(localName)) 206 property.setType(attrs.getValue(i)); 207 } 208 } 209 }); 210 211 return schema; 212 } 213 214 private PropertyInfo getProperty(Object parent, String property) throws Throwable 215 { 216 BeanInfo beanInfo = config.getBeanInfo(parent.getClass()); 217 Set properties = beanInfo.getProperties(); 218 if (properties != null && properties.size() > 0) 219 { 220 for (Iterator i = properties.iterator(); i.hasNext();) 221 { 222 PropertyInfo prop = (PropertyInfo) i.next(); 223 if (prop.getName().equals(property)) 224 { 225 if (prop.getSetter() == null) 226 throw new IllegalArgumentException ("Property '" + property + "' is read only " + prop); 227 return prop; 228 } 229 } 230 } 231 throw new IllegalArgumentException ("No property '" + property + "' for " + beanInfo); 232 } 233 234 243 private Object convertValue(PropertyInfo info, String override, Object value) throws Throwable 244 { 245 TypeInfo type = info.getType(); 246 if (override != null) 247 type = typeInfoFactory.getTypeInfo(override, null); 248 return type.convertValue(value); 249 } 250 251 public static class Holder 252 { 253 private Object object; 254 255 public Holder() 256 { 257 } 258 259 public Object getValue() 260 { 261 return object; 262 } 263 264 public void setValue(Object object) 265 { 266 this.object = object; 267 } 268 } 269 270 public static class Property extends Holder 271 { 272 private String property; 273 274 private String type; 275 276 public Property() 277 { 278 } 279 280 public String getProperty() 281 { 282 return property; 283 } 284 285 public void setProperty(String property) 286 { 287 this.property = property; 288 } 289 290 public String getType() 291 { 292 return type; 293 } 294 295 public void setType(String type) 296 { 297 this.type = type; 298 } 299 } 300 } 301 | Popular Tags |