|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| |
|
5 |
| |
|
6 |
| |
|
7 |
| |
|
8 |
| |
|
9 |
| |
|
10 |
| |
|
11 |
| |
|
12 |
| |
|
13 |
| |
|
14 |
| |
|
15 |
| |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| |
|
21 |
| |
|
22 |
| |
|
23 |
| |
|
24 |
| |
|
25 |
| |
|
26 |
| |
|
27 |
| |
|
28 |
| |
|
29 |
| |
|
30 |
| |
|
31 |
| |
|
32 |
| |
|
33 |
| |
|
34 |
| |
|
35 |
| package edu.rice.cs.plt.reflect; |
|
36 |
| |
|
37 |
| import java.io.Serializable; |
|
38 |
| import java.io.File; |
|
39 |
| |
|
40 |
| |
|
41 |
| public enum JavaVersion { |
|
42 |
0
| UNRECOGNIZED { public String versionString() { return "?"; } },
|
|
43 |
1
| JAVA_1_1 { public String versionString() { return "1.1"; } },
|
|
44 |
1
| JAVA_1_2 { public String versionString() { return "1.2"; } },
|
|
45 |
1
| JAVA_1_3 { public String versionString() { return "1.3"; } },
|
|
46 |
15
| JAVA_1_4 { public String versionString() { return "1.4"; } },
|
|
47 |
22
| JAVA_5 { public String versionString() { return "5"; } },
|
|
48 |
26
| JAVA_6 { public String versionString() { return "6"; } },
|
|
49 |
18
| JAVA_7 { public String versionString() { return "7"; } },
|
|
50 |
1
| FUTURE { public String versionString() { return ">7"; } };
|
|
51 |
| |
|
52 |
| |
|
53 |
| |
|
54 |
| |
|
55 |
| |
|
56 |
| |
|
57 |
| |
|
58 |
| public static final JavaVersion CURRENT = parseClassVersion(System.getProperty("java.class.version", "")); |
|
59 |
| |
|
60 |
| |
|
61 |
| public static final JavaVersion.FullVersion CURRENT_FULL = |
|
62 |
| parseFullVersion(System.getProperty("java.version", ""), |
|
63 |
| System.getProperty("java.runtime.name", ""), |
|
64 |
| System.getProperty("java.vm.vendor", ""), |
|
65 |
| null); |
|
66 |
| |
|
67 |
| |
|
68 |
| |
|
69 |
| |
|
70 |
| |
|
71 |
0
| public boolean supports(JavaVersion v) { return compareTo(v) >= 0; }
|
|
72 |
| |
|
73 |
| |
|
74 |
| public abstract String versionString(); |
|
75 |
| |
|
76 |
| |
|
77 |
8
| public String toString() { return "Java " + versionString(); }
|
|
78 |
| |
|
79 |
| |
|
80 |
8
| public FullVersion fullVersion() {
|
|
81 |
8
| return new FullVersion(this, 0, 0, ReleaseType.STABLE, null, VendorType.UNKNOWN, "", null);
|
|
82 |
| } |
|
83 |
| |
|
84 |
| |
|
85 |
| |
|
86 |
| |
|
87 |
| |
|
88 |
| |
|
89 |
5
| public static JavaVersion parseClassVersion(String text) {
|
|
90 |
5
| int dot = text.indexOf('.');
|
|
91 |
0
| if (dot == -1) { return UNRECOGNIZED; }
|
|
92 |
5
| try {
|
|
93 |
5
| int major = Integer.parseInt(text.substring(0, dot));
|
|
94 |
5
| int minor = Integer.parseInt(text.substring(dot+1));
|
|
95 |
| |
|
96 |
5
| return parseClassVersion(major, minor);
|
|
97 |
| } |
|
98 |
0
| catch (NumberFormatException e) { return UNRECOGNIZED; }
|
|
99 |
| } |
|
100 |
| |
|
101 |
| |
|
102 |
| |
|
103 |
| |
|
104 |
| |
|
105 |
| |
|
106 |
5
| public static JavaVersion parseClassVersion(int major, int minor) {
|
|
107 |
5
| switch (major) {
|
|
108 |
0
| case 45:
|
|
109 |
0
| if (minor >= 3) { return JAVA_1_1; }
|
|
110 |
0
| else { return UNRECOGNIZED; }
|
|
111 |
0
| case 46: return JAVA_1_2;
|
|
112 |
0
| case 47: return JAVA_1_3;
|
|
113 |
1
| case 48: return JAVA_1_4;
|
|
114 |
1
| case 49: return JAVA_5;
|
|
115 |
2
| case 50: return JAVA_6;
|
|
116 |
1
| case 51: return JAVA_7;
|
|
117 |
| } |
|
118 |
0
| return (major > 51) ? FUTURE : UNRECOGNIZED;
|
|
119 |
| } |
|
120 |
| |
|
121 |
| |
|
122 |
| |
|
123 |
| |
|
124 |
0
| public static JavaVersion parseClassVersion(java.io.File classFile) {
|
|
125 |
0
| java.io.FileInputStream fis = null;
|
|
126 |
0
| try {
|
|
127 |
0
| fis = new java.io.FileInputStream(classFile);
|
|
128 |
0
| return parseClassVersion(fis);
|
|
129 |
| } |
|
130 |
0
| catch(java.io.IOException ioe) { return UNRECOGNIZED; }
|
|
131 |
| finally { |
|
132 |
0
| if (fis!=null) {
|
|
133 |
0
| try { fis.close(); }
|
|
134 |
| catch(java.io.IOException ioe) { } |
|
135 |
| } |
|
136 |
| } |
|
137 |
| } |
|
138 |
| |
|
139 |
| |
|
140 |
| |
|
141 |
| |
|
142 |
0
| public static JavaVersion parseClassVersion(java.io.InputStream is) {
|
|
143 |
0
| java.io.DataInputStream dis = null;
|
|
144 |
0
| try {
|
|
145 |
0
| dis = new java.io.DataInputStream(is);
|
|
146 |
0
| int magic = dis.readInt();
|
|
147 |
0
| if (magic != 0xCAFEBABE) { return UNRECOGNIZED; }
|
|
148 |
0
| int minor = dis.readUnsignedShort();
|
|
149 |
0
| int major = dis.readUnsignedShort();
|
|
150 |
0
| return parseClassVersion(major, minor);
|
|
151 |
| } |
|
152 |
0
| catch(java.io.IOException ioe) { return UNRECOGNIZED; }
|
|
153 |
| finally { |
|
154 |
0
| if (dis!=null) {
|
|
155 |
0
| try { dis.close(); }
|
|
156 |
| catch(java.io.IOException ioe) { } |
|
157 |
| } |
|
158 |
| } |
|
159 |
| } |
|
160 |
| |
|
161 |
| |
|
162 |
| |
|
163 |
| |
|
164 |
| |
|
165 |
| |
|
166 |
| |
|
167 |
| |
|
168 |
| |
|
169 |
78
| public static FullVersion parseFullVersion(String java_version,
|
|
170 |
| String java_runtime_name, |
|
171 |
| String java_vm_vendor, |
|
172 |
| File location) { |
|
173 |
78
| VendorType vendor = VendorType.UNKNOWN;
|
|
174 |
78
| String vendorString = null;
|
|
175 |
| |
|
176 |
78
| if (vendor == VendorType.UNKNOWN) {
|
|
177 |
78
| if (java_runtime_name.toLowerCase().contains("openjdk")) {
|
|
178 |
11
| vendor = VendorType.OPENJDK;
|
|
179 |
11
| vendorString = "OpenJDK";
|
|
180 |
| } |
|
181 |
67
| else if (java_vm_vendor.toLowerCase().contains("apple")) {
|
|
182 |
9
| vendor = VendorType.APPLE;
|
|
183 |
9
| vendorString = "Apple";
|
|
184 |
| } |
|
185 |
58
| else if (java_vm_vendor.toLowerCase().contains("sun") ||
|
|
186 |
| java_vm_vendor.toLowerCase().contains("oracle")) { |
|
187 |
25
| vendor = VendorType.ORACLE;
|
|
188 |
25
| vendorString = "Sun";
|
|
189 |
| } |
|
190 |
| } |
|
191 |
| |
|
192 |
78
| String number;
|
|
193 |
78
| String typeString;
|
|
194 |
| |
|
195 |
| |
|
196 |
78
| if ((!java_version.startsWith("1.")) && (java_version.replaceAll("[^\\.]","").length()==1)) {
|
|
197 |
0
| java_version = "1."+java_version;
|
|
198 |
| } |
|
199 |
78
| int dash = java_version.indexOf('-');
|
|
200 |
71
| if (dash == -1) { number = java_version; typeString = null; }
|
|
201 |
7
| else { number = java_version.substring(0, dash); typeString = java_version.substring(dash+1); }
|
|
202 |
| |
|
203 |
78
| int dot1 = number.indexOf('.');
|
|
204 |
78
| if (dot1 == -1) {
|
|
205 |
0
| try {
|
|
206 |
0
| int feature = Integer.parseInt(number);
|
|
207 |
| |
|
208 |
0
| ReleaseType type;
|
|
209 |
0
| if (typeString == null) { type = ReleaseType.STABLE; }
|
|
210 |
0
| else if (typeString.startsWith("ea")) { type = ReleaseType.EARLY_ACCESS; }
|
|
211 |
0
| else if (typeString.startsWith("beta")) { type = ReleaseType.BETA; }
|
|
212 |
0
| else if (typeString.startsWith("rc")) { type = ReleaseType.RELEASE_CANDIDATE; }
|
|
213 |
0
| else { type = ReleaseType.UNRECOGNIZED; }
|
|
214 |
| |
|
215 |
0
| JavaVersion version = UNRECOGNIZED;
|
|
216 |
0
| switch (feature) {
|
|
217 |
0
| case 1: version = JAVA_1_1; break;
|
|
218 |
0
| case 2: version = JAVA_1_2; break;
|
|
219 |
0
| case 3: version = JAVA_1_3; break;
|
|
220 |
0
| case 4: version = JAVA_1_4; break;
|
|
221 |
0
| case 5: version = JAVA_5; break;
|
|
222 |
0
| case 6: version = JAVA_6; break;
|
|
223 |
0
| case 7: version = JAVA_7; break;
|
|
224 |
0
| default: if (feature > 7) { version = FUTURE; } break;
|
|
225 |
| } |
|
226 |
0
| return new FullVersion(version, 0, 0, type, typeString, vendor, vendorString, location);
|
|
227 |
| } |
|
228 |
| catch(NumberFormatException nfe) { |
|
229 |
0
| return new FullVersion(UNRECOGNIZED, 0, 0, ReleaseType.STABLE, null, vendor, vendorString, location);
|
|
230 |
| } |
|
231 |
| } |
|
232 |
| |
|
233 |
78
| int dot2 = number.indexOf('.', dot1+1);
|
|
234 |
0
| if (dot2 == -1) { return new FullVersion(UNRECOGNIZED, 0, 0,
|
|
235 |
| ReleaseType.STABLE, null, |
|
236 |
| vendor, vendorString, location); } |
|
237 |
78
| int underscore = number.indexOf('_', dot2+1);
|
|
238 |
37
| if (underscore == -1) { underscore = number.indexOf('.', dot2+1); }
|
|
239 |
30
| if (underscore == -1) { underscore = number.length(); }
|
|
240 |
78
| try {
|
|
241 |
78
| int major = Integer.parseInt(number.substring(0, dot1));
|
|
242 |
78
| int feature = Integer.parseInt(number.substring(dot1+1, dot2));
|
|
243 |
78
| int maintenance = Integer.parseInt(number.substring(dot2+1, underscore));
|
|
244 |
78
| int update = (underscore >= number.length()) ? 0 : Integer.parseInt(number.substring(underscore+1));
|
|
245 |
| |
|
246 |
78
| ReleaseType type;
|
|
247 |
71
| if (typeString == null) { type = ReleaseType.STABLE; }
|
|
248 |
0
| else if (typeString.startsWith("ea")) { type = ReleaseType.EARLY_ACCESS; }
|
|
249 |
7
| else if (typeString.startsWith("beta")) { type = ReleaseType.BETA; }
|
|
250 |
0
| else if (typeString.startsWith("rc")) { type = ReleaseType.RELEASE_CANDIDATE; }
|
|
251 |
0
| else { type = ReleaseType.UNRECOGNIZED; }
|
|
252 |
| |
|
253 |
78
| JavaVersion version = UNRECOGNIZED;
|
|
254 |
78
| if (major == 1) {
|
|
255 |
78
| switch (feature) {
|
|
256 |
0
| case 1: version = JAVA_1_1; break;
|
|
257 |
0
| case 2: version = JAVA_1_2; break;
|
|
258 |
0
| case 3: version = JAVA_1_3; break;
|
|
259 |
14
| case 4: version = JAVA_1_4; break;
|
|
260 |
21
| case 5: version = JAVA_5; break;
|
|
261 |
26
| case 6: version = JAVA_6; break;
|
|
262 |
17
| case 7: version = JAVA_7; break;
|
|
263 |
0
| default: if (feature > 7) { version = FUTURE; } break;
|
|
264 |
| } |
|
265 |
| } |
|
266 |
| |
|
267 |
78
| return new FullVersion(version, maintenance, update, type, typeString, vendor, vendorString, location);
|
|
268 |
| } |
|
269 |
| catch (NumberFormatException e) { |
|
270 |
0
| return new FullVersion(UNRECOGNIZED, 0, 0, ReleaseType.STABLE, null, vendor, vendorString, location);
|
|
271 |
| } |
|
272 |
| } |
|
273 |
| |
|
274 |
| |
|
275 |
| |
|
276 |
| |
|
277 |
| |
|
278 |
| |
|
279 |
| |
|
280 |
| |
|
281 |
| |
|
282 |
65
| public static FullVersion parseFullVersion(String java_version,
|
|
283 |
| String java_runtime_name, |
|
284 |
| String java_vm_vendor) { |
|
285 |
65
| return parseFullVersion(java_version, java_runtime_name, java_vm_vendor, null);
|
|
286 |
| } |
|
287 |
| |
|
288 |
| |
|
289 |
| |
|
290 |
| |
|
291 |
| |
|
292 |
| |
|
293 |
| |
|
294 |
| |
|
295 |
9
| public static FullVersion parseFullVersion(String text) {
|
|
296 |
9
| return parseFullVersion(text, "", "", null);
|
|
297 |
| } |
|
298 |
| |
|
299 |
| |
|
300 |
| |
|
301 |
| |
|
302 |
| |
|
303 |
| |
|
304 |
| public static class FullVersion implements Comparable<FullVersion>, Serializable { |
|
305 |
| private JavaVersion _majorVersion; |
|
306 |
| private int _maintenance; |
|
307 |
| private int _update; |
|
308 |
| private ReleaseType _type; |
|
309 |
| private String _typeString; |
|
310 |
| private VendorType _vendor; |
|
311 |
| private String _vendorString; |
|
312 |
| private File _location; |
|
313 |
| |
|
314 |
| |
|
315 |
86
| private FullVersion(JavaVersion majorVersion, int maintenance, int update, ReleaseType type,
|
|
316 |
| String typeString, VendorType vendor, String vendorString, File location) { |
|
317 |
86
| _majorVersion = majorVersion;
|
|
318 |
86
| _maintenance = maintenance;
|
|
319 |
86
| _update = update;
|
|
320 |
86
| _type = type;
|
|
321 |
86
| _typeString = typeString;
|
|
322 |
86
| _vendor = vendor;
|
|
323 |
86
| _vendorString = vendorString;
|
|
324 |
86
| _location = location;
|
|
325 |
| } |
|
326 |
| |
|
327 |
| |
|
328 |
42
| public JavaVersion majorVersion() { return _majorVersion; }
|
|
329 |
| |
|
330 |
| |
|
331 |
0
| public FullVersion onlyMajorVersionAndVendor() {
|
|
332 |
0
| return new FullVersion(_majorVersion, 0, 0, ReleaseType.STABLE, null, _vendor, _vendorString, _location);
|
|
333 |
| } |
|
334 |
| |
|
335 |
| |
|
336 |
0
| public int maintenance() { return _maintenance; }
|
|
337 |
| |
|
338 |
| |
|
339 |
0
| public int update() { return _update; }
|
|
340 |
| |
|
341 |
| |
|
342 |
0
| public ReleaseType release() { return _type; }
|
|
343 |
| |
|
344 |
| |
|
345 |
13
| public VendorType vendor() { return _vendor; }
|
|
346 |
| |
|
347 |
0
| public File location() { return _location; }
|
|
348 |
| |
|
349 |
| |
|
350 |
0
| public boolean supports(JavaVersion v) { return _majorVersion.supports(v); }
|
|
351 |
| |
|
352 |
| |
|
353 |
| |
|
354 |
| |
|
355 |
| |
|
356 |
| |
|
357 |
| |
|
358 |
165
| public int compareTo(FullVersion v) {
|
|
359 |
165
| int result = _majorVersion.compareTo(v._majorVersion);
|
|
360 |
165
| if (result == 0) {
|
|
361 |
66
| result = _maintenance - v._maintenance;
|
|
362 |
66
| if (result == 0) {
|
|
363 |
45
| result = _update - v._update;
|
|
364 |
45
| if (result == 0) {
|
|
365 |
30
| result = _type.compareTo(v._type);
|
|
366 |
30
| if (result == 0) {
|
|
367 |
23
| result = _vendor.compareTo(v._vendor);
|
|
368 |
23
| if (result == 0 && !_type.equals(ReleaseType.STABLE)) {
|
|
369 |
0
| result = _typeString.compareTo(v._typeString);
|
|
370 |
0
| if (result == 0 && _vendor.equals(VendorType.UNKNOWN)) {
|
|
371 |
0
| if (_location == null) {
|
|
372 |
0
| if (v._location == null) return 0;
|
|
373 |
0
| else return -1;
|
|
374 |
| } |
|
375 |
| else { |
|
376 |
0
| if (v._location == null) return 1;
|
|
377 |
0
| else return _location.compareTo(v._location);
|
|
378 |
| } |
|
379 |
| } |
|
380 |
| } |
|
381 |
23
| else if (result == 0 && _vendor.equals(VendorType.UNKNOWN)) {
|
|
382 |
5
| if (_location == null) {
|
|
383 |
0
| if (v._location == null) return 0;
|
|
384 |
0
| else return -1;
|
|
385 |
| } |
|
386 |
| else { |
|
387 |
2
| if (v._location == null) return 1;
|
|
388 |
3
| else return _location.compareTo(v._location);
|
|
389 |
| } |
|
390 |
| } |
|
391 |
| } |
|
392 |
| } |
|
393 |
| } |
|
394 |
| } |
|
395 |
160
| return result;
|
|
396 |
| } |
|
397 |
| |
|
398 |
77
| public boolean equals(Object o) {
|
|
399 |
77
| if (this == o) { return true; }
|
|
400 |
0
| else if (!(o instanceof FullVersion)) { return false; }
|
|
401 |
| else { |
|
402 |
0
| FullVersion v = (FullVersion) o;
|
|
403 |
0
| return _majorVersion.equals(v._majorVersion) &&
|
|
404 |
| _maintenance == v._maintenance && |
|
405 |
| _update == v._update && |
|
406 |
| _type.equals(v._type) && |
|
407 |
| _vendor.equals(v._vendor) && |
|
408 |
| (_type.equals(ReleaseType.STABLE) || _typeString.equals(v._typeString)) && |
|
409 |
| (!_vendor.equals(VendorType.UNKNOWN) || |
|
410 |
| ((_location==null) && (v._location==null)) || (_location.equals(v._location))); |
|
411 |
| } |
|
412 |
| } |
|
413 |
| |
|
414 |
0
| public int hashCode() {
|
|
415 |
0
| int stringHash = _typeString == null ? 0 : _typeString.hashCode();
|
|
416 |
0
| int fileHash = _location == null ? 0 : _location.hashCode();
|
|
417 |
0
| return _majorVersion.hashCode() ^ (_maintenance << 1) ^ (_update << 2) ^ (_type.hashCode() << 3)
|
|
418 |
| ^ (_vendor.hashCode() << 4) ^ (stringHash << 5) ^ fileHash; |
|
419 |
| } |
|
420 |
| |
|
421 |
85
| private String stringSuffix() {
|
|
422 |
85
| StringBuilder result = new StringBuilder();
|
|
423 |
85
| result.append("." + _maintenance);
|
|
424 |
47
| if (_update != 0) { result.append("_" + _update); }
|
|
425 |
7
| if (!_type.equals(ReleaseType.STABLE)) { result.append('-').append(_typeString); }
|
|
426 |
85
| return result.toString();
|
|
427 |
| } |
|
428 |
| |
|
429 |
77
| private String stringSuffixWithVendor() {
|
|
430 |
77
| StringBuilder result = new StringBuilder(stringSuffix());
|
|
431 |
77
| if ((!_vendor.equals(VendorType.ORACLE)) &&
|
|
432 |
| (!_vendor.equals(VendorType.APPLE)) && |
|
433 |
| (!_vendor.equals(VendorType.UNKNOWN))) { |
|
434 |
11
| result.append('-').append(_vendorString);
|
|
435 |
| } |
|
436 |
77
| return result.toString();
|
|
437 |
| } |
|
438 |
| |
|
439 |
| |
|
440 |
77
| public String versionString() { return _majorVersion.versionString() + stringSuffixWithVendor(); }
|
|
441 |
| |
|
442 |
8
| public String toString() { return _majorVersion + stringSuffix(); }
|
|
443 |
| |
|
444 |
| } |
|
445 |
| |
|
446 |
| private static enum ReleaseType { UNRECOGNIZED, EARLY_ACCESS, BETA, RELEASE_CANDIDATE, STABLE; } |
|
447 |
| |
|
448 |
| |
|
449 |
| public static enum VendorType { UNKNOWN, OPENJDK, APPLE, ORACLE; } |
|
450 |
| } |