1 package org.apache.maven.repository.indexing;
4 * Copyright 2001-2005 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
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 import java.io.FileInputStream;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.Collection;
28 import java.util.Enumeration;
29 import java.util.zip.ZipEntry;
30 import java.util.zip.ZipException;
31 import java.util.zip.ZipFile;
33 import org.apache.lucene.document.Document;
34 import org.apache.lucene.document.Field;
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.artifact.repository.ArtifactRepository;
40 * Class used to index Artifact objects in a specified repository
42 * @author Edwin Punzalan
44 public class ArtifactRepositoryIndexer
45 extends AbstractRepositoryIndexer
47 private static final String NAME = "name";
48 private static final String GROUPID = "groupId";
49 private static final String ARTIFACTID = "artifactId";
50 private static final String VERSION = "version";
51 private static final String SHA1 = "sha1";
52 private static final String MD5 = "md5";
53 private static final String CLASSES = "classes";
54 private static final String PACKAGES = "packages";
55 private static final String FILES = "files";
57 private static final String[] FIELDS = { NAME, GROUPID, ARTIFACTID, VERSION, SHA1, MD5,
58 CLASSES, PACKAGES, FILES };
60 private ArtifactRepository repository;
62 private StringBuffer classes;
63 private StringBuffer packages;
64 private StringBuffer files;
68 * @todo change repository to layout ???
70 * @param repository the repository where the indexed artifacts are located. This is necessary only to distinguish
71 * between default and legacy directory structure of the artifact location.
72 * @param path the directory where the index is located or will be created.
74 public ArtifactRepositoryIndexer( ArtifactRepository repository, String path )
75 throws RepositoryIndexerException
77 this.repository = repository;
83 * method for collecting the available index fields usable for searching
85 * @return index field names
87 public String[] getIndexFields()
93 * generic method for indexing
95 * @param obj the object to be indexed by this indexer
97 public void addObjectIndex(Object obj)
98 throws RepositoryIndexerException
100 if ( obj instanceof Artifact )
102 addArtifactIndex( (Artifact) obj );
106 throw new RepositoryIndexerException( "This instance of indexer cannot index instances of " +
107 obj.getClass().getName() );
112 * method to index a given artifact
114 * @param artifact the Artifact object to be indexed
116 public void addArtifactIndex( Artifact artifact )
117 throws RepositoryIndexerException
121 throw new RepositoryIndexerException( "Unable to add artifact index on a closed index" );
128 processArtifactContents( artifact.getFile() );
130 //@todo should some of these fields be Keyword instead of Text ?
131 Document doc = new Document();
132 doc.add( Field.Text( NAME, repository.pathOf( artifact ) ) );
133 doc.add( Field.Text( GROUPID, artifact.getGroupId() ) );
134 doc.add( Field.Text( ARTIFACTID, artifact.getArtifactId() ) );
135 doc.add( Field.Text( VERSION, artifact.getVersion() ) );
136 doc.add( Field.Text( SHA1, getSha1( artifact ) ) );
137 doc.add( Field.Text( MD5, getMd5( artifact ) ) );
138 doc.add( Field.Text( CLASSES, classes.toString() ) );
139 doc.add( Field.Text( PACKAGES, packages.toString() ) );
140 doc.add( Field.Text( FILES, files.toString() ) );
141 indexWriter.addDocument( doc );
147 throw new RepositoryIndexerException( e );
151 private String getSha1( Artifact artifact )
152 throws FileNotFoundException, IOException, NoSuchAlgorithmException
154 FileInputStream fIn = new FileInputStream( artifact.getFile() );
155 return new String( getChecksum( fIn, "SHA-1" ) );
158 private String getMd5( Artifact artifact )
159 throws FileNotFoundException, IOException, NoSuchAlgorithmException
161 FileInputStream fIn = new FileInputStream( artifact.getFile() );
162 return new String( getChecksum( fIn, "MD5" ) );
165 private byte[] getChecksum( InputStream inStream, String algorithm )
166 throws IOException, NoSuchAlgorithmException
168 byte[] buffer = new byte[ 256 ];
169 MessageDigest complete = MessageDigest.getInstance( algorithm );
173 numRead = inStream.read( buffer );
176 complete.update( buffer, 0, numRead );
179 while ( numRead != -1 );
182 return complete.digest();
185 private void initBuffers()
187 classes = new StringBuffer();
188 packages = new StringBuffer();
189 files = new StringBuffer();
192 private void removeBuffers()
199 private void processArtifactContents( File artifact )
200 throws IOException, ZipException
203 ZipFile jar = new ZipFile( artifact );
204 for ( Enumeration entries = jar.entries(); entries.hasMoreElements(); )
206 ZipEntry entry = (ZipEntry) entries.nextElement();
207 if ( addIfClassEntry( entry ) )
209 addClassPackage( entry.getName() );
215 private boolean addIfClassEntry( ZipEntry entry )
217 boolean isAdded = false;
219 String name = entry.getName();
220 if( name.endsWith( ".class") )
222 // TODO verify if class is public or protected
223 if( name.lastIndexOf( "$" ) == -1)
225 int idx = name.lastIndexOf( '/' );
226 if ( idx < 0 ) idx = 0;
227 String classname = name.substring( idx, name.length() - 6 );
228 classes.append( classname ).append( "\n" );
236 private boolean addClassPackage( String name )
238 boolean isAdded = false;
240 int idx = name.lastIndexOf( '/' );
243 String packageName = name.substring( 0, idx ).replace( '/', '.' ) + "\n";
244 if ( packages.indexOf( packageName ) < 0 )
246 packages.append( packageName ).append( "\n" );
254 private boolean addFile( ZipEntry entry )
256 boolean isAdded = false;
258 String name = entry.getName();
259 int idx = name.lastIndexOf( '/' );
262 name = name.substring( idx + 1 );
265 if ( files.indexOf( name + "\n" ) < 0 )
267 files.append( name ).append( "\n" );