1 18 19 package org.apache.tools.ant.taskdefs; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.net.URL ; 25 import java.util.Map ; 26 import java.util.HashMap ; 27 import java.util.Enumeration ; 28 import java.util.Locale ; 29 import java.util.NoSuchElementException ; 30 import java.util.Properties ; 31 32 import org.apache.tools.ant.AntTypeDefinition; 33 import org.apache.tools.ant.ComponentHelper; 34 import org.apache.tools.ant.BuildException; 35 import org.apache.tools.ant.Project; 36 import org.apache.tools.ant.ProjectHelper; 37 import org.apache.tools.ant.MagicNames; 38 import org.apache.tools.ant.util.FileUtils; 39 import org.apache.tools.ant.types.EnumeratedAttribute; 40 41 48 public abstract class Definer extends DefBase { 49 50 54 private static final String ANTLIB_XML = "/antlib.xml"; 55 56 private static class ResourceStack extends ThreadLocal { 57 public Object initialValue() { 58 return new HashMap (); 59 } 60 Map getStack() { 61 return (Map ) get(); 62 } 63 } 64 private static ResourceStack resourceStack = new ResourceStack(); 65 private String name; 66 private String classname; 67 private File file; 68 private String resource; 69 70 private int format = Format.PROPERTIES; 71 private boolean definerSet = false; 72 private int onError = OnError.FAIL; 73 private String adapter; 74 private String adaptTo; 75 76 private Class adapterClass; 77 private Class adaptToClass; 78 79 84 public static class OnError extends EnumeratedAttribute { 85 86 public static final int FAIL = 0, REPORT = 1, IGNORE = 2, FAIL_ALL = 3; 87 88 91 public static final String POLICY_FAIL = "fail"; 92 95 public static final String POLICY_REPORT = "report"; 96 99 public static final String POLICY_IGNORE = "ignore"; 100 103 public static final String POLICY_FAILALL = "failall"; 104 105 108 public OnError() { 109 super(); 110 } 111 112 116 public OnError(String value) { 117 setValue(value); 118 } 119 120 124 public String [] getValues() { 125 return new String [] {POLICY_FAIL, POLICY_REPORT, POLICY_IGNORE, POLICY_FAILALL}; 126 } 127 } 128 129 134 public static class Format extends EnumeratedAttribute { 135 136 public static final int PROPERTIES = 0, XML = 1; 137 138 142 public String [] getValues() { 143 return new String [] {"properties", "xml"}; 144 } 145 } 146 147 157 public void setOnError(OnError onError) { 158 this.onError = onError.getIndex(); 159 } 160 161 165 public void setFormat(Format format) { 166 this.format = format.getIndex(); 167 } 168 169 172 public String getName() { 173 return name; 174 } 175 176 179 public File getFile() { 180 return file; 181 } 182 183 186 public String getResource() { 187 return resource; 188 } 189 190 191 196 public void execute() throws BuildException { 197 ClassLoader al = createLoader(); 198 199 if (!definerSet) { 200 if (getURI() == null) { 205 throw new BuildException( 206 "name, file or resource attribute of " 207 + getTaskName() + " is undefined", 208 getLocation()); 209 } 210 211 if (getURI().startsWith(MagicNames.ANTLIB_PREFIX)) { 212 String uri1 = getURI(); 214 setResource(makeResourceFromURI(uri1)); 215 } else { 216 throw new BuildException( 217 "Only antlib URIs can be located from the URI alone," 218 + "not the URI " + getURI()); 219 } 220 } 221 222 if (name != null) { 223 if (classname == null) { 224 throw new BuildException( 225 "classname attribute of " + getTaskName() + " element " 226 + "is undefined", getLocation()); 227 } 228 addDefinition(al, name, classname); 229 } else { 230 if (classname != null) { 231 String msg = "You must not specify classname " 232 + "together with file or resource."; 233 throw new BuildException(msg, getLocation()); 234 } 235 Enumeration urls = null; 236 if (file != null) { 237 final URL url = fileToURL(); 238 if (url == null) { 239 return; 240 } 241 urls = new Enumeration () { 242 private boolean more = true; 243 public boolean hasMoreElements() { 244 return more; 245 } 246 public Object nextElement() throws NoSuchElementException { 247 if (more) { 248 more = false; 249 return url; 250 } else { 251 throw new NoSuchElementException (); 252 } 253 } 254 }; 255 } else { 256 urls = resourceToURLs(al); 257 } 258 259 while (urls.hasMoreElements()) { 260 URL url = (URL ) urls.nextElement(); 261 262 int fmt = this.format; 263 if (url.toString().toLowerCase(Locale.US).endsWith(".xml")) { 264 fmt = Format.XML; 265 } 266 267 if (fmt == Format.PROPERTIES) { 268 loadProperties(al, url); 269 break; 270 } else { 271 if (resourceStack.getStack().get(url) != null) { 272 log("Warning: Recursive loading of " + url 273 + " ignored" 274 + " at " + getLocation() 275 + " originally loaded at " 276 + resourceStack.getStack().get(url), 277 Project.MSG_WARN); 278 } else { 279 try { 280 resourceStack.getStack().put(url, getLocation()); 281 loadAntlib(al, url); 282 } finally { 283 resourceStack.getStack().remove(url); 284 } 285 } 286 } 287 } 288 } 289 } 290 291 297 298 public static String makeResourceFromURI(String uri) { 299 String path = uri.substring(MagicNames.ANTLIB_PREFIX.length()); 300 String resource; 301 if (path.startsWith("//")) { 302 resource = path.substring("//".length()); 305 if (!resource.endsWith(".xml")) { 306 resource = resource + ANTLIB_XML; 308 } 309 } else { 310 resource = path.replace('.', '/') + ANTLIB_XML; 312 } 313 return resource; 314 } 315 316 324 private URL fileToURL() { 325 String message = null; 326 if (!(file.exists())) { 327 message = "File " + file + " does not exist"; 328 } 329 if (message == null && !(file.isFile())) { 330 message = "File " + file + " is not a file"; 331 } 332 try { 333 if (message == null) { 334 return file.toURL(); 335 } 336 } catch (Exception ex) { 337 message = 338 "File " + file + " cannot use as URL: " 339 + ex.toString(); 340 } 341 switch (onError) { 343 case OnError.FAIL_ALL: 344 throw new BuildException(message); 345 case OnError.FAIL: 346 case OnError.REPORT: 348 log(message, Project.MSG_WARN); 349 break; 350 case OnError.IGNORE: 351 log(message, Project.MSG_VERBOSE); 353 break; 354 default: 355 break; 357 } 358 return null; 359 } 360 361 private Enumeration resourceToURLs(ClassLoader classLoader) { 362 Enumeration ret; 363 try { 364 ret = classLoader.getResources(resource); 365 } catch (IOException e) { 366 throw new BuildException( 367 "Could not fetch resources named " + resource, 368 e, getLocation()); 369 } 370 if (!ret.hasMoreElements()) { 371 String message = "Could not load definitions from resource " 372 + resource + ". It could not be found."; 373 switch (onError) { 374 case OnError.FAIL_ALL: 375 throw new BuildException(message); 376 case OnError.FAIL: 377 case OnError.REPORT: 378 log(message, Project.MSG_WARN); 379 break; 380 case OnError.IGNORE: 381 log(message, Project.MSG_VERBOSE); 382 break; 383 default: 384 break; 386 } 387 } 388 return ret; 389 } 390 391 397 protected void loadProperties(ClassLoader al, URL url) { 398 InputStream is = null; 399 try { 400 is = url.openStream(); 401 if (is == null) { 402 log("Could not load definitions from " + url, 403 Project.MSG_WARN); 404 return; 405 } 406 Properties props = new Properties (); 407 props.load(is); 408 Enumeration keys = props.keys(); 409 while (keys.hasMoreElements()) { 410 name = ((String ) keys.nextElement()); 411 classname = props.getProperty(name); 412 addDefinition(al, name, classname); 413 } 414 } catch (IOException ex) { 415 throw new BuildException(ex, getLocation()); 416 } finally { 417 FileUtils.close(is); 418 } 419 } 420 421 427 private void loadAntlib(ClassLoader classLoader, URL url) { 428 try { 429 Antlib antlib = Antlib.createAntlib(getProject(), url, getURI()); 430 antlib.setClassLoader(classLoader); 431 antlib.setURI(getURI()); 432 antlib.execute(); 433 } catch (BuildException ex) { 434 throw ProjectHelper.addLocationToBuildException( 435 ex, getLocation()); 436 } 437 } 438 439 444 public void setFile(File file) { 445 if (definerSet) { 446 tooManyDefinitions(); 447 } 448 definerSet = true; 449 this.file = file; 450 } 451 452 457 public void setResource(String res) { 458 if (definerSet) { 459 tooManyDefinitions(); 460 } 461 definerSet = true; 462 this.resource = res; 463 } 464 465 475 public void setAntlib(String antlib) { 476 if (definerSet) { 477 tooManyDefinitions(); 478 } 479 if (!antlib.startsWith("antlib:")) { 480 throw new BuildException( 481 "Invalid antlib attribute - it must start with antlib:"); 482 } 483 setURI(antlib); 484 this.resource = antlib.substring("antlib:".length()).replace('.', '/') 485 + "/antlib.xml"; 486 definerSet = true; 487 } 488 489 493 public void setName(String name) { 494 if (definerSet) { 495 tooManyDefinitions(); 496 } 497 definerSet = true; 498 this.name = name; 499 } 500 501 506 public String getClassname() { 507 return classname; 508 } 509 510 516 public void setClassname(String classname) { 517 this.classname = classname; 518 } 519 520 530 531 public void setAdapter(String adapter) { 532 this.adapter = adapter; 533 } 534 535 540 protected void setAdapterClass(Class adapterClass) { 541 this.adapterClass = adapterClass; 542 } 543 544 551 public void setAdaptTo(String adaptTo) { 552 this.adaptTo = adaptTo; 553 } 554 555 562 protected void setAdaptToClass(Class adaptToClass) { 563 this.adaptToClass = adaptToClass; 564 } 565 566 567 575 protected void addDefinition(ClassLoader al, String name, String classname) 576 throws BuildException { 577 Class cl = null; 578 try { 579 try { 580 name = ProjectHelper.genComponentName(getURI(), name); 581 582 if (onError != OnError.IGNORE) { 583 cl = Class.forName(classname, true, al); 584 } 585 586 if (adapter != null) { 587 adapterClass = Class.forName(adapter, true, al); 588 } 589 590 if (adaptTo != null) { 591 adaptToClass = Class.forName(adaptTo, true, al); 592 } 593 594 AntTypeDefinition def = new AntTypeDefinition(); 595 def.setName(name); 596 def.setClassName(classname); 597 def.setClass(cl); 598 def.setAdapterClass(adapterClass); 599 def.setAdaptToClass(adaptToClass); 600 def.setClassLoader(al); 601 if (cl != null) { 602 def.checkClass(getProject()); 603 } 604 ComponentHelper.getComponentHelper(getProject()) 605 .addDataTypeDefinition(def); 606 } catch (ClassNotFoundException cnfe) { 607 String msg = getTaskName() + " class " + classname 608 + " cannot be found"; 609 throw new BuildException(msg, cnfe, getLocation()); 610 } catch (NoClassDefFoundError ncdfe) { 611 String msg = getTaskName() + " A class needed by class " 612 + classname + " cannot be found: " + ncdfe.getMessage(); 613 throw new BuildException(msg, ncdfe, getLocation()); 614 } 615 } catch (BuildException ex) { 616 switch (onError) { 617 case OnError.FAIL_ALL: 618 case OnError.FAIL: 619 throw ex; 620 case OnError.REPORT: 621 log(ex.getLocation() + "Warning: " + ex.getMessage(), 622 Project.MSG_WARN); 623 break; 624 default: 625 log(ex.getLocation() + ex.getMessage(), 626 Project.MSG_DEBUG); 627 } 628 } 629 } 630 631 635 private void tooManyDefinitions() { 636 throw new BuildException( 637 "Only one of the attributes name, file and resource" 638 + " can be set", getLocation()); 639 } 640 } 641 | Popular Tags |