001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.kernel.repository;
018
019 import java.util.StringTokenizer;
020 import java.io.Serializable;
021
022 /**
023 * Default implementation of artifact versioning.
024 *
025 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
026 * @version $Id: Version.java 476049 2006-11-17 04:35:17Z kevan $
027 */
028 // This code was lifted from Apache Maven
029 public class Version implements Comparable, Serializable {
030 // Geronimo adds Serial UID because we serialize versions into config.ser
031 private static final long serialVersionUID = 7941704456058067109L;
032
033 private Integer majorVersion;
034
035 private Integer minorVersion;
036
037 private Integer incrementalVersion;
038
039 private Integer buildNumber;
040
041 private String qualifier;
042
043 public Version(String version) {
044 parseVersion(version);
045 }
046
047 public int compareTo(Object o) {
048 Version otherVersion = (Version) o;
049
050 int result = compareIntegers(majorVersion, otherVersion.majorVersion);
051 if (result == 0) {
052 result = compareIntegers(minorVersion, otherVersion.minorVersion);
053 }
054 if (result == 0) {
055 result = compareIntegers(incrementalVersion, otherVersion.incrementalVersion);
056 }
057 if (result == 0) {
058 if (buildNumber != null || otherVersion.buildNumber != null) {
059 result = compareIntegers(buildNumber, otherVersion.buildNumber);
060 } else if (qualifier != null) {
061 if (otherVersion.qualifier != null) {
062 if (qualifier.length() > otherVersion.qualifier.length() &&
063 qualifier.startsWith(otherVersion.qualifier)) {
064 // here, the longer one that otherwise match is considered older
065 result = -1;
066 } else if (qualifier.length() < otherVersion.qualifier.length() &&
067 otherVersion.qualifier.startsWith(qualifier)) {
068 // here, the longer one that otherwise match is considered older
069 result = 1;
070 } else {
071 result = qualifier.compareTo(otherVersion.qualifier);
072 }
073 } else {
074 // otherVersion has no qualifier but we do - that's newer
075 result = -1;
076 }
077 } else if (otherVersion.qualifier != null) {
078 // otherVersion has a qualifier but we don't, we're newer
079 result = 1;
080 }
081 }
082 return result;
083 }
084
085 private int compareIntegers(Integer i1, Integer i2) {
086 // treat null as 0 in comparison
087 if (i1 == null ? i2 == null : i1.equals(i2)) {
088 return 0;
089 } else if (i1 == null) {
090 return -i2.intValue();
091 } else if (i2 == null) {
092 return i1.intValue();
093 } else {
094 return i1.intValue() - i2.intValue();
095 }
096 }
097
098 public int getMajorVersion() {
099 return majorVersion != null ? majorVersion.intValue() : 0;
100 }
101
102 public int getMinorVersion() {
103 return minorVersion != null ? minorVersion.intValue() : 0;
104 }
105
106 public int getIncrementalVersion() {
107 return incrementalVersion != null ? incrementalVersion.intValue() : 0;
108 }
109
110 public int getBuildNumber() {
111 return buildNumber != null ? buildNumber.intValue() : 0;
112 }
113
114 public String getQualifier() {
115 return qualifier;
116 }
117
118 public final void parseVersion(String version) {
119 int index = version.indexOf("-");
120
121 String part1;
122 String part2 = null;
123
124 if (index < 0) {
125 part1 = version;
126 } else {
127 part1 = version.substring(0, index);
128 part2 = version.substring(index + 1);
129 }
130
131 if (part2 != null) {
132 try {
133 if (part2.length() == 1 || !part2.startsWith("0")) {
134 buildNumber = Integer.valueOf(part2);
135 } else {
136 qualifier = part2;
137 }
138 }
139 catch (NumberFormatException e) {
140 qualifier = part2;
141 }
142 }
143
144 if (part1.indexOf(".") < 0 && !part1.startsWith("0")) {
145 try {
146 majorVersion = Integer.valueOf(part1);
147 }
148 catch (NumberFormatException e) {
149 // qualifier is the whole version, including "-"
150 qualifier = version;
151 buildNumber = null;
152 }
153 } else {
154 boolean fallback = false;
155 StringTokenizer tok = new StringTokenizer(part1, ".");
156 try {
157 majorVersion = getNextIntegerToken(tok);
158 if (tok.hasMoreTokens()) {
159 minorVersion = getNextIntegerToken(tok);
160 }
161 if (tok.hasMoreTokens()) {
162 incrementalVersion = getNextIntegerToken(tok);
163 }
164 if (tok.hasMoreTokens()) {
165 fallback = true;
166 }
167 }
168 catch (NumberFormatException e) {
169 fallback = true;
170 }
171
172 if (fallback) {
173 // qualifier is the whole version, including "-"
174 qualifier = version;
175 majorVersion = null;
176 minorVersion = null;
177 incrementalVersion = null;
178 }
179 }
180 }
181
182 private static Integer getNextIntegerToken(StringTokenizer tok) {
183 String s = tok.nextToken();
184 if (s.length() > 1 && s.startsWith("0")) {
185 throw new NumberFormatException("Number part has a leading 0: '" + s + "'");
186 }
187 return Integer.valueOf(s);
188 }
189
190 public String toString() {
191 StringBuffer buf = new StringBuffer();
192 if (majorVersion != null) {
193 buf.append(majorVersion);
194 }
195 if (minorVersion != null) {
196 buf.append(".");
197 buf.append(minorVersion);
198 }
199 if (incrementalVersion != null) {
200 buf.append(".");
201 buf.append(incrementalVersion);
202 }
203 if (buildNumber != null) {
204 buf.append("-");
205 buf.append(buildNumber);
206 } else if (qualifier != null) {
207 if (buf.length() > 0) {
208 buf.append("-");
209 }
210 buf.append(qualifier);
211 }
212 return buf.toString();
213 }
214
215 public boolean equals(Object other) {
216 if (this == other) {
217 return true;
218 }
219 if (other == null || this.getClass() != other.getClass()) {
220 return false;
221 }
222 Version v = (Version) other;
223 if (majorVersion == null? v.majorVersion != null: !majorVersion.equals(v.majorVersion)) {
224 return false;
225 }
226 if (minorVersion == null? v.minorVersion != null: !minorVersion.equals(v.minorVersion)) {
227 return false;
228 }
229 if (incrementalVersion == null? v.incrementalVersion != null: !incrementalVersion.equals(v.incrementalVersion)) {
230 return false;
231 }
232 if (buildNumber == null? v.buildNumber != null: !buildNumber.equals(v.buildNumber)) {
233 return false;
234 }
235 return qualifier == null ? v.qualifier == null : qualifier.equals(v.qualifier);
236 }
237
238 public int hashCode() {
239 int hashCode = 0;
240 if (majorVersion != null) {
241 hashCode = majorVersion.intValue();
242 }
243 if (minorVersion != null) {
244 hashCode = 37 * hashCode + minorVersion.intValue();
245 }
246 if (incrementalVersion != null) {
247 hashCode = 37 * hashCode + incrementalVersion.intValue();
248 }
249 if (buildNumber != null) {
250 hashCode = 37 * hashCode + buildNumber.intValue();
251 }
252 if (qualifier != null) {
253 hashCode = 37 * hashCode + qualifier.hashCode();
254 }
255 return hashCode;
256 }
257 }