##### Coverage Report - org.owasp.dependencycheck.utils.DependencyVersion

Classes in this File | Line Coverage | Branch Coverage | Complexity
DependencyVersion |
92% | 76/82
80% | 50/62
| 5.090909090909091;5.091

1 |  |
     /*
2 |  |
      * This file is part of dependency-check-core.
3 |  |
      *
4 |  |
      * Dependency-check-core is free software: you can redistribute it and/or modify it
5 |  |
      * under the terms of the GNU General Public License as published by the Free
6 |  |
      * Software Foundation, either version 3 of the License, or (at your option) any
7 |  |
      * later version.
8 |  |
      *
9 |  |
      * Dependency-check-core is distributed in the hope that it will be useful, but
10 |  |
      * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 |  |
      * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 |  |
      * details.
13 |  |
      *
14 |  |
      * You should have received a copy of the GNU General Public License along with
15 |  |
      * dependency-check-core. If not, see http://www.gnu.org/licenses/.
16 |  |
      *
17 |  |
      * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
18 |  |
      */
19 |  |
     package org.owasp.dependencycheck.utils;
20 |  |
21 |  |
     import java.util.ArrayList;
22 |  |
     import java.util.Iterator;
23 |  |
     import java.util.List;
24 |  |
     import java.util.regex.Matcher;
25 |  |
     import java.util.regex.Pattern;
26 |  |
     import org.apache.commons.lang.StringUtils;
27 |  |
28 |  |
     /**
29 |  |
      * <p>Simple object to track the parts of a version number. The parts are
30 |  |
      * contained in a List such that version 1.2.3 will be stored as:
31 |  |
      * <code>versionParts[0] = 1;
32 |  |
      * versionParts[1] = 2;
33 |  |
      * versionParts[2] = 3;
34 |  |
      * </code></p>
35 |  |
      * <p>Note, the parser contained in this class expects the version numbers to be
36 |  |
      * separated by periods. If a different separator is used the parser will likely
37 |  |
      * fail.</p>
38 |  |
      *
39 |  |
      * @author Jeremy Long (jeremy.long@owasp.org)
40 |  |
      */
