1 87 package org.codehaus.loom.components.extensions.pkgmgr.impl; 88 89 import java.io.File ; 90 import java.io.IOException ; 91 import java.util.ArrayList ; 92 import java.util.Collections ; 93 import java.util.HashMap ; 94 import java.util.Iterator ; 95 import java.util.Map ; 96 import java.util.StringTokenizer ; 97 import java.util.jar.JarFile ; 98 import java.util.jar.Manifest ; 99 100 import org.codehaus.loom.components.extensions.pkgmgr.ExtensionManager; 101 import org.codehaus.loom.components.extensions.pkgmgr.OptionalPackage; 102 import org.codehaus.loom.extension.Extension; 103 104 115 public class DefaultExtensionManager 116 implements ExtensionManager 117 { 118 private static final boolean DEBUG = false; 119 120 121 private static final String SEPARATOR = "|"; 122 123 124 private final Map m_packages = new HashMap (); 125 126 127 private File [] m_path; 128 129 133 private boolean m_needToScan; 134 135 138 public DefaultExtensionManager() 139 { 140 this( new File [ 0 ] ); 141 } 142 143 149 public DefaultExtensionManager( final File [] path ) 150 { 151 setPath( path ); 152 } 153 154 160 public File [] getPaths() 161 { 162 return m_path; 163 } 164 165 175 public synchronized OptionalPackage[] getOptionalPackages( 176 final Extension extension ) 177 { 178 if( m_needToScan ) 179 { 180 scanPath(); 181 } 182 183 final ArrayList results = new ArrayList (); 184 final ArrayList candidates = (ArrayList )m_packages.get( 185 extension.getExtensionName() ); 186 if( null != candidates ) 187 { 188 final int size = candidates.size(); 189 for( int i = 0; i < size; i++ ) 190 { 191 final OptionalPackage optionalPackage = (OptionalPackage)candidates.get( 192 i ); 193 final Extension[] extensions = optionalPackage.getAvailableExtensions(); 194 195 for( int j = 0; j < extensions.length; j++ ) 196 { 197 if( extensions[ j ].isCompatibleWith( extension ) ) 198 { 199 results.add( optionalPackage ); 200 } 201 } 202 } 203 } 204 205 final OptionalPackageComparator comparator = 206 new OptionalPackageComparator( extension.getExtensionName() ); 207 Collections.sort( results, comparator ); 208 return (OptionalPackage[])results.toArray( new OptionalPackage[ 0 ] ); 209 } 210 211 216 protected synchronized OptionalPackage[] getAllOptionalPackages() 217 { 218 final ArrayList packages = new ArrayList (); 220 final Iterator iterator = m_packages.values().iterator(); 221 while( iterator.hasNext() ) 222 { 223 final ArrayList list = (ArrayList )iterator.next(); 224 final int size = list.size(); 225 for( int i = 0; i < size; i++ ) 226 { 227 final OptionalPackage optionalPackage = (OptionalPackage)list.get( 228 i ); 229 if( !packages.contains( optionalPackage ) ) 230 { 231 packages.add( optionalPackage ); 232 } 233 } 234 } 235 236 return (OptionalPackage[])packages.toArray( 237 new OptionalPackage[ packages.size() ] ); 238 } 239 240 245 protected void addPathElements( final String [] pathElements ) 246 { 247 final File [] path = toFiles( pathElements ); 248 addPathElements( path ); 249 } 250 251 256 protected synchronized void addPathElements( final File [] path ) 257 { 258 validatePath( path ); 259 final File [] files = resolvePath( path ); 260 m_path = mergePaths( files ); 261 m_needToScan = true; 262 } 263 264 270 protected void addPathElements( final String pathString ) 271 { 272 final String [] pathElements = split( pathString, SEPARATOR ); 273 addPathElements( pathElements ); 274 } 275 276 282 protected synchronized void setPath( final String pathString ) 283 { 284 final String [] pathElements = split( pathString, SEPARATOR ); 285 setPath( pathElements ); 286 } 287 288 293 protected synchronized void setPath( final String [] pathElements ) 294 { 295 final File [] path = toFiles( pathElements ); 296 setPath( path ); 297 } 298 299 304 protected synchronized void setPath( final File [] path ) 305 { 306 validatePath( path ); 307 m_path = resolvePath( path ); 308 m_needToScan = true; 309 } 310 311 316 protected final synchronized void scanPath() 317 { 318 clearCache(); 319 320 for( int i = 0; i < m_path.length; i++ ) 321 { 322 scanDirectory( m_path[ i ] ); 323 } 324 } 325 326 332 private synchronized void scanDirectory( final File directory ) 333 { 334 final File [] files = directory.listFiles(); 335 for( int i = 0; i < files.length; i++ ) 336 { 337 final File file = files[ i ]; 338 final String name = file.getName(); 339 340 if( !name.endsWith( ".jar" ) ) 341 { 342 final String message = 343 "Skipping " + file + " as it does not end with '.jar'"; 344 debug( message ); 345 continue; 346 } 347 348 if( !file.isFile() ) 349 { 350 final String message = 351 "Skipping " + file + " as it is not a file."; 352 debug( message ); 353 continue; 354 } 355 356 if( !file.canRead() ) 357 { 358 final String message = 359 "Skipping " + file + " as it is not readable."; 360 debug( message ); 361 continue; 362 } 363 364 try 365 { 366 final OptionalPackage optionalPackage = getOptionalPackage( 367 file ); 368 cacheOptionalPackage( optionalPackage ); 369 } 370 catch( final IOException ioe ) 371 { 372 final String message = 373 "Skipping " + 374 file + 375 " as it could not be loaded " + 376 "due to " + ioe; 377 debug( message ); 378 } 379 } 380 } 381 382 385 protected final synchronized void clearCache() 386 { 387 m_packages.clear(); 388 m_needToScan = true; 389 } 390 391 398 protected final synchronized void cacheOptionalPackage( 399 final OptionalPackage optionalPackage ) 400 { 401 m_needToScan = false; 402 403 if( optionalPackage.getAvailableExtensions().length == 0 ) 405 { 406 return; 407 } 408 409 final Extension extension = optionalPackage.getAvailableExtensions()[ 0 ]; 410 ArrayList candidates = (ArrayList )m_packages.get( 411 extension.getExtensionName() ); 412 if( null == candidates ) 413 { 414 candidates = new ArrayList (); 415 m_packages.put( extension.getExtensionName(), candidates ); 416 } 417 418 candidates.add( optionalPackage ); 419 } 420 421 428 private OptionalPackage getOptionalPackage( final File archive ) 429 throws IOException 430 { 431 final File file = archive.getCanonicalFile(); 432 final JarFile jarFile = new JarFile ( file ); 433 try 434 { 435 final Manifest manifest = jarFile.getManifest(); 436 if( null == manifest ) 437 { 438 return null; 439 } 440 final Extension[] available = Extension.getAvailable( manifest ); 441 final Extension[] required = Extension.getRequired( manifest ); 442 443 return new OptionalPackage( file, available, required ); 444 } 445 finally 446 { 447 jarFile.close(); 448 } 449 } 450 451 456 protected void debug( final String message ) 457 { 458 if( DEBUG ) 459 { 460 System.out.println( message ); 461 } 462 } 463 464 471 private File [] resolvePath( final File [] path ) 472 { 473 final File [] resultPath = new File [ path.length ]; 474 for( int i = 0; i < path.length; i++ ) 475 { 476 resultPath[ i ] = resolveFile( path[ i ] ); 477 } 478 return resultPath; 479 } 480 481 487 private File resolveFile( final File file ) 488 { 489 try 490 { 491 return file.getCanonicalFile(); 492 } 493 catch( IOException e ) 494 { 495 return file.getAbsoluteFile(); 496 } 497 } 498 499 504 private void validatePath( final File [] path ) 505 { 506 if( null == path ) 507 { 508 throw new NullPointerException ( "path" ); 509 } 510 511 for( int i = 0; i < path.length; i++ ) 512 { 513 validatePathElement( path[ i ] ); 514 } 515 } 516 517 523 private void validatePathElement( final File file ) 524 { 525 if( !file.exists() || !file.isDirectory() ) 526 { 527 final String message = "path element " + 528 file + 529 " must exist and must be a directory"; 530 throw new IllegalArgumentException ( message ); 531 } 532 } 533 534 540 private File [] mergePaths( final File [] files ) 541 { 542 final File [] resultPath = 543 new File [ m_path.length + files.length ]; 544 System.arraycopy( m_path, 0, resultPath, 0, m_path.length ); 545 System.arraycopy( files, m_path.length, resultPath, 0, files.length ); 546 return resultPath; 547 } 548 549 555 private File [] toFiles( final String [] pathElements ) 556 { 557 final File [] path = new File [ pathElements.length ]; 558 for( int i = 0; i < path.length; i++ ) 559 { 560 path[ i ] = new File ( pathElements[ i ] ); 561 } 562 return path; 563 } 564 565 572 private static String [] split( final String string, final String onToken ) 573 { 574 final StringTokenizer tokenizer = new StringTokenizer ( string, 575 onToken ); 576 final String [] result = new String [ tokenizer.countTokens() ]; 577 578 for( int i = 0; i < result.length; i++ ) 579 { 580 result[ i ] = tokenizer.nextToken(); 581 } 582 583 return result; 584 } 585 } 586 | Popular Tags |