1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.treeview;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.lucene.search.BooleanClause;
32 import org.apache.lucene.search.BooleanQuery;
33 import org.apache.lucene.search.Query;
34 import org.apache.maven.index.ArtifactInfo;
35 import org.apache.maven.index.Field;
36 import org.apache.maven.index.Indexer;
37 import org.apache.maven.index.IteratorSearchRequest;
38 import org.apache.maven.index.IteratorSearchResponse;
39 import org.apache.maven.index.MAVEN;
40 import org.apache.maven.index.expr.SourcedSearchExpression;
41 import org.apache.maven.index.treeview.TreeNode.Type;
42 import org.codehaus.plexus.util.StringUtils;
43
44 @Singleton
45 @Named
46 public class DefaultIndexTreeView implements IndexTreeView {
47
48 private final Indexer indexer;
49
50 @Inject
51 public DefaultIndexTreeView(Indexer indexer) {
52 this.indexer = indexer;
53 }
54
55 protected Indexer getIndexer() {
56 return indexer;
57 }
58
59 public TreeNode listNodes(TreeViewRequest request) throws IOException {
60
61 String name;
62
63 if (!"/".equals(request.getPath())) {
64
65 if (request.getPath().endsWith("/")) {
66 name = request.getPath().substring(0, request.getPath().length() - 1);
67 } else {
68 name = request.getPath();
69 }
70
71 name = name.substring(name.lastIndexOf('/') + 1);
72
73
74 if (!name.equals("/") && name.endsWith("/")) {
75 name = name.substring(0, name.length() - 1);
76 }
77
78 } else {
79 name = "/";
80 }
81
82
83 TreeNode result = request.getFactory().createGNode(this, request, request.getPath(), name);
84
85 if (request.hasFieldHints()) {
86 listChildren(result, request, null);
87 } else {
88
89 if ("/".equals(request.getPath())) {
90
91 Set<String> rootGroups = request.getIndexingContext().getRootGroups();
92
93 for (String group : rootGroups) {
94 if (group.length() > 0) {
95 result.getChildren()
96 .add(request.getFactory()
97 .createGNode(this, request, request.getPath() + group + "/", group));
98 }
99 }
100 } else {
101 Set<String> allGroups = request.getIndexingContext().getAllGroups();
102
103 listChildren(result, request, allGroups);
104 }
105 }
106
107 return result;
108 }
109
110
111
112
113
114
115
116 protected void listChildren(TreeNode root, TreeViewRequest request, Set<String> allGroups) throws IOException {
117 String path = root.getPath();
118
119 Map<String, TreeNode> folders = new HashMap<>();
120
121 String rootPartialGroupId = StringUtils.strip(root.getPath().replaceAll("/", "."), ".");
122
123 folders.put(Type.G + ":" + rootPartialGroupId, root);
124
125 try (IteratorSearchResponse artifacts = getArtifacts(root, request)) {
126 for (ArtifactInfo ai : artifacts) {
127 String versionKey = Type.V + ":" + ai.getArtifactId() + ":" + ai.getVersion();
128
129 TreeNode versionResource = folders.get(versionKey);
130
131 if (versionResource == null) {
132 String artifactKey = Type.A + ":" + ai.getArtifactId();
133
134 TreeNode artifactResource = folders.get(artifactKey);
135
136 if (artifactResource == null) {
137 TreeNode groupParentResource = root;
138
139 TreeNode groupResource;
140
141
142 String partialGroupId = null;
143
144 String[] groupIdElems = ai.getGroupId().split("\\.");
145
146 for (String groupIdElem : groupIdElems) {
147 if (partialGroupId == null) {
148 partialGroupId = groupIdElem;
149 } else {
150 partialGroupId = partialGroupId + "." + groupIdElem;
151 }
152
153 String groupKey = Type.G + ":" + partialGroupId;
154
155 groupResource = folders.get(groupKey);
156
157
158 if (groupResource == null
159 && groupParentResource.getPath().length()
160 < getPathForAi(ai, MAVEN.GROUP_ID).length()) {
161 String gNodeName = partialGroupId.lastIndexOf('.') > -1
162 ? partialGroupId.substring(partialGroupId.lastIndexOf('.') + 1)
163 : partialGroupId;
164
165 groupResource = request.getFactory()
166 .createGNode(
167 this,
168 request,
169 "/" + partialGroupId.replaceAll("\\.", "/") + "/",
170 gNodeName);
171
172 groupParentResource.getChildren().add(groupResource);
173
174 folders.put(groupKey, groupResource);
175
176 groupParentResource = groupResource;
177 } else if (groupResource != null) {
178
179 if (groupResource.getPath().equals(getPathForAi(ai, MAVEN.GROUP_ID))) {
180 break;
181 }
182
183 groupParentResource = groupResource;
184 }
185 }
186
187 artifactResource = request.getFactory()
188 .createANode(this, request, ai, getPathForAi(ai, MAVEN.ARTIFACT_ID));
189
190 groupParentResource.getChildren().add(artifactResource);
191
192 folders.put(artifactKey, artifactResource);
193 }
194
195 versionResource =
196 request.getFactory().createVNode(this, request, ai, getPathForAi(ai, MAVEN.VERSION));
197
198 artifactResource.getChildren().add(versionResource);
199
200 folders.put(versionKey, versionResource);
201 }
202
203 String nodePath = getPathForAi(ai, null);
204
205 versionResource.getChildren().add(request.getFactory().createArtifactNode(this, request, ai, nodePath));
206 }
207 }
208
209 if (!request.hasFieldHints()) {
210 Set<String> groups = getGroups(path, allGroups);
211
212 for (String group : groups) {
213 TreeNode groupResource = root.findChildByPath(path + group + "/", Type.G);
214
215 if (groupResource == null) {
216 groupResource = request.getFactory().createGNode(this, request, path + group + "/", group);
217
218 root.getChildren().add(groupResource);
219 } else {
220
221
222 listChildren(groupResource, request, allGroups);
223 }
224 }
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237 protected String getPathForAi(ArtifactInfo ai, Field field) {
238 StringBuilder sb = new StringBuilder("/");
239
240 sb.append(ai.getGroupId().replaceAll("\\.", "/"));
241
242 if (MAVEN.GROUP_ID.equals(field)) {
243
244 return sb.append("/").toString();
245 }
246
247 sb.append("/").append(ai.getArtifactId());
248
249 if (MAVEN.ARTIFACT_ID.equals(field)) {
250
251 return sb.append("/").toString();
252 }
253
254 sb.append("/").append(ai.getVersion());
255
256 if (MAVEN.VERSION.equals(field)) {
257
258 return sb.append("/").toString();
259 }
260
261 sb.append("/").append(ai.getArtifactId()).append("-").append(ai.getVersion());
262
263 if (ai.getClassifier() != null) {
264 sb.append("-").append(ai.getClassifier());
265 }
266
267 sb.append(".").append(ai.getFileExtension() == null ? "jar" : ai.getFileExtension());
268
269 return sb.toString();
270 }
271
272 protected Set<String> getGroups(String path, Set<String> allGroups) {
273 path = path.substring(1).replace('/', '.');
274
275 int n = path.length();
276
277 Set<String> result = new HashSet<>();
278
279 for (String group : allGroups) {
280 if (group.startsWith(path)) {
281 group = group.substring(n);
282
283 int nextDot = group.indexOf('.');
284
285 if (nextDot > -1) {
286 group = group.substring(0, nextDot);
287 }
288
289 if (group.length() > 0) {
290 result.add(group);
291 }
292 }
293 }
294
295 return result;
296 }
297
298 protected IteratorSearchResponse getArtifacts(TreeNode root, TreeViewRequest request) throws IOException {
299 if (request.hasFieldHints()) {
300 return getHintedArtifacts(root, request);
301 }
302
303 String path = root.getPath();
304
305 IteratorSearchResponse result;
306
307 String g;
308
309 String a;
310
311 String v;
312
313
314 String wp;
315
316
317 if (path.endsWith("/")) {
318 path = path.substring(0, path.length() - 1);
319 }
320
321
322
323
324 wp = path;
325
326 g = wp.substring(1).replace('/', '.');
327
328 result = getArtifactsByG(g, request);
329
330 if (result.getTotalHitsCount() > 0) {
331 return result;
332 } else {
333 result.close();
334 }
335
336
337
338 if (path.lastIndexOf('/') > 0) {
339
340 wp = path;
341
342 a = wp.substring(wp.lastIndexOf('/') + 1);
343
344 g = wp.substring(1, wp.lastIndexOf('/')).replace('/', '.');
345
346 result = getArtifactsByGA(g, a, request);
347
348 if (result.getTotalHitsCount() > 0) {
349 return result;
350 } else {
351 result.close();
352 }
353
354
355
356 try {
357
358 wp = path;
359
360 v = wp.substring(wp.lastIndexOf('/') + 1);
361
362 wp = wp.substring(0, wp.lastIndexOf('/'));
363
364 a = wp.substring(wp.lastIndexOf('/') + 1);
365
366 g = wp.substring(1, wp.lastIndexOf('/')).replace('/', '.');
367
368 result = getArtifactsByGAV(g, a, v, request);
369
370 if (result.getTotalHitsCount() > 0) {
371 return result;
372 } else {
373 result.close();
374 }
375 } catch (StringIndexOutOfBoundsException e) {
376
377 }
378 }
379
380
381 return IteratorSearchResponse.empty(result.getQuery());
382 }
383
384 protected IteratorSearchResponse getHintedArtifacts(TreeNode root, TreeViewRequest request) throws IOException {
385
386 if (request.hasFieldHint(MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID, MAVEN.VERSION)) {
387 return getArtifactsByGAV(
388 request.getFieldHint(MAVEN.GROUP_ID),
389 request.getFieldHint(MAVEN.ARTIFACT_ID),
390 request.getFieldHint(MAVEN.VERSION),
391 request);
392 } else if (request.hasFieldHint(MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID)) {
393 return getArtifactsByGA(
394 request.getFieldHint(MAVEN.GROUP_ID), request.getFieldHint(MAVEN.ARTIFACT_ID), request);
395 } else if (request.hasFieldHint(MAVEN.GROUP_ID)) {
396 return getArtifactsByG(request.getFieldHint(MAVEN.GROUP_ID), request);
397 } else {
398
399 return IteratorSearchResponse.empty(null);
400 }
401 }
402
403 protected IteratorSearchResponse getArtifactsByG(String g, TreeViewRequest request) throws IOException {
404 return getArtifactsByGAVField(g, null, null, request);
405 }
406
407 protected IteratorSearchResponse getArtifactsByGA(String g, String a, TreeViewRequest request) throws IOException {
408 return getArtifactsByGAVField(g, a, null, request);
409 }
410
411 protected IteratorSearchResponse getArtifactsByGAV(String g, String a, String v, TreeViewRequest request)
412 throws IOException {
413 return getArtifactsByGAVField(g, a, v, request);
414 }
415
416 protected IteratorSearchResponse getArtifactsByGAVField(String g, String a, String v, TreeViewRequest request)
417 throws IOException {
418 assert g != null;
419
420 Query groupIdQ;
421 Query artifactIdQ = null;
422 Query versionQ = null;
423
424
425 groupIdQ = getIndexer().constructQuery(MAVEN.GROUP_ID, new SourcedSearchExpression(g));
426
427 if (StringUtils.isNotBlank(a)) {
428 artifactIdQ = getIndexer().constructQuery(MAVEN.ARTIFACT_ID, new SourcedSearchExpression(a));
429 }
430
431 if (StringUtils.isNotBlank(v)) {
432 versionQ = getIndexer().constructQuery(MAVEN.VERSION, new SourcedSearchExpression(v));
433 }
434
435 BooleanQuery.Builder qb = new BooleanQuery.Builder().add(new BooleanClause(groupIdQ, BooleanClause.Occur.MUST));
436
437 if (artifactIdQ != null) {
438 qb.add(new BooleanClause(artifactIdQ, BooleanClause.Occur.MUST));
439 }
440
441 if (versionQ != null) {
442 qb.add(new BooleanClause(versionQ, BooleanClause.Occur.MUST));
443 }
444
445 IteratorSearchRequest searchRequest = new IteratorSearchRequest(qb.build(), request.getArtifactInfoFilter());
446
447 searchRequest.getContexts().add(request.getIndexingContext());
448
449 IteratorSearchResponse result = getIndexer().searchIterator(searchRequest);
450
451 return result;
452 }
453 }