Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/extcheck/ExtCheck.java
38920 views
1
/*
2
* Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.tools.extcheck;
27
28
import java.util.*;
29
import java.net.MalformedURLException;
30
import java.util.Vector;
31
import java.io.*;
32
import java.util.StringTokenizer;
33
import java.net.URL;
34
import java.util.jar.JarFile;
35
import java.util.jar.JarEntry;
36
import java.util.jar.Manifest;
37
import java.util.jar.Attributes;
38
import java.util.jar.Attributes.Name;
39
import java.net.URLConnection;
40
import java.security.Permission;
41
import java.util.jar.*;
42
import java.net.JarURLConnection;
43
import sun.net.www.ParseUtil;
44
45
/**
46
* ExtCheck reports on clashes between a specified (target)
47
* jar file and jar files already installed in the extensions
48
* directory.
49
*
50
* @author Benedict Gomes
51
* @since 1.2
52
*/
53
54
public class ExtCheck {
55
56
private static final boolean DEBUG = false;
57
58
// The following strings hold the values of the version variables
59
// for the target jar file
60
private String targetSpecTitle;
61
private String targetSpecVersion;
62
private String targetSpecVendor;
63
private String targetImplTitle;
64
private String targetImplVersion;
65
private String targetImplVendor;
66
private String targetsealed;
67
68
/* Flag to indicate whether extra information should be dumped to stdout */
69
private boolean verboseFlag;
70
71
/*
72
* Create a new instance of the jar reporting tool for a particular
73
* targetFile.
74
* @param targetFile is the file to compare against.
75
* @param verbose indicates whether to dump filenames and manifest
76
* information (on conflict) to the standard output.
77
*/
78
static ExtCheck create(File targetFile, boolean verbose) {
79
return new ExtCheck(targetFile, verbose);
80
}
81
82
private ExtCheck(File targetFile, boolean verbose) {
83
verboseFlag = verbose;
84
investigateTarget(targetFile);
85
}
86
87
88
private void investigateTarget(File targetFile) {
89
verboseMessage("Target file:" + targetFile);
90
Manifest targetManifest = null;
91
try {
92
File canon = new File(targetFile.getCanonicalPath());
93
URL url = ParseUtil.fileToEncodedURL(canon);
94
if (url != null){
95
JarLoader loader = new JarLoader(url);
96
JarFile jarFile = loader.getJarFile();
97
targetManifest = jarFile.getManifest();
98
}
99
} catch (MalformedURLException e){
100
error("Malformed URL ");
101
} catch (IOException e) {
102
error("IO Exception ");
103
}
104
if (targetManifest == null)
105
error("No manifest available in "+targetFile);
106
Attributes attr = targetManifest.getMainAttributes();
107
if (attr != null) {
108
targetSpecTitle = attr.getValue(Name.SPECIFICATION_TITLE);
109
targetSpecVersion = attr.getValue(Name.SPECIFICATION_VERSION);
110
targetSpecVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
111
targetImplTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
112
targetImplVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
113
targetImplVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
114
targetsealed = attr.getValue(Name.SEALED);
115
} else {
116
error("No attributes available in the manifest");
117
}
118
if (targetSpecTitle == null)
119
error("The target file does not have a specification title");
120
if (targetSpecVersion == null)
121
error("The target file does not have a specification version");
122
verboseMessage("Specification title:" + targetSpecTitle);
123
verboseMessage("Specification version:" + targetSpecVersion);
124
if (targetSpecVendor != null)
125
verboseMessage("Specification vendor:" + targetSpecVendor);
126
if (targetImplVersion != null)
127
verboseMessage("Implementation version:" + targetImplVersion);
128
if (targetImplVendor != null)
129
verboseMessage("Implementation vendor:" + targetImplVendor);
130
verboseMessage("");
131
}
132
133
/**
134
* Verify that none of the jar files in the install directory
135
* has the same specification-title and the same or a newer
136
* specification-version.
137
*
138
* @return Return true if the target jar file is newer
139
* than any installed jar file with the same specification-title,
140
* otherwise return false
141
*/
142
boolean checkInstalledAgainstTarget(){
143
String s = System.getProperty("java.ext.dirs");
144
File [] dirs;
145
if (s != null) {
146
StringTokenizer st =
147
new StringTokenizer(s, File.pathSeparator);
148
int count = st.countTokens();
149
dirs = new File[count];
150
for (int i = 0; i < count; i++) {
151
dirs[i] = new File(st.nextToken());
152
}
153
} else {
154
dirs = new File[0];
155
}
156
157
boolean result = true;
158
for (int i = 0; i < dirs.length; i++) {
159
String[] files = dirs[i].list();
160
if (files != null) {
161
for (int j = 0; j < files.length; j++) {
162
try {
163
File f = new File(dirs[i],files[j]);
164
File canon = new File(f.getCanonicalPath());
165
URL url = ParseUtil.fileToEncodedURL(canon);
166
if (url != null){
167
result = result && checkURLRecursively(1,url);
168
}
169
} catch (MalformedURLException e){
170
error("Malformed URL");
171
} catch (IOException e) {
172
error("IO Exception");
173
}
174
}
175
}
176
}
177
if (result) {
178
generalMessage("No conflicting installed jar found.");
179
} else {
180
generalMessage("Conflicting installed jar found. "
181
+ " Use -verbose for more information.");
182
}
183
return result;
184
}
185
186
/**
187
* Recursively verify that a jar file, and any urls mentioned
188
* in its class path, do not conflict with the target jar file.
189
*
190
* @param indent is the current nesting level
191
* @param url is the path to the jar file being checked.
192
* @return true if there is no newer URL, otherwise false
193
*/
194
private boolean checkURLRecursively(int indent, URL url)
195
throws IOException
196
{
197
verboseMessage("Comparing with " + url);
198
JarLoader jarloader = new JarLoader(url);
199
JarFile j = jarloader.getJarFile();
200
Manifest man = j.getManifest();
201
if (man != null) {
202
Attributes attr = man.getMainAttributes();
203
if (attr != null){
204
String title = attr.getValue(Name.SPECIFICATION_TITLE);
205
String version = attr.getValue(Name.SPECIFICATION_VERSION);
206
String vendor = attr.getValue(Name.SPECIFICATION_VENDOR);
207
String implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
208
String implVersion
209
= attr.getValue(Name.IMPLEMENTATION_VERSION);
210
String implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
211
String sealed = attr.getValue(Name.SEALED);
212
if (title != null){
213
if (title.equals(targetSpecTitle)){
214
if (version != null){
215
if (version.equals(targetSpecVersion) ||
216
isNotOlderThan(version,targetSpecVersion)){
217
verboseMessage("");
218
verboseMessage("CONFLICT DETECTED ");
219
verboseMessage("Conflicting file:"+ url);
220
verboseMessage("Installed Version:" +
221
version);
222
if (implTitle != null)
223
verboseMessage("Implementation Title:"+
224
implTitle);
225
if (implVersion != null)
226
verboseMessage("Implementation Version:"+
227
implVersion);
228
if (implVendor != null)
229
verboseMessage("Implementation Vendor:"+
230
implVendor);
231
return false;
232
}
233
}
234
}
235
}
236
}
237
}
238
boolean result = true;
239
URL[] loaderList = jarloader.getClassPath();
240
if (loaderList != null) {
241
for(int i=0; i < loaderList.length; i++){
242
if (url != null){
243
boolean res = checkURLRecursively(indent+1,loaderList[i]);
244
result = res && result;
245
}
246
}
247
}
248
return result;
249
}
250
251
/**
252
* See comment in method java.lang.Package.isCompatibleWith.
253
* Return true if already is not older than target. i.e. the
254
* target file may be superseded by a file already installed
255
*/
256
private boolean isNotOlderThan(String already,String target)
257
throws NumberFormatException
258
{
259
if (already == null || already.length() < 1) {
260
throw new NumberFormatException("Empty version string");
261
}
262
263
// Until it matches scan and compare numbers
264
StringTokenizer dtok = new StringTokenizer(target, ".", true);
265
StringTokenizer stok = new StringTokenizer(already, ".", true);
266
while (dtok.hasMoreTokens() || stok.hasMoreTokens()) {
267
int dver;
268
int sver;
269
if (dtok.hasMoreTokens()) {
270
dver = Integer.parseInt(dtok.nextToken());
271
} else
272
dver = 0;
273
274
if (stok.hasMoreTokens()) {
275
sver = Integer.parseInt(stok.nextToken());
276
} else
277
sver = 0;
278
279
if (sver < dver)
280
return false; // Known to be incompatible
281
if (sver > dver)
282
return true; // Known to be compatible
283
284
// Check for and absorb separators
285
if (dtok.hasMoreTokens())
286
dtok.nextToken();
287
if (stok.hasMoreTokens())
288
stok.nextToken();
289
// Compare next component
290
}
291
// All components numerically equal
292
return true;
293
}
294
295
296
/**
297
* Prints out message if the verboseFlag is set
298
*/
299
void verboseMessage(String message){
300
if (verboseFlag) {
301
System.err.println(message);
302
}
303
}
304
305
void generalMessage(String message){
306
System.err.println(message);
307
}
308
309
/**
310
* Throws a RuntimeException with a message describing the error.
311
*/
312
static void error(String message) throws RuntimeException {
313
throw new RuntimeException(message);
314
}
315
316
317
/**
318
* Inner class used to represent a loader of resources and classes
319
* from a base URL. Somewhat modified version of code in
320
* sun.misc.URLClassPath.JarLoader
321
*/
322
private static class JarLoader {
323
private final URL base;
324
private JarFile jar;
325
private URL csu;
326
327
/*
328
* Creates a new Loader for the specified URL.
329
*/
330
JarLoader(URL url) {
331
String urlName = url + "!/";
332
URL tmpBaseURL = null;
333
try {
334
tmpBaseURL = new URL("jar","",urlName);
335
jar = findJarFile(url);
336
csu = url;
337
} catch (MalformedURLException e) {
338
ExtCheck.error("Malformed url "+urlName);
339
} catch (IOException e) {
340
ExtCheck.error("IO Exception occurred");
341
}
342
base = tmpBaseURL;
343
344
}
345
346
/*
347
* Returns the base URL for this Loader.
348
*/
349
URL getBaseURL() {
350
return base;
351
}
352
353
JarFile getJarFile() {
354
return jar;
355
}
356
357
private JarFile findJarFile(URL url) throws IOException {
358
// Optimize case where url refers to a local jar file
359
if ("file".equals(url.getProtocol())) {
360
String path = url.getFile().replace('/', File.separatorChar);
361
File file = new File(path);
362
if (!file.exists()) {
363
throw new FileNotFoundException(path);
364
}
365
return new JarFile(path);
366
}
367
URLConnection uc = getBaseURL().openConnection();
368
//uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
369
return ((JarURLConnection)uc).getJarFile();
370
}
371
372
373
/*
374
* Returns the JAR file local class path, or null if none.
375
*/
376
URL[] getClassPath() throws IOException {
377
Manifest man = jar.getManifest();
378
if (man != null) {
379
Attributes attr = man.getMainAttributes();
380
if (attr != null) {
381
String value = attr.getValue(Name.CLASS_PATH);
382
if (value != null) {
383
return parseClassPath(csu, value);
384
}
385
}
386
}
387
return null;
388
}
389
390
/*
391
* Parses value of the Class-Path manifest attribute and returns
392
* an array of URLs relative to the specified base URL.
393
*/
394
private URL[] parseClassPath(URL base, String value)
395
throws MalformedURLException
396
{
397
StringTokenizer st = new StringTokenizer(value);
398
URL[] urls = new URL[st.countTokens()];
399
int i = 0;
400
while (st.hasMoreTokens()) {
401
String path = st.nextToken();
402
urls[i] = new URL(base, path);
403
i++;
404
}
405
return urls;
406
}
407
}
408
409
410
}
411
412