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