1 17 18 package org.apache.avalon.repository.main; 19 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.FileOutputStream ; 25 import java.net.Authenticator ; 26 import java.net.URL ; 27 import java.net.URLClassLoader ; 28 import java.net.JarURLConnection ; 29 import java.util.Enumeration ; 30 import java.util.Properties ; 31 import java.util.jar.Manifest ; 32 import java.util.jar.JarFile ; 33 import java.util.zip.ZipEntry ; 34 35 import javax.naming.directory.Attributes ; 36 37 import org.apache.avalon.repository.Artifact; 38 import org.apache.avalon.repository.Repository; 39 import org.apache.avalon.repository.RepositoryException; 40 import org.apache.avalon.repository.meta.FactoryDescriptor; 41 import org.apache.avalon.repository.provider.Factory; 42 import org.apache.avalon.repository.provider.InitialContext; 43 import org.apache.avalon.repository.provider.RepositoryCriteria; 44 import org.apache.avalon.repository.provider.Builder; 45 import org.apache.avalon.repository.util.LoaderUtils; 46 import org.apache.avalon.repository.util.RepositoryUtils; 47 48 49 57 public class DefaultInitialContext extends AbstractBuilder implements InitialContext 58 { 59 63 66 public static final String BLOCK_GROUP_KEY = "Block-Group"; 67 68 72 75 private final String m_key; 76 77 80 private final Factory m_factory; 81 82 85 private final File m_cache; 86 87 90 private final File m_base; 91 92 95 private final Repository m_repository; 96 97 private final LoaderUtils m_loader; 98 99 103 106 private boolean m_online; 107 108 111 private String [] m_hosts; 112 113 117 128 DefaultInitialContext( 129 String key, ClassLoader parent, Artifact artifact, 130 Artifact[] candidates, File base, File cache, 131 String proxyHost, int proxyPort, String proxyUsername, 132 String proxyPassword, String [] hosts, boolean online ) 133 throws RepositoryException 134 { 135 if( null == key ) throw new NullPointerException ( "key" ); 136 if( null == base ) throw new NullPointerException ( "base" ); 137 if( null == parent ) throw new NullPointerException ( "parent" ); 138 if( null == artifact ) throw new NullPointerException ( "artifact" ); 139 if( null == cache ) throw new NullPointerException ( "cache" ); 140 if( null == hosts ) throw new NullPointerException ( "hosts" ); 141 if( null == candidates ) throw new NullPointerException ( "candidates" ); 142 143 m_key = key; 144 m_base = base; 145 m_cache = cache; 146 m_online = online; 147 m_hosts = hosts; 148 149 m_loader = new LoaderUtils( m_online ); 150 151 setupProxy( proxyHost, proxyPort, proxyUsername, proxyPassword ); 152 153 Attributes attributes = loadAttributes( m_cache, m_hosts, artifact ); 154 FactoryDescriptor descriptor = new FactoryDescriptor( attributes ); 155 String factory = descriptor.getFactory(); 156 if( null == factory ) 157 { 158 final String error = 159 "Required property 'avalon.artifact.factory' not present in artifact: " 160 + artifact + " under the active cache: [" + m_cache + "] using the " 161 + "attribute sequence: " + attributes; 162 throw new IllegalArgumentException ( error ); 163 } 164 165 170 Artifact[] dependencies = descriptor.getDependencies(); 171 172 int n = dependencies.length; 173 URL [] urls = new URL [ n + 1]; 174 for( int i=0; i<n; i++ ) 175 { 176 urls[i] = m_loader.getResource( 177 dependencies[i], m_hosts, m_cache, true ); 178 } 179 180 urls[ n ] = m_loader.getResource( 181 artifact, m_hosts, m_cache, true ); 182 183 187 ClassLoader classloader = new URLClassLoader ( urls, parent ); 188 Class clazz = loadFactoryClass( classloader, factory ); 189 190 194 try 195 { 196 m_factory = createDelegate( classloader, clazz, this ); 197 RepositoryCriteria criteria = 198 (RepositoryCriteria) m_factory.createDefaultCriteria(); 199 criteria.setCacheDirectory( m_cache ); 200 criteria.setHosts( m_hosts ); 201 criteria.setOnlineMode( online ); 202 criteria.setFactoryArtifacts( candidates ); 203 m_repository = (Repository) m_factory.create( criteria ); 204 } 205 catch( Throwable e ) 206 { 207 final String error = 208 "Unable to establish a factory for the supplied artifact:"; 209 StringBuffer buffer = new StringBuffer ( error ); 210 buffer.append( "\n artifact: " + artifact ); 211 buffer.append( "\n build: " + descriptor.getBuild() ); 212 buffer.append( "\n factory: " + descriptor.getFactory() ); 213 buffer.append( "\n source: " 214 + clazz.getProtectionDomain().getCodeSource().getLocation() ); 215 buffer.append( "\n cache: " + m_cache ); 216 throw new RepositoryException( buffer.toString(), e ); 217 } 218 } 219 220 private void setupProxy( 221 final String host, final int port, final String username, final String password ) 222 { 223 if( null == host ) return; 224 Properties system = System.getProperties(); 225 system.put( "proxySet", "true" ); 226 system.put( "proxyHost", host ); 227 system.put( "proxyPort", String.valueOf( port ) ); 228 if( null != username ) 229 { 230 Authenticator authenticator = 231 new DefaultAuthenticator( username, password ); 232 Authenticator.setDefault( authenticator ); 233 } 234 } 235 236 240 244 public Repository getRepository() 245 { 246 return m_repository; 247 } 248 249 254 public boolean getOnlineMode() 255 { 256 return m_online; 257 } 258 259 266 public String getApplicationKey() 267 { 268 return m_key; 269 } 270 271 276 public File getInitialWorkingDirectory() 277 { 278 return m_base; 279 } 280 281 286 public File getInitialCacheDirectory() 287 { 288 return m_cache; 289 } 290 291 295 public String [] getInitialHosts() 296 { 297 return m_hosts; 298 } 299 300 304 public Factory getInitialFactory() 305 { 306 return m_factory; 307 } 308 309 315 public Builder newBuilder( Artifact artifact ) 316 throws Exception 317 { 318 return new DefaultBuilder( this, artifact ); 319 } 320 321 328 public Builder newBuilder( ClassLoader classloader, Artifact artifact ) 329 throws Exception 330 { 331 return new DefaultBuilder( this, classloader, artifact ); 332 } 333 334 339 public Manifest install( URL url ) throws RepositoryException 340 { 341 String path = url.getFile(); 342 343 try 344 { 345 File temp = File.createTempFile( "avalon-", "-bar" ); 346 temp.delete(); 347 m_loader.getResource( url.toString(), temp, true ); 348 temp.deleteOnExit(); 349 StringBuffer buffer = new StringBuffer (); 350 Manifest manifest = expand( temp.toURL(), buffer ); 351 352 356 System.out.println( buffer.toString() ); 357 return manifest; 358 } 359 catch( RepositoryException e ) 360 { 361 throw e; 362 } 363 catch( Throwable e ) 364 { 365 final String error = 366 "Cannot install target: " + url; 367 throw new RepositoryException( error, e ); 368 } 369 } 370 371 375 381 private Manifest expand( URL url, StringBuffer buffer ) throws RepositoryException 382 { 383 try 384 { 385 URL jurl = new URL ( "jar:" + url.toString() + "!/" ); 386 JarURLConnection connection = (JarURLConnection ) jurl.openConnection(); 387 Manifest manifest = connection.getManifest(); 388 389 final String group = getBlockGroup( manifest ); 390 391 buffer.append( "\nBlock Group: " + group ); 392 final File root = new File ( m_cache, group ); 393 buffer.append( "\nLocal target: " + root ); 394 JarFile jar = connection.getJarFile(); 395 Enumeration entries = jar.entries(); 396 while( entries.hasMoreElements() ) 397 { 398 ZipEntry entry = (ZipEntry ) entries.nextElement(); 399 if( !entry.getName().startsWith( "META-INF" ) ) 400 { 401 installEntry( buffer, root, jar, entry ); 402 } 403 } 404 buffer.append( "\nInstall successful." ); 405 return manifest; 406 } 407 catch( Throwable e ) 408 { 409 final String error = 410 "Could not install block: " + url; 411 throw new RepositoryException( error, e ); 412 } 413 } 414 415 private String getBlockGroup( Manifest manifest ) 416 { 417 return (String ) manifest.getMainAttributes().getValue( BLOCK_GROUP_KEY ); 418 } 419 420 427 private void installEntry( 428 StringBuffer buffer, File root, JarFile jar, ZipEntry entry ) throws Exception 429 { 430 if( entry.isDirectory() ) return; 431 432 final String name = entry.getName(); 433 File file = new File ( root, name ); 434 435 long timestamp = entry.getTime(); 436 if( file.exists() ) 437 { 438 if( file.lastModified() == timestamp ) 439 { 440 buffer.append( "\nEntry: " + name + " (already exists)" ); 441 return; 442 } 443 else if( file.lastModified() > timestamp ) 444 { 445 buffer.append( "\nEntry: " + name + " (local version is more recent)" ); 446 return; 447 } 448 else 449 { 450 buffer.append( "\nEntry: " + name + " (updating local version)" ); 451 } 452 } 453 else 454 { 455 buffer.append( "\nEntry: " + name ); 456 } 457 458 InputStream is = jar.getInputStream( entry ); 459 if ( is == null ) 460 { 461 final String error = 462 "Entry returned a null input stream: " + name; 463 buffer.append( "\n " + error ); 464 throw new IOException ( error ); 465 } 466 467 file.getParentFile().mkdirs(); 468 FileOutputStream fos = new FileOutputStream ( file ); 469 byte[] buf = new byte[100 * 1024]; 470 int length; 471 while ( ( length = is.read( buf ) ) >= 0 ) 472 { 473 fos.write( buf, 0, length ); 474 } 475 fos.close(); 476 is.close(); 477 478 if ( timestamp < 0 ) 479 { 480 file.setLastModified( System.currentTimeMillis() ); 481 } 482 else 483 { 484 file.setLastModified( timestamp ); 485 } 486 } 487 488 private Attributes loadAttributes( File cache, String [] hosts, Artifact artifact ) 489 throws RepositoryException 490 { 491 try 492 { 493 return RepositoryUtils.getAttributes( cache, artifact ); 494 } 495 catch( RepositoryException re ) 496 { 497 return RepositoryUtils.getAttributes( hosts, artifact ); 498 } 499 } 500 } 501 | Popular Tags |