1 8 package org.codehaus.loom.classman.builder; 9 10 import java.io.File ; 11 import java.io.IOException ; 12 import java.net.JarURLConnection ; 13 import java.net.URL ; 14 import java.net.URLClassLoader ; 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.Set ; 20 import java.util.jar.Manifest ; 21 22 import org.codehaus.loom.classman.runtime.JoinClassLoader; 23 import org.codehaus.loom.extension.Extension; 24 import org.codehaus.spice.salt.i18n.ResourceManager; 25 import org.codehaus.spice.salt.i18n.Resources; 26 import org.codehaus.spice.salt.io.FileUtil; 27 import org.codehaus.spice.salt.io.PathMatcher; 28 29 42 public class SimpleLoaderResolver 43 implements LoaderResolver 44 { 45 46 private static final Resources REZ = 47 ResourceManager.getPackageResources( SimpleLoaderResolver.class ); 48 49 50 private File m_baseDirectory; 51 52 58 public SimpleLoaderResolver( final File baseDirectory ) 59 { 60 setBaseDirectory( baseDirectory ); 61 } 62 63 70 public URL resolveExtension( final Extension extension ) 71 throws Exception 72 { 73 throw new UnsupportedOperationException (); 74 } 75 76 83 public URL resolveURL( final String location ) 84 throws Exception 85 { 86 final File file = getFileFor( location ); 87 String url = file.toURL().toString(); 88 if( file.isDirectory() ) 89 { 90 url += "/"; 91 } 92 return new URL ( url ); 93 } 94 95 104 public URL [] resolveFileSet( final String baseDirectory, 105 final String [] includes, 106 final String [] excludes ) 107 throws Exception 108 { 109 final File base = getFileFor( "." ); 110 return resolveFileSet( base, baseDirectory, includes, excludes ); 111 } 112 113 121 public ClassLoader createJoinClassLoader( final ClassLoader [] classLoaders ) 122 throws Exception 123 { 124 return new JoinClassLoader( classLoaders, 125 ClassLoader.getSystemClassLoader() ); 126 } 127 128 137 public ClassLoader createClassLoader( final ClassLoader parent, 138 final URL [] urls ) 139 throws Exception 140 { 141 final URL [] classpath = determineCompleteClasspath( urls ); 142 return new URLClassLoader ( classpath, parent ); 143 } 144 145 154 protected final URL [] determineCompleteClasspath( final URL [] urls ) 155 throws Exception 156 { 157 final ArrayList classpathSet = new ArrayList (); 158 159 for( int i = 0; i < urls.length; i++ ) 161 { 162 final URL url = urls[ i ]; 163 classpathSet.add( url ); 164 } 165 166 final File [] files = getOptionalPackagesFor( urls ); 169 for( int i = 0; i < files.length; i++ ) 170 { 171 final File file = files[ i ]; 172 classpathSet.add( file.toURL() ); 173 } 174 175 return (URL [])classpathSet.toArray( new URL [ classpathSet.size() ] ); 177 } 178 179 185 protected File getFileFor( final String location ) 186 throws IOException 187 { 188 File base = getBaseDirectory(); 189 if( null == base ) 190 { 191 base = new File ( "." ); 192 } 193 194 return new File ( base, location ).getCanonicalFile(); 195 } 196 197 202 protected File getBaseDirectory() 203 { 204 return m_baseDirectory; 205 } 206 207 212 protected void setBaseDirectory( File baseDirectory ) 213 { 214 m_baseDirectory = baseDirectory; 215 } 216 217 224 protected final File [] getOptionalPackagesFor( final URL [] classPath ) 225 throws Exception 226 { 227 final Manifest [] manifests = getManifests( classPath ); 228 final Extension[] available = getAvailable( manifests ); 229 final Extension[] required = Extension.getRequired( manifests ); 230 231 if( isDebugEnabled() ) 232 { 233 final String message1 = 234 REZ.format( "available-extensions", 235 Arrays.asList( available ) ); 236 debug( message1 ); 237 final String message2 = 238 REZ.format( "required-extensions", 239 Arrays.asList( required ) ); 240 debug( message2 ); 241 } 242 243 if( 0 == required.length ) 244 { 245 return new File [ 0 ]; 246 } 247 248 final Set dependencies = new HashSet (); 249 final Set unsatisfied = new HashSet (); 250 251 scanDependencies( required, 252 available, 253 dependencies, 254 unsatisfied ); 255 256 final int size = unsatisfied.size(); 257 if( 0 != size ) 258 { 259 final Iterator iterator = unsatisfied.iterator(); 260 while( iterator.hasNext() ) 261 { 262 final Extension extension = (Extension)iterator.next(); 263 final Object [] params = new Object [] 264 { 265 extension.getExtensionName(), 266 extension.getSpecificationVendor(), 267 extension.getSpecificationVersion(), 268 extension.getImplementationVendor(), 269 extension.getImplementationVendorID(), 270 extension.getImplementationVersion(), 271 extension.getImplementationURL() 272 }; 273 final String message = REZ.format( "missing.extension", 274 params ); 275 warn( message ); 276 } 277 278 final String message = 279 REZ.format( "unsatisfied.extensions", new Integer ( size ) ); 280 throw new Exception ( message ); 281 } 282 283 if( isDebugEnabled() ) 284 { 285 final String message = 286 REZ.format( "optional-packages-added", dependencies ); 287 debug( message ); 288 } 289 290 return (File [])dependencies.toArray( new File [ dependencies.size() ] ); 291 } 292 293 294 302 private Extension[] getAvailable( final Manifest [] manifests ) 303 { 304 final ArrayList set = new ArrayList (); 305 for( int i = 0; i < manifests.length; i++ ) 306 { 307 try 308 { 309 final Extension[] extensions = Extension.getAvailable( manifests[ i ] ); 310 for( int j = 0; j < extensions.length; j++ ) 311 { 312 set.add( extensions[ j ] ); 313 } 314 } 315 catch( final Exception e ) 316 { 317 final String message = 318 REZ.format( "malformed.extension", manifests[ i ] ); 319 warn( message, e ); 320 } 321 } 322 return (Extension[])set.toArray( new Extension[ set.size() ] ); 323 } 324 325 335 protected void scanDependencies( final Extension[] required, 336 final Extension[] available, 337 final Set dependencies, 338 final Set unsatisfied ) 339 { 340 throw new UnsupportedOperationException (); 341 } 342 343 349 protected void warn( final String message ) 350 { 351 } 352 353 360 protected void warn( final String message, final Throwable t ) 361 { 362 } 363 364 370 protected boolean isDebugEnabled() 371 { 372 return false; 373 } 374 375 381 protected void debug( final String message ) 382 { 383 } 384 385 393 private Manifest [] getManifests( final URL [] classPath ) 394 throws Exception 395 { 396 final ArrayList manifests = new ArrayList (); 397 398 for( int i = 0; i < classPath.length; i++ ) 399 { 400 final URL element = classPath[ i ]; 401 if( element.getFile().endsWith( ".jar" ) ) 402 { 403 try 404 { 405 final URL url = new URL ( "jar:" + element + "!/" ); 406 final JarURLConnection connection = 407 (JarURLConnection )url.openConnection(); 408 final Manifest manifest = connection.getManifest(); 409 if( null != manifest ) 410 { 411 manifests.add( manifest ); 412 } 413 } 414 catch( final IOException ioe ) 415 { 416 final String message = 417 REZ.format( "bad-classpath-entry", element ); 418 throw new Exception ( message ); 419 } 420 } 421 } 422 423 return (Manifest [])manifests.toArray( new Manifest [ 0 ] ); 424 } 425 426 435 protected final URL [] resolveFileSet( final File base, 436 final String baseDirectory, 437 final String [] includes, 438 final String [] excludes ) 439 { 440 final String newBaseDirectory = FileUtil.normalize( baseDirectory ); 443 final String [] newIncludes = prefixPatterns( newBaseDirectory, 444 includes ); 445 final String [] newExcludes = prefixPatterns( newBaseDirectory, 446 excludes ); 447 final PathMatcher matcher = new PathMatcher( newIncludes, 448 newExcludes ); 449 final File [] files = FileUtil.resolveFileSet( base, matcher ); 450 try 451 { 452 return FileUtil.toURLs( files ); 453 } 454 catch( IOException ioe ) 455 { 456 throw new IllegalArgumentException ( ioe.getMessage() ); 457 } 458 } 459 460 468 private String [] prefixPatterns( final String prefix, 469 final String [] patterns ) 470 { 471 if( 0 == prefix.length() || ".".equals( prefix ) ) 472 { 473 return patterns; 474 } 475 476 final String [] newPatterns = new String [ patterns.length ]; 477 for( int i = 0; i < newPatterns.length; i++ ) 478 { 479 newPatterns[ i ] = prefix + "/" + patterns[ i ]; 480 } 481 return newPatterns; 482 } 483 } | Popular Tags |