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+
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+}