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