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