1 18 package org.apache.tools.ant.taskdefs.optional.extension; 19 20 import java.text.ParseException ; 21 import java.util.ArrayList ; 22 import java.util.Arrays ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 import java.util.jar.Attributes ; 26 import java.util.jar.Manifest ; 27 28 import org.apache.tools.ant.util.StringUtils; 29 30 41 public final class Specification { 42 43 private static final String MISSING = "Missing "; 44 45 48 public static final Attributes.Name SPECIFICATION_TITLE 49 = Attributes.Name.SPECIFICATION_TITLE; 50 51 54 public static final Attributes.Name SPECIFICATION_VERSION 55 = Attributes.Name.SPECIFICATION_VERSION; 56 57 60 public static final Attributes.Name SPECIFICATION_VENDOR 61 = Attributes.Name.SPECIFICATION_VENDOR; 62 63 66 public static final Attributes.Name IMPLEMENTATION_TITLE 67 = Attributes.Name.IMPLEMENTATION_TITLE; 68 69 72 public static final Attributes.Name IMPLEMENTATION_VERSION 73 = Attributes.Name.IMPLEMENTATION_VERSION; 74 75 78 public static final Attributes.Name IMPLEMENTATION_VENDOR 79 = Attributes.Name.IMPLEMENTATION_VENDOR; 80 81 85 public static final Compatibility COMPATIBLE = 86 new Compatibility("COMPATIBLE"); 87 88 92 public static final Compatibility REQUIRE_SPECIFICATION_UPGRADE = 93 new Compatibility("REQUIRE_SPECIFICATION_UPGRADE"); 94 95 99 public static final Compatibility REQUIRE_VENDOR_SWITCH = 100 new Compatibility("REQUIRE_VENDOR_SWITCH"); 101 102 106 public static final Compatibility REQUIRE_IMPLEMENTATION_CHANGE = 107 new Compatibility("REQUIRE_IMPLEMENTATION_CHANGE"); 108 109 115 public static final Compatibility INCOMPATIBLE = 116 new Compatibility("INCOMPATIBLE"); 117 118 121 private String specificationTitle; 122 123 127 private DeweyDecimal specificationVersion; 128 129 133 private String specificationVendor; 134 135 138 private String implementationTitle; 139 140 144 private String implementationVendor; 145 146 150 private String implementationVersion; 151 152 155 private String [] sections; 156 157 166 public static Specification[] getSpecifications(final Manifest manifest) 167 throws ParseException { 168 if (null == manifest) { 169 return new Specification[ 0 ]; 170 } 171 172 final ArrayList results = new ArrayList (); 173 174 final Map entries = manifest.getEntries(); 175 final Iterator keys = entries.keySet().iterator(); 176 while (keys.hasNext()) { 177 final String key = (String ) keys.next(); 178 final Attributes attributes = (Attributes ) entries.get(key); 179 final Specification specification 180 = getSpecification(key, attributes); 181 if (null != specification) { 182 results.add(specification); 183 } 184 } 185 186 final ArrayList trimmedResults = removeDuplicates(results); 187 return (Specification[]) trimmedResults.toArray(new Specification[trimmedResults.size()]); 188 } 189 190 202 public Specification(final String specificationTitle, 203 final String specificationVersion, 204 final String specificationVendor, 205 final String implementationTitle, 206 final String implementationVersion, 207 final String implementationVendor) { 208 this(specificationTitle, specificationVersion, specificationVendor, 209 implementationTitle, implementationVersion, implementationVendor, 210 null); 211 } 212 213 226 public Specification(final String specificationTitle, 227 final String specificationVersion, 228 final String specificationVendor, 229 final String implementationTitle, 230 final String implementationVersion, 231 final String implementationVendor, 232 final String [] sections) { 233 this.specificationTitle = specificationTitle; 234 this.specificationVendor = specificationVendor; 235 236 if (null != specificationVersion) { 237 try { 238 this.specificationVersion 239 = new DeweyDecimal(specificationVersion); 240 } catch (final NumberFormatException nfe) { 241 final String error = "Bad specification version format '" 242 + specificationVersion + "' in '" + specificationTitle 243 + "'. (Reason: " + nfe + ")"; 244 throw new IllegalArgumentException (error); 245 } 246 } 247 248 this.implementationTitle = implementationTitle; 249 this.implementationVendor = implementationVendor; 250 this.implementationVersion = implementationVersion; 251 252 if (null == this.specificationTitle) { 253 throw new NullPointerException ("specificationTitle"); 254 } 255 256 String [] copy = null; 257 if (null != sections) { 258 copy = new String [ sections.length ]; 259 System.arraycopy(sections, 0, copy, 0, sections.length); 260 } 261 this.sections = copy; 262 } 263 264 269 public String getSpecificationTitle() { 270 return specificationTitle; 271 } 272 273 278 public String getSpecificationVendor() { 279 return specificationVendor; 280 } 281 282 287 public String getImplementationTitle() { 288 return implementationTitle; 289 } 290 291 296 public DeweyDecimal getSpecificationVersion() { 297 return specificationVersion; 298 } 299 300 305 public String getImplementationVendor() { 306 return implementationVendor; 307 } 308 309 314 public String getImplementationVersion() { 315 return implementationVersion; 316 } 317 318 325 public String [] getSections() { 326 if (null == sections) { 327 return null; 328 } 329 final String [] newSections = new String [ sections.length ]; 330 System.arraycopy(sections, 0, newSections, 0, sections.length); 331 return newSections; 332 } 333 334 343 public Compatibility getCompatibilityWith(final Specification other) { 344 if (!specificationTitle.equals(other.getSpecificationTitle())) { 346 return INCOMPATIBLE; 347 } 348 349 final DeweyDecimal otherSpecificationVersion 351 = other.getSpecificationVersion(); 352 if (null != specificationVersion) { 353 if (null == otherSpecificationVersion 354 || !isCompatible(specificationVersion, otherSpecificationVersion)) { 355 return REQUIRE_SPECIFICATION_UPGRADE; 356 } 357 } 358 359 final String otherImplementationVendor 361 = other.getImplementationVendor(); 362 if (null != implementationVendor) { 363 if (null == otherImplementationVendor 364 || !implementationVendor.equals(otherImplementationVendor)) { 365 return REQUIRE_VENDOR_SWITCH; 366 } 367 } 368 369 final String otherImplementationVersion 371 = other.getImplementationVersion(); 372 if (null != implementationVersion) { 373 if (null == otherImplementationVersion 374 || !implementationVersion.equals(otherImplementationVersion)) { 375 return REQUIRE_IMPLEMENTATION_CHANGE; 376 } 377 } 378 379 return COMPATIBLE; 381 } 382 383 391 public boolean isCompatibleWith(final Specification other) { 392 return (COMPATIBLE == getCompatibilityWith(other)); 393 } 394 395 400 public String toString() { 401 final String brace = ": "; 402 403 final StringBuffer sb 404 = new StringBuffer (SPECIFICATION_TITLE.toString()); 405 sb.append(brace); 406 sb.append(specificationTitle); 407 sb.append(StringUtils.LINE_SEP); 408 409 if (null != specificationVersion) { 410 sb.append(SPECIFICATION_VERSION); 411 sb.append(brace); 412 sb.append(specificationVersion); 413 sb.append(StringUtils.LINE_SEP); 414 } 415 416 if (null != specificationVendor) { 417 sb.append(SPECIFICATION_VENDOR); 418 sb.append(brace); 419 sb.append(specificationVendor); 420 sb.append(StringUtils.LINE_SEP); 421 } 422 423 if (null != implementationTitle) { 424 sb.append(IMPLEMENTATION_TITLE); 425 sb.append(brace); 426 sb.append(implementationTitle); 427 sb.append(StringUtils.LINE_SEP); 428 } 429 430 if (null != implementationVersion) { 431 sb.append(IMPLEMENTATION_VERSION); 432 sb.append(brace); 433 sb.append(implementationVersion); 434 sb.append(StringUtils.LINE_SEP); 435 } 436 437 if (null != implementationVendor) { 438 sb.append(IMPLEMENTATION_VENDOR); 439 sb.append(brace); 440 sb.append(implementationVendor); 441 sb.append(StringUtils.LINE_SEP); 442 } 443 444 return sb.toString(); 445 } 446 447 454 private boolean isCompatible(final DeweyDecimal first, 455 final DeweyDecimal second) { 456 return first.isGreaterThanOrEqual(second); 457 } 458 459 469 private static ArrayList removeDuplicates(final ArrayList list) { 470 final ArrayList results = new ArrayList (); 471 final ArrayList sections = new ArrayList (); 472 while (list.size() > 0) { 473 final Specification specification = (Specification) list.remove(0); 474 final Iterator iterator = list.iterator(); 475 while (iterator.hasNext()) { 476 final Specification other = (Specification) iterator.next(); 477 if (isEqual(specification, other)) { 478 final String [] otherSections = other.getSections(); 479 if (null != sections) { 480 sections.addAll(Arrays.asList(otherSections)); 481 } 482 iterator.remove(); 483 } 484 } 485 486 final Specification merged = 487 mergeInSections(specification, sections); 488 results.add(merged); 489 sections.clear(); 491 } 492 493 return results; 494 } 495 496 504 private static boolean isEqual(final Specification specification, 505 final Specification other) { 506 return 507 specification.getSpecificationTitle().equals(other.getSpecificationTitle()) 508 && specification.getSpecificationVersion().isEqual(other.getSpecificationVersion()) 509 && specification.getSpecificationVendor().equals(other.getSpecificationVendor()) 510 && specification.getImplementationTitle().equals(other.getImplementationTitle()) 511 && specification.getImplementationVersion().equals(other.getImplementationVersion()) 512 && specification.getImplementationVendor().equals(other.getImplementationVendor()); 513 } 514 515 523 private static Specification mergeInSections(final Specification specification, 524 final ArrayList sectionsToAdd) { 525 if (0 == sectionsToAdd.size()) { 526 return specification; 527 } 528 sectionsToAdd.addAll(Arrays.asList(specification.getSections())); 529 530 final String [] sections = 531 (String []) sectionsToAdd.toArray(new String [sectionsToAdd.size()]); 532 533 return new Specification(specification.getSpecificationTitle(), 534 specification.getSpecificationVersion().toString(), 535 specification.getSpecificationVendor(), 536 specification.getImplementationTitle(), 537 specification.getImplementationVersion(), 538 specification.getImplementationVendor(), 539 sections); 540 } 541 542 548 private static String getTrimmedString(final String value) { 549 return value == null ? null : value.trim(); 550 } 551 552 558 private static Specification getSpecification(final String section, 559 final Attributes attributes) 560 throws ParseException { 561 final String name 565 = getTrimmedString(attributes.getValue(SPECIFICATION_TITLE)); 566 if (null == name) { 567 return null; 568 } 569 570 final String specVendor 571 = getTrimmedString(attributes.getValue(SPECIFICATION_VENDOR)); 572 if (null == specVendor) { 573 throw new ParseException (MISSING + SPECIFICATION_VENDOR, 0); 574 } 575 576 final String specVersion 577 = getTrimmedString(attributes.getValue(SPECIFICATION_VERSION)); 578 if (null == specVersion) { 579 throw new ParseException (MISSING + SPECIFICATION_VERSION, 0); 580 } 581 582 final String impTitle 583 = getTrimmedString(attributes.getValue(IMPLEMENTATION_TITLE)); 584 if (null == impTitle) { 585 throw new ParseException (MISSING + IMPLEMENTATION_TITLE, 0); 586 } 587 588 final String impVersion 589 = getTrimmedString(attributes.getValue(IMPLEMENTATION_VERSION)); 590 if (null == impVersion) { 591 throw new ParseException (MISSING + IMPLEMENTATION_VERSION, 0); 592 } 593 594 final String impVendor 595 = getTrimmedString(attributes.getValue(IMPLEMENTATION_VENDOR)); 596 if (null == impVendor) { 597 throw new ParseException (MISSING + IMPLEMENTATION_VENDOR, 0); 598 } 599 600 return new Specification(name, specVersion, specVendor, 601 impTitle, impVersion, impVendor, 602 new String []{section}); 603 } 604 } 605 | Popular Tags |