1 37 package net.sourceforge.cruisecontrol; 38 39 import java.util.ArrayList ; 40 import java.util.Collection ; 41 import java.util.HashMap ; 42 import java.util.HashSet ; 43 import java.util.Iterator ; 44 import java.util.Map ; 45 import java.util.Properties ; 46 import java.util.Set ; 47 import java.util.TreeMap ; 48 49 import net.sourceforge.cruisecontrol.labelincrementers.DefaultLabelIncrementer; 50 51 import org.apache.log4j.Logger; 52 import org.jdom.Element; 53 54 58 public class CruiseControlConfig implements SelfConfiguringPlugin { 59 private static final Logger LOG = Logger.getLogger(CruiseControlConfig.class); 60 61 public static final String LABEL_INCREMENTER = "labelincrementer"; 62 63 public static final boolean FAIL_UPON_MISSING_PROPERTY = false; 64 65 private static final Set KNOWN_ROOT_CHILD_NAMES = new HashSet (); 66 static { 67 KNOWN_ROOT_CHILD_NAMES.add("property"); 68 KNOWN_ROOT_CHILD_NAMES.add("plugin"); 69 KNOWN_ROOT_CHILD_NAMES.add("system"); 70 } 71 72 static class MapWithParent implements Map { 76 private Map parent; 77 private Map thisMap; 78 79 MapWithParent(Map parent) { 80 this.parent = parent; 81 this.thisMap = new HashMap (); 82 } 83 84 public int size() { 85 int size = thisMap.size(); 86 if (parent != null) { 87 Set keys = parent.keySet(); 88 for (Iterator iterator = keys.iterator(); iterator.hasNext();) { 89 String key = (String ) iterator.next(); 90 if (!thisMap.containsKey(key)) { 91 size++; 92 } 93 } 94 } 95 return size; 96 } 97 98 public boolean isEmpty() { 99 boolean parentIsEmpty = parent == null || parent.isEmpty(); 100 return parentIsEmpty && thisMap.isEmpty(); 101 } 102 103 public boolean containsKey(Object key) { 104 return thisMap.containsKey(key) 105 || (parent != null && parent.containsKey(key)); 106 } 107 108 public boolean containsValue(Object value) { 109 return thisMap.containsValue(value) 110 || (parent != null && parent.containsValue(value)); 111 } 112 113 public Object get(Object key) { 114 Object value = thisMap.get(key); 115 if (value == null && parent != null) { 116 value = parent.get(key); 117 } 118 return value; 119 } 120 121 public Object put(Object o, Object o1) { 122 return thisMap.put(o, o1); 123 } 124 125 public Object remove(Object key) { 126 throw new UnsupportedOperationException ("'remove' not supported on MapWithParent"); 127 } 128 129 public void putAll(Map map) { 130 thisMap.putAll(map); 131 } 132 133 public void clear() { 134 throw new UnsupportedOperationException ("'clear' not supported on MapWithParent"); 135 } 136 137 public Set keySet() { 138 Set keys = new HashSet (thisMap.keySet()); 139 if (parent != null) { 140 keys.addAll(parent.keySet()); 141 } 142 return keys; 143 } 144 145 public Collection values() { 146 throw new UnsupportedOperationException ("not implemented"); 147 148 162 } 163 164 public Set entrySet() { 165 Set entries = new HashSet (thisMap.entrySet()); 166 if (parent != null) { 167 entries.addAll(parent.entrySet()); 168 } 169 return entries; 170 } 171 } 172 173 private Map rootProperties = new HashMap (); 174 private PluginRegistry rootPlugins = PluginRegistry.createRegistry(); 175 private Map projectConfigs = new TreeMap (); private ProjectNameSet projectNames = new ProjectNameSet(); private Map projectPluginRegistries = new TreeMap (); 179 180 public CruiseControlConfig() { 181 } 182 183 CruiseControlConfig(Properties globalProperties) { 185 this.rootProperties.putAll(globalProperties); 186 } 187 188 public void configure(Element rootElement) throws CruiseControlException { 189 for (Iterator i = rootElement.getChildren("property").iterator(); i.hasNext(); ) { 191 handleRootProperty((Element) i.next()); 192 } 193 for (Iterator i = rootElement.getChildren("plugin").iterator(); i.hasNext(); ) { 194 handleRootPlugin((Element) i.next()); 195 } 196 197 for (Iterator i = rootElement.getChildren().iterator(); i.hasNext(); ) { 199 Element childElement = (Element) i.next(); 200 final String nodeName = childElement.getName(); 201 if (isProject(nodeName)) { 202 handleProject(childElement); 203 } else if (!KNOWN_ROOT_CHILD_NAMES.contains(nodeName)) { 204 throw new CruiseControlException("cannot handle child of <" + nodeName + ">"); 205 } 206 } 207 } 208 209 private boolean isProject(String nodeName) throws CruiseControlException { 210 return rootPlugins.isPluginRegistered(nodeName) 211 && ProjectConfig.class.isAssignableFrom(rootPlugins.getPluginClass(nodeName)); 212 } 213 214 private void handleRootPlugin(Element pluginElement) throws CruiseControlException { 215 String pluginName = pluginElement.getAttributeValue("name"); 216 if (pluginName == null) { 217 LOG.warn("Config contains plugin without a name-attribute, ignoring it"); 218 return; 219 } 220 rootPlugins.register(pluginElement); 221 } 222 223 private void handleRootProperty(Element childElement) throws CruiseControlException { 224 ProjectXMLHelper.registerProperty(rootProperties, childElement, FAIL_UPON_MISSING_PROPERTY); 225 } 226 227 private void handleProject(Element projectElement) throws CruiseControlException { 228 229 String projectName = getProjectName(projectElement); 230 231 if (projectConfigs.containsKey(projectName)) { 232 final String duplicateEntriesMessage = "Duplicate entries in config file for project name " + projectName; 233 throw new CruiseControlException(duplicateEntriesMessage); 234 } 235 236 MapWithParent nonFullyResolvedProjectProperties = new MapWithParent(rootProperties); 242 LOG.debug("Setting property \"project.name\" to \"" + projectName + "\"."); 244 nonFullyResolvedProjectProperties.put("project.name", projectName); 245 for (Iterator projProps = projectElement.getChildren("property").iterator(); projProps.hasNext(); ) { 247 final Element propertyElement = (Element) projProps.next(); 248 ProjectXMLHelper.registerProperty(nonFullyResolvedProjectProperties, 249 propertyElement, FAIL_UPON_MISSING_PROPERTY); 250 } 251 Map thisProperties = nonFullyResolvedProjectProperties.thisMap; 253 for (Iterator iterator = rootProperties.keySet().iterator(); iterator.hasNext();) { 254 String key = (String ) iterator.next(); 255 if (!thisProperties.containsKey(key)) { 256 String value = (String ) rootProperties.get(key); 257 thisProperties.put(key, ProjectXMLHelper.parsePropertiesInString(thisProperties, value, false)); 258 } 259 } 260 261 ProjectXMLHelper.parsePropertiesInElement(projectElement, thisProperties, FAIL_UPON_MISSING_PROPERTY); 263 264 PluginRegistry projectPlugins = PluginRegistry.createRegistry(rootPlugins); 266 for (Iterator pluginIter = projectElement.getChildren("plugin").iterator(); pluginIter.hasNext(); ) { 267 projectPlugins.register((Element) pluginIter.next()); 268 } 269 270 projectElement.removeChildren("property"); 271 projectElement.removeChildren("plugin"); 272 273 LOG.debug("**************** configuring project" + projectName + " *******************"); 274 ProjectHelper projectHelper = new ProjectXMLHelper(thisProperties, projectPlugins); 275 ProjectConfig projectConfig = (ProjectConfig) projectHelper.configurePlugin(projectElement, false); 276 277 projectConfig.setProperties(thisProperties); 278 279 if (projectConfig.getLabelIncrementer() == null) { 280 LabelIncrementer labelIncrementer; 281 Class labelIncrClass = projectPlugins.getPluginClass(LABEL_INCREMENTER); 282 try { 283 labelIncrementer = (LabelIncrementer) labelIncrClass.newInstance(); 284 } catch (Exception e) { 285 LOG.error("Error instantiating label incrementer named " 286 + labelIncrClass.getName() 287 + "in project " 288 + projectName 289 + ". Using DefaultLabelIncrementer instead.", 290 e); 291 labelIncrementer = new DefaultLabelIncrementer(); 292 } 293 projectConfig.add(labelIncrementer); 294 } 295 296 Log log = projectConfig.getLog(); 297 if (log == null) { 298 log = new Log(); 299 } 300 301 log.setProjectName(projectName); 302 log.validate(); 303 projectConfig.add(log); 304 305 projectConfig.validate(); 306 LOG.debug("**************** end configuring project" + projectName + " *******************"); 307 308 this.projectConfigs.put(projectName, projectConfig); 309 projectNames.add(projectName); 310 this.projectPluginRegistries.put(projectName, projectPlugins); 311 } 312 313 private String getProjectName(Element childElement) throws CruiseControlException { 314 if (!isProject(childElement.getName())) { 315 throw new IllegalStateException ("Invalid Node <" + childElement.getName() + "> (not a project)"); 316 } 317 String rawName = childElement.getAttribute("name").getValue(); 318 return ProjectXMLHelper.parsePropertiesInString(rootProperties, rawName, false); 319 } 320 321 public ProjectConfig getConfig(String name) { 322 return (ProjectConfig) this.projectConfigs.get(name); 323 } 324 325 public Set getProjectNames() { 326 return projectNames; 329 } 330 331 PluginRegistry getRootPlugins() { 332 return rootPlugins; 333 } 334 335 PluginRegistry getProjectPlugins(String name) { 336 return (PluginRegistry) this.projectPluginRegistries.get(name); 337 } 338 339 345 private class ProjectNameSet implements Set { 346 private ArrayList list = new ArrayList (); 347 348 public int size() { 349 return list.size(); 350 } 351 352 public void clear() { 353 list.clear(); 354 } 355 356 public boolean isEmpty() { 357 return list.isEmpty(); 358 } 359 360 public Object [] toArray() { 361 return list.toArray(); 362 } 363 364 public boolean add(Object o) { 365 if (o == null) { 366 throw new IllegalArgumentException ("null not a valid project name"); 367 } 368 if (!(o instanceof String )) { 369 throw new IllegalArgumentException ("project names must be strings"); 370 } 371 if (list.contains(o)) { 372 return false; 373 } 374 list.add(o); 375 return true; 376 } 377 378 public boolean contains(Object o) { 379 return list.contains(o); 380 } 381 382 public boolean remove(Object o) { 383 return list.remove(o); 384 } 385 386 public boolean addAll(Collection c) { 387 return list.addAll(c); 388 } 389 390 public boolean containsAll(Collection c) { 391 return list.containsAll(c); 392 } 393 394 public boolean removeAll(Collection c) { 395 return list.removeAll(c); 396 } 397 398 public boolean retainAll(Collection c) { 399 return list.retainAll(c); 400 } 401 402 public Iterator iterator() { 403 return list.iterator(); 404 } 405 406 public Object [] toArray(Object [] a) { 407 return list.toArray(a); 408 } 409 410 } 411 412 } 413 | Popular Tags |