KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > repository > main > DefaultInitialContext


1 /*
2  * Copyright 2004 Apache Software Foundation
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  *
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.avalon.repository.main;
19
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.net.Authenticator JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLClassLoader JavaDoc;
28 import java.net.JarURLConnection JavaDoc;
29 import java.util.Enumeration JavaDoc;
30 import java.util.Properties JavaDoc;
31 import java.util.jar.Manifest JavaDoc;
32 import java.util.jar.JarFile JavaDoc;
33 import java.util.zip.ZipEntry JavaDoc;
34
35 import javax.naming.directory.Attributes JavaDoc;
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 /**
50  * Sets up the environment to create repositories by downloading the required
51  * jars, preparing a ClassLoader and delegating calls to repository factory
52  * methods using the newly configured ClassLoader.
53  *
54  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
55  * @version $Revision: 1.27 $
56  */

57 public class DefaultInitialContext extends AbstractBuilder implements InitialContext
58 {
59     //------------------------------------------------------------------
60
// public static
61
//------------------------------------------------------------------
62

63    /**
64     * Group identifier manifest key.
65     */

66     public static final String JavaDoc BLOCK_GROUP_KEY = "Block-Group";
67
68     //------------------------------------------------------------------
69
// immutable state
70
//------------------------------------------------------------------
71

72    /**
73     * The application key.
74     */

75     private final String JavaDoc m_key;
76         
77    /**
78     * The instantiated delegate cache manager factory.
79     */

80     private final Factory m_factory;
81
82    /**
83     * The initial cache directory.
84     */

85     private final File JavaDoc m_cache;
86
87    /**
88     * The base working directory.
89     */

90     private final File JavaDoc m_base;
91
92    /**
93     * System repository established by the intial context.
94     */

95     private final Repository m_repository;
96
97     private final LoaderUtils m_loader;
98
99     // ------------------------------------------------------------------------
100
// mutable state
101
// ------------------------------------------------------------------------
102

103    /**
104     * The online connection policy.
105     */

106     private boolean m_online;
107
108    /**
109     * The initial remote host names.
110     */

111     private String JavaDoc[] m_hosts;
112
113     // ------------------------------------------------------------------------
114
// constructors
115
// ------------------------------------------------------------------------
116

117     /**
118      * Creates an initial repository context.
119      *
120      * @param parent the parent classloader
121      * @param artifact an artifact referencing the default implementation
122      * @param candidates factory artifact sequence for registration
123      * @param base the base working directory
124      * @param cache the cache directory
125      * @param hosts a set of initial remote repository addresses
126      * @throws RepositoryException if an error occurs during establishment
127      */

128     DefaultInitialContext(
129       String JavaDoc key, ClassLoader JavaDoc parent, Artifact artifact,
130       Artifact[] candidates, File JavaDoc base, File JavaDoc cache,
131       String JavaDoc proxyHost, int proxyPort, String JavaDoc proxyUsername,
132       String JavaDoc proxyPassword, String JavaDoc[] hosts, boolean online )
133       throws RepositoryException
134     {
135         if( null == key ) throw new NullPointerException JavaDoc( "key" );
136         if( null == base ) throw new NullPointerException JavaDoc( "base" );
137         if( null == parent ) throw new NullPointerException JavaDoc( "parent" );
138         if( null == artifact ) throw new NullPointerException JavaDoc( "artifact" );
139         if( null == cache ) throw new NullPointerException JavaDoc( "cache" );
140         if( null == hosts ) throw new NullPointerException JavaDoc( "hosts" );
141         if( null == candidates ) throw new NullPointerException JavaDoc( "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 JavaDoc attributes = loadAttributes( m_cache, m_hosts, artifact );
154         FactoryDescriptor descriptor = new FactoryDescriptor( attributes );
155         String JavaDoc factory = descriptor.getFactory();
156         if( null == factory )
157         {
158             final String JavaDoc 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 JavaDoc( error );
163         }
164
165         //
166
// Grab all of the dependents in one hit because this is
167
// the implementation so we can ignore api/spi spread.
168
//
169

170         Artifact[] dependencies = descriptor.getDependencies();
171
172         int n = dependencies.length;
173         URL JavaDoc[] urls = new URL JavaDoc[ 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         //
184
// create the classloader
185
//
186

187         ClassLoader JavaDoc classloader = new URLClassLoader JavaDoc( urls, parent );
188         Class JavaDoc clazz = loadFactoryClass( classloader, factory );
189
190         //
191
// load the cache manager factory implementation
192
//
193

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 JavaDoc e )
206         {
207             final String JavaDoc error =
208               "Unable to establish a factory for the supplied artifact:";
209             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc( 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 JavaDoc host, final int port, final String JavaDoc username, final String JavaDoc password )
222     {
223         if( null == host ) return;
224         Properties JavaDoc 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 JavaDoc authenticator =
231               new DefaultAuthenticator( username, password );
232             Authenticator.setDefault( authenticator );
233         }
234     }
235
236     // ------------------------------------------------------------------------
237
// InitialContext
238
// ------------------------------------------------------------------------
239

240    /**
241     * Return the inital repository.
242     * @return the repository
243     */

244     public Repository getRepository()
245     {
246         return m_repository;
247     }
248
249    /**
250     * Get the online mode of the repository.
251     *
252     * @return the online mode
253     */

254     public boolean getOnlineMode()
255     {
256         return m_online;
257     }
258
259     /**
260      * Return the application key. The value of the key may be used
261      * to resolve property files by using the convention
262      * [key].properties.
263      *
264      * @return the application key.
265      */

266     public String JavaDoc getApplicationKey()
267     {
268         return m_key;
269     }
270
271     /**
272      * Return the base working directory.
273      *
274      * @return the base directory
275      */

276     public File JavaDoc getInitialWorkingDirectory()
277     {
278         return m_base;
279     }
280     
281     /**
282      * Return cache root directory.
283      *
284      * @return the cache directory
285      */

286     public File JavaDoc getInitialCacheDirectory()
287     {
288         return m_cache;
289     }
290     
291     /**
292      * Return the initial set of host names.
293      * @return the host names sequence
294      */

295     public String JavaDoc[] getInitialHosts()
296     {
297         return m_hosts;
298     }
299
300    /**
301     * Return the initial repository factory.
302     * @return the initial repository factory
303     */

304     public Factory getInitialFactory()
305     {
306         return m_factory;
307     }
308
309    /**
310     * Create a factory builder using a supplied artifact.
311     * @param artifact the factory artifact
312     * @return the factory builder
313     * @exception Exception if a builder creation error occurs
314     */

315     public Builder newBuilder( Artifact artifact )
316       throws Exception JavaDoc
317     {
318         return new DefaultBuilder( this, artifact );
319     }
320
321    /**
322     * Create a factory builder using a supplied artifact.
323     * @param classloader the parent classloader
324     * @param artifact the factory artifact
325     * @return the factory
326     * @exception Exception if a factory creation error occurs
327     */

328     public Builder newBuilder( ClassLoader JavaDoc classloader, Artifact artifact )
329       throws Exception JavaDoc
330     {
331         return new DefaultBuilder( this, classloader, artifact );
332     }
333
334    /**
335     * Install a block archive into the repository cache.
336     * @param url the block archive url
337     * @return the block manifest
338     */

339     public Manifest JavaDoc install( URL JavaDoc url ) throws RepositoryException
340     {
341         String JavaDoc path = url.getFile();
342
343         try
344         {
345             File JavaDoc temp = File.createTempFile( "avalon-", "-bar" );
346             temp.delete();
347             m_loader.getResource( url.toString(), temp, true );
348             temp.deleteOnExit();
349             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
350             Manifest JavaDoc manifest = expand( temp.toURL(), buffer );
351
352             //
353
// need a logging solution
354
//
355

356             System.out.println( buffer.toString() );
357             return manifest;
358         }
359         catch( RepositoryException e )
360         {
361             throw e;
362         }
363         catch( Throwable JavaDoc e )
364         {
365             final String JavaDoc error =
366               "Cannot install target: " + url;
367             throw new RepositoryException( error, e );
368         }
369     }
370
371     // ------------------------------------------------------------------------
372
// implementation
373
// ------------------------------------------------------------------------
374

375    /**
376     * Expand a block archive into the repository.
377     * @param url the block archive url
378     * @param buffer a string buffer against which messages may be logged
379     * @return the block manifest
380     */

381     private Manifest JavaDoc expand( URL JavaDoc url, StringBuffer JavaDoc buffer ) throws RepositoryException
382     {
383         try
384         {
385             URL JavaDoc jurl = new URL JavaDoc( "jar:" + url.toString() + "!/" );
386             JarURLConnection JavaDoc connection = (JarURLConnection JavaDoc) jurl.openConnection();
387             Manifest JavaDoc manifest = connection.getManifest();
388
389             final String JavaDoc group = getBlockGroup( manifest );
390
391             buffer.append( "\nBlock Group: " + group );
392             final File JavaDoc root = new File JavaDoc( m_cache, group );
393             buffer.append( "\nLocal target: " + root );
394             JarFile JavaDoc jar = connection.getJarFile();
395             Enumeration JavaDoc entries = jar.entries();
396             while( entries.hasMoreElements() )
397             {
398                 ZipEntry JavaDoc entry = (ZipEntry JavaDoc) 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 JavaDoc e )
408         {
409             final String JavaDoc error =
410               "Could not install block: " + url;
411             throw new RepositoryException( error, e );
412         }
413     }
414
415     private String JavaDoc getBlockGroup( Manifest JavaDoc manifest )
416     {
417         return (String JavaDoc) manifest.getMainAttributes().getValue( BLOCK_GROUP_KEY );
418     }
419
420    /**
421     * Internal utility to install a entry from a jar file into the local repository.
422     * @param buffer the buffer to log messages to
423     * @param root the root directory corresponding to the bar group
424     * @param jar the block archive
425     * @param entry the entry from the archive to install
426     */

427     private void installEntry(
428       StringBuffer JavaDoc buffer, File JavaDoc root, JarFile JavaDoc jar, ZipEntry JavaDoc entry ) throws Exception JavaDoc
429     {
430         if( entry.isDirectory() ) return;
431         
432         final String JavaDoc name = entry.getName();
433         File JavaDoc file = new File JavaDoc( 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 JavaDoc is = jar.getInputStream( entry );
459         if ( is == null )
460         {
461             final String JavaDoc error =
462               "Entry returned a null input stream: " + name;
463             buffer.append( "\n " + error );
464             throw new IOException JavaDoc( error );
465         }
466
467         file.getParentFile().mkdirs();
468         FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc( 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 JavaDoc loadAttributes( File JavaDoc cache, String JavaDoc[] 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