1 7 package org.jboss.cache.factories; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.buddyreplication.NextMemberBuddyLocator; 12 import org.jboss.cache.config.BuddyReplicationConfig; 13 import org.jboss.cache.config.BuddyReplicationConfig.BuddyLocatorConfig; 14 import org.jboss.cache.config.CacheLoaderConfig; 15 import org.jboss.cache.config.Configuration; 16 import org.jboss.cache.config.ConfigurationException; 17 import org.jboss.cache.config.EvictionConfig; 18 import org.jboss.cache.config.EvictionRegionConfig; 19 import org.jboss.cache.config.MissingPolicyException; 20 import org.jboss.cache.eviction.EvictionPolicy; 21 import org.jboss.cache.eviction.EvictionPolicyConfig; 22 import org.jboss.cache.util.Util; 23 import org.jboss.cache.xml.XmlHelper; 24 import org.w3c.dom.Attr ; 25 import org.w3c.dom.Element ; 26 import org.w3c.dom.NamedNodeMap ; 27 import org.w3c.dom.Node ; 28 import org.w3c.dom.NodeList ; 29 30 import java.beans.PropertyEditor ; 31 import java.beans.PropertyEditorManager ; 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.lang.reflect.Method ; 35 import java.util.ArrayList ; 36 import java.util.HashMap ; 37 import java.util.Iterator ; 38 import java.util.List ; 39 import java.util.Map ; 40 import java.util.Map.Entry; 41 import java.util.Properties ; 42 43 50 public class XmlConfigurationParser 51 { 52 private static Log log = LogFactory.getLog(XmlConfigurationParser.class); 53 54 public static final String ATTR = "attribute"; 55 public static final String NAME = "name"; 56 57 public Configuration parseFile(String filename) 58 { 59 return parseStream(getAsInputStreamFromClassLoader(filename)); 60 } 61 62 public Configuration parseStream(InputStream stream) 63 { 64 if (stream == null) throw new ConfigurationException("Input stream for configuration xml is null!"); 66 67 Element root = XmlHelper.getDocumentRoot(stream); 68 Element mbeanElement = getMBeanElement(root); 69 70 ParsedAttributes attributes = extractAttributes(mbeanElement); 71 72 String defaultEvictionClass = attributes.stringAttribs.remove("EvictionPolicyClass"); 75 76 String keepStats = attributes.stringAttribs.remove("UseMbean"); 78 if (keepStats != null && attributes.stringAttribs.get("ExposeManagementStatistics") == null) 79 { 80 attributes.stringAttribs.put("ExposeManagementStatistics", keepStats); 81 } 82 83 Configuration c = new Configuration(); 84 setValues(c, attributes.stringAttribs, false); 85 setXmlValues(c, attributes.xmlAttribs, defaultEvictionClass); 87 88 return c; 89 } 90 91 protected InputStream getAsInputStreamFromClassLoader(String filename) 92 { 93 return Thread.currentThread().getContextClassLoader().getResourceAsStream(filename); 94 } 95 96 protected Element getMBeanElement(Element root) 97 { 98 NodeList list = root.getElementsByTagName(XmlHelper.ROOT); 100 if (list == null) throw new ConfigurationException("Can't find " + XmlHelper.ROOT + " tag"); 101 102 if (list.getLength() > 1) throw new ConfigurationException("Has multiple " + XmlHelper.ROOT + " tag"); 103 104 Node node = list.item(0); 105 Element element = null; 106 if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) 107 { 108 element = (Element ) node; 109 } 110 else 111 { 112 throw new ConfigurationException("Can't find " + XmlHelper.ROOT + " element"); 113 } 114 return element; 115 } 116 117 118 protected static void setValues(Object target, Map attribs, boolean isXmlAttribs) 119 { 120 Class objectClass = target.getClass(); 121 122 for (Iterator iter = attribs.entrySet().iterator(); iter.hasNext();) 124 { 125 Map.Entry entry = (Map.Entry ) iter.next(); 126 String propName = (String ) entry.getKey(); 127 String setter = getSetterName(propName); 128 Method method = null; 129 130 try 131 { 132 if (isXmlAttribs) 133 { 134 method = objectClass.getMethod(setter, new Class []{Element .class}); 135 method.invoke(target, new Object []{entry.getValue()}); 136 } 137 else 138 { 139 method = objectClass.getMethod(setter, new Class []{String .class}); 140 method.invoke(target, new Object []{entry.getValue()}); 141 } 142 143 continue; 144 } 145 catch (NoSuchMethodException me) 146 { 147 } 150 catch (Exception e) 151 { 152 throw new ConfigurationException("Unable to invoke setter " + setter + " on " + objectClass, e); 153 } 154 155 for (Method m : objectClass.getMethods()) 157 { 158 if (setter.equals(m.getName())) 159 { 160 Class paramTypes[] = m.getParameterTypes(); 161 if (paramTypes.length != 1) 162 { 163 throw new ConfigurationException("Setter " + setter + " does not contain the expected number of params. Has " + paramTypes.length + " instead of just 1."); 164 } 165 166 Class parameterType = paramTypes[0]; 167 PropertyEditor editor = PropertyEditorManager.findEditor(parameterType); 168 if (editor == null) 169 { 170 throw new ConfigurationException("Couldn't find a property editor for parameter type " + parameterType); 171 } 172 173 editor.setAsText((String ) attribs.get(propName)); 174 175 Object parameter = editor.getValue(); 176 178 try 179 { 180 m.invoke(target, new Object []{parameter}); 181 } 182 catch (Exception e) 183 { 184 throw new ConfigurationException("Unable to invoke setter " + setter + " on " + objectClass, e); 185 } 186 } 187 } 188 } 189 } 190 191 protected void setXmlValues(Configuration conf, Map <String , Element > attribs, String defaultEvictionClass) 192 { 193 for (Iterator it = attribs.entrySet().iterator(); it.hasNext();) 194 { 195 Map.Entry entry = (Entry) it.next(); 196 String propname = (String ) entry.getKey(); 197 if ("BuddyReplicationConfiguration".equals(propname) 198 || "BuddyReplicationConfig".equals(propname)) 199 { 200 BuddyReplicationConfig brc = parseBuddyReplicationConfig((Element ) entry.getValue()); 201 conf.setBuddyReplicationConfig(brc); 202 } 203 else if ("CacheLoaderConfiguration".equals(propname) 204 || "CacheLoaderConfig".equals(propname)) 205 { 206 CacheLoaderConfig clc = parseCacheLoaderConfig((Element ) entry.getValue()); 207 conf.setCacheLoaderConfig(clc); 208 } 209 else if ("EvictionPolicyConfiguration".equals(propname) 210 || "EvictionPolicyConfig".equals(propname)) 211 { 212 EvictionConfig ec = parseEvictionConfig((Element ) entry.getValue(), 213 defaultEvictionClass); 214 conf.setEvictionConfig(ec); 215 } 216 else if ("ClusterConfig".equals(propname)) 217 { 218 String jgc = parseClusterConfigXml((Element ) entry.getValue()); 219 conf.setClusterConfig(jgc); 220 } 221 else 222 { 223 throw new ConfigurationException("Unknown configuration element " + propname); 224 } 225 } 226 } 227 228 public static BuddyReplicationConfig parseBuddyReplicationConfig(Element element) 229 { 230 BuddyReplicationConfig brc = new BuddyReplicationConfig(); 231 brc.setEnabled(XmlHelper.readBooleanContents(element, "buddyReplicationEnabled")); 232 brc.setDataGravitationRemoveOnFind(XmlHelper.readBooleanContents(element, "dataGravitationRemoveOnFind", true)); 233 brc.setDataGravitationSearchBackupTrees(XmlHelper.readBooleanContents(element, "dataGravitationSearchBackupTrees", true)); 234 brc.setAutoDataGravitation(brc.isEnabled() && XmlHelper.readBooleanContents(element, "autoDataGravitation", false)); 235 236 String strBuddyCommunicationTimeout = XmlHelper.readStringContents(element, "buddyCommunicationTimeout"); 237 try 238 { 239 brc.setBuddyCommunicationTimeout(Integer.parseInt(strBuddyCommunicationTimeout)); 240 } 241 catch (Exception e) 242 { 243 } 244 finally 245 { 246 if (log.isDebugEnabled()) 247 { 248 log.debug("Using buddy communication timeout of " + brc.getBuddyCommunicationTimeout() + " millis"); 249 } 250 } 251 String buddyPoolName = XmlHelper.readStringContents(element, "buddyPoolName"); 252 if ("".equals(buddyPoolName)) 253 { 254 buddyPoolName = null; 255 } 256 257 brc.setBuddyPoolName(buddyPoolName); 258 259 261 String buddyLocatorClass = XmlHelper.readStringContents(element, "buddyLocatorClass"); 262 if (buddyLocatorClass == null || buddyLocatorClass.length() == 0) 263 { 264 buddyLocatorClass = NextMemberBuddyLocator.class.getName(); 265 } 266 Properties props = null; 267 try 268 { 269 props = XmlHelper.readPropertiesContents(element, "buddyLocatorProperties"); 270 } 271 catch (IOException e) 272 { 273 log.warn("Caught exception reading buddyLocatorProperties", e); 274 log.error("Unable to read buddyLocatorProperties specified! Using defaults for [" + buddyLocatorClass + "]"); 275 } 276 BuddyLocatorConfig blc = new BuddyLocatorConfig(); 277 blc.setBuddyLocatorClass(buddyLocatorClass); 278 blc.setBuddyLocatorProperties(props); 279 brc.setBuddyLocatorConfig(blc); 280 281 return brc; 282 } 283 284 public static CacheLoaderConfig parseCacheLoaderConfig(Element element) 285 { 286 CacheLoaderConfig clc = new CacheLoaderConfig(); 287 clc.setPassivation(XmlHelper.readBooleanContents(element, "passivation")); 288 clc.setPreload(XmlHelper.readStringContents(element, "preload")); 289 clc.setShared(XmlHelper.readBooleanContents(element, "shared")); 290 291 NodeList cacheLoaderNodes = element.getElementsByTagName("cacheloader"); 292 for (int i = 0; i < cacheLoaderNodes.getLength(); i++) 293 { 294 Node node = cacheLoaderNodes.item(i); 295 if (node.getNodeType() == Node.ELEMENT_NODE) 296 { 297 Element indivElement = (Element ) node; 298 CacheLoaderConfig.IndividualCacheLoaderConfig iclc = new CacheLoaderConfig.IndividualCacheLoaderConfig(); 299 iclc.setAsync(XmlHelper.readBooleanContents(indivElement, "async", false)); 300 iclc.setIgnoreModifications(XmlHelper.readBooleanContents(indivElement, "ignoreModifications", false)); 301 iclc.setFetchPersistentState(XmlHelper.readBooleanContents(indivElement, "fetchPersistentState", false)); 302 iclc.setPurgeOnStartup(XmlHelper.readBooleanContents(indivElement, "purgeOnStartup", false)); 303 iclc.setClassName(XmlHelper.readStringContents(indivElement, "class")); 304 try 305 { 306 iclc.setProperties(XmlHelper.readPropertiesContents(indivElement, "properties")); 307 } 308 catch (IOException e) 309 { 310 throw new ConfigurationException("Problem loader cache loader properties", e); 311 } 312 iclc.setSingletonStore(XmlHelper.readBooleanContents(indivElement, "singletonStore", false)); 313 iclc.setPushStateWhenCoordinator(XmlHelper.readBooleanAttribute(indivElement, "singletonStore", "pushStateWhenCoordinator", false)); 314 clc.addIndividualCacheLoaderConfig(iclc); 315 } 316 } 317 318 return clc; 319 } 320 321 public static EvictionConfig parseEvictionConfig(Element element, String defaultEvictionClass) 322 { 323 EvictionConfig ec = new EvictionConfig(); 324 325 ec.setDefaultEvictionPolicyClass(defaultEvictionClass); 326 327 if (element != null) 328 { 329 String temp = XmlHelper.getTagContents(element, 332 EvictionConfig.EVICTION_POLICY_CLASS, ATTR, NAME); 333 if (temp != null && temp.length() > 0) 334 { 335 defaultEvictionClass = temp; 336 ec.setDefaultEvictionPolicyClass(defaultEvictionClass); 337 } 338 339 temp = XmlHelper.getTagContents(element, 340 EvictionConfig.WAKEUP_INTERVAL_SECONDS, ATTR, NAME); 341 342 int wakeupIntervalSeconds = 0; 343 if (temp != null) 344 { 345 wakeupIntervalSeconds = Integer.parseInt(temp); 346 } 347 348 if (wakeupIntervalSeconds <= 0) 349 { 350 wakeupIntervalSeconds = EvictionConfig.WAKEUP_DEFAULT; 351 } 352 353 ec.setWakeupIntervalSeconds(wakeupIntervalSeconds); 354 355 int eventQueueSize = 0; 356 temp = XmlHelper.getTagContents(element, 357 EvictionConfig.EVENT_QUEUE_SIZE, ATTR, NAME); 358 359 if (temp != null) 360 { 361 eventQueueSize = Integer.parseInt(temp); 362 } 363 364 if (eventQueueSize <= 0) 365 { 366 eventQueueSize = EvictionConfig.EVENT_QUEUE_SIZE_DEFAULT; 367 } 368 369 ec.setDefaultEventQueueSize(eventQueueSize); 370 371 NodeList list = element.getElementsByTagName(EvictionRegionConfig.REGION); 372 if (list != null && list.getLength() > 0) 373 { 374 List regionConfigs = new ArrayList (list.getLength()); 375 for (int i = 0; i < list.getLength(); i++) 376 { 377 org.w3c.dom.Node node = list.item(i); 378 if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) 379 { 380 continue; 381 } 382 try 383 { 384 regionConfigs.add(parseEvictionRegionConfig((Element ) node, defaultEvictionClass, eventQueueSize)); 385 } 386 catch (MissingPolicyException ignored) 387 { 388 LogFactory.getLog(EvictionConfig.class).warn(ignored.getLocalizedMessage()); 392 } 393 } 394 395 ec.setEvictionRegionConfigs(regionConfigs); 396 } 397 } 398 399 return ec; 400 401 } 402 403 public static EvictionRegionConfig parseEvictionRegionConfig(Element element, 404 String defaultEvictionClass, 405 int defaultQueueCapacity) 406 { 407 EvictionRegionConfig erc = new EvictionRegionConfig(); 408 409 erc.setRegionName(element.getAttribute(EvictionRegionConfig.NAME)); 410 411 String temp = element.getAttribute(EvictionRegionConfig.EVENT_QUEUE_SIZE); 412 if (temp != null && temp.length() > 0) 413 { 414 erc.setEventQueueSize(Integer.parseInt(temp)); 415 } 416 else 417 { 418 erc.setEventQueueSize(defaultQueueCapacity); 419 } 420 421 String evictionClass = element.getAttribute(EvictionRegionConfig.REGION_POLICY_CLASS); 422 if (evictionClass == null || evictionClass.length() == 0) 423 { 424 evictionClass = defaultEvictionClass; 425 if (evictionClass == null || evictionClass.length() == 0) 427 { 428 throw new MissingPolicyException( 429 "There is no Eviction Policy Class specified on the region or for the entire cache!"); 430 } 431 } 432 433 EvictionPolicy policy = null; 434 try 435 { 436 policy = (EvictionPolicy) Util.loadClass(evictionClass).newInstance(); 437 } 438 catch (RuntimeException e) 439 { 440 throw e; 441 } 442 catch (Exception e) 443 { 444 throw new RuntimeException ("Eviction class is not properly loaded in classloader", e); 445 } 446 447 EvictionPolicyConfig epc = null; 448 try 449 { 450 epc = policy.getEvictionConfigurationClass().newInstance(); 451 } 452 catch (RuntimeException e) 453 { 454 throw e; 455 } 456 catch (Exception e) 457 { 458 throw new RuntimeException ("Failed to instantiate eviction configuration of class " + 459 policy.getEvictionConfigurationClass(), e); 460 } 461 462 parseEvictionPolicyConfig(element, epc); 463 464 erc.setEvictionPolicyConfig(epc); 465 466 return erc; 467 } 468 469 public static void parseEvictionPolicyConfig(Element element, EvictionPolicyConfig target) 470 { 471 target.reset(); 472 ParsedAttributes attributes = extractAttributes(element); 473 setValues(target, attributes.stringAttribs, false); 474 setValues(target, attributes.xmlAttribs, true); 475 target.validate(); 476 } 477 478 483 public static String parseClusterConfigXml(Element config) 484 { 485 StringBuffer buffer = new StringBuffer (); 486 NodeList stack = config.getChildNodes(); 487 int length = stack.getLength(); 488 489 for (int s = 0; s < length; s++) 490 { 491 org.w3c.dom.Node node = stack.item(s); 492 if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) 493 { 494 continue; 495 } 496 497 Element tag = (Element ) node; 498 String protocol = tag.getTagName(); 499 buffer.append(protocol); 500 NamedNodeMap attrs = tag.getAttributes(); 501 int attrLength = attrs.getLength(); 502 if (attrLength > 0) 503 { 504 buffer.append('('); 505 } 506 for (int a = 0; a < attrLength; a++) 507 { 508 Attr attr = (Attr ) attrs.item(a); 509 String name = attr.getName(); 510 String value = attr.getValue(); 511 buffer.append(name); 512 buffer.append('='); 513 buffer.append(value); 514 if (a < attrLength - 1) 515 { 516 buffer.append(';'); 517 } 518 } 519 if (attrLength > 0) 520 { 521 buffer.append(')'); 522 } 523 buffer.append(':'); 524 } 525 buffer.setLength(buffer.length() - 1); 527 return buffer.toString(); 528 } 529 530 protected static ParsedAttributes extractAttributes(Element source) 531 { 532 Map <String , String > stringAttribs = new HashMap <String , String >(); 533 Map <String , Element > xmlAttribs = new HashMap <String , Element >(); 534 NodeList list = source.getElementsByTagName(XmlHelper.ATTR); 535 if (log.isDebugEnabled()) log.debug("Attribute size: " + list.getLength()); 536 537 538 for (int loop = 0; loop < list.getLength(); loop++) 540 { 541 Node node = list.item(loop); 542 if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) continue; 543 544 Element element = (Element ) node; 546 String name = element.getAttribute(XmlHelper.NAME); 547 String valueStr = XmlHelper.getElementContent(element, true); 548 549 Element valueXml = null; 550 if (valueStr.length() == 0) 551 { 552 valueXml = XmlHelper.getConfigSubElement(element); 554 } 555 556 558 if (valueStr.length() > 0) stringAttribs.put(name, valueStr); 559 if (valueXml != null) xmlAttribs.put(name, valueXml); 560 } 561 562 return new ParsedAttributes(stringAttribs, xmlAttribs); 563 } 564 565 private static String getSetterName(String propName) 566 { 567 StringBuffer sb = new StringBuffer ("set"); 568 if (propName != null && propName.length() > 0) 569 { 570 sb.append(propName.substring(0, 1).toUpperCase()); 571 if (propName.length() > 1) 572 { 573 sb.append(propName.substring(1)); 574 } 575 } 576 return sb.toString(); 577 } 578 579 static class ParsedAttributes 580 { 581 Map <String , String > stringAttribs; 582 Map <String , Element > xmlAttribs; 583 584 ParsedAttributes(Map strings, Map elements) 585 { 586 this.stringAttribs = strings; 587 this.xmlAttribs = elements; 588 } 589 } 590 } 591 | Popular Tags |