1 package org.apache.maven.repository.indexing;
4 * Copyright 2005-2006 The Apache Software Foundation.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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;
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;
39 * Class used to index Artifact objects in a specified repository
41 * @author Edwin Punzalan
43 public class ArtifactRepositoryIndex
44 extends AbstractRepositoryIndex
46 private static final String NAME = "name";
48 private static final String GROUPID = "groupId";
50 private static final String ARTIFACTID = "artifactId";
52 private static final String VERSION = "version";
54 private static final String SHA1 = "sha1";
56 private static final String MD5 = "md5";
58 private static final String CLASSES = "classes";
60 private static final String PACKAGES = "packages";
62 private static final String FILES = "files";
64 private static final String[] FIELDS = {NAME, GROUPID, ARTIFACTID, VERSION, SHA1, MD5, CLASSES, PACKAGES, FILES};
66 private Analyzer analyzer;
68 private StringBuffer classes;
70 private StringBuffer packages;
72 private StringBuffer files;
75 * method to get the Analyzer used to create indices
77 * @return the Analyzer object used to create the artifact indices
79 public Analyzer getAnalyzer()
81 if ( analyzer == null )
83 analyzer = new ArtifactRepositoryIndexAnalyzer( new SimpleAnalyzer() );
90 * method for collecting the available index fields usable for searching
92 * @return index field names
94 public String[] getIndexFields()
100 * generic method for indexing
102 * @param obj the object to be indexed by this indexer
104 public void index( Object obj )
105 throws RepositoryIndexException
107 if ( obj instanceof Artifact )
109 indexArtifact( (Artifact) obj );
113 throw new RepositoryIndexException(
114 "This instance of indexer cannot index instances of " + obj.getClass().getName() );
119 * method to index a given artifact
121 * @param artifact the Artifact object to be indexed
123 public void indexArtifact( Artifact artifact )
124 throws RepositoryIndexException
128 throw new RepositoryIndexException( "Unable to add artifact index on a closed index" );
135 processArtifactContents( artifact.getFile() );
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 );
152 catch ( Exception e )
154 throw new RepositoryIndexException( e );
158 private String getSha1( Artifact artifact )
159 throws FileNotFoundException, IOException, NoSuchAlgorithmException
161 FileInputStream fIn = new FileInputStream( artifact.getFile() );
162 return new String( getChecksum( fIn, "SHA-1" ) );
165 private String getMd5( Artifact artifact )
166 throws FileNotFoundException, IOException, NoSuchAlgorithmException
168 FileInputStream fIn = new FileInputStream( artifact.getFile() );
169 return new String( getChecksum( fIn, "MD5" ) );
172 private byte[] getChecksum( InputStream inStream, String algorithm )
173 throws IOException, NoSuchAlgorithmException
175 byte[] buffer = new byte[ 256 ];
176 MessageDigest complete = MessageDigest.getInstance( algorithm );
180 numRead = inStream.read( buffer );
183 complete.update( buffer, 0, numRead );
186 while ( numRead != -1 );
189 return complete.digest();
192 private void initBuffers()
194 classes = new StringBuffer();
195 packages = new StringBuffer();
196 files = new StringBuffer();
199 private void removeBuffers()
206 private void processArtifactContents( File artifact )
207 throws IOException, ZipException
210 ZipFile jar = new ZipFile( artifact );
211 for ( Enumeration entries = jar.entries(); entries.hasMoreElements(); )
213 ZipEntry entry = (ZipEntry) entries.nextElement();
214 if ( addIfClassEntry( entry ) )
216 addClassPackage( entry.getName() );
222 private boolean addIfClassEntry( ZipEntry entry )
224 boolean isAdded = false;
226 String name = entry.getName();
227 if ( name.endsWith( ".class" ) )
229 // TODO verify if class is public or protected
230 if ( name.lastIndexOf( "$" ) == -1 )
232 int idx = name.lastIndexOf( '/' );
237 String classname = name.substring( idx, name.length() - 6 );
238 classes.append( classname ).append( "\n" );
246 private boolean addClassPackage( String name )
248 boolean isAdded = false;
250 int idx = name.lastIndexOf( '/' );
253 String packageName = name.substring( 0, idx ).replace( '/', '.' ) + "\n";
254 if ( packages.indexOf( packageName ) < 0 )
256 packages.append( packageName ).append( "\n" );
264 private boolean addFile( ZipEntry entry )
266 boolean isAdded = false;
268 String name = entry.getName();
269 int idx = name.lastIndexOf( '/' );
272 name = name.substring( idx + 1 );
275 if ( files.indexOf( name + "\n" ) < 0 )
277 files.append( name ).append( "\n" );