]> source.dussan.org Git - archiva.git/blob
e7cfcc3464bd1e009691cecc85b76dc98085e26f
[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.SimpleAnalyzer;
21 import org.apache.lucene.document.Document;
22 import org.apache.lucene.document.Field;
23 import org.apache.maven.artifact.Artifact;
24
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.security.MessageDigest;
31 import java.security.NoSuchAlgorithmException;
32 import java.util.Enumeration;
33 import java.util.zip.ZipEntry;
34 import java.util.zip.ZipException;
35 import java.util.zip.ZipFile;
36
37
38 /**
39  * Class used to index Artifact objects in a specified repository
40  *
41  * @author Edwin Punzalan
42  */
43 public class ArtifactRepositoryIndex
44     extends AbstractRepositoryIndex
45 {
46     private static final String NAME = "name";
47
48     private static final String GROUPID = "groupId";
49
50     private static final String ARTIFACTID = "artifactId";
51
52     private static final String VERSION = "version";
53
54     private static final String SHA1 = "sha1";
55
56     private static final String MD5 = "md5";
57
58     private static final String CLASSES = "classes";
59
60     private static final String PACKAGES = "packages";
61
62     private static final String FILES = "files";
63
64     private static final String[] FIELDS = {NAME, GROUPID, ARTIFACTID, VERSION, SHA1, MD5, CLASSES, PACKAGES, FILES};
65
66     private Analyzer analyzer;
67
68     private StringBuffer classes;
69
70     private StringBuffer packages;
71
72     private StringBuffer files;
73
74     private static final int CHEKCSUM_BUFFER_SIZE = 256;
75
76     /**
77      * method to get the Analyzer used to create indices
78      *
79      * @return the Analyzer object used to create the artifact indices
80      */
81     public Analyzer getAnalyzer()
82     {
83         if ( analyzer == null )
84         {
85             analyzer = new ArtifactRepositoryIndexAnalyzer( new SimpleAnalyzer() );
86         }
87
88         return analyzer;
89     }
90
91     /**
92      * method for collecting the available index fields usable for searching
93      *
94      * @return index field names
95      */
96     public String[] getIndexFields()
97     {
98         return FIELDS;
99     }
100
101     /**
102      * generic method for indexing
103      *
104      * @param obj the object to be indexed by this indexer
105      */
106     public void index( Object obj )
107         throws RepositoryIndexException
108     {
109         if ( obj instanceof Artifact )
110         {
111             indexArtifact( (Artifact) obj );
112         }
113         else
114         {
115             throw new RepositoryIndexException(
116                 "This instance of indexer cannot index instances of " + obj.getClass().getName() );
117         }
118     }
119
120     /**
121      * method to index a given artifact
122      *
123      * @param artifact the Artifact object to be indexed
124      */
125     public void indexArtifact( Artifact artifact )
126         throws RepositoryIndexException
127     {
128         if ( !isOpen() )
129         {
130             throw new RepositoryIndexException( "Unable to add artifact index on a closed index" );
131         }
132
133         try
134         {
135             getIndexWriter();
136
137             processArtifactContents( artifact.getFile() );
138
139             //@todo should some of these fields be Keyword instead of Text ?
140             Document doc = new Document();
141             doc.add( Field.Text( NAME, artifact.getFile().getName() ) );
142             doc.add( Field.Text( GROUPID, artifact.getGroupId() ) );
143             doc.add( Field.Text( ARTIFACTID, artifact.getArtifactId() ) );
144             doc.add( Field.Text( VERSION, artifact.getVersion() ) );
145             doc.add( Field.Text( SHA1, getSha1( artifact ) ) );
146             doc.add( Field.Text( MD5, getMd5( artifact ) ) );
147             doc.add( Field.Text( CLASSES, classes.toString() ) );
148             doc.add( Field.Text( PACKAGES, packages.toString() ) );
149             doc.add( Field.Text( FILES, files.toString() ) );
150             indexWriter.addDocument( doc );
151
152             removeBuffers();
153         }
154         catch ( Exception e )
155         {
156             throw new RepositoryIndexException( e );
157         }
158     }
159
160     private String getSha1( Artifact artifact )
161         throws FileNotFoundException, IOException, NoSuchAlgorithmException
162     {
163         FileInputStream fIn = new FileInputStream( artifact.getFile() );
164         return new String( getChecksum( fIn, "SHA-1" ) );
165     }
166
167     private String getMd5( Artifact artifact )
168         throws FileNotFoundException, IOException, NoSuchAlgorithmException
169     {
170         FileInputStream fIn = new FileInputStream( artifact.getFile() );
171         return new String( getChecksum( fIn, "MD5" ) );
172     }
173
174     private byte[] getChecksum( InputStream inStream, String algorithm )
175         throws IOException, NoSuchAlgorithmException
176     {
177         byte[] buffer = new byte[ CHEKCSUM_BUFFER_SIZE ];
178         MessageDigest complete = MessageDigest.getInstance( algorithm );
179         int numRead;
180         do
181         {
182             numRead = inStream.read( buffer );
183             if ( numRead > 0 )
184             {
185                 complete.update( buffer, 0, numRead );
186             }
187         }
188         while ( numRead != -1 );
189         inStream.close();
190
191         return complete.digest();
192     }
193
194     private void initBuffers()
195     {
196         classes = new StringBuffer();
197         packages = new StringBuffer();
198         files = new StringBuffer();
199     }
200
201     private void removeBuffers()
202     {
203         classes = null;
204         packages = null;
205         files = null;
206     }
207
208     private void processArtifactContents( File artifact )
209         throws IOException, ZipException
210     {
211         initBuffers();
212         ZipFile jar = new ZipFile( artifact );
213         for ( Enumeration entries = jar.entries(); entries.hasMoreElements(); )
214         {
215             ZipEntry entry = (ZipEntry) entries.nextElement();
216             if ( addIfClassEntry( entry ) )
217             {
218                 addClassPackage( entry.getName() );
219             }
220             addFile( entry );
221         }
222     }
223
224     private boolean addIfClassEntry( ZipEntry entry )
225     {
226         boolean isAdded = false;
227
228         String name = entry.getName();
229         if ( name.endsWith( ".class" ) )
230         {
231             // TODO verify if class is public or protected
232             if ( name.lastIndexOf( "$" ) == -1 )
233             {
234                 int idx = name.lastIndexOf( '/' );
235                 if ( idx < 0 )
236                 {
237                     idx = 0;
238                 }
239                 String classname = name.substring( idx, name.length() - 6 );
240                 classes.append( classname ).append( "\n" );
241                 isAdded = true;
242             }
243         }
244
245         return isAdded;
246     }
247
248     private boolean addClassPackage( String name )
249     {
250         boolean isAdded = false;
251
252         int idx = name.lastIndexOf( '/' );
253         if ( idx > 0 )
254         {
255             String packageName = name.substring( 0, idx ).replace( '/', '.' ) + "\n";
256             if ( packages.indexOf( packageName ) < 0 )
257             {
258                 packages.append( packageName ).append( "\n" );
259             }
260             isAdded = true;
261         }
262
263         return isAdded;
264     }
265
266     private boolean addFile( ZipEntry entry )
267     {
268         String name = entry.getName();
269         int idx = name.lastIndexOf( '/' );
270         if ( idx >= 0 )
271         {
272             name = name.substring( idx + 1 );
273         }
274
275         boolean isAdded = false;
276
277         if ( files.indexOf( name + "\n" ) < 0 )
278         {
279             files.append( name ).append( "\n" );
280             isAdded = true;
281         }
282
283         return isAdded;
284     }
285 }