1 17 package org.apache.ws.jaxme.util; 18 19 import java.lang.reflect.Constructor ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.util.ArrayList ; 23 import java.util.List ; 24 25 import javax.xml.namespace.QName ; 26 27 import org.xml.sax.Attributes ; 28 import org.xml.sax.ContentHandler ; 29 import org.xml.sax.Locator ; 30 import org.xml.sax.SAXException ; 31 import org.xml.sax.SAXParseException ; 32 33 34 54 public class Configurator implements ContentHandler , NamespaceResolver { 55 private static final Class [] zeroClasses = new Class [0]; 56 private static final Object [] zeroObjects = new Object [0]; 57 private static final Class [] oneClassString = new Class []{String .class}; 58 private static final Class [] oneClassAttributes = new Class []{Attributes .class}; 59 60 private String [] namespaces; 61 private List beans = new ArrayList (); 62 private List names = new ArrayList (); 63 private Object currentBean; 64 private String currentName; 65 private Locator locator; 66 private Object beanFactory; 67 private Object rootObject; 68 private Object resultBean; 69 private int ignoreLevel = 0; 70 private NamespaceSupport nss = new NamespaceSupport(); 71 boolean nssNeedsContext; 72 73 79 public void setNamespace(String pNamespace) { 80 setNamespaces(new String []{pNamespace}); 81 } 82 83 88 public void setNamespaces(String [] pNamespaces) { 89 namespaces = pNamespaces; 90 } 91 92 95 public String [] getNamespaces() { 96 return namespaces; 97 } 98 99 101 public void setDocumentLocator(Locator pLocator) { 102 locator = pLocator; 103 } 104 105 107 public Locator getDocumentLocator() { 108 return locator; 109 } 110 111 116 public void setBeanFactory(Object pFactory) { 117 beanFactory = pFactory; 118 } 119 120 125 public Object getBeanFactory() { 126 return beanFactory == null ? this : beanFactory; 127 } 128 129 132 public void setRootObject(Object pRootObject) { 133 rootObject = pRootObject; 134 } 135 136 139 public Object getRootObject() { 140 return rootObject; 141 } 142 143 public void startDocument() throws SAXException { 144 currentBean = null; 145 currentName = null; 146 beans.clear(); 147 names.clear(); 148 ignoreLevel = 0; 149 nss.reset(); 150 nssNeedsContext = true; 151 } 152 public void endDocument() throws SAXException {} 153 154 public void startPrefixMapping(String pPrefix, String pURI) 155 throws SAXException { 156 nss.declarePrefix(pPrefix, pURI); 157 } 158 159 public void endPrefixMapping(String pPrefix) 160 throws SAXException { 161 nss.undeclarePrefix(pPrefix); 162 } 163 164 167 protected boolean isNamespaceMatching(String pNamespace) { 168 if (pNamespace == null) { 169 pNamespace = ""; 170 } 171 String [] myNamespaces = getNamespaces(); 172 if (myNamespaces == null || myNamespaces.length == 0) { 173 return pNamespace.length() == 0; 174 } else { 175 for (int i = 0; i < myNamespaces.length; i++) { 176 String s = myNamespaces[i]; 177 if (s == null) { 178 s = ""; 179 } 180 if (s.equals(pNamespace)) { 181 return true; 182 } 183 } 184 return false; 185 } 186 } 187 188 191 protected String getMethodNameFor(String pPrefix, String pName) { 192 StringBuffer result = new StringBuffer (pPrefix); 193 for (int i = 0; i < pName.length(); i++) { 194 char c = pName.charAt(i); 195 if (i == 0) { 196 if (Character.isJavaIdentifierStart(c)) { 197 result.append(Character.toUpperCase(c)); 198 } else { 199 result.append('_'); 200 } 201 } else { 202 if (Character.isJavaIdentifierPart(c)) { 203 result.append(c); 204 } else { 205 result.append('_'); 206 } 207 } 208 } 209 return result.toString(); 210 } 211 212 218 public void startElement(String pNamespaceURI, String pQName, 219 String pLocalName, Attributes pAttr) throws SAXException { 220 if (ignoreLevel > 0) { 221 ++ignoreLevel; 222 return; 223 } 224 225 if (!isNamespaceMatching(pNamespaceURI)) { 226 if (currentBean == null) { 227 String [] myNamespaces = getNamespaces(); 228 if (myNamespaces == null || myNamespaces.length == 0) { 229 throw new SAXParseException ("The document element must have the default namespace.", 230 getDocumentLocator()); 231 } else { 232 StringBuffer sb = new StringBuffer ("The document element must have either of the namespaces: "); 233 for (int i = 0; i < myNamespaces.length; i++) { 234 if (i > 0) sb.append(","); 235 String s = myNamespaces[i]; 236 if (s == null) { 237 s = ""; 238 } 239 sb.append('"').append(s).append('"'); 240 } 241 throw new SAXParseException (sb.toString(), getDocumentLocator()); 242 } 243 } 244 245 ++ignoreLevel; 246 return; } 248 249 Object o; 250 if (currentBean == null && rootObject != null) { 251 o = rootObject; 252 } else { 253 o = null; 254 Object factory = (currentBean == null) ? beanFactory : currentBean; 255 String methodName = getMethodNameFor("create", pLocalName); 256 try { 257 o = invokeMethod(methodName, factory, oneClassAttributes, 258 new Object []{pAttr}); 259 } catch (SAXParseException e) { 260 if (e.getException() != null && 261 e.getException() instanceof NoSuchMethodException ) { 262 try { 263 o = invokeMethod(methodName, factory, zeroClasses, zeroObjects); 264 e = null; 265 } catch (SAXParseException f) { 266 if (f.getException() != null && 267 f.getException() instanceof NoSuchMethodException ) { 268 if (currentBean == null) { 269 throw new SAXParseException ("Invalid document element: " + pQName, 270 getDocumentLocator()); 271 } else { 272 throw new SAXParseException ("Invalid child element name: " + pQName, 273 getDocumentLocator()); 274 } 275 } 276 throw f; 277 } 278 } 279 if (e != null) { 280 throw e; 281 } 282 } 283 if (o == null) { 284 throw new SAXParseException ("Method " + methodName + " of class " + 285 factory.getClass().getName() + 286 " did not return an object.", 287 getDocumentLocator()); 288 } 289 } 290 291 if (currentBean == null) { 292 resultBean = o; 293 } else { 294 beans.add(currentBean); 295 names.add(currentName); 296 } 297 currentBean = o; 298 currentName = pQName; 299 300 if (pAttr != null) { 301 for (int i = 0; i < pAttr.getLength(); i++) { 302 String uri = pAttr.getURI(i); 303 if (uri == null || uri.length() == 0 || isNamespaceMatching(uri)) { 304 String value = pAttr.getValue(i); 305 String qName = pAttr.getQName(i); 306 String setMethodName = getMethodNameFor("set", pAttr.getLocalName(i)); 307 Method [] methods = currentBean.getClass().getMethods(); 308 for (int j = 0; j < methods.length; j++) { 309 Method method = methods[j]; 310 if (!setMethodName.equals(method.getName())) { 311 continue; 312 } 313 Class [] argClasses = method.getParameterTypes(); 314 if (argClasses.length != 1) { 315 continue; 316 } 317 Object [] args = null; 318 if (argClasses[0] == String .class) { 319 args = new Object []{value}; 320 } else if (argClasses[0] == Integer .class || 321 argClasses[0] == Integer.TYPE) { 322 try { 323 args = new Object []{new Integer (value)}; 324 } catch (Exception e) { 325 throw new SAXParseException ("Attribute " + qName + 326 " contains an invalid Integer value: " + 327 value, getDocumentLocator()); 328 } 329 } else if (argClasses[0] == Long .class || 330 argClasses[0] == Long.TYPE) { 331 try { 332 args = new Object []{new Long (value)}; 333 } catch (Exception e) { 334 throw new SAXParseException ("Attribute " + qName + 335 " contains an invalid Long value: " + 336 value, getDocumentLocator()); 337 } 338 } else if (argClasses[0] == Short .class || 339 argClasses[0] == Short.TYPE) { 340 try { 341 args = new Object []{new Short (value)}; 342 } catch (Exception e) { 343 throw new SAXParseException ("Attribute " + qName + 344 " contains an invalid Short value: " + 345 value, getDocumentLocator()); 346 } 347 } else if (argClasses[0] == Byte .class || 348 argClasses[0] == Byte.TYPE) { 349 try { 350 args = new Object []{new Byte (value)}; 351 } catch (Exception e) { 352 throw new SAXParseException ("Attribute " + qName + 353 " contains an invalid Byte value: " + 354 value, getDocumentLocator()); 355 } 356 } else if (argClasses[0] == Boolean .class || 357 argClasses[0] == Boolean.TYPE) { 358 try { 359 args = new Object []{Boolean.valueOf(value)}; 360 } catch (Exception e) { 361 throw new SAXParseException ("Attribute " + qName + 362 " contains an invalid Boolean value: " + 363 value, getDocumentLocator()); 364 } 365 } else if (argClasses[0] == Character .class || 366 argClasses[0] == Character.TYPE) { 367 if (value.length() != 1) { 368 throw new SAXParseException ("Attribute " + qName + 369 " contains an invalid Character value: " + 370 value, getDocumentLocator()); 371 } 372 args = new Object []{new Character (value.charAt(0))}; 373 } else if (argClasses[0] == Class .class) { 374 Class c; 375 try { 376 c = ClassLoader.getClass(value); 377 } catch (Exception e) { 378 throw new SAXParseException ("Failed to load class " + value, 379 getDocumentLocator(), e); 380 } 381 args = new Object []{c}; 382 } else if (argClasses[0] == QName .class) { 383 try { 384 QName name = QName.valueOf(value); 385 args = new Object []{name}; 386 } catch (Exception e) { 387 throw new SAXParseException ("Failed to parse QName " + value, 388 getDocumentLocator()); 389 } 390 } else { 391 try { 393 Constructor con = argClasses[0].getConstructor(oneClassString); 394 args = new Object []{con.newInstance(new Object []{value})}; 395 } catch (InvocationTargetException e) { 396 Throwable t = e.getTargetException(); 397 throw new SAXParseException ("Failed to invoke constructor of class " + 398 argClasses[0].getClass().getName(), 399 getDocumentLocator(), 400 (t instanceof Exception ) ? ((Exception ) t) : e); 401 } catch (NoSuchMethodException e) { 402 throw new SAXParseException ("Attribute " + qName + 403 " has an invalid type: " + 404 argClasses[0].getClass().getName(), 405 getDocumentLocator()); 406 } catch (IllegalAccessException e) { 407 throw new SAXParseException ("Illegal access to constructor of class " + 408 argClasses[0].getClass().getName(), 409 getDocumentLocator(), e); 410 } catch (InstantiationException e) { 411 throw new SAXParseException ("Failed to instantiate class " + 412 argClasses[0].getClass().getName(), 413 getDocumentLocator(), e); 414 } 415 } 416 417 try { 418 method.invoke(currentBean, args); 419 } catch (IllegalAccessException e) { 420 throw new SAXParseException ("Illegal access to method " + setMethodName + 421 " of class " + currentBean.getClass().getName(), 422 getDocumentLocator(), e); 423 } catch (InvocationTargetException e) { 424 Throwable t = e.getTargetException(); 425 throw new SAXParseException ("Failed to invoke method " + setMethodName + 426 " of class " + currentBean.getClass().getName(), 427 getDocumentLocator(), 428 (t instanceof Exception ) ? ((Exception ) t) : e); 429 } 430 } 431 } 432 } 433 } 434 } 435 436 protected Object invokeMethod(String pMethodName, Object pBean, 437 Class [] pSignature, Object [] pArgs) 438 throws SAXException { 439 try { 440 Method m = pBean.getClass().getMethod(pMethodName, pSignature); 441 return m.invoke(pBean, pArgs); 442 } catch (IllegalAccessException e) { 443 throw new SAXParseException ("Illegal access to method " + pMethodName + 444 " of class " + pBean.getClass().getName(), 445 getDocumentLocator(), e); 446 } catch (NoSuchMethodException e) { 447 throw new SAXParseException ("No such method in class " + 448 pBean.getClass().getName() + ": " + pMethodName, 449 getDocumentLocator(), e); 450 } catch (InvocationTargetException e) { 451 Throwable t = e.getTargetException(); 452 throw new SAXParseException ("Failed to invoke method " + pMethodName + 453 " of class " + pBean.getClass().getName(), 454 getDocumentLocator(), 455 (t instanceof Exception ) ? ((Exception ) t) : e); 456 } 457 } 458 459 462 public void endElement(String namespaceURI, String qName, String localName) 463 throws SAXException { 464 if (ignoreLevel > 0) { 465 --ignoreLevel; 466 return; 467 } 468 469 Object previousBean = currentBean; 470 if (beans.size() > 0) { 471 currentBean = beans.remove(beans.size()-1); 472 currentName = names.remove(names.size()-1).toString(); 473 } else { 474 currentBean = null; 475 currentName = null; 476 } 477 try { 478 invokeMethod("finish", previousBean, zeroClasses, zeroObjects); 479 } catch (SAXParseException e) { 480 if (e.getException() == null || 481 !(e.getException() instanceof NoSuchMethodException )) { 482 throw e; 483 } 484 } 485 } 486 487 492 public void characters(char[] ch, int start, int length) 493 throws SAXException { 494 if (ignoreLevel > 0) { 495 return; 496 } 497 498 String s = new String (ch, start, length); 499 try { 500 invokeMethod("addText", currentBean, oneClassString, new String []{s}); 501 } catch (SAXParseException e) { 502 if (e.getException() != null && 503 (e.getException() instanceof NoSuchMethodException )) { 504 boolean allWhitespace = true; 505 for (int i = 0; i < length; i++) { 506 if (!Character.isWhitespace(ch[start+i])) { 507 allWhitespace = false; 508 break; 509 } 510 } 511 if (allWhitespace) { 512 } else { 514 throw new SAXParseException ("Element " + currentName + 515 " doesn't support embedded text.", 516 getDocumentLocator()); 517 } 518 } else { 519 throw e; 520 } 521 } 522 } 523 524 public void ignorableWhitespace(char[] ch, int start, int length) 525 throws SAXException { 526 } 527 528 public void processingInstruction(String target, String data) 529 throws SAXException { 530 } 531 532 public void skippedEntity(String name) throws SAXException { 533 } 534 535 537 public Object getResult() { return resultBean; } 538 539 public boolean processName(String pName, String [] parts) { 540 int offset = pName.indexOf(':'); 541 if (offset == -1) { 542 String uri = nss.getNamespaceURI(""); 543 if (uri == null) { 544 parts[0] = ""; 545 } else { 546 parts[0] = uri; 547 } 548 parts[1] = pName; 549 parts[2] = pName; 550 return true; 551 } else { 552 String uri = nss.getNamespaceURI(pName.substring(0, offset)); 553 if (uri == null) { 554 return false; 555 } else { 556 parts[0] = uri; 557 parts[1] = pName.substring(offset+1); 558 parts[2] = pName; 559 return true; 560 } 561 } 562 } 563 } 564 | Popular Tags |