1 17 18 package org.apache.avalon.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 41 public final class Specification 42 { 43 47 public static final Attributes.Name SPECIFICATION_TITLE = Attributes.Name.SPECIFICATION_TITLE; 48 49 53 public static final Attributes.Name SPECIFICATION_VERSION = Attributes.Name.SPECIFICATION_VERSION; 54 55 59 public static final Attributes.Name SPECIFICATION_VENDOR = Attributes.Name.SPECIFICATION_VENDOR; 60 61 65 public static final Attributes.Name IMPLEMENTATION_TITLE = Attributes.Name.IMPLEMENTATION_TITLE; 66 67 71 public static final Attributes.Name IMPLEMENTATION_VERSION = Attributes.Name.IMPLEMENTATION_VERSION; 72 73 77 public static final Attributes.Name IMPLEMENTATION_VENDOR = Attributes.Name.IMPLEMENTATION_VENDOR; 78 79 83 public static final Compatability COMPATIBLE = 84 new Compatability( "COMPATIBLE" ); 85 86 90 public static final Compatability REQUIRE_SPECIFICATION_UPGRADE = 91 new Compatability( "REQUIRE_SPECIFICATION_UPGRADE" ); 92 93 97 public static final Compatability REQUIRE_VENDOR_SWITCH = 98 new Compatability( "REQUIRE_VENDOR_SWITCH" ); 99 100 104 public static final Compatability REQUIRE_IMPLEMENTATION_CHANGE = 105 new Compatability( "REQUIRE_IMPLEMENTATION_CHANGE" ); 106 107 113 public static final Compatability INCOMPATIBLE = 114 new Compatability( "INCOMPATIBLE" ); 115 116 119 private String m_specificationTitle; 120 121 125 private DeweyDecimal m_specificationVersion; 126 127 131 private String m_specificationVendor; 132 133 136 private String m_implementationTitle; 137 138 142 private String m_implementationVendor; 143 144 148 private String m_implementationVersion; 149 150 153 private String [] m_sections; 154 155 162 public static Specification[] getSpecifications( final Manifest manifest ) 163 throws ParseException 164 { 165 if( null == manifest ) 166 { 167 return new Specification[ 0 ]; 168 } 169 170 final ArrayList results = new ArrayList (); 171 172 final Map entries = manifest.getEntries(); 173 final Iterator keys = entries.keySet().iterator(); 174 while( keys.hasNext() ) 175 { 176 final String key = (String )keys.next(); 177 final Attributes attributes = (Attributes )entries.get( key ); 178 final Specification specification = getSpecification( key, attributes ); 179 if( null != specification ) 180 { 181 results.add( specification ); 182 } 183 } 184 185 final ArrayList trimmedResults = removeDuplicates( results ); 186 return (Specification[])trimmedResults.toArray( new Specification[ 0 ] ); 187 } 188 189 201 public Specification( final String specificationTitle, 202 final String specificationVersion, 203 final String specificationVendor, 204 final String implementationTitle, 205 final String implementationVersion, 206 final String implementationVendor ) 207 { 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 { 234 m_specificationTitle = specificationTitle; 235 m_specificationVendor = specificationVendor; 236 237 if( null != specificationVersion ) 238 { 239 try 240 { 241 m_specificationVersion = new DeweyDecimal( specificationVersion ); 242 } 243 catch( final NumberFormatException nfe ) 244 { 245 250 } 256 } 257 258 m_implementationTitle = implementationTitle; 259 m_implementationVendor = implementationVendor; 260 m_implementationVersion = implementationVersion; 261 262 if( null == m_specificationTitle ) 263 { 264 throw new NullPointerException ( "specificationTitle" ); 265 } 266 267 String [] copy = null; 268 if( null != sections ) 269 { 270 copy = new String [ sections.length ]; 271 System.arraycopy( sections, 0, copy, 0, sections.length ); 272 } 273 m_sections = copy; 274 } 275 276 281 public String getSpecificationTitle() 282 { 283 return m_specificationTitle; 284 } 285 286 291 public String getSpecificationVendor() 292 { 293 return m_specificationVendor; 294 } 295 296 301 public String getImplementationTitle() 302 { 303 return m_implementationTitle; 304 } 305 306 311 public DeweyDecimal getSpecificationVersion() 312 { 313 return m_specificationVersion; 314 } 315 316 321 public String getImplementationVendor() 322 { 323 return m_implementationVendor; 324 } 325 326 331 public String getImplementationVersion() 332 { 333 return m_implementationVersion; 334 } 335 336 343 public String [] getSections() 344 { 345 if( null == m_sections ) 346 { 347 return null; 348 } 349 else 350 { 351 final String [] sections = new String [ m_sections.length ]; 352 System.arraycopy( m_sections, 0, sections, 0, m_sections.length ); 353 return sections; 354 } 355 } 356 357 365 public Compatability getCompatibilityWith( final Specification other ) 366 { 367 if( !m_specificationTitle.equals( other.getSpecificationTitle() ) ) 369 { 370 return INCOMPATIBLE; 371 } 372 373 final DeweyDecimal specificationVersion = other.getSpecificationVersion(); 375 if( null != specificationVersion ) 376 { 377 if( null == m_specificationVersion || 378 !isCompatible( m_specificationVersion, specificationVersion ) ) 379 { 380 return REQUIRE_SPECIFICATION_UPGRADE; 381 } 382 } 383 384 final String implementationVendor = other.getImplementationVendor(); 386 if( null != implementationVendor ) 387 { 388 if( null == m_implementationVendor || 389 !m_implementationVendor.equals( implementationVendor ) ) 390 { 391 return REQUIRE_VENDOR_SWITCH; 392 } 393 } 394 395 final String implementationVersion = other.getImplementationVersion(); 397 if( null != implementationVersion ) 398 { 399 if( null == m_implementationVersion || 400 !m_implementationVersion.equals( implementationVersion ) ) 401 { 402 return REQUIRE_IMPLEMENTATION_CHANGE; 403 } 404 } 405 406 return COMPATIBLE; 408 } 409 410 418 public boolean isCompatibleWith( final Specification other ) 419 { 420 return ( COMPATIBLE == getCompatibilityWith( other ) ); 421 } 422 423 428 public String toString() 429 { 430 final String lineSeparator = System.getProperty( "line.separator" ); 431 final String brace = ": "; 432 433 final StringBuffer sb = new StringBuffer ( SPECIFICATION_TITLE.toString() ); 434 sb.append( brace ); 435 sb.append( m_specificationTitle ); 436 sb.append( lineSeparator ); 437 438 if( null != m_specificationVersion ) 439 { 440 sb.append( SPECIFICATION_VERSION ); 441 sb.append( brace ); 442 sb.append( m_specificationVersion ); 443 sb.append( lineSeparator ); 444 } 445 446 if( null != m_specificationVendor ) 447 { 448 sb.append( SPECIFICATION_VENDOR ); 449 sb.append( brace ); 450 sb.append( m_specificationVendor ); 451 sb.append( lineSeparator ); 452 } 453 454 if( null != m_implementationTitle ) 455 { 456 sb.append( IMPLEMENTATION_TITLE ); 457 sb.append( brace ); 458 sb.append( m_implementationTitle ); 459 sb.append( lineSeparator ); 460 } 461 462 if( null != m_implementationVersion ) 463 { 464 sb.append( IMPLEMENTATION_VERSION ); 465 sb.append( brace ); 466 sb.append( m_implementationVersion ); 467 sb.append( lineSeparator ); 468 } 469 470 if( null != m_implementationVendor ) 471 { 472 sb.append( IMPLEMENTATION_VENDOR ); 473 sb.append( brace ); 474 sb.append( m_implementationVendor ); 475 sb.append( lineSeparator ); 476 } 477 478 return sb.toString(); 479 } 480 481 488 private boolean isCompatible( final DeweyDecimal first, final DeweyDecimal second ) 489 { 490 return first.isGreaterThanOrEqual( second ); 491 } 492 493 503 private static ArrayList removeDuplicates( final ArrayList list ) 504 { 505 final ArrayList results = new ArrayList (); 506 final ArrayList sections = new ArrayList (); 507 while( list.size() > 0 ) 508 { 509 final Specification specification = (Specification)list.remove( 0 ); 510 final Iterator iterator = list.iterator(); 511 while( iterator.hasNext() ) 512 { 513 final Specification other = (Specification)iterator.next(); 514 if( isEqual( specification, other ) ) 515 { 516 final String [] otherSections = other.getSections(); 517 if( null != sections ) 518 { 519 sections.addAll( Arrays.asList( otherSections ) ); 520 } 521 iterator.remove(); 522 } 523 } 524 525 final Specification merged = 526 mergeInSections( specification, sections ); 527 results.add( merged ); 528 sections.clear(); 530 } 531 532 return results; 533 } 534 535 543 private static boolean isEqual( final Specification specification, 544 final Specification other ) 545 { 546 return 547 specification.getSpecificationTitle().equals( other.getSpecificationTitle() ) && 548 specification.getSpecificationVersion().isEqual( other.getSpecificationVersion() ) && 549 specification.getSpecificationVendor().equals( other.getSpecificationVendor() ) && 550 specification.getImplementationTitle().equals( other.getImplementationTitle() ) && 551 specification.getImplementationVersion().equals( other.getImplementationVersion() ) && 552 specification.getImplementationVendor().equals( other.getImplementationVendor() ); 553 } 554 555 563 private static Specification mergeInSections( final Specification specification, 564 final ArrayList sectionsToAdd ) 565 { 566 if( 0 == sectionsToAdd.size() ) 567 { 568 return specification; 569 } 570 else 571 { 572 sectionsToAdd.addAll( Arrays.asList( specification.getSections() ) ); 573 574 final String [] sections = 575 (String [])sectionsToAdd.toArray( new String [ sectionsToAdd.size() ] ); 576 577 return new Specification( specification.getSpecificationTitle(), 578 specification.getSpecificationVersion().toString(), 579 specification.getSpecificationVendor(), 580 specification.getImplementationTitle(), 581 specification.getImplementationVersion(), 582 specification.getImplementationVendor(), 583 sections ); 584 } 585 } 586 587 593 private static String getTrimmedString( final String value ) 594 { 595 if( null == value ) 596 { 597 return null; 598 } 599 else 600 { 601 return value.trim(); 602 } 603 } 604 605 611 private static Specification getSpecification( final String section, 612 final Attributes attributes ) 613 throws ParseException 614 { 615 final String name = getTrimmedString( attributes.getValue( SPECIFICATION_TITLE ) ); 619 if( null == name ) 620 { 621 return null; 622 } 623 624 final String specVendor = getTrimmedString( attributes.getValue( SPECIFICATION_VENDOR ) ); 625 if( null == specVendor ) 626 { 627 throw new ParseException ( "Missing " + SPECIFICATION_VENDOR, 0 ); 628 } 629 630 final String specVersion = getTrimmedString( attributes.getValue( SPECIFICATION_VERSION ) ); 631 if( null == specVersion ) 632 { 633 throw new ParseException ( "Missing " + SPECIFICATION_VERSION, 0 ); 634 } 635 636 final String impTitle = getTrimmedString( attributes.getValue( IMPLEMENTATION_TITLE ) ); 637 if( null == impTitle ) 638 { 639 throw new ParseException ( "Missing " + IMPLEMENTATION_TITLE, 0 ); 640 } 641 642 final String impVersion = getTrimmedString( attributes.getValue( IMPLEMENTATION_VERSION ) ); 643 if( null == impVersion ) 644 { 645 throw new ParseException ( "Missing " + IMPLEMENTATION_VERSION, 0 ); 646 } 647 648 final String impVendor = getTrimmedString( attributes.getValue( IMPLEMENTATION_VENDOR ) ); 649 if( null == impVendor ) 650 { 651 throw new ParseException ( "Missing " + IMPLEMENTATION_VENDOR, 0 ); 652 } 653 654 return new Specification( name, specVersion, specVendor, 655 impTitle, impVersion, impVendor, 656 new String []{section} ); 657 } 658 } 659 | Popular Tags |