1 16 package org.directwebremoting.impl; 17 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.lang.reflect.Method ; 21 import java.util.Arrays ; 22 import java.util.HashMap ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.StringTokenizer ; 26 27 import javax.servlet.ServletContext ; 28 import javax.xml.parsers.DocumentBuilder ; 29 import javax.xml.parsers.DocumentBuilderFactory ; 30 import javax.xml.parsers.ParserConfigurationException ; 31 32 import org.directwebremoting.AjaxFilter; 33 import org.directwebremoting.Container; 34 import org.directwebremoting.WebContextFactory; 35 import org.directwebremoting.extend.AccessControl; 36 import org.directwebremoting.extend.AjaxFilterManager; 37 import org.directwebremoting.extend.Configurator; 38 import org.directwebremoting.extend.ConverterManager; 39 import org.directwebremoting.extend.Creator; 40 import org.directwebremoting.extend.CreatorManager; 41 import org.directwebremoting.extend.TypeHintContext; 42 import org.directwebremoting.util.LocalUtil; 43 import org.directwebremoting.util.LogErrorHandler; 44 import org.directwebremoting.util.Logger; 45 import org.directwebremoting.util.Messages; 46 import org.w3c.dom.Document ; 47 import org.w3c.dom.Element ; 48 import org.w3c.dom.NamedNodeMap ; 49 import org.w3c.dom.Node ; 50 import org.w3c.dom.NodeList ; 51 import org.xml.sax.SAXException ; 52 53 57 public class DwrXmlConfigurator implements Configurator 58 { 59 67 public void setServletResourceName(String servletResourceName) throws IOException , ParserConfigurationException , SAXException 68 { 69 this.servletResourceName = servletResourceName; 70 71 ServletContext servletContext = WebContextFactory.get().getServletContext(); 72 if (servletContext == null) 73 { 74 throw new IOException (Messages.getString("DwrXmlConfigurator.MissingServletContext")); 75 } 76 77 InputStream in = null; 78 try 79 { 80 in = servletContext.getResourceAsStream(servletResourceName); 81 if (in == null) 82 { 83 throw new IOException (Messages.getString("DwrXmlConfigurator.MissingConfigFile", servletResourceName)); 84 } 85 86 log.debug("Configuring from servlet resource: " + servletResourceName); 87 setInputStream(in); 88 } 89 finally 90 { 91 LocalUtil.close(in); 92 } 93 } 94 95 102 public void setClassResourceName(String classResourceName) throws IOException , ParserConfigurationException , SAXException 103 { 104 this.classResourceName = classResourceName; 105 106 InputStream in = getClass().getResourceAsStream(classResourceName); 107 if (in == null) 108 { 109 throw new IOException (Messages.getString("DwrXmlConfigurator.MissingConfigFile", classResourceName)); 110 } 111 112 log.debug("Configuring from class resource: " + classResourceName); 113 setInputStream(in); 114 } 115 116 123 public void setInputStream(InputStream in) throws ParserConfigurationException , SAXException , IOException 124 { 125 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 126 dbf.setValidating(true); 127 128 DocumentBuilder db = dbf.newDocumentBuilder(); 129 db.setEntityResolver(new DTDEntityResolver()); 130 db.setErrorHandler(new LogErrorHandler()); 131 132 document = db.parse(in); 133 } 134 135 139 public void setDocument(Document document) 140 { 141 this.document = document; 142 } 143 144 147 public void configure(Container container) 148 { 149 accessControl = (AccessControl) container.getBean(AccessControl.class.getName()); 150 ajaxFilterManager = (AjaxFilterManager) container.getBean(AjaxFilterManager.class.getName()); 151 converterManager = (ConverterManager) container.getBean(ConverterManager.class.getName()); 152 creatorManager = (CreatorManager) container.getBean(CreatorManager.class.getName()); 153 154 Element root = document.getDocumentElement(); 155 156 NodeList rootChildren = root.getChildNodes(); 157 for (int i = 0; i < rootChildren.getLength(); i++) 158 { 159 Node node = rootChildren.item(i); 160 if (node.getNodeType() == Node.ELEMENT_NODE) 161 { 162 Element child = (Element ) node; 163 164 if (child.getNodeName().equals(ELEMENT_INIT)) 165 { 166 loadInits(child); 167 } 168 else if (child.getNodeName().equals(ELEMENT_ALLOW)) 169 { 170 loadAllows(child); 171 } 172 else if (child.getNodeName().equals(ELEMENT_SIGNATURES)) 173 { 174 loadSignature(child); 175 } 176 } 177 } 178 } 179 180 184 private void loadInits(Element child) 185 { 186 NodeList inits = child.getChildNodes(); 187 for (int j = 0; j < inits.getLength(); j++) 188 { 189 if (inits.item(j).getNodeType() == Node.ELEMENT_NODE) 190 { 191 Element initer = (Element ) inits.item(j); 192 193 if (initer.getNodeName().equals(ATTRIBUTE_CREATOR)) 194 { 195 String id = initer.getAttribute(ATTRIBUTE_ID); 196 String className = initer.getAttribute(ATTRIBUTE_CLASS); 197 creatorManager.addCreatorType(id, className); 198 } 199 else if (initer.getNodeName().equals(ATTRIBUTE_CONVERTER)) 200 { 201 String id = initer.getAttribute(ATTRIBUTE_ID); 202 String className = initer.getAttribute(ATTRIBUTE_CLASS); 203 converterManager.addConverterType(id, className); 204 } 205 } 206 } 207 } 208 209 213 private void loadAllows(Element child) 214 { 215 NodeList allows = child.getChildNodes(); 216 for (int j = 0; j < allows.getLength(); j++) 217 { 218 if (allows.item(j).getNodeType() == Node.ELEMENT_NODE) 219 { 220 Element allower = (Element ) allows.item(j); 221 222 if (allower.getNodeName().equals(ELEMENT_CREATE)) 223 { 224 loadCreate(allower); 225 } 226 else if (allower.getNodeName().equals(ELEMENT_CONVERT)) 227 { 228 loadConvert(allower); 229 } 230 else if (allower.getNodeName().equals(ELEMENT_FILTER)) 231 { 232 loadFilter(allower); 233 } 234 } 235 } 236 } 237 238 242 private void loadConvert(Element allower) 243 { 244 String match = allower.getAttribute(ATTRIBUTE_MATCH); 245 String type = allower.getAttribute(ATTRIBUTE_CONVERTER); 246 247 try 248 { 249 Map params = createSettingMap(allower); 250 converterManager.addConverter(match, type, params); 251 } 252 catch (NoClassDefFoundError ex) 253 { 254 log.info("Convertor '" + type + "' not loaded due to NoClassDefFoundError. (match='" + match + "'). Cause: " + ex.getMessage()); 255 } 256 catch (Exception ex) 257 { 258 log.error("Failed to add convertor: match=" + match + ", type=" + type, ex); 259 } 260 } 261 262 266 private void loadCreate(Element allower) 267 { 268 String type = allower.getAttribute(ATTRIBUTE_CREATOR); 269 String javascript = allower.getAttribute(ATTRIBUTE_JAVASCRIPT); 270 271 try 272 { 273 Map params = createSettingMap(allower); 274 creatorManager.addCreator(javascript, type, params); 275 276 processPermissions(javascript, allower); 277 processAuth(javascript, allower); 278 processParameters(javascript, allower); 279 processAjaxFilters(javascript, allower); 280 } 281 catch (NoClassDefFoundError ex) 282 { 283 log.info("Creator '" + type + "' not loaded due to NoClassDefFoundError. (javascript='" + javascript + "'). Cause: " + ex.getMessage()); 284 } 285 catch (Exception ex) 286 { 287 log.error("Failed to add creator: type=" + type + ", javascript=" + javascript, ex); 288 } 289 } 290 291 295 private void loadFilter(Element allower) 296 { 297 String type = allower.getAttribute(ATTRIBUTE_CLASS); 298 299 try 300 { 301 Class impl = LocalUtil.classForName(type); 302 AjaxFilter object = (AjaxFilter) impl.newInstance(); 303 304 LocalUtil.setParams(object, createSettingMap(allower), ignore); 305 306 ajaxFilterManager.addAjaxFilter(object); 307 } 308 catch (ClassCastException ex) 309 { 310 log.error(type + " does not implement " + AjaxFilter.class.getName(), ex); 311 } 312 catch (NoClassDefFoundError ex) 313 { 314 log.info("Missing class for filter (class='" + type + "'). Cause: " + ex.getMessage()); 315 } 316 catch (Exception ex) 317 { 318 log.error("Failed to add filter: class=" + type, ex); 319 } 320 } 321 322 328 private static Map createSettingMap(Element parent) 329 { 330 Map params = new HashMap (); 331 332 NamedNodeMap attrs = parent.getAttributes(); 334 for (int i = 0; i < attrs.getLength(); i++) 335 { 336 Node node = attrs.item(i); 337 String name = node.getNodeName(); 338 String value = node.getNodeValue(); 339 params.put(name, value); 340 } 341 342 NodeList locNodes = parent.getElementsByTagName(ELEMENT_PARAM); 344 for (int i = 0; i < locNodes.getLength(); i++) 345 { 346 Element element = (Element ) locNodes.item(i); 349 350 if (element.getParentNode() != parent) 354 { 355 continue; 356 } 357 358 String name = element.getAttribute(ATTRIBUTE_NAME); 359 if (name != null) 360 { 361 String value = element.getAttribute(ATTRIBUTE_VALUE); 362 if (value == null || value.length() == 0) 363 { 364 StringBuffer buffer = new StringBuffer (); 365 NodeList textNodes = element.getChildNodes(); 366 367 for (int j = 0; j < textNodes.getLength(); j++) 368 { 369 buffer.append(textNodes.item(j).getNodeValue()); 370 } 371 372 value = buffer.toString(); 373 } 374 375 params.put(name, value); 376 } 377 } 378 379 return params; 380 } 381 382 388 private void processPermissions(String javascript, Element parent) 389 { 390 NodeList incNodes = parent.getElementsByTagName(ELEMENT_INCLUDE); 391 for (int i = 0; i < incNodes.getLength(); i++) 392 { 393 Element include = (Element ) incNodes.item(i); 394 String method = include.getAttribute(ATTRIBUTE_METHOD); 395 accessControl.addIncludeRule(javascript, method); 396 } 397 398 NodeList excNodes = parent.getElementsByTagName(ELEMENT_EXCLUDE); 399 for (int i = 0; i < excNodes.getLength(); i++) 400 { 401 Element include = (Element ) excNodes.item(i); 402 String method = include.getAttribute(ATTRIBUTE_METHOD); 403 accessControl.addExcludeRule(javascript, method); 404 } 405 } 406 407 412 private void processAuth(String javascript, Element parent) 413 { 414 NodeList nodes = parent.getElementsByTagName(ELEMENT_AUTH); 415 for (int i = 0; i < nodes.getLength(); i++) 416 { 417 Element include = (Element ) nodes.item(i); 418 419 String method = include.getAttribute(ATTRIBUTE_METHOD); 420 String role = include.getAttribute(ATTRIBUTE_ROLE); 421 422 accessControl.addRoleRestriction(javascript, method, role); 423 } 424 } 425 426 431 private void processAjaxFilters(String javascript, Element parent) 432 { 433 NodeList nodes = parent.getElementsByTagName(ELEMENT_FILTER); 434 for (int i = 0; i < nodes.getLength(); i++) 435 { 436 Element include = (Element ) nodes.item(i); 437 438 String type = include.getAttribute(ATTRIBUTE_CLASS); 439 AjaxFilter filter = (AjaxFilter) LocalUtil.classNewInstance(javascript, type, AjaxFilter.class); 440 if (filter != null) 441 { 442 LocalUtil.setParams(filter, createSettingMap(include), ignore); 443 ajaxFilterManager.addAjaxFilter(filter, javascript); 444 } 445 } 446 } 447 448 452 private void loadSignature(Element element) 453 { 454 StringBuffer sigtext = new StringBuffer (); 455 456 element.normalize(); 458 459 NodeList nodes = element.getChildNodes(); 460 for (int i = 0; i < nodes.getLength(); i++) 461 { 462 Node node = nodes.item(i); 463 short type = node.getNodeType(); 464 if (type != Node.TEXT_NODE && type != Node.CDATA_SECTION_NODE) 465 { 466 log.warn("Ignoring illegal node type: " + type); 467 continue; 468 } 469 470 sigtext.append(node.getNodeValue()); 471 } 472 473 SignatureParser sigp = new SignatureParser(converterManager, creatorManager); 474 sigp.parse(sigtext.toString()); 475 } 476 477 484 private void processParameters(String javascript, Element parent) throws ClassNotFoundException 485 { 486 NodeList nodes = parent.getElementsByTagName(ELEMENT_PARAMETER); 487 for (int i = 0; i < nodes.getLength(); i++) 488 { 489 Element include = (Element ) nodes.item(i); 490 491 String methodName = include.getAttribute(ATTRIBUTE_METHOD); 492 493 Creator creator = creatorManager.getCreator(javascript); 495 Class dest = creator.getType(); 496 497 Method method = null; 498 Method [] methods = dest.getMethods(); 499 for (int j = 0; j < methods.length; j++) 500 { 501 Method test = methods[j]; 502 if (test.getName().equals(methodName)) 503 { 504 if (method == null) 505 { 506 method = test; 507 } 508 else 509 { 510 log.warn("Setting extra type info to overloaded methods may fail with <parameter .../>"); 511 } 512 } 513 } 514 515 if (method == null) 516 { 517 log.error("Unable to find method called: " + methodName + " on type: " + dest.getName() + " from creator: " + javascript); 518 continue; 519 } 520 521 String number = include.getAttribute(ATTRIBUTE_NUMBER); 522 int paramNo = Integer.parseInt(number); 523 524 String types = include.getAttribute(ATTRIBUTE_TYPE); 525 StringTokenizer st = new StringTokenizer (types, ","); 526 527 int j = 0; 528 while (st.hasMoreTokens()) 529 { 530 String type = st.nextToken(); 531 Class clazz = LocalUtil.classForName(type.trim()); 532 TypeHintContext thc = new TypeHintContext(converterManager, method, paramNo).createChildContext(j++); 533 converterManager.setExtraTypeInfo(thc, clazz); 534 } 535 } 536 } 537 538 541 public String toString() 542 { 543 if (servletResourceName != null) 544 { 545 return "DwrXmlConfigurator[ServletResource:" + servletResourceName + "]"; 546 } 547 else 548 { 549 return "DwrXmlConfigurator[ClassResource:" + classResourceName + "]"; 550 } 551 } 552 553 556 private Document document; 557 558 561 private static List ignore = Arrays.asList(new String [] { "class", }); 562 563 566 public static final Logger log = Logger.getLogger(DwrXmlConfigurator.class); 567 568 571 private AjaxFilterManager ajaxFilterManager = null; 572 573 576 private ConverterManager converterManager = null; 577 578 581 private CreatorManager creatorManager = null; 582 583 586 private AccessControl accessControl = null; 587 588 592 private String classResourceName; 593 594 598 private String servletResourceName; 599 600 603 private static final String ELEMENT_INIT = "init"; 604 605 private static final String ELEMENT_ALLOW = "allow"; 606 607 private static final String ELEMENT_CREATE = "create"; 608 609 private static final String ELEMENT_CONVERT = "convert"; 610 611 private static final String ELEMENT_PARAM = "param"; 612 613 private static final String ELEMENT_INCLUDE = "include"; 614 615 private static final String ELEMENT_EXCLUDE = "exclude"; 616 617 private static final String ELEMENT_PARAMETER = "parameter"; 618 619 private static final String ELEMENT_AUTH = "auth"; 620 621 private static final String ELEMENT_SIGNATURES = "signatures"; 622 623 private static final String ELEMENT_FILTER = "filter"; 624 625 628 private static final String ATTRIBUTE_ID = "id"; 629 630 private static final String ATTRIBUTE_CLASS = "class"; 631 632 private static final String ATTRIBUTE_CONVERTER = "converter"; 633 634 private static final String ATTRIBUTE_MATCH = "match"; 635 636 private static final String ATTRIBUTE_JAVASCRIPT = "javascript"; 637 638 private static final String ATTRIBUTE_CREATOR = "creator"; 639 640 private static final String ATTRIBUTE_NAME = "name"; 641 642 private static final String ATTRIBUTE_VALUE = "value"; 643 644 private static final String ATTRIBUTE_METHOD = "method"; 645 646 private static final String ATTRIBUTE_ROLE = "role"; 647 648 private static final String ATTRIBUTE_NUMBER = "number"; 649 650 private static final String ATTRIBUTE_TYPE = "type"; 651 } 652 | Popular Tags |