]> source.dussan.org Git - archiva.git/blob
61d15e537be69f09bcb0e0fff95cc68e40073641
[archiva.git] /
1 package org.apache.maven.repository.indexing;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import org.apache.lucene.analysis.Analyzer;
20 import org.apache.lucene.analysis.CharTokenizer;
21 import org.apache.lucene.analysis.SimpleAnalyzer;
22 import org.apache.lucene.analysis.TokenStream;
23 import org.apache.lucene.document.DateField;
24 import org.apache.lucene.document.Document;
25 import org.apache.lucene.document.Field;
26 import org.apache.maven.artifact.Artifact;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.repository.digest.Digester;
29 import org.codehaus.plexus.util.FileUtils;
30 import org.codehaus.plexus.util.IOUtil;
31
32 import java.io.File;
33 import java.io.FileInputStream;
34 import java.io.FileNotFoundException;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.Reader;
38 import java.security.NoSuchAlgorithmException;
39 import java.util.Enumeration;
40 import java.util.zip.ZipEntry;
41 import java.util.zip.ZipException;
42 import java.util.zip.ZipFile;
43 import java.util.zip.ZipOutputStream;
44
45 /**
46  * @author Edwin Punzalan
47  */
48 public class EclipseRepositoryIndex
49     extends AbstractRepositoryIndex
50 {
51     private static final String JAR_NAME = "j";
52
53     private static final String JAR_SIZE = "s";
54
55     private static final String JAR_DATE = "d";
56
57     private static final String NAMES = "c";
58
59     private static final String MD5 = "m";
60
61     private Digester digester;
62
63
64     /**
65      * Class constructor
66      *
67      * @param indexPath  the path where the lucene index will be created/updated.
68      * @param repository the repository where the indexed artifacts are located
69      * @param digester   the digester object to generate the checksum strings
70      */
71     public EclipseRepositoryIndex( File indexPath, ArtifactRepository repository, Digester digester )
72     {
73         super( indexPath, repository );
74
75         this.digester = digester;
76     }
77
78     /**
79      * @see AbstractRepositoryIndex#getAnalyzer()
80      */
81     public Analyzer getAnalyzer()
82     {
83         return new EclipseIndexAnalyzer( new SimpleAnalyzer() );
84     }
85
86     /**
87      * Method to index a given artifact for use with the eclipse plugin
88      *
89      * @param artifact the Artifact object to be indexed
90      * @throws RepositoryIndexException
91      */
92     public void indexArtifact( Artifact artifact )
93         throws RepositoryIndexException
94     {
95         File artifactFile = artifact.getFile();
96         if ( artifactFile != null && artifactFile.getName().endsWith( ".jar" ) && artifactFile.exists() )
97         {
98             String md5;
99             try
100             {
101                 md5 = digester.createChecksum( artifactFile, "MD5" );
102             }
103             catch ( FileNotFoundException e )
104             {
105                 throw new RepositoryIndexException( "Unable to compute checksum.", e );
106             }
107             catch ( NoSuchAlgorithmException e )
108             {
109                 throw new RepositoryIndexException( "Unable to compute checksum.", e );
110             }
111             catch ( IOException e )
112             {
113                 throw new RepositoryIndexException( "Unable to compute checksum.", e );
114             }
115
116             StringBuffer classes;
117             try
118             {
119                 // TODO: improve
120                 classes = new StringBuffer();
121                 if ( "jar".equals( artifact.getType() ) )
122                 {
123                     ZipFile jar = new ZipFile( artifact.getFile() );
124
125                     for ( Enumeration entries = jar.entries(); entries.hasMoreElements(); )
126                     {
127                         ZipEntry entry = (ZipEntry) entries.nextElement();
128                         addIfClassEntry( entry, classes );
129                     }
130                 }
131             }
132             catch ( ZipException e )
133             {
134                 throw new RepositoryIndexException( "Error reading from artifact file: " + artifact.getFile(), e );
135             }
136             catch ( IOException e )
137             {
138                 throw new RepositoryIndexException( "Error reading from artifact file", e );
139             }
140
141             Document doc = new Document();
142             doc.add( Field.Text( MD5, md5 ) );
143             doc.add( Field.Text( JAR_NAME, artifactFile.getName() ) );
144             doc.add( Field.Text( JAR_DATE, DateField.timeToString( artifactFile.lastModified() ) ) );
145             doc.add( Field.Text( JAR_SIZE, Long.toString( artifactFile.length() ) ) );
146             doc.add( Field.Text( NAMES, classes.toString() ) );
147
148             try
149             {
150                 if ( !isOpen() )
151                 {
152                     open();
153                 }
154                 getIndexWriter().addDocument( doc );
155             }
156             catch ( IOException e )
157             {
158                 throw new RepositoryIndexException( "Error opening index.", e );
159             }
160         }
161     }
162
163     /**
164      * method to create an archived copy of the index contents
165      *
166      * @return File object to the archive
167      * @throws IOException
168      */
169     public File getCompressedCopy()
170         throws IOException
171     {
172         File indexPath = getIndexPath();
173         String name = indexPath.getName();
174
175         File outputFile = new File( indexPath.getParent(), name + ".zip" );
176         FileUtils.fileDelete( outputFile.getAbsolutePath() );
177
178         ZipOutputStream zos = new ZipOutputStream( new FileOutputStream( outputFile ) );
179         zos.setLevel( 9 );
180
181         File[] files = indexPath.listFiles();
182         try
183         {
184             for ( int i = 0; i < files.length; i++ )
185             {
186                 writeFile( zos, files[i] );
187             }
188         }
189         finally
190         {
191             zos.close();
192         }
193
194         return outputFile;
195     }
196
197     private static void writeFile( ZipOutputStream zos, File file )
198         throws IOException
199     {
200         ZipEntry e = new ZipEntry( file.getName() );
201         zos.putNextEntry( e );
202
203         FileInputStream is = new FileInputStream( file );
204         try
205         {
206             IOUtil.copy( is, zos );
207         }
208         finally
209         {
210             is.close();
211         }
212         zos.flush();
213
214         zos.closeEntry();
215     }
216
217     /**
218      * @see AbstractRepositoryIndex#deleteIfIndexed(Object)
219      */
220     public void deleteIfIndexed( Object object )
221         throws RepositoryIndexException, IOException
222     {
223         if ( object instanceof Artifact )
224         {
225             Artifact artifact = (Artifact) object;
226             if ( indexExists() )
227             {
228                 validateIndex( FIELDS );
229
230                 String md5;
231                 try
232                 {
233                     md5 = digester.createChecksum( artifact.getFile(), "MD5" );
234                 }
235                 catch ( FileNotFoundException e )
236                 {
237                     throw new RepositoryIndexException( "Unable to create index.", e );
238                 }
239                 catch ( NoSuchAlgorithmException e )
240                 {
241                     throw new RepositoryIndexException( "Unable to create index.", e );
242                 }
243                 catch ( IOException e )
244                 {
245                     throw new RepositoryIndexException( "Unable to create index.", e );
246                 }
247
248                 deleteDocument( MD5, md5 );
249             }
250         }
251         else
252         {
253             throw new RepositoryIndexException( "Object is not of type artifact." );
254         }
255     }
256
257     /**
258      * Class used to analyze the lucene index
259      */
260     private static class EclipseIndexAnalyzer
261         extends Analyzer
262     {
263         private Analyzer defaultAnalyzer;
264
265         /**
266          * constructor to for this analyzer
267          *
268          * @param defaultAnalyzer the analyzer to use as default for the general fields of the artifact indeces
269          */
270         EclipseIndexAnalyzer( Analyzer defaultAnalyzer )
271         {
272             this.defaultAnalyzer = defaultAnalyzer;
273         }
274
275         /**
276          * Method called by lucence during indexing operations
277          *
278          * @param fieldName the field name that the lucene object is currently processing
279          * @param reader    a Reader object to the index stream
280          * @return an analyzer to specific to the field name or the default analyzer if none is present
281          */
282         public TokenStream tokenStream( String fieldName, Reader reader )
283         {
284             TokenStream tokenStream;
285
286             if ( "s".equals( fieldName ) )
287             {
288                 tokenStream = new EclipseIndexTokenizer( reader );
289             }
290             else
291             {
292                 tokenStream = defaultAnalyzer.tokenStream( fieldName, reader );
293             }
294
295             return tokenStream;
296         }
297     }
298
299     /**
300      * Class used to tokenize the eclipse index
301      */
302     private static class EclipseIndexTokenizer
303         extends CharTokenizer
304     {
305         /**
306          * Constructor with the required reader to the index stream
307          *
308          * @param reader the Reader object of the index stream
309          */
310         EclipseIndexTokenizer( Reader reader )
311         {
312             super( reader );
313         }
314
315         /**
316          * method that lucene calls to check tokenization of a stream character
317          *
318          * @param character char currently being processed
319          * @return true if the char is a token, false if the char is a stop char
320          */
321         protected boolean isTokenChar( char character )
322         {
323             return true;
324         }
325     }
326 }