1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.creator;
20
21 import javax.inject.Named;
22 import javax.inject.Singleton;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.security.DigestInputStream;
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Enumeration;
33 import java.util.jar.Attributes;
34 import java.util.jar.Manifest;
35 import java.util.zip.ZipEntry;
36 import java.util.zip.ZipFile;
37
38 import org.apache.lucene.document.Document;
39 import org.apache.maven.index.ArtifactContext;
40 import org.apache.maven.index.ArtifactInfo;
41 import org.apache.maven.index.IndexerField;
42 import org.apache.maven.index.IndexerFieldVersion;
43 import org.apache.maven.index.OSGI;
44 import org.codehaus.plexus.util.StringUtils;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 @Singleton
65 @Named(OsgiArtifactIndexCreator.ID)
66 public class OsgiArtifactIndexCreator extends AbstractIndexCreator {
67 public static final String ID = "osgi-metadatas";
68
69 public static final IndexerField FLD_SHA256 = new IndexerField(
70 OSGI.SHA256,
71 IndexerFieldVersion.V4,
72 "sha256",
73 "SHA-256 (not analyzed, stored)",
74 IndexerField.KEYWORD_STORED);
75
76 private static final String BSN = "Bundle-SymbolicName";
77
78 public static final IndexerField FLD_BUNDLE_SYMBOLIC_NAME = new IndexerField(
79 OSGI.SYMBOLIC_NAME,
80 IndexerFieldVersion.V4,
81 BSN,
82 "Bundle-SymbolicName (indexed, stored)",
83 IndexerField.ANALYZED_STORED);
84
85 private static final String BV = "Bundle-Version";
86
87 public static final IndexerField FLD_BUNDLE_VERSION = new IndexerField(
88 OSGI.VERSION, IndexerFieldVersion.V4, BV, "Bundle-Version (indexed, stored)", IndexerField.ANALYZED_STORED);
89
90 private static final String BEP = "Export-Package";
91
92 public static final IndexerField FLD_BUNDLE_EXPORT_PACKAGE = new IndexerField(
93 OSGI.EXPORT_PACKAGE,
94 IndexerFieldVersion.V4,
95 BEP,
96 "Export-Package (indexed, stored)",
97 IndexerField.ANALYZED_STORED);
98
99 @Deprecated
100 private static final String BES = "Export-Service";
101
102 @Deprecated
103 public static final IndexerField FLD_BUNDLE_EXPORT_SERVIVE = new IndexerField(
104 OSGI.EXPORT_SERVICE,
105 IndexerFieldVersion.V4,
106 BES,
107 "Export-Service (indexed, stored)",
108 IndexerField.ANALYZED_STORED);
109
110 private static final String BD = "Bundle-Description";
111
112 public static final IndexerField FLD_BUNDLE_DESCRIPTION = new IndexerField(
113 OSGI.DESCRIPTION,
114 IndexerFieldVersion.V4,
115 BD,
116 "Bundle-Description (indexed, stored)",
117 IndexerField.ANALYZED_STORED);
118
119 private static final String BN = "Bundle-Name";
120
121 public static final IndexerField FLD_BUNDLE_NAME = new IndexerField(
122 OSGI.NAME, IndexerFieldVersion.V4, BN, "Bundle-Name (indexed, stored)", IndexerField.ANALYZED_STORED);
123
124 private static final String BL = "Bundle-License";
125
126 public static final IndexerField FLD_BUNDLE_LICENSE = new IndexerField(
127 OSGI.LICENSE, IndexerFieldVersion.V4, BL, "Bundle-License (indexed, stored)", IndexerField.ANALYZED_STORED);
128
129 private static final String BDU = "Bundle-DocURL";
130
131 public static final IndexerField FLD_BUNDLE_DOCURL = new IndexerField(
132 OSGI.DOCURL, IndexerFieldVersion.V4, BDU, "Bundle-DocURL (indexed, stored)", IndexerField.ANALYZED_STORED);
133
134 private static final String BIP = "Import-Package";
135
136 public static final IndexerField FLD_BUNDLE_IMPORT_PACKAGE = new IndexerField(
137 OSGI.IMPORT_PACKAGE,
138 IndexerFieldVersion.V4,
139 BIP,
140 "Import-Package (indexed, stored)",
141 IndexerField.ANALYZED_STORED);
142
143 private static final String BRB = "Require-Bundle";
144
145 public static final IndexerField FLD_BUNDLE_REQUIRE_BUNDLE = new IndexerField(
146 OSGI.REQUIRE_BUNDLE,
147 IndexerFieldVersion.V4,
148 BRB,
149 "Require-Bundle (indexed, stored)",
150 IndexerField.ANALYZED_STORED);
151
152 private static final String PROVIDE_CAPABILITY = "Provide-Capability";
153
154 public static final IndexerField FLD_BUNDLE_PROVIDE_CAPABILITY = new IndexerField(
155 OSGI.PROVIDE_CAPABILITY,
156 IndexerFieldVersion.V4,
157 PROVIDE_CAPABILITY,
158 "Provide-Capability (indexed, stored)",
159 IndexerField.ANALYZED_STORED);
160
161 private static final String REQUIRE_CAPABILITY = "Require-Capability";
162
163 public static final IndexerField FLD_BUNDLE_REQUIRE_CAPABILITY = new IndexerField(
164 OSGI.REQUIRE_CAPABILITY,
165 IndexerFieldVersion.V4,
166 REQUIRE_CAPABILITY,
167 "Require-Capability (indexed, stored)",
168 IndexerField.ANALYZED_STORED);
169
170 private static final String FRAGMENT_HOST = "Fragment-Host";
171
172 public static final IndexerField FLD_BUNDLE_FRAGMENT_HOST = new IndexerField(
173 OSGI.FRAGMENT_HOST,
174 IndexerFieldVersion.V4,
175 FRAGMENT_HOST,
176 "Fragment-Host (indexed, stored)",
177 IndexerField.ANALYZED_STORED);
178
179 private static final String BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
180
181 public static final IndexerField FLD_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT = new IndexerField(
182 OSGI.BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT,
183 IndexerFieldVersion.V4,
184 BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT,
185 "Bundle-RequiredExecutionEnvironment (indexed, stored)",
186 IndexerField.ANALYZED_STORED);
187
188 public Collection<IndexerField> getIndexerFields() {
189 return Arrays.asList(
190 FLD_BUNDLE_SYMBOLIC_NAME,
191 FLD_BUNDLE_VERSION,
192 FLD_BUNDLE_EXPORT_PACKAGE,
193 FLD_BUNDLE_EXPORT_SERVIVE,
194 FLD_BUNDLE_DESCRIPTION,
195 FLD_BUNDLE_NAME,
196 FLD_BUNDLE_LICENSE,
197 FLD_BUNDLE_DOCURL,
198 FLD_BUNDLE_IMPORT_PACKAGE,
199 FLD_BUNDLE_REQUIRE_BUNDLE,
200 FLD_BUNDLE_PROVIDE_CAPABILITY,
201 FLD_BUNDLE_REQUIRE_CAPABILITY,
202 FLD_BUNDLE_FRAGMENT_HOST,
203 FLD_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT,
204 FLD_SHA256);
205 }
206
207 public OsgiArtifactIndexCreator() {
208 super(ID);
209 }
210
211 public void populateArtifactInfo(ArtifactContext artifactContext) throws IOException {
212 ArtifactInfo ai = artifactContext.getArtifactInfo();
213
214 File artifactFile = artifactContext.getArtifact();
215
216
217
218 if (artifactFile != null
219 && artifactFile.isFile()
220 && artifactFile.getName().endsWith(".jar")) {
221 updateArtifactInfo(ai, artifactFile);
222 }
223 }
224
225 public void updateDocument(ArtifactInfo artifactInfo, Document document) {
226
227 if (artifactInfo.getBundleSymbolicName() != null) {
228 document.add(FLD_BUNDLE_SYMBOLIC_NAME.toField(artifactInfo.getBundleSymbolicName()));
229 }
230
231 if (artifactInfo.getBundleVersion() != null) {
232 document.add(FLD_BUNDLE_VERSION.toField(artifactInfo.getBundleVersion()));
233 }
234
235 if (artifactInfo.getBundleExportPackage() != null) {
236 document.add(FLD_BUNDLE_EXPORT_PACKAGE.toField(artifactInfo.getBundleExportPackage()));
237 }
238
239 if (artifactInfo.getBundleExportService() != null) {
240 document.add(FLD_BUNDLE_EXPORT_SERVIVE.toField(artifactInfo.getBundleExportService()));
241 }
242
243 if (artifactInfo.getBundleDescription() != null) {
244 document.add(FLD_BUNDLE_DESCRIPTION.toField(artifactInfo.getBundleDescription()));
245 }
246
247 if (artifactInfo.getBundleName() != null) {
248 document.add(FLD_BUNDLE_NAME.toField(artifactInfo.getBundleName()));
249 }
250
251 if (artifactInfo.getBundleLicense() != null) {
252 document.add(FLD_BUNDLE_LICENSE.toField(artifactInfo.getBundleLicense()));
253 }
254
255 if (artifactInfo.getBundleDocUrl() != null) {
256 document.add(FLD_BUNDLE_DOCURL.toField(artifactInfo.getBundleDocUrl()));
257 }
258
259 if (artifactInfo.getBundleImportPackage() != null) {
260 document.add(FLD_BUNDLE_IMPORT_PACKAGE.toField(artifactInfo.getBundleImportPackage()));
261 }
262
263 if (artifactInfo.getBundleRequireBundle() != null) {
264 document.add(FLD_BUNDLE_REQUIRE_BUNDLE.toField(artifactInfo.getBundleRequireBundle()));
265 }
266
267 if (artifactInfo.getBundleProvideCapability() != null) {
268 document.add(FLD_BUNDLE_PROVIDE_CAPABILITY.toField(artifactInfo.getBundleProvideCapability()));
269 }
270
271 if (artifactInfo.getBundleRequireCapability() != null) {
272 document.add(FLD_BUNDLE_REQUIRE_CAPABILITY.toField(artifactInfo.getBundleRequireCapability()));
273 }
274
275 if (artifactInfo.getBundleFragmentHost() != null) {
276 document.add(FLD_BUNDLE_FRAGMENT_HOST.toField(artifactInfo.getBundleFragmentHost()));
277 }
278
279 String bree = artifactInfo.getBundleRequiredExecutionEnvironment();
280 if (bree != null) {
281 document.add(FLD_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT.toField(bree));
282 }
283
284 if (artifactInfo.getSha256() != null) {
285 document.add(FLD_SHA256.toField(artifactInfo.getSha256()));
286 }
287 }
288
289 public boolean updateArtifactInfo(Document document, ArtifactInfo artifactInfo) {
290 boolean updated = false;
291
292 String bundleSymbolicName = document.get(FLD_BUNDLE_SYMBOLIC_NAME.getKey());
293
294 if (bundleSymbolicName != null) {
295 artifactInfo.setBundleSymbolicName(bundleSymbolicName);
296
297 updated = true;
298 }
299
300 String bundleVersion = document.get(FLD_BUNDLE_VERSION.getKey());
301
302 if (bundleVersion != null) {
303 artifactInfo.setBundleVersion(bundleVersion);
304
305 updated = true;
306 }
307
308 String bundleExportPackage = document.get(FLD_BUNDLE_EXPORT_PACKAGE.getKey());
309
310 if (bundleExportPackage != null) {
311 artifactInfo.setBundleExportPackage(bundleExportPackage);
312
313 updated = true;
314 }
315
316 String bundleExportService = document.get(FLD_BUNDLE_EXPORT_SERVIVE.getKey());
317
318 if (bundleExportService != null) {
319 artifactInfo.setBundleExportService(bundleExportService);
320
321 updated = true;
322 }
323
324 String bundleDescription = document.get(FLD_BUNDLE_DESCRIPTION.getKey());
325
326 if (bundleDescription != null) {
327 artifactInfo.setBundleDescription(bundleDescription);
328
329 updated = true;
330 }
331
332 String bundleName = document.get(FLD_BUNDLE_NAME.getKey());
333
334 if (bundleName != null) {
335 artifactInfo.setBundleName(bundleName);
336
337 updated = true;
338 }
339
340 String bundleLicense = document.get(FLD_BUNDLE_LICENSE.getKey());
341
342 if (bundleLicense != null) {
343 artifactInfo.setBundleLicense(bundleLicense);
344
345 updated = true;
346 }
347
348 String bundleDocUrl = document.get(FLD_BUNDLE_DOCURL.getKey());
349
350 if (bundleDocUrl != null) {
351 artifactInfo.setBundleDocUrl(bundleDocUrl);
352
353 updated = true;
354 }
355
356 String bundleImportPackage = document.get(FLD_BUNDLE_IMPORT_PACKAGE.getKey());
357
358 if (bundleImportPackage != null) {
359 artifactInfo.setBundleImportPackage(bundleImportPackage);
360
361 updated = true;
362 }
363
364 String bundleRequireBundle = document.get(FLD_BUNDLE_REQUIRE_BUNDLE.getKey());
365
366 if (bundleRequireBundle != null) {
367 artifactInfo.setBundleRequireBundle(bundleRequireBundle);
368
369 updated = true;
370 }
371
372 String bundleProvideCapability = document.get(FLD_BUNDLE_PROVIDE_CAPABILITY.getKey());
373
374 if (bundleProvideCapability != null) {
375 artifactInfo.setBundleProvideCapability(bundleProvideCapability);
376
377 updated = true;
378 }
379
380 String bundleRequireCapability = document.get(FLD_BUNDLE_REQUIRE_CAPABILITY.getKey());
381
382 if (bundleRequireCapability != null) {
383 artifactInfo.setBundleRequireCapability(bundleRequireCapability);
384
385 updated = true;
386 }
387
388 String bundleFragmentHost = document.get(FLD_BUNDLE_FRAGMENT_HOST.getKey());
389
390 if (bundleFragmentHost != null) {
391 artifactInfo.setBundleFragmentHost(bundleFragmentHost);
392
393 updated = true;
394 }
395
396 String bundleRequiredExecutionEnvironment = document.get(FLD_BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT.getKey());
397
398 if (bundleRequiredExecutionEnvironment != null) {
399 artifactInfo.setBundleRequiredExecutionEnvironment(bundleRequiredExecutionEnvironment);
400
401 updated = true;
402 }
403
404 String sha256 = document.get(FLD_SHA256.getKey());
405
406 if (sha256 != null) {
407 artifactInfo.setSha256(sha256);
408
409 updated = true;
410 }
411
412 return updated;
413 }
414
415 private boolean updateArtifactInfo(ArtifactInfo ai, File f) throws IOException {
416 boolean updated = false;
417
418 try (ZipFile zipFile = new ZipFile(f)) {
419 final Enumeration<? extends ZipEntry> entries = zipFile.entries();
420
421 while (entries.hasMoreElements()) {
422 ZipEntry zipEntry = entries.nextElement();
423
424 if (zipEntry.getName().equals("META-INF/MANIFEST.MF")) {
425 Manifest manifest = new Manifest(zipFile.getInputStream(zipEntry));
426
427 Attributes mainAttributes = manifest.getMainAttributes();
428
429 if (mainAttributes != null) {
430 String attValue = mainAttributes.getValue(BSN);
431 if (StringUtils.isNotBlank(attValue)) {
432 ai.setBundleSymbolicName(attValue);
433 updated = true;
434 } else {
435 ai.setBundleSymbolicName(null);
436 }
437
438 attValue = mainAttributes.getValue(BV);
439 if (StringUtils.isNotBlank(attValue)) {
440 ai.setBundleVersion(attValue);
441 updated = true;
442 } else {
443 ai.setBundleVersion(null);
444 }
445
446 attValue = mainAttributes.getValue(BEP);
447 if (StringUtils.isNotBlank(attValue)) {
448 ai.setBundleExportPackage(attValue);
449 updated = true;
450 } else {
451 ai.setBundleExportPackage(null);
452 }
453
454 attValue = mainAttributes.getValue(BES);
455 if (StringUtils.isNotBlank(attValue)) {
456 ai.setBundleExportService(attValue);
457 updated = true;
458 } else {
459 ai.setBundleExportService(null);
460 }
461
462 attValue = mainAttributes.getValue(BD);
463 if (StringUtils.isNotBlank(attValue)) {
464 ai.setBundleDescription(attValue);
465 updated = true;
466 } else {
467 ai.setBundleDescription(null);
468 }
469
470 attValue = mainAttributes.getValue(BN);
471 if (StringUtils.isNotBlank(attValue)) {
472 ai.setBundleName(attValue);
473 updated = true;
474 } else {
475 ai.setBundleName(null);
476 }
477
478 attValue = mainAttributes.getValue(BL);
479 if (StringUtils.isNotBlank(attValue)) {
480 ai.setBundleLicense(attValue);
481 updated = true;
482 } else {
483 ai.setBundleLicense(null);
484 }
485
486 attValue = mainAttributes.getValue(BDU);
487 if (StringUtils.isNotBlank(attValue)) {
488 ai.setBundleDocUrl(attValue);
489 updated = true;
490 } else {
491 ai.setBundleDocUrl(null);
492 }
493
494 attValue = mainAttributes.getValue(BIP);
495 if (StringUtils.isNotBlank(attValue)) {
496 ai.setBundleImportPackage(attValue);
497 updated = true;
498 } else {
499 ai.setBundleImportPackage(null);
500 }
501
502 attValue = mainAttributes.getValue(BRB);
503 if (StringUtils.isNotBlank(attValue)) {
504 ai.setBundleRequireBundle(attValue);
505 updated = true;
506 } else {
507 ai.setBundleRequireBundle(null);
508 }
509
510 attValue = mainAttributes.getValue(PROVIDE_CAPABILITY);
511 if (StringUtils.isNotBlank(attValue)) {
512 ai.setBundleProvideCapability(attValue);
513 updated = true;
514 } else {
515 ai.setBundleProvideCapability(null);
516 }
517
518 attValue = mainAttributes.getValue(REQUIRE_CAPABILITY);
519 if (StringUtils.isNotBlank(attValue)) {
520 ai.setBundleRequireCapability(attValue);
521 updated = true;
522 } else {
523 ai.setBundleRequireCapability(null);
524 }
525
526 attValue = mainAttributes.getValue(FRAGMENT_HOST);
527 if (StringUtils.isNotBlank(attValue)) {
528 ai.setBundleFragmentHost(attValue);
529 updated = true;
530 } else {
531 ai.setBundleFragmentHost(null);
532 }
533
534 attValue = mainAttributes.getValue(BUNDLE_REQUIRED_EXECUTION_ENVIRONMENT);
535 if (StringUtils.isNotBlank(attValue)) {
536 ai.setBundleRequiredExecutionEnvironment(attValue);
537 updated = true;
538 } else {
539 ai.setBundleRequiredExecutionEnvironment(null);
540 }
541 }
542 }
543 }
544 }
545
546
547 if (ai.getBundleSymbolicName() != null) {
548 String sha256 = computeSha256(f);
549 if (sha256 != null) {
550 ai.setSha256(sha256);
551 updated = true;
552 } else {
553 ai.setSha256(null);
554 }
555 }
556
557 return updated;
558 }
559
560 private String computeSha256(File f) throws IOException {
561 String sha256 = null;
562 try {
563 MessageDigest digest = MessageDigest.getInstance("SHA-256");
564
565 try (DigestInputStream in = new DigestInputStream(new FileInputStream(f), digest)) {
566 byte[] buf = new byte[8192];
567 while (in.read(buf) >= 0) {
568
569 }
570 byte[] digestBytes = digest.digest();
571 StringBuilder builder = new StringBuilder(64);
572 for (int b : digestBytes) {
573 b &= 0xff;
574 builder.append(String.format("%02x", b));
575 sha256 = builder.toString();
576 }
577 }
578
579 } catch (NoSuchAlgorithmException e) {
580 }
581 return sha256;
582 }
583
584 @Override
585 public String toString() {
586 return ID;
587 }
588 }