1 package org.apache.maven.index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.List;
31
32 import org.apache.lucene.queryParser.ParseException;
33 import org.apache.lucene.search.Query;
34 import org.apache.maven.index.context.ContextMemberProvider;
35 import org.apache.maven.index.context.DefaultIndexingContext;
36 import org.apache.maven.index.context.ExistingLuceneIndexMismatchException;
37 import org.apache.maven.index.context.IndexCreator;
38 import org.apache.maven.index.context.IndexingContext;
39 import org.apache.maven.index.context.MergedIndexingContext;
40 import org.apache.maven.index.expr.SearchExpression;
41 import org.apache.maven.index.expr.SourcedSearchExpression;
42 import org.apache.maven.index.util.IndexCreatorSorter;
43 import org.codehaus.plexus.component.annotations.Component;
44 import org.codehaus.plexus.component.annotations.Requirement;
45 import org.codehaus.plexus.logging.AbstractLogEnabled;
46 import org.codehaus.plexus.util.IOUtil;
47
48
49
50
51
52
53 @Component( role = Indexer.class )
54 public class DefaultIndexer
55 extends AbstractLogEnabled
56 implements Indexer
57 {
58 @Requirement
59 private SearchEngine searcher;
60
61 @Requirement
62 private IndexerEngine indexerEngine;
63
64 @Requirement
65 private QueryCreator queryCreator;
66
67
68
69
70
71 public IndexingContext createIndexingContext( String id, String repositoryId, File repository, File indexDirectory,
72 String repositoryUrl, String indexUpdateUrl, boolean searchable,
73 boolean reclaim, List<? extends IndexCreator> indexers )
74 throws IOException, ExistingLuceneIndexMismatchException, IllegalArgumentException
75 {
76 final IndexingContext context =
77 new DefaultIndexingContext( id, repositoryId, repository, indexDirectory, repositoryUrl, indexUpdateUrl,
78 IndexCreatorSorter.sort( indexers ), reclaim );
79 context.setSearchable( searchable );
80 return context;
81 }
82
83 public IndexingContext createMergedIndexingContext( String id, String repositoryId, File repository,
84 File indexDirectory, boolean searchable,
85 ContextMemberProvider membersProvider )
86 throws IOException
87 {
88 IndexingContext context =
89 new MergedIndexingContext( id, repositoryId, repository, indexDirectory, searchable, membersProvider );
90 return context;
91 }
92
93 public void closeIndexingContext( IndexingContext context, boolean deleteFiles )
94 throws IOException
95 {
96 context.close( deleteFiles );
97 }
98
99
100
101
102
103 public void addArtifactsToIndex( Collection<ArtifactContext> ac, IndexingContext context )
104 throws IOException
105 {
106 if ( ac != null && !ac.isEmpty() )
107 {
108 for ( ArtifactContext actx : ac )
109 {
110 indexerEngine.update( context, actx );
111 }
112
113 context.commit();
114 }
115 }
116
117 public void deleteArtifactsFromIndex( Collection<ArtifactContext> ac, IndexingContext context )
118 throws IOException
119 {
120 if ( ac != null && !ac.isEmpty() )
121 {
122 for ( ArtifactContext actx : ac )
123 {
124 indexerEngine.remove( context, actx );
125
126 context.commit();
127 }
128 }
129 }
130
131
132
133
134
135 public FlatSearchResponse searchFlat( FlatSearchRequest request )
136 throws IOException
137 {
138 if ( request.getContexts().isEmpty() )
139 {
140 return new FlatSearchResponse( request.getQuery(), 0, Collections.<ArtifactInfo> emptySet() );
141 }
142 else
143 {
144 return searcher.forceSearchFlatPaged( request, request.getContexts() );
145 }
146 }
147
148 public IteratorSearchResponse searchIterator( IteratorSearchRequest request )
149 throws IOException
150 {
151 if ( request.getContexts().isEmpty() )
152 {
153 return IteratorSearchResponse.empty( request.getQuery() );
154 }
155 else
156 {
157 return searcher.forceSearchIteratorPaged( request, request.getContexts() );
158 }
159 }
160
161 public GroupedSearchResponse searchGrouped( GroupedSearchRequest request )
162 throws IOException
163 {
164 if ( request.getContexts().isEmpty() )
165 {
166 return new GroupedSearchResponse( request.getQuery(), 0, Collections.<String, ArtifactInfoGroup> emptyMap() );
167 }
168 else
169 {
170
171 return searcher.forceSearchGrouped( request, request.getContexts() );
172 }
173 }
174
175
176
177
178
179 public Collection<ArtifactInfo> identify( final File artifact, final Collection<IndexingContext> contexts )
180 throws IOException
181 {
182 FileInputStream is = null;
183 try
184 {
185 final MessageDigest sha1 = MessageDigest.getInstance( "SHA-1" );
186 is = new FileInputStream( artifact );
187 final byte[] buff = new byte[4096];
188 int n;
189 while ( ( n = is.read( buff ) ) > -1 )
190 {
191 sha1.update( buff, 0, n );
192 }
193 byte[] digest = sha1.digest();
194 return identify( constructQuery( MAVEN.SHA1, new SourcedSearchExpression( encode( digest ) ) ), contexts );
195 }
196 catch ( NoSuchAlgorithmException ex )
197 {
198 IOException ioe = new IOException( "Unable to calculate digest" );
199 ioe.initCause( ex );
200 throw ioe;
201 }
202 finally
203 {
204 IOUtil.close( is );
205 }
206 }
207
208 public Collection<ArtifactInfo> identify( Query query, Collection<IndexingContext> contexts )
209 throws IOException
210 {
211 final IteratorSearchResponse result =
212 searcher.searchIteratorPaged( new IteratorSearchRequest( query ), contexts );
213 try
214 {
215 final ArrayList<ArtifactInfo> ais = new ArrayList<ArtifactInfo>( result.getTotalHitsCount() );
216 for ( ArtifactInfo ai : result )
217 {
218 ais.add( ai );
219 }
220 return ais;
221 }
222 finally
223 {
224 result.close();
225 }
226 }
227
228
229
230
231
232 public Query constructQuery( Field field, SearchExpression expression )
233 throws IllegalArgumentException
234 {
235 try
236 {
237 return queryCreator.constructQuery( field, expression );
238 }
239 catch ( ParseException e )
240 {
241 throw new IllegalArgumentException( e );
242 }
243 }
244
245
246
247 private static final char[] DIGITS = "0123456789abcdef".toCharArray();
248
249 private static String encode( byte[] digest )
250 {
251 char[] buff = new char[digest.length * 2];
252
253 int n = 0;
254
255 for ( byte b : digest )
256 {
257 buff[n++] = DIGITS[( 0xF0 & b ) >> 4];
258 buff[n++] = DIGITS[0x0F & b];
259 }
260
261 return new String( buff );
262 }
263 }