History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/extcheck/ExtCheck.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/extcheck/ExtCheck.java+410−0
@@ -0,0 +1,410 @@
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
26package com.sun.tools.extcheck;
27
28import java.util.*;
29import java.net.MalformedURLException;
30import java.util.Vector;
31import java.io.*;
32import java.util.StringTokenizer;
33import java.net.URL;
34import java.util.jar.JarFile;
35import java.util.jar.JarEntry;
36import java.util.jar.Manifest;
37import java.util.jar.Attributes;
38import java.util.jar.Attributes.Name;
39import java.net.URLConnection;
40import java.security.Permission;
41import java.util.jar.*;
42import java.net.JarURLConnection;
43import 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
54public 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}