View Javadoc
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 (StringUtils.isNotEmpty(val)) {
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 (StringUtils.isNotEmpty(val)) {
124                 if (val.length() > size) {
125                     largest = val;
126                     size = val.length();
127                 }
128             }
129         }
130         return largest;
131     }
132 }