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