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.IOException;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.apache.lucene.document.Document;
29 import org.apache.lucene.index.CorruptIndexException;
30 import org.apache.lucene.index.IndexReader;
31 import org.apache.lucene.index.MultiBits;
32 import org.apache.lucene.index.Term;
33 import org.apache.lucene.search.IndexSearcher;
34 import org.apache.lucene.search.TermQuery;
35 import org.apache.lucene.search.TopScoreDocCollector;
36 import org.apache.lucene.util.Bits;
37 import org.apache.maven.index.context.IndexingContext;
38
39
40
41
42
43
44 public class DefaultScannerListener
45 implements ArtifactScanningListener
46 {
47 private final IndexingContext context;
48
49 private final IndexerEngine indexerEngine;
50
51 private final boolean update;
52
53 private final ArtifactScanningListener listener;
54
55 private final Set<String> uinfos = new HashSet<>();
56
57 private final Set<String> processedUinfos = new HashSet<>();
58
59 private final Set<String> allGroups = new HashSet<>();
60
61 private final Set<String> groups = new HashSet<>();
62
63 private final List<Exception> exceptions = new ArrayList<>();
64
65 private int count = 0;
66
67 public DefaultScannerListener( IndexingContext context,
68 IndexerEngine indexerEngine, boolean update,
69 ArtifactScanningListener listener )
70 {
71 this.context = context;
72 this.indexerEngine = indexerEngine;
73 this.update = update;
74 this.listener = listener;
75 }
76
77 public void scanningStarted( IndexingContext ctx )
78 {
79 try
80 {
81 if ( update )
82 {
83 initialize( ctx );
84 }
85 }
86 catch ( IOException ex )
87 {
88 exceptions.add( ex );
89 }
90
91 if ( listener != null )
92 {
93 listener.scanningStarted( ctx );
94 }
95 }
96
97 public void artifactDiscovered( ArtifactContext ac )
98 {
99 String uinfo = ac.getArtifactInfo().getUinfo();
100
101
102
103
104
105 if ( processedUinfos.contains( uinfo ) )
106 {
107 return;
108 }
109
110 boolean adding = processedUinfos.add( uinfo );
111
112 if ( uinfos.contains( uinfo ) )
113 {
114
115 uinfos.remove( uinfo );
116 return;
117 }
118
119 try
120 {
121 if ( listener != null )
122 {
123 listener.artifactDiscovered( ac );
124 }
125
126 if ( adding )
127 {
128 indexerEngine.index( context, ac );
129 }
130 else
131 {
132 indexerEngine.update( context, ac );
133 }
134
135 for ( Exception e : ac.getErrors() )
136 {
137 artifactError( ac, e );
138 }
139
140 groups.add( ac.getArtifactInfo().getRootGroup() );
141 allGroups.add( ac.getArtifactInfo().getGroupId() );
142
143 count++;
144 }
145 catch ( IOException ex )
146 {
147 artifactError( ac, ex );
148 }
149 }
150
151 public void scanningFinished( IndexingContext ctx, ScanningResult result )
152 {
153 result.setTotalFiles( count );
154
155 for ( Exception ex : exceptions )
156 {
157 result.addException( ex );
158 }
159
160 try
161 {
162 context.optimize();
163
164 context.setRootGroups( groups );
165
166 context.setAllGroups( allGroups );
167
168 if ( update && !context.isReceivingUpdates() )
169 {
170 removeDeletedArtifacts( context, result, result.getRequest().getStartingPath() );
171 }
172 }
173 catch ( IOException ex )
174 {
175 result.addException( ex );
176 }
177
178 if ( listener != null )
179 {
180 listener.scanningFinished( ctx, result );
181 }
182
183 if ( result.getDeletedFiles() > 0 || result.getTotalFiles() > 0 )
184 {
185 try
186 {
187 context.updateTimestamp( true );
188
189 context.optimize();
190 }
191 catch ( Exception ex )
192 {
193 result.addException( ex );
194 }
195 }
196 }
197
198 public void artifactError( ArtifactContext ac, Exception e )
199 {
200 exceptions.add( e );
201
202 if ( listener != null )
203 {
204 listener.artifactError( ac, e );
205 }
206 }
207
208 private void initialize( IndexingContext ctx )
209 throws IOException, CorruptIndexException
210 {
211 final IndexSearcher indexSearcher = ctx.acquireIndexSearcher();
212 try
213 {
214 final IndexReader r = indexSearcher.getIndexReader();
215 Bits liveDocs = MultiBits.getLiveDocs( r );
216
217 for ( int i = 0; i < r.maxDoc(); i++ )
218 {
219 if ( liveDocs == null || liveDocs.get( i ) )
220 {
221 Document d = r.document( i );
222
223 String uinfo = d.get( ArtifactInfo.UINFO );
224
225 if ( uinfo != null )
226 {
227
228
229
230
231
232
233 if ( !ctx.isReceivingUpdates() )
234 {
235 uinfos.add( uinfo );
236 }
237
238
239
240 String groupId = uinfo.substring( 0, uinfo.indexOf( '|' ) );
241 int n = groupId.indexOf( '.' );
242 groups.add( n == -1 ? groupId : groupId.substring( 0, n ) );
243 allGroups.add( groupId );
244 }
245 }
246 }
247 }
248 finally
249 {
250 ctx.releaseIndexSearcher( indexSearcher );
251 }
252 }
253
254 private void removeDeletedArtifacts( IndexingContext context, ScanningResult result, String contextPath )
255 throws IOException
256 {
257 int deleted = 0;
258
259 final IndexSearcher indexSearcher = context.acquireIndexSearcher();
260 try
261 {
262 for ( String uinfo : uinfos )
263 {
264 TopScoreDocCollector collector = TopScoreDocCollector.create( 1, Integer.MAX_VALUE );
265
266 indexSearcher.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), collector );
267
268 if ( collector.getTotalHits() > 0 )
269 {
270 String[] ra = ArtifactInfo.FS_PATTERN.split( uinfo );
271
272 ArtifactInfo ai = new ArtifactInfo();
273
274 ai.setRepository( context.getRepositoryId() );
275
276 ai.setGroupId( ra[0] );
277
278 ai.setArtifactId( ra[1] );
279
280 ai.setVersion( ra[2] );
281
282 if ( ra.length > 3 )
283 {
284 ai.setClassifier( ArtifactInfo.renvl( ra[3] ) );
285 }
286
287 if ( ra.length > 4 )
288 {
289 ai.setPackaging( ArtifactInfo.renvl( ra[4] ) );
290 }
291
292
293 ArtifactContext ac = new ArtifactContext( null, null, null, ai, ai.calculateGav() );
294
295 for ( int i = 0; i < collector.getTotalHits(); i++ )
296 {
297 if ( contextPath == null
298 || context.getGavCalculator().gavToPath( ac.getGav() ).startsWith( contextPath ) )
299 {
300 indexerEngine.remove( context, ac );
301 }
302
303 deleted++;
304 }
305 }
306 }
307 }
308 finally
309 {
310 context.releaseIndexSearcher( indexSearcher );
311 }
312
313 if ( deleted > 0 )
314 {
315 context.commit();
316 }
317
318 result.setDeletedFiles( deleted );
319 }
320
321 }