1 20 package org.enhydra.barracuda.core.event; 21 22 import java.io.*; 23 import java.lang.reflect.*; 24 import java.util.*; 25 import javax.servlet.*; 26 import javax.servlet.http.*; 27 28 import org.apache.log4j.*; 29 import org.apache.log4j.xml.*; 30 import org.xml.sax.*; 31 import org.xml.sax.helpers.*; 32 33 import org.enhydra.barracuda.core.event.*; 34 import org.enhydra.barracuda.plankton.*; 35 import org.enhydra.barracuda.plankton.xml.*; 36 import org.enhydra.barracuda.core.util.dom.*; 37 38 125 public class DefaultApplicationAssembler extends DefaultHandler implements ApplicationAssembler { 126 127 protected static final Logger logger = Logger.getLogger(DefaultApplicationAssembler.class.getName()); 129 130 public static String DEFAULT_PARSER = "org.apache.xerces.parsers.SAXParser"; 132 133 private static final String CONSTANT = "constant"; 135 private static final String EVENT_ALIAS = "event-alias"; 136 private static final String EVENT_GATEWAY = "event-gateway"; 137 private static final String EVENT_INTEREST = "event-interest"; 138 private static final String SET_PROPERTY = "set-property"; 139 140 private static final String CLASS = "class"; 142 private static final String DELEGATE = "delegateRuntimeValue"; 143 private static final String EVENT = "event"; 144 private static final String FACTORY = "factory"; 145 private static final String NAME = "name"; 146 147 148 158 public void assemble(EventGateway irootGateway, ServletConfig iservletConfig, String iassemblySourceFile) { 159 assemble(irootGateway, iservletConfig, iassemblySourceFile, null); 160 } 161 162 173 public void assemble(EventGateway irootGateway, ServletConfig iservletConfig, String iassemblySourceFile, String iparserClass) { 174 AssemblerXMLReader assemblerXmlReader = new AssemblerXMLReader(iparserClass, irootGateway); 176 assemblerXmlReader.setup(); 177 178 if (logger.isInfoEnabled()) logger.info("Assembling system from input source"); 179 if (logger.isDebugEnabled()) logger.debug("assembly path is: " + iassemblySourceFile); 180 try { 181 if (iservletConfig != null) { 182 184 ServletContext context = iservletConfig.getServletContext(); 185 assemblerXmlReader.setServletContext(context); if (!hasMethod("getResourcePaths", context.getClass(), new Class []{String .class})) { 187 InputStream is = getAssemblyResourceAsStream(context, iassemblySourceFile); 189 if (is != null) { 190 assemblerXmlReader.processXmlFile(is); 191 } 192 } else { 193 String normalizedResourcePath = "/"+getNormalizedPath(iassemblySourceFile); 196 197 String dirPath = normalizedResourcePath.substring(0, normalizedResourcePath.lastIndexOf("/")+1); 199 String fileMatch = normalizedResourcePath.substring(normalizedResourcePath.lastIndexOf("/")+1); 200 String beginMatch = fileMatch; String endMatch = ".xml"; if (fileMatch.indexOf(".") != -1) endMatch = fileMatch; 204 if (fileMatch.indexOf("*") != -1) { 206 beginMatch = fileMatch.substring(0, fileMatch.indexOf("*")); 207 endMatch = fileMatch.substring(fileMatch.indexOf("*")+1); 208 if (!(endMatch.length() > 0)) endMatch = ".xml"; } 211 212 if (logger.isDebugEnabled()) logger.debug("dirPath is : " + dirPath); 213 if (logger.isDebugEnabled()) logger.debug("fileMatch is: " + fileMatch); 214 if (logger.isDebugEnabled()) logger.debug("beginMatch is: " + beginMatch); 215 if (logger.isDebugEnabled()) logger.debug("endMatch is: " + endMatch); 216 217 Set paths = context.getResourcePaths(dirPath); 218 if (logger.isDebugEnabled()) logger.debug("resource paths returned: " + paths.size()); 219 Iterator iter = paths.iterator(); 220 while (iter.hasNext()) { 221 String currentPath = (String )iter.next(); 222 if (logger.isDebugEnabled()) logger.debug("current path is: " + currentPath); 223 if (currentPath.indexOf(dirPath+beginMatch) != -1 && currentPath.endsWith(endMatch)) { 224 InputStream is = getAssemblyResourceAsStream(context, currentPath); 225 if (is != null) { 226 assemblerXmlReader.processXmlFile(is); 227 } 228 } 229 } 230 } 231 } else { 232 InputStream is = getAssemblyResourceAsStream(null, iassemblySourceFile); 237 if (is != null) { 238 assemblerXmlReader.processXmlFile(is); 239 } 240 } 241 if (logger.isInfoEnabled()) logger.info("Assembly complete!"); 242 } catch (Exception e) { 243 logger.warn("Error assembling system!", e); 244 e.printStackTrace(System.err); 245 } 246 } 247 248 private static boolean hasMethod(String methodName, Class clazz, Class [] parameterTypes) { 249 Method method = null; 250 try { 251 method = clazz.getMethod(methodName, parameterTypes); 252 } catch (Exception e) {} 253 if (method != null) return true; 254 return false; 255 } 256 257 private static InputStream getAssemblyResourceAsStream(ServletContext context, String resource) { 258 InputStream is = null; 259 String normalizedResourcePath = getNormalizedPath(resource); 260 if (context!=null) { 262 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file via servlet context at: /"+normalizedResourcePath); 265 is = context.getResourceAsStream("/" + normalizedResourcePath); 266 267 if (is==null) { 270 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file via servlet context at: /WEB-INF/"+normalizedResourcePath); 273 is = context.getResourceAsStream("/WEB-INF/" + normalizedResourcePath); 274 if (is==null) { 275 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file via servlet context at: /WEB-INF/classes/"+normalizedResourcePath); 279 is = context.getResourceAsStream("/WEB-INF/classes/" + normalizedResourcePath); 280 } 281 } 282 } 283 284 if (is==null) { 286 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file inside the local classloader: "+normalizedResourcePath); 287 is = DefaultApplicationAssembler.class.getClassLoader().getResourceAsStream(normalizedResourcePath); 288 if (is==null) { 289 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file inside all available classloaders: "+normalizedResourcePath); 292 is = Thread.currentThread().getContextClassLoader().getResourceAsStream(normalizedResourcePath); 293 } 294 } 295 296 if (is==null) { 298 if (logger.isDebugEnabled()) logger.debug("Attempting to load assembly file via file IO at: "+resource); 299 File f = new File(resource); 300 try { 301 is = new FileInputStream(f); 302 } catch (FileNotFoundException fnfe) {} 303 } 304 305 if (is==null) { 306 logger.warn("Unable to load assembly file"+resource); 307 } 308 return is; 309 } 310 311 private static String getNormalizedPath(String resourcePath) { 313 String path = resourcePath; 314 if (path!=null) { 315 if (path.startsWith("/")) path = (path.length() > 1) ? path.substring(1) : ""; 316 } 317 return path; 318 } 319 320 324 class AssemblerXMLReader extends DefaultHandler { 325 ServletContext servletContext; 326 String parserClass = null; EventGateway rootGateway = null; 328 EventGateway curGateway = null; 329 Stack objStack = null; 330 DOMLoader domLoader = null; 331 boolean needPropVal = false; 332 String className = null; 333 String propName = null; 334 String propVal = null; 335 String propDelegate = null; 336 int depth = 0; 337 338 XMLReader parser = null; 341 public AssemblerXMLReader() {} 343 344 public AssemblerXMLReader(String parserClass, EventGateway rootGateway) { 345 setParserClass(parserClass); 346 setRootGateway(rootGateway); 347 } 348 349 353 public void setParserClass(String parserClass) { 354 this.parserClass = parserClass; 355 } 356 357 361 public void setRootGateway(EventGateway rootGateway) { 362 this.rootGateway = rootGateway; 363 } 364 365 370 public void setServletContext(ServletContext iservletContext) { 371 this.servletContext = iservletContext; 372 } 373 374 377 public void setup() { 378 try { 379 if (parserClass==null) parserClass = DEFAULT_PARSER; 380 logger.info("Instantiating parser ("+parserClass+")"); 381 parser = (XMLReader) Class.forName(parserClass, true, Thread.currentThread().getContextClassLoader()).newInstance(); 382 } catch (Exception e) { 383 logger.warn("Error assembling system!", e); 384 e.printStackTrace(System.err); 385 } 386 } 387 388 public void processXmlFile(InputStream is) { 390 try { 391 InputSource source = new InputSource(is); 393 394 logger.info("Parsing the source file..."); 396 parser.setContentHandler(this); 397 parser.setErrorHandler(this); 398 parser.parse(source); 399 } catch (org.xml.sax.SAXParseException spe) { 400 logger.warn("Error assembling system!", spe); 401 spe.printStackTrace(System.err); 402 } catch (org.xml.sax.SAXException se) { 403 if (se.getException() != null) { 404 logger.warn("Error assembling system!", se.getException()); 405 se.getException().printStackTrace(System.err); 406 } else { 407 logger.warn("Error assembling system!", se); 408 se.printStackTrace(System.err); 409 } 410 } catch (Exception e) { 411 logger.warn("Error assembling system!", e); 412 e.printStackTrace(System.err); 413 } 414 } 415 416 public void startDocument() { 417 curGateway = rootGateway; 418 objStack = new Stack(); 419 objStack.push(curGateway); 420 } 421 422 public void startElement(String uri, String local, String raw, Attributes attrs) throws SAXException { 423 String curTag = local; 424 logger.debug("uri:"+uri+" local:"+local+" raw:"+raw+" attrs:"+attrs); 425 426 if (curTag.equals(EVENT_GATEWAY)) { 428 429 depth++; 431 EventGateway eg = null; 432 String eventGatewayClassName = attrs.getValue(CLASS); 433 logger.debug("Creating event gateway: "+eventGatewayClassName); 434 try { 435 eg = (EventGateway) Class.forName(eventGatewayClassName, true, Thread.currentThread().getContextClassLoader()).newInstance(); 436 objStack.push(eg); 437 } catch (Exception e) { 438 String msg = "Error instantiating event gateway"; 439 logger.warn(msg+": ", e); 440 throw new SAXException(msg, e); 441 } 442 443 logger.debug("Adding event gateway: "+eg.getClass().getName()); 446 if (curGateway!=null) curGateway.add(eg); 447 curGateway = eg; 448 449 } else if (curTag.equals(EVENT_INTEREST)) { 451 String listenerFactoryClassName = attrs.getValue(FACTORY); 453 454 ListenerFactory lf = null; 456 try { 457 Field field = curGateway.getClass().getField(listenerFactoryClassName); 458 if (field!=null) { 459 logger.debug("Getting listener factory from gateway: "+field); 460 lf = (ListenerFactory) field.get(curGateway); 461 } 462 } catch (Exception e) { 463 logger.debug("Failed! "+e+" (this err is not fatal)"); 464 } 465 466 if (lf==null) { 468 logger.debug("Creating listener factory: "+listenerFactoryClassName); 469 try { 470 lf = (ListenerFactory) Class.forName(listenerFactoryClassName, true, Thread.currentThread().getContextClassLoader()).newInstance(); 471 } catch (Exception e) { 473 String msg = "Error instantiating listener factory"; 474 logger.warn(msg+": ",e); 475 throw new SAXException(msg, e); 476 } 477 } 478 479 if (lf!=null) objStack.push(lf); 482 483 String eventClassName = attrs.getValue(EVENT); 485 Class ev = null; 486 if (eventClassName!=null) { 487 logger.debug("Creating event class: "+eventClassName); 488 try { 489 ev = Class.forName(eventClassName, true, Thread.currentThread().getContextClassLoader()); 490 } catch (Exception e) { 491 String msg = "Error creating event class"; 492 logger.warn(msg+": ",e); 493 throw new SAXException(msg, e); 494 } 495 } 496 497 if (ev!=null) curGateway.specifyLocalEventInterests(lf, ev); 499 else curGateway.specifyLocalEventInterests(lf); 500 501 } else if (curTag.equals(EVENT_ALIAS)) { 503 String eventClassName = attrs.getValue(EVENT); 505 Class ev = null; 506 logger.debug("Creating event class: "+eventClassName); 507 try { 508 ev = Class.forName(eventClassName, true, Thread.currentThread().getContextClassLoader()); 509 } catch (Exception e) { 510 String msg = "Error creating event class"; 511 logger.warn(msg+": ",e); 512 throw new SAXException(msg, e); 513 } 514 515 curGateway.specifyLocalEventAliases(ev); 517 518 } else if (curTag.equals(SET_PROPERTY)) { 520 propName = attrs.getValue(NAME); 522 propDelegate = attrs.getValue(DELEGATE); 523 propVal = null; 524 needPropVal = (propDelegate == null) ? true : false; 525 526 } else if (curTag.equals(CONSTANT)) { 528 className = attrs.getValue(CLASS); 529 propName = attrs.getValue(NAME); 530 propDelegate = attrs.getValue(DELEGATE); 531 propVal = null; 532 needPropVal = (propDelegate == null) ? true : false; 533 } 534 } 535 536 public void endElement(String uri, String local, String raw) throws SAXException { 537 String curTag = local; 538 539 if (curTag.equals(EVENT_GATEWAY)) { 541 logger.debug("Finished w/ gateway: " + curGateway.getClass().getName()); 542 curGateway = curGateway.getParent(); 543 objStack.pop(); 544 depth--; 545 546 } else if (curTag.equals(EVENT_INTEREST)) { 548 objStack.pop(); 549 550 } else if (curTag.equals(SET_PROPERTY)) { 552 Object parent = objStack.peek(); 553 try { 554 String methodName = propName; 555 logger.debug("methodName:" + methodName); 556 Class clazz = parent.getClass(); 557 Method methods[] = clazz.getMethods(); 558 boolean success = false; 559 boolean delegate = Boolean.valueOf(propDelegate).booleanValue(); 560 if (logger.isDebugEnabled()) logger.debug("delegate a runtime value? " + delegate); 561 562 for (int i=0; i<methods.length; i++) { 563 Method m = methods[i]; 564 if (!m.getName().equalsIgnoreCase("set" + propName)) continue; 565 methodName = m.getName(); 566 Class paramTypes[] = m.getParameterTypes(); 567 if (paramTypes.length>1) continue; 568 Class paramType = paramTypes[0]; 569 if (logger.isDebugEnabled()) logger.debug("method:" + methodName + " paramType:" + paramType); 570 success = setMethod(parent, m, paramType, propVal, delegate); 571 if (!success) continue; 572 if (logger.isDebugEnabled()) { 573 if (delegate) logger.debug("delegate runtime setting of " + parent + "." + methodName + "(\"" + paramType + "\") successful"); 574 else logger.debug(parent + "." + methodName + "(\"" + propVal + "\") successful"); 575 } 576 break; 577 } 578 579 if (!success) { 580 Field field = clazz.getField(propName); 581 Class paramType = field.getType(); 582 success = setField(parent, field, paramType, propVal, delegate); 583 if (success) { 584 if (logger.isDebugEnabled()) { 585 if (delegate) logger.debug("delegate runtime setting of " + parent + "." + propName + " of type " + paramType + " successful"); 586 else logger.debug(parent + "." + propName + "=\"" + propVal + "\" successful"); 587 } 588 } else { 589 throw new SAXException(""); } 591 } 592 } catch (Exception e) { 593 String msg = "Error setting " + propName + " in parent:" + parent; 594 logger.warn(msg+": ",e); 595 throw new SAXException(msg, e); 596 } 597 } else if(curTag.equals(CONSTANT)) { 598 Class clazz = null; 599 boolean delegate = Boolean.valueOf(propDelegate).booleanValue(); 600 try { 601 clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); 602 if (logger.isDebugEnabled()) logger.debug("class:" + className); 603 Field field = clazz.getField(propName); 604 Class paramType = field.getType(); 605 if (logger.isDebugEnabled()) logger.debug("field:" + propName); 606 boolean success = setField(clazz, field, paramType, propVal, delegate); 607 if (success) { 608 if (logger.isDebugEnabled()) { 609 if (delegate) logger.debug("delegate runtime setting of " + clazz + "." + propName + " of type " + paramType + " successful"); 610 else logger.debug(clazz + "." + propName + "=\"" + propVal + "\" successful"); 611 } 612 } else { 613 throw new SAXException(""); } 615 } catch(Exception e) { 616 String msg = "Error setting " + propName + " in target:" + clazz; 617 logger.warn(msg+": ",e); 618 throw new SAXException(msg, e); 619 } 620 } 621 } 622 623 public void characters(char ch[], int start, int length) { 624 if(needPropVal) { 625 propVal = XMLUtil.fromXMLUnicodeString(new String (ch, start, length)); 626 needPropVal = false; 627 } else { 628 logger.debug("[characters] " + new String (ch, start, length)); 629 } 630 } 631 632 public void ignorableWhitespace(char ch[], int start, int length) { 633 logger.debug("[whitespace] " + new String (ch, start, length)); 634 } 635 636 public void warning(SAXParseException ex) { 637 System.err.println("[Warning] " + getLocationString(ex) + ": " + ex.getMessage()); 638 } 639 640 public void error(SAXParseException ex) { 641 System.err.println("[Error] " + getLocationString(ex) + ": " + ex.getMessage()); 642 } 643 644 public void fatalError(SAXParseException ex) throws SAXException { 645 System.err.println("[Fatal Error] " + getLocationString(ex) + ": " + ex.getMessage()); 646 } 647 648 private String getLocationString(SAXParseException ex) { 649 StringBuffer str = new StringBuffer (); 650 String systemId = ex.getSystemId(); 651 if (systemId!=null) { 652 int index = systemId.lastIndexOf(47); 653 if (index!=-1) systemId = systemId.substring(index + 1); 654 str.append(systemId); 655 } 656 str.append(':'); 657 str.append(ex.getLineNumber()); 658 str.append(':'); 659 str.append(ex.getColumnNumber()); 660 return str.toString(); 661 } 662 663 public boolean setMethod(Object target, Method m, Class paramType, String propVal, boolean delegate) throws InvocationTargetException, IllegalAccessException { 664 if (paramType.equals(String .class)) { 665 m.invoke(target, new Object [] {propVal}); 666 return true; 667 } else if (paramType.equals(boolean.class) || paramType.equals(Boolean .class)) { 668 m.invoke(target, new Object [] {new Boolean (propVal)}); 669 return true; 670 } else if (paramType.equals(byte.class) || paramType.equals(Byte .class)) { 671 m.invoke(target, new Object [] {new Byte (propVal)}); 672 return true; 673 } else if (paramType.equals(char.class) || paramType.equals(Character .class)) { 674 byte b[] = propVal.getBytes(); 675 m.invoke(target, new Object [] {new Character ((char)b[0])}); 676 return true; 677 } else if (paramType.equals(double.class) || paramType.equals(Double .class)) { 678 m.invoke(target, new Object [] {new Double (propVal)}); 679 return true; 680 } else if (paramType.equals(float.class) || paramType.equals(Float .class)) { 681 m.invoke(target, new Object [] {new Float (propVal)}); 682 return true; 683 } else if (paramType.equals(int.class) || paramType.equals(Integer .class)) { 684 m.invoke(target, new Object [] {new Integer (propVal)}); 685 return true; 686 } else if (paramType.equals(long.class) || paramType.equals(Long .class)) { 687 m.invoke(target, new Object [] {new Long (propVal)}); 688 return true; 689 } else if (paramType.equals(short.class) || paramType.equals(Short .class)) { 690 m.invoke(target, new Object [] {new Short (propVal)}); 691 return true; 692 693 } else if (delegate && paramType.equals(ServletContext.class)) { 695 m.invoke(target, new Object [] {servletContext}); 696 return true; 697 } else { 698 return false; 699 } 700 } 701 702 public boolean setField(Object target, Field field, Class paramType, String propVal, boolean delegate) throws IllegalAccessException { 703 if (paramType.equals(String .class)) { 704 field.set(target, propVal); 705 return true; 706 } else if (paramType.equals(boolean.class) || paramType.equals(Boolean .class)) { 707 field.set(target, new Boolean (propVal)); 708 return true; 709 } else if (paramType.equals(byte.class) || paramType.equals(Byte .class)) { 710 field.set(target, new Byte (propVal)); 711 return true; 712 } else if (paramType.equals(char.class) || paramType.equals(Character .class)) { 713 byte b[] = propVal.getBytes(); 714 field.set(target, new Character ((char)b[0])); 715 return true; 716 } else if (paramType.equals(double.class) || paramType.equals(Double .class)) { 717 field.set(target, new Double (propVal)); 718 return true; 719 } else if (paramType.equals(float.class) || paramType.equals(Float .class)) { 720 field.set(target, new Float (propVal)); 721 return true; 722 } else if (paramType.equals(int.class) || paramType.equals(Integer .class)) { 723 field.set(target, new Integer (propVal)); 724 return true; 725 } else if (paramType.equals(long.class) || paramType.equals(Long .class)) { 726 field.set(target, new Long (propVal)); 727 return true; 728 } else if (paramType.equals(short.class) || paramType.equals(Short .class)) { 729 field.set(target, new Short (propVal)); 730 return true; 731 732 } else if (delegate && paramType.equals(ServletContext.class)) { 734 field.set(target, servletContext); 735 return true; 736 } else { 737 return false; 738 } 739 } 740 } 741 743 744 745 746 public static void main(String [] args) { 747 try { 748 DOMConfigurator.configure("../WEB-INF/log4j.xml"); 750 751 new DefaultApplicationAssembler().assemble(null, null, "../WEB-INF/event-gateway.xml"); 753 } catch (Exception e) { 754 System.out.println("Unexpected Exception: "+e); 755 e.printStackTrace(); 756 } 757 } 758 759 } 760 | Popular Tags |