1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.shared.jar.identification;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.List;
26
27 import org.apache.maven.shared.jar.JarAnalyzer;
28 import org.codehaus.plexus.util.StringUtils;
29
30 import static java.util.Objects.requireNonNull;
31
32 /**
33 * Analyze the JAR file to identify Maven artifact metadata. This class is thread safe and immutable as long as all
34 * provided exposers are, as it retains no state.
35 *
36 * If using Plexus, the class will use all available exposers in the container.
37 *
38 * Note that you must first create an instance of {@link org.apache.maven.shared.jar.JarAnalyzer} - see its Javadoc for
39 * a typical use.
40 */
41 @Singleton
42 @Named
43 public class JarIdentificationAnalysis {
44 /**
45 * The Maven information exposers to use during identification.
46 */
47 private final List<JarIdentificationExposer> exposers;
48
49 @Inject
50 public JarIdentificationAnalysis(List<JarIdentificationExposer> exposers) {
51 this.exposers = requireNonNull(exposers);
52 }
53
54 /**
55 * Analyze a JAR and find any associated Maven metadata. Note that if the provided JAR analyzer has previously
56 * analyzed the JAR, the cached results will be returned. You must obtain a new JAR analyzer to the re-read the
57 * contents of the file.
58 *
59 * @param jarAnalyzer the JAR to analyze. This must not yet have been closed.
60 * @return the Maven metadata discovered
61 */
62 public JarIdentification analyze(JarAnalyzer jarAnalyzer) {
63 JarIdentification taxon = jarAnalyzer.getJarData().getJarIdentification();
64 if (taxon != null) {
65 return taxon;
66 }
67
68 taxon = new JarIdentification();
69
70 for (JarIdentificationExposer exposer : exposers) {
71 exposer.expose(taxon, jarAnalyzer);
72 }
73
74 normalize(taxon);
75
76 jarAnalyzer.getJarData().setJarIdentification(taxon);
77
78 return taxon;
79 }
80
81 private void normalize(JarIdentification taxon) {
82 if (StringUtils.isEmpty(taxon.getGroupId())) {
83 taxon.setGroupId(pickSmallest(taxon.getPotentialGroupIds()));
84 }
85
86 if (StringUtils.isEmpty(taxon.getArtifactId())) {
87 taxon.setArtifactId(pickLargest(taxon.getPotentialArtifactIds()));
88 }
89
90 if (StringUtils.isEmpty(taxon.getVersion())) {
91 taxon.setVersion(pickSmallest(taxon.getPotentialVersions()));
92 }
93
94 if (StringUtils.isEmpty(taxon.getName())) {
95 taxon.setName(pickLargest(taxon.getPotentialNames()));
96 }
97
98 if (StringUtils.isEmpty(taxon.getVendor())) {
99 taxon.setVendor(pickLargest(taxon.getPotentialVendors()));
100 }
101 }
102
103 private String pickSmallest(List<String> list) {
104 String smallest = null;
105
106 int size = Integer.MAX_VALUE;
107 for (String val : list) {
108 if (val != null && !val.isEmpty()) {
109 if (val.length() < size) {
110 smallest = val;
111 size = val.length();
112 }
113 }
114 }
115
116 return smallest;
117 }
118
119 private String pickLargest(List<String> list) {
120 String largest = null;
121 int size = Integer.MIN_VALUE;
122 for (String val : list) {
123 if (val != null && !val.isEmpty()) {
124 if (val.length() > size) {
125 largest = val;
126 size = val.length();
127 }
128 }
129 }
130 return largest;
131 }
132 }