KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > extension > DefaultPackageRepository


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.extension;
9
10 import java.io.File JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.jar.JarFile JavaDoc;
15 import java.util.jar.Manifest JavaDoc;
16 import org.apache.avalon.excalibur.io.FileUtil;
17 import org.apache.avalon.excalibur.util.DeweyDecimal;
18
19 /**
20  * <p>Interface used to contain "Optional Packages" (formerly known as
21  * "Standard Extensions"). It is assumed that each "Optional Package" is
22  * represented by a single file on the file system. This Repository searches
23  * a path to find the Optional Packages.</p>
24  *
25  * @author <a HREF="mailto:peter@apache.org">Peter Donald</a>
26  * @version $Revision: 1.9 $ $Date: 2001/12/11 09:53:34 $
27  * @see OptionalPackage
28  * @see PackageRepository
29  */

30 public class DefaultPackageRepository
31     implements PackageRepository
32 {
33     private static final boolean DEBUG = false;
34
35     /**
36      * Map between files and <code>OptionalPackage</code> objects.
37      */

38     private final HashMap JavaDoc m_packages = new HashMap JavaDoc();
39
40     /**
41      * The set of directories in which to look for Optional Packages
42      */

43     private File JavaDoc[] m_path;
44
45     /**
46      * Flag set when it is necessary to scan paths to
47      * build "Optional Package" list
48      */

49     private boolean m_needToScan;
50
51     /**
52      * Construct a package repository with path.
53      *
54      * @param path The set of directories in which to look for Optional Packages
55      */

56     public DefaultPackageRepository( final File JavaDoc[] path )
57     {
58         setPath( path );
59     }
60
61     /**
62      * Return all the <code>OptionalPackage</code>s that satisfy specified
63      * <code>Extension</code>. It is expected that this <code>Extension</code>
64      * object will be one retrieved via getLocalExtension() method. If the
65      * specified <code>Extension</code> is not local then <code>null</code>
66      * is returned.
67      *
68      * @param extension Description of the optional package
69      * @see #isLocal()
70      */

71     public synchronized OptionalPackage[] getOptionalPackages( final Extension extension )
72     {
73         if( m_needToScan )
74         {
75             //Check cache consistency and reload if necessary..
76
scanPath();
77         }
78
79         final ArrayList JavaDoc results = new ArrayList JavaDoc();
80         final ArrayList JavaDoc candidates = (ArrayList JavaDoc)m_packages.get( extension.getExtensionName() );
81         if( null != candidates )
82         {
83             final int size = candidates.size();
84             for( int i = 0; i < size; i++ )
85             {
86                 final OptionalPackage optionalPackage = (OptionalPackage)candidates.get( i );
87                 final Extension[] extensions = optionalPackage.getAvailableExtensions();
88
89                 for( int j = 0; j < extensions.length; j++ )
90                 {
91                     if( extensions[ j ].isCompatibleWith( extension ) )
92                     {
93                         results.add( optionalPackage );
94                     }
95                 }
96             }
97         }
98
99         //TODO: Sort packages so that most relevent is first
100
//ie Sort on spec version first and then on Imp version
101

102         return (OptionalPackage[])results.toArray( new OptionalPackage[ 0 ] );
103     }
104
105     /**
106      * Set the path for the Repository.
107      *
108      * @param path the list of directories in which to search
109      */

110     protected synchronized void setPath( final File JavaDoc[] path )
111     {
112         if( null == path )
113         {
114             throw new NullPointerException JavaDoc( "path property is null" );
115         }
116
117         for( int i = 0; i < path.length; i++ )
118         {
119             final File JavaDoc directory = path[ i ];
120             
121             if( !directory.exists() || !directory.isDirectory() )
122             {
123                 throw new IllegalArgumentException JavaDoc( "path element " + directory +
124                                                     " must exist and must be a directory" );
125             }
126         }
127
128         m_path = path;
129         m_needToScan = true;
130     }
131
132     /**
133      * Scan the path for this repository and reload all
134      * the "Optional Packages" found in the path.
135      *
136      */

137     protected final synchronized void scanPath()
138     {
139         clearCache();
140
141         for( int i = 0; i < m_path.length; i++ )
142         {
143             scanDirectory( m_path[ i ] );
144         }
145     }
146
147     private synchronized void scanDirectory( final File JavaDoc directory )
148     {
149         final File JavaDoc[] files = directory.listFiles();
150         for( int i = 0; i < files.length; i++ )
151         {
152             final File JavaDoc file = files[ i ];
153             final String JavaDoc name = file.getName();
154
155             if( !name.endsWith( ".jar" ) )
156             {
157                 debug( "Skipping " + file + " as it does not end with '.jar'" );
158                 continue;
159             }
160
161             if( !file.isFile() )
162             {
163                 debug( "Skipping " + file + " as it is not a file." );
164                 continue;
165             }
166
167             if( !file.canRead() )
168             {
169                 debug( "Skipping " + file + " as it is not readable." );
170                 continue;
171             }
172
173             try
174             {
175                 final OptionalPackage optionalPackage = getOptionalPackage( file );
176                 cacheOptionalPackage( optionalPackage );
177             }
178             catch( final IOException JavaDoc ioe )
179             {
180                 debug( "Skipping " + file + " as it could not be loaded due to " + ioe );
181             }
182         }
183     }
184
185     /**
186      * Clear internal cache of optional packages.
187      *
188      */

189     protected synchronized final void clearCache()
190     {
191         m_packages.clear();
192         m_needToScan = true;
193     }
194
195     /**
196      * Add OptionalPackage to internal cache of Optional Packages.
197      * Note that this method is only protected so that unit tests can sub-class
198      * and add entries to PackageRepository by calling this method.
199      *
200      * @param optionalPackage the OptionalPackage to be added to repository
201      */

202     protected synchronized final void cacheOptionalPackage( final OptionalPackage optionalPackage )
203     {
204         m_needToScan = false;
205         final Extension extension = optionalPackage.getAvailableExtensions()[ 0 ];
206         ArrayList JavaDoc candidates = (ArrayList JavaDoc)m_packages.get( extension.getExtensionName() );
207         if( null == candidates )
208         {
209             candidates = new ArrayList JavaDoc();
210             m_packages.put( extension.getExtensionName(), candidates );
211         }
212
213         //TODO: Add this in descending order so that don't have to sort in
214
//getOptionalPackages ????
215
//yes, sort by Spec Version then vendor, Imp Version
216
candidates.add( optionalPackage );
217     }
218
219     /**
220      * Construct an OptionalPackage out of the specified jar archive.
221      *
222      * @param archive the file object for Jar archive
223      * @return the OptionalPackage constructed
224      * @exception IOException if an error occurs
225      */

226     private OptionalPackage getOptionalPackage( final File JavaDoc archive )
227         throws IOException JavaDoc
228     {
229         final File JavaDoc file = archive.getCanonicalFile();
230         final JarFile JavaDoc jarFile = new JarFile JavaDoc( file );
231         final Manifest JavaDoc manifest = jarFile.getManifest();
232
233         try
234         {
235             if( null == manifest ) return null;
236             final Extension[] available = Extension.getAvailable( manifest );
237             final Extension[] required = Extension.getRequired( manifest );
238
239             return new OptionalPackage( file, available, required );
240         }
241         finally
242         {
243             jarFile.close();
244         }
245     }
246
247     protected void debug( final String JavaDoc message )
248     {
249         if( DEBUG ) System.out.println( message );
250         //getLogger().debug( message );
251
}
252 }
253
Popular Tags