41 | 13 |
     public class DependencyVersion implements Iterable, Comparable<DependencyVersion> {
42 |  |
43 |  |
         /**
44 |  |
          * Constructor for a empty DependencyVersion.
45 |  |
          */
46 | 20 |
         public DependencyVersion() {
47 | 20 |
         }
48 |  |
49 |  |
         /**
50 |  |
          * Constructor for a DependencyVersion that will parse a version string.
51 |  |
          * <b>Note</b>, this should only be used when the version passed in is
52 |  |
          * already known to be a well formated version number. Otherwise,
53 |  |
          * DependencyVersionUtil.parseVersion() should be used instead.
54 |  |
          *
55 |  |
          * @param version the well formated version number to parse
56 |  |
          */
57 | 12808 |
         public DependencyVersion(String version) {
58 | 12808 |
             parseVersion(version);
59 | 12808 |
         }
60 |  |
61 |  |
         /**
62 |  |
          * Parses a version string into its sub parts: major, minor, revision,
63 |  |
          * build, etc. <b>Note</b>, this should only be used to parse something that
64 |  |
          * is already known to be a version number.
65 |  |
          *
66 |  |
          * @param version the version string to parse
67 |  |
          */
68 |  |
         public final void parseVersion(String version) {
69 | 12810 |
             versionParts = new ArrayList<String>();
70 | 12810 |
             if (version != null) {
71 | 12810 |
                 final Pattern rx = Pattern.compile("(\\d+|[a-z]+\\d+|(release|beta|alpha)$)");
72 | 12810 |
                 final Matcher matcher = rx.matcher(version.toLowerCase());
73 | 52728 |
                 while (matcher.find()) {
74 | 39918 |
                     versionParts.add(matcher.group());
75 |  |
                 }
76 | 12810 |
                 if (versionParts.isEmpty()) {
77 | 77 |
                     versionParts.add(version);
78 |  |
                 }
79 |  |
             }
80 | 12810 |
         }
81 |  |
         /**
82 |  |
          * A list of the version parts.
83 |  |
          */
84 |  |
         private List<String> versionParts;
85 |  |
86 |  |
         /**
87 |  |
          * Get the value of versionParts.
88 |  |
          *
89 |  |
          * @return the value of versionParts
90 |  |
          */
91 |  |
         public List<String> getVersionParts() {
92 | 18190 |
             return versionParts;
93 |  |
         }
94 |  |
95 |  |
         /**
96 |  |
          * Set the value of versionParts.
97 |  |
          *
98 |  |
          * @param versionParts new value of versionParts
99 |  |
          */
100 |  |
         public void setVersionParts(List<String> versionParts) {
101 | 19 |
             this.versionParts = versionParts;
102 | 19 |
         }
103 |  |
104 |  |
         /**
105 |  |
          * Retrieves an iterator for the version parts.
106 |  |
          *
107 |  |
          * @return an iterator for the version parts
108 |  |
          */
109 |  |
         public Iterator iterator() {
110 | 1 |
             return versionParts.iterator();
111 |  |
         }
112 |  |
113 |  |
         /**
114 |  |
          * Reconstructs the version string from the split version parts.
115 |  |
          *
116 |  |
          * @return a string representing the version.
117 |  |
          */
118 |  |
         @Override
119 |  |
         public String toString() {
120 | 3681 |
             return StringUtils.join(versionParts.toArray(), ".");
121 |  |
         }
122 |  |
123 |  |
         /**
124 |  |
          * Compares the equality of this object to the one passed in as a parameter.
125 |  |
          *
126 |  |
          * @param obj the object to compare equality
127 |  |
          * @return returns true only if the two objects are equal, otherwise false
128 |  |
          */
129 |  |
         @Override
130 |  |
         public boolean equals(Object obj) {
131 | 12444 |
             if (obj == null) {
132 | 0 |
                 return false;
133 |  |
             }
134 | 12444 |
             if (getClass() != obj.getClass()) {
135 | 0 |
                 return false;
136 |  |
             }
137 | 12444 |
             final DependencyVersion other = (DependencyVersion) obj;
138 | 12444 |
             final int max = (this.versionParts.size() < other.versionParts.size())
139 |  |
                     ? this.versionParts.size() : other.versionParts.size();
140 |  |
             //TODO steal better version of code from compareTo
141 | 18863 |
             for (int i = 0; i < max; i++) {
142 | 18174 |
                 final String thisPart = this.versionParts.get(i);
143 | 18174 |
                 final String otherPart = other.versionParts.get(i);
144 | 18174 |
                 if (!thisPart.equals(otherPart)) {
145 | 11755 |
                     return false;
146 |  |
                 }
147 |  |
             }
148 | 689 |
             if (this.versionParts.size() > max) {
149 | 86 |
                 for (int i = max; i < this.versionParts.size(); i++) {
150 | 86 |
                     if (!"0".equals(this.versionParts.get(i))) {
151 | 86 |
                         return false;
152 |  |
                     }
153 |  |
                 }
154 |  |
             }
155 |  |
156 | 603 |
             if (other.versionParts.size() > max) {
157 | 463 |
                 for (int i = max; i < other.versionParts.size(); i++) {
158 | 447 |
                     if (!"0".equals(other.versionParts.get(i))) {
159 | 415 |
                         return false;
160 |  |
                     }
161 |  |
                 }
162 |  |
             }
163 |  |
164 |  |
             /*
165 |  |
              *  if (this.versionParts != other.versionParts && (this.versionParts == null || !this.versionParts.equals(other.versionParts))) {
166 |  |
              *      return false;
167 |  |
              *  }
168 |  |
              */
169 | 188 |
             return true;
170 |  |
         }
171 |  |
172 |  |
         /**
173 |  |
          * Calculates the hashCode for this object.
174 |  |
          *
175 |  |
          * @return the hashCode
176 |  |
          */
177 |  |
         @Override
178 |  |
         public int hashCode() {
179 | 1 |
             int hash = 5;
180 | 1 |
             hash = 71 * hash + (this.versionParts != null ? this.versionParts.hashCode() : 0);
181 | 1 |
             return hash;
182 |  |
         }
183 |  |
184 |  |
         /**
185 |  |
          * Determines if the three most major major version parts are identical. For
186 |  |
          * instances, if version 1.2.3.4 was compared to 1.2.3 this function would
187 |  |
          * return true.
188 |  |
          *
189 |  |
          * @param version the version number to compare
190 |  |
          * @return true if the first three major parts of the version are identical
191 |  |
          */
192 |  |
         public boolean matchesAtLeastThreeLevels(DependencyVersion version) {
193 | 8335 |
             if (version == null) {
194 | 0 |
                 return false;
195 |  |
             }
196 |  |
197 | 8335 |
             boolean ret = true;
198 | 8335 |
             int max = (this.versionParts.size() < version.versionParts.size())
199 |  |
                     ? this.versionParts.size() : version.versionParts.size();
200 |  |
201 | 8335 |
             if (max > 3) {
202 | 2 |
                 max = 3;
203 |  |
             }
204 |  |
205 | 12626 |
             for (int i = 0; i < max; i++) {
206 | 12212 |
                 if (this.versionParts.get(i) == null || !this.versionParts.get(i).equals(version.versionParts.get(i))) {
207 | 7921 |
                     ret = false;
208 | 7921 |
                     break;
209 |  |
                 }
210 |  |
             }
211 |  |
212 | 8335 |
             return ret;
213 |  |
         }
214 |  |
215 |  |
         @Override
216 |  |
         public int compareTo(DependencyVersion version) {
217 | 54 |
             if (version == null) {
218 | 0 |
                 return 1;
219 |  |
             }
220 | 54 |
             final List<String> left = this.getVersionParts();
221 | 54 |
             final List<String> right = version.getVersionParts();
222 | 54 |
             final int max = left.size() < right.size() ? left.size() : right.size();
223 |  |
224 | 88 |
             for (int i = 0; i < max; i++) {
225 | 81 |
                 final String lStr = left.get(i);
226 | 81 |
                 final String rStr = right.get(i);
227 | 81 |
                 if (lStr.equals(rStr)) {
228 | 34 |
                     continue;
229 |  |
                 }
230 |  |
                 try {
231 | 47 |
                     final int l = Integer.parseInt(lStr);
232 | 46 |
                     final int r = Integer.parseInt(rStr);
233 | 41 |
                     if (l < r) {
234 | 32 |
                         return -1;
235 | 9 |
                     } else if (l > r) {
236 | 9 |
                         return 1;
237 |  |
                     }
238 | 6 |
                 } catch (NumberFormatException ex) {
239 | 6 |
                     final int comp = left.get(i).compareTo(right.get(i));
240 | 6 |
                     if (comp < 0) {
241 | 0 |
                         return -1;
242 | 6 |
                     } else if (comp > 0) {
243 | 6 |
                         return 1;
244 |  |
                     }
245 | 0 |
                 }
246 |  |
             }
247 | 7 |
             if (left.size() < right.size()) {
248 | 3 |
                 return -1;
249 | 4 |
             } else if (left.size() > right.size()) {
250 | 3 |
                 return 1;
251 |  |
             } else {
252 | 1 |
                 return 0;
253 |  |
             }
254 |  |
         }
255 |  |
     }