1 17 18 package org.apache.avalon.extension.manager.impl; 19 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.util.ArrayList ; 23 import java.util.Collections ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 import java.util.StringTokenizer ; 28 import java.util.jar.JarFile ; 29 import java.util.jar.Manifest ; 30 31 import org.apache.avalon.extension.Extension; 32 import org.apache.avalon.extension.manager.ExtensionManager; 33 import org.apache.avalon.extension.manager.OptionalPackage; 34 35 46 public class DefaultExtensionManager 47 implements ExtensionManager 48 { 49 private static final boolean DEBUG = false; 50 51 54 private static final String SEPARATOR = "|"; 55 56 59 private final Map m_packages = new HashMap (); 60 61 64 private File [] m_path; 65 66 70 private boolean m_needToScan; 71 72 75 public DefaultExtensionManager() 76 { 77 this( new File [ 0 ] ); 78 } 79 80 85 public DefaultExtensionManager( final File [] path ) 86 { 87 setPath( path ); 88 } 89 90 98 public File [] getPaths() 99 { 100 return m_path; 101 } 102 103 114 public synchronized OptionalPackage[] getOptionalPackages( final Extension extension ) 115 { 116 if( m_needToScan ) 117 { 118 scanPath(); 119 } 120 121 final ArrayList results = new ArrayList (); 122 final ArrayList candidates = (ArrayList )m_packages.get( extension.getExtensionName() ); 123 if( null != candidates ) 124 { 125 final int size = candidates.size(); 126 for( int i = 0; i < size; i++ ) 127 { 128 final OptionalPackage optionalPackage = (OptionalPackage)candidates.get( i ); 129 final Extension[] extensions = optionalPackage.getAvailableExtensions(); 130 131 for( int j = 0; j < extensions.length; j++ ) 132 { 133 if( extensions[ j ].isCompatibleWith( extension ) ) 134 { 135 results.add( optionalPackage ); 136 } 137 } 138 } 139 } 140 141 final OptionalPackageComparator comparator = 142 new OptionalPackageComparator( extension.getExtensionName() ); 143 Collections.sort( results, comparator ); 144 return (OptionalPackage[])results.toArray( new OptionalPackage[ 0 ] ); 145 } 146 147 152 protected synchronized OptionalPackage[] getAllOptionalPackages() 153 { 154 final ArrayList packages = new ArrayList (); 156 final Iterator iterator = m_packages.values().iterator(); 157 while( iterator.hasNext() ) 158 { 159 final ArrayList list = (ArrayList )iterator.next(); 160 final int size = list.size(); 161 for( int i = 0; i < size; i++ ) 162 { 163 final OptionalPackage optionalPackage = (OptionalPackage)list.get( i ); 164 if( !packages.contains( optionalPackage ) ) 165 { 166 packages.add( optionalPackage ); 167 } 168 } 169 } 170 171 return (OptionalPackage[])packages.toArray( new OptionalPackage[ packages.size() ] ); 172 } 173 174 179 protected void addPathElements( final String [] pathElements ) 180 { 181 final File [] path = toFiles( pathElements ); 182 addPathElements( path ); 183 } 184 185 190 protected synchronized void addPathElements( final File [] path ) 191 { 192 validatePath( path ); 193 final File [] files = resolvePath( path ); 194 m_path = mergePaths( files ); 195 m_needToScan = true; 196 } 197 198 204 protected void addPathElements( final String pathString ) 205 { 206 final String [] pathElements = split( pathString, SEPARATOR ); 207 addPathElements( pathElements ); 208 } 209 210 216 protected synchronized void setPath( final String pathString ) 217 { 218 final String [] pathElements = split( pathString, SEPARATOR ); 219 setPath( pathElements ); 220 } 221 222 227 protected synchronized void setPath( final String [] pathElements ) 228 { 229 final File [] path = toFiles( pathElements ); 230 setPath( path ); 231 } 232 233 238 protected synchronized void setPath( final File [] path ) 239 { 240 validatePath( path ); 241 m_path = resolvePath( path ); 242 m_needToScan = true; 243 } 244 245 251 protected final synchronized void scanPath() 252 { 253 clearCache(); 254 255 for( int i = 0; i < m_path.length; i++ ) 256 { 257 scanDirectory( m_path[ i ] ); 258 } 259 } 260 261 268 private synchronized void scanDirectory( final File directory ) 269 { 270 final File [] files = directory.listFiles(); 271 for( int i = 0; i < files.length; i++ ) 272 { 273 final File file = files[ i ]; 274 final String name = file.getName(); 275 276 if( !name.endsWith( ".jar" ) ) 277 { 278 final String message = 279 "Skipping " + file + " as it does not end with '.jar'"; 280 debug( message ); 281 continue; 282 } 283 284 if( !file.isFile() ) 285 { 286 final String message = 287 "Skipping " + file + " as it is not a file."; 288 debug( message ); 289 continue; 290 } 291 292 if( !file.canRead() ) 293 { 294 final String message = 295 "Skipping " + file + " as it is not readable."; 296 debug( message ); 297 continue; 298 } 299 300 try 301 { 302 final OptionalPackage optionalPackage = getOptionalPackage( file ); 303 cacheOptionalPackage( optionalPackage ); 304 } 305 catch( final IOException ioe ) 306 { 307 final String message = 308 "Skipping " + file + " as it could not be loaded " + 309 "due to " + ioe; 310 debug( message ); 311 } 312 } 313 } 314 315 318 protected final synchronized void clearCache() 319 { 320 m_packages.clear(); 321 m_needToScan = true; 322 } 323 324 331 protected final synchronized void cacheOptionalPackage( final OptionalPackage optionalPackage ) 332 { 333 m_needToScan = false; 334 335 if( optionalPackage.getAvailableExtensions().length == 0 ) 337 { 338 return; 339 } 340 341 final Extension extension = optionalPackage.getAvailableExtensions()[ 0 ]; 342 ArrayList candidates = (ArrayList )m_packages.get( extension.getExtensionName() ); 343 if( null == candidates ) 344 { 345 candidates = new ArrayList (); 346 m_packages.put( extension.getExtensionName(), candidates ); 347 } 348 349 candidates.add( optionalPackage ); 350 } 351 352 359 private OptionalPackage getOptionalPackage( final File archive ) 360 throws IOException 361 { 362 final File file = archive.getCanonicalFile(); 363 final JarFile jarFile = new JarFile ( file ); 364 try 365 { 366 final Manifest manifest = jarFile.getManifest(); 367 if( null == manifest ) 368 { 369 return null; 370 } 371 final Extension[] available = Extension.getAvailable( manifest ); 372 final Extension[] required = Extension.getRequired( manifest ); 373 374 return new OptionalPackage( file, available, required ); 375 } 376 finally 377 { 378 jarFile.close(); 379 } 380 } 381 382 387 protected void debug( final String message ) 388 { 389 if( DEBUG ) 390 { 391 System.out.println( message ); 392 } 393 } 394 395 402 private File [] resolvePath( final File [] path ) 403 { 404 final File [] resultPath = new File [ path.length ]; 405 for( int i = 0; i < path.length; i++ ) 406 { 407 resultPath[ i ] = resolveFile( path[ i ] ); 408 } 409 return resultPath; 410 } 411 412 419 private File resolveFile( final File file ) 420 { 421 try 422 { 423 return file.getCanonicalFile(); 424 } 425 catch( IOException e ) 426 { 427 return file.getAbsoluteFile(); 428 } 429 } 430 431 436 private void validatePath( final File [] path ) 437 { 438 if( null == path ) 439 { 440 throw new NullPointerException ( "path" ); 441 } 442 443 for( int i = 0; i < path.length; i++ ) 444 { 445 validatePathElement( path[ i ] ); 446 } 447 } 448 449 455 private void validatePathElement( final File file ) 456 { 457 if( !file.exists() || !file.isDirectory() ) 458 { 459 final String message = "path element " + file + 460 " must exist and must be a directory"; 461 throw new IllegalArgumentException ( message ); 462 } 463 } 464 465 471 private File [] mergePaths( final File [] files ) 472 { 473 final File [] resultPath = 474 new File [ m_path.length + files.length ]; 475 System.arraycopy( m_path, 0, resultPath, 0, m_path.length ); 476 System.arraycopy( files, m_path.length, resultPath, 0, files.length ); 477 return resultPath; 478 } 479 480 486 private File [] toFiles( final String [] pathElements ) 487 { 488 final File [] path = new File [ pathElements.length ]; 489 for( int i = 0; i < path.length; i++ ) 490 { 491 path[ i ] = new File ( pathElements[ i ] ); 492 } 493 return path; 494 } 495 496 503 private static String [] split( final String string, final String onToken ) 504 { 505 final StringTokenizer tokenizer = new StringTokenizer ( string, onToken ); 506 final String [] result = new String [ tokenizer.countTokens() ]; 507 508 for( int i = 0; i < result.length; i++ ) 509 { 510 result[ i ] = tokenizer.nextToken(); 511 } 512 513 return result; 514 } 515 } 516 | Popular Tags |