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.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, Collections.emptyMap() );
186 }
187 else
188 {
189
190 return searcher.forceSearchGrouped( request, request.getContexts() );
191 }
192 }
193
194
195
196
197
198 public Collection<ArtifactInfo> identify( final File artifact, final Collection<IndexingContext> contexts )
199 throws IOException
200 {
201 try ( FileInputStream is = new FileInputStream( artifact ) )
202 {
203 final MessageDigest sha1 = MessageDigest.getInstance( "SHA-1" );
204 final byte[] buff = new byte[4096];
205 int n;
206 while ( ( n = is.read( buff ) ) > -1 )
207 {
208 sha1.update( buff, 0, n );
209 }
210 byte[] digest = sha1.digest();
211 return identify( constructQuery( MAVEN.SHA1, new SourcedSearchExpression( encode( digest ) ) ), contexts );
212 }
213 catch ( NoSuchAlgorithmException ex )
214 {
215 throw new IOException( "Unable to calculate digest", ex );
216 }
217 }
218
219 public Collection<ArtifactInfo> identify( Query query, Collection<IndexingContext> contexts )
220 throws IOException
221 {
222 try ( IteratorSearchResponse result = searcher.searchIteratorPaged(
223 new IteratorSearchRequest( query ), contexts ) )
224 {
225 final List<ArtifactInfo> ais = new ArrayList<>( result.getTotalHitsCount() );
226 for ( ArtifactInfo ai : result )
227 {
228 ais.add( ai );
229 }
230 return ais;
231 }
232 }
233
234
235
236
237
238 public Query constructQuery( Field field, SearchExpression expression )
239 throws IllegalArgumentException
240 {
241 try
242 {
243 return queryCreator.constructQuery( field, expression );
244 }
245 catch ( ParseException e )
246 {
247 throw new IllegalArgumentException( e );
248 }
249 }
250
251 public Query constructQuery( Field field, String expression, SearchType searchType )
252 throws IllegalArgumentException
253 {
254 return constructQuery( field, new SearchTypedStringSearchExpression( expression, searchType ) );
255 }
256
257
258 private static final char[] DIGITS = "0123456789abcdef".toCharArray();
259
260 private static String encode( byte[] digest )
261 {
262 char[] buff = new char[digest.length * 2];
263
264 int n = 0;
265
266 for ( byte b : digest )
267 {
268 buff[n++] = DIGITS[( 0xF0 & b ) >> 4];
269 buff[n++] = DIGITS[0x0F & b];
270 }
271
272 return new String( buff );
273 }
274 }