1 17 package org.apache.ws.jaxme.xs.parser.impl; 18 19 import java.lang.reflect.Constructor ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Modifier ; 23 import java.lang.reflect.UndeclaredThrowableException ; 24 25 import org.apache.ws.jaxme.xs.XSParser; 26 import org.apache.ws.jaxme.xs.parser.*; 27 import org.xml.sax.SAXException ; 28 29 30 35 public class AttributeSetterImpl implements AttributeSetter { 36 static final Class [] ONE_STRING_CLASS = new Class []{String .class}; 37 private static final Class [] FOUR_STRING_CLASSES = 38 new Class []{String .class, String .class, String .class, String .class}; 39 40 protected XSContext getData() { 41 XSContext result = XSParser.getRunningInstance().getContext(); 42 if (result == null) { 43 throw new IllegalStateException ("Parser data is not set."); 44 } 45 return result; 46 } 47 48 63 public void setAttribute(String pQName, String pNamespaceURI, String pLocalName, String pValue) 64 throws SAXException { 65 XsSAXParser handler = ((XsSAXParser) getData().getCurrentContentHandler()); 66 if (handler == null) { 67 throw new IllegalStateException ("Current XsSAXParser is null."); 68 } 69 Object bean = ((XsSAXParser) getData().getCurrentContentHandler()).getBean(); 70 try { 71 Method m = bean.getClass().getMethod("setAttribute", FOUR_STRING_CLASSES); 72 if (Modifier.isPublic(m.getModifiers())) { 73 Object [] o = new Object []{pQName, pNamespaceURI, pLocalName, pValue}; 74 Object result = invokeMethod(bean, m, pQName, o); 75 if (!boolean.class.equals(m.getReturnType()) || ((Boolean ) result).booleanValue()) { 76 return; 77 } 78 } 79 } catch (NoSuchMethodException e) { 80 } 81 82 if (!setProperty(bean, pQName, pLocalName, pValue)) { 83 throw new IllegalStateException ("Unknown attribute of " + bean.getClass().getName() + ": " + pQName); 84 } 85 } 86 87 88 91 protected Object invokeMethod(Object pBean, Method pMethod, String pName, Object [] pArgs) throws SAXException { 92 try { 93 return pMethod.invoke(pBean, pArgs); 94 } catch (InvocationTargetException e) { 95 Throwable t = e.getTargetException(); 96 if (t instanceof SAXException ) { 97 throw (SAXException ) t; 98 } else if (t instanceof RuntimeException ) { 99 throw (RuntimeException ) t; 100 } else { 101 throw new UndeclaredThrowableException (t); 102 } 103 } catch (IllegalAccessException e) { 104 StringBuffer sb = new StringBuffer ("Failed to invoke method "); 105 sb.append(pMethod.getName()).append(" of class ").append(pBean.getClass().getName()); 106 sb.append(" with argument "); 107 for (int i = 0; i < pArgs.length; i++) { 108 if (i > 0) { 109 sb.append(", "); 110 } 111 sb.append(pArgs[i]); 112 } 113 sb.append(": ").append(e.getClass().getName()).append(", ").append(e.getMessage()); 114 throw new IllegalStateException (sb.toString()); 115 } 116 } 117 118 private interface ParameterClass { 119 public Object matches(Class pClass); 120 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, 121 Method pMethod, Object pMethodObject, String pQName) 122 throws SAXException ; 123 } 124 125 private static class StringClass implements ParameterClass { 126 public Object matches(Class pClass) { 127 return String .class.equals(pClass) ? Boolean.TRUE : null; 128 } 129 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, 130 Method pMethod, Object pMethodObject, String pQName) throws SAXException { 131 pAttributeSetter.invokeMethod(pBean, pMethod, pQName, new Object []{pValue}); 132 } 133 } 134 135 private static class ValueOfParameterClass implements ParameterClass { 136 public Object matches(Class pClass) { 137 try { 138 Method valueOfMethod = pClass.getMethod("valueOf", ONE_STRING_CLASS); 139 if (Modifier.isPublic(valueOfMethod.getModifiers()) && !void.class.equals(valueOfMethod.getReturnType())) { 140 return valueOfMethod; 141 } 142 } catch (NoSuchMethodException e) { 143 } 144 return null; 145 } 146 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, 147 Method pMethod, Object pMethodObject, String pQName) throws SAXException { 148 Method m = (Method ) pMethodObject; 149 Object o; 150 try { 151 o = m.invoke(null, new Object []{pValue}); 152 } catch (InvocationTargetException e) { 153 throw new IllegalArgumentException ("Illegal argument for attribute '" + pQName + "': " + pValue + 154 "; " + e.getTargetException().getClass().getName() + 155 ", " + e.getTargetException().getMessage()); 156 } catch (IllegalAccessException e) { 157 throw new IllegalStateException ("Invalid access to method " + m.getName() + " of class " + 158 pBean.getClass() + ": IllegalAccessException, " + e.getMessage()); 159 } 160 pAttributeSetter.invokeMethod(pBean, pMethod, pQName, new Object []{o}); 161 } 162 } 163 164 private static class StringConstructorClass implements ParameterClass { 165 public Object matches(Class pClass) { 166 try { 167 Constructor con = pClass.getConstructor(ONE_STRING_CLASS); 168 if (Modifier.isPublic(con.getModifiers())) { 169 return con; 170 } 171 } catch (NoSuchMethodException e) { 172 } 173 return null; 174 } 175 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, 176 Method pMethod, Object pMethodObject, String pQName) throws SAXException { 177 Constructor con = (Constructor ) pMethodObject; 178 Object o; 179 try { 180 o = con.newInstance(new Object []{pValue}); 181 } catch (InvocationTargetException e) { 182 throw new IllegalArgumentException ("Illegal argument for attribute '" + pQName + "': " + pValue + 183 "; " + e.getTargetException().getClass().getName() + 184 ", " + e.getTargetException().getMessage()); 185 } catch (InstantiationException e) { 186 throw new IllegalStateException ("Invalid access to constructor " + pBean.getClass().getName() + 187 "(): " + e.getClass().getName() + ", " + e.getMessage()); 188 } catch (IllegalAccessException e) { 189 throw new IllegalStateException ("Invalid access to constructor " + pBean.getClass().getName() + 190 "(): " + e.getClass().getName() + ", " + e.getMessage()); 191 } 192 pAttributeSetter.invokeMethod(pBean, pMethod, pQName, new Object []{o}); 193 } 194 } 195 196 private static class PrimitiveParameterClass extends StringConstructorClass { 197 private final Class primitiveClass; 198 private final Class nonPrimitiveClass; 199 private final Constructor stringConstructor; 200 private PrimitiveParameterClass(Class pPrimitiveClass, Class pNonPrimitiveClass) { 201 primitiveClass = pPrimitiveClass; 202 nonPrimitiveClass = pNonPrimitiveClass; 203 try { 204 stringConstructor = pNonPrimitiveClass.getConstructor(ONE_STRING_CLASS); 205 } catch (NoSuchMethodException e) { 206 throw new IllegalStateException ("The primitive class " + pNonPrimitiveClass.getName() + 207 " doesn't have a string valued constructor!"); 208 } 209 } 210 public Object matches(Class pClass) { 211 return (primitiveClass.equals(pClass) || nonPrimitiveClass.equals(pClass)) ? stringConstructor : null; 212 } 213 } 214 215 private static class CharacterClass implements ParameterClass { 216 public Object matches(Class pClass) { 217 return (Character.TYPE.equals(pClass) || Character .class.equals(pClass)) ? Boolean.TRUE : null; 218 } 219 220 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, Method pMethod, Object pMethodObject, String pQName) throws SAXException { 221 if (pValue.length() != 1) { 222 throw new IllegalArgumentException ("Invalid value for '" + pQName +"': " + pValue + 223 "; must have exactly one character."); 224 } 225 pAttributeSetter.invokeMethod(pBean, pMethod, pQName, new Object []{new Character (pValue.charAt(0))}); 226 } 227 } 228 229 private static class BooleanClass implements ParameterClass { 230 public Object matches(Class pClass) { 231 return (Boolean.TYPE.equals(pClass) || Boolean .class.equals(pClass)) ? Boolean.TRUE : null; 232 } 233 234 public void invoke(AttributeSetterImpl pAttributeSetter, Object pBean, String pValue, Method pMethod, Object pMethodObject, String pQName) throws SAXException { 235 Boolean b = ("true".equals(pValue) || "1".equals(pValue)) ? Boolean.TRUE : Boolean.FALSE; 236 pAttributeSetter.invokeMethod(pBean, pMethod, pQName, new Object []{b}); 237 } 238 } 239 240 private static final ParameterClass[] knownClasses = new ParameterClass[]{ 241 new BooleanClass(), 242 new StringClass(), 243 new ValueOfParameterClass(), 244 new StringConstructorClass(), 245 new CharacterClass(), 246 new PrimitiveParameterClass(long.class, Long .class), 247 new PrimitiveParameterClass(int.class, Integer .class), 248 new PrimitiveParameterClass(short.class, Short .class), 249 new PrimitiveParameterClass(byte.class, Byte .class), 250 new PrimitiveParameterClass(double.class, Double .class), 251 new PrimitiveParameterClass(float.class, Float .class), 252 new CharacterClass(), 253 }; 254 255 306 protected boolean setProperty(Object pBean, String pQName, String pName, String pValue) 307 throws SAXException { 308 Class c = pBean.getClass(); 309 String s = "set" + Character.toUpperCase(pName.charAt(0)) + pName.substring(1); 310 int parameterClassNum = knownClasses.length; 311 Method [] methods = c.getMethods(); 312 Method method = null; 313 Object methodObject = null; 314 for (int i = 0; i < methods.length; i++) { 315 Method m = methods[i]; 316 if (!s.equals(m.getName()) || !Modifier.isPublic(m.getModifiers())) { 317 continue; 318 } 319 320 Class [] params = m.getParameterTypes(); 321 if (params.length != 1) { 322 continue; 323 } 324 325 Class paramsClass = params[0]; 326 for (int j = 0; j < parameterClassNum; j++) { 327 ParameterClass parameterClass = knownClasses[j]; 328 Object o = parameterClass.matches(paramsClass); 329 if (o != null) { 330 parameterClassNum = j; 331 method = m; 332 methodObject = o; 333 break; 334 } 335 } 336 } 337 338 if (method == null) { 339 return false; 340 } else { 341 knownClasses[parameterClassNum].invoke(this, pBean, pValue, method, methodObject, pQName); 342 return true; 343 } 344 } 345 } 346 | Popular Tags |