|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.tools.extcheck; |
|
|
|
import java.util.*; |
|
import java.net.MalformedURLException; |
|
import java.util.Vector; |
|
import java.io.*; |
|
import java.util.StringTokenizer; |
|
import java.net.URL; |
|
import java.util.jar.JarFile; |
|
import java.util.jar.JarEntry; |
|
import java.util.jar.Manifest; |
|
import java.util.jar.Attributes; |
|
import java.util.jar.Attributes.Name; |
|
import java.net.URLConnection; |
|
import java.security.Permission; |
|
import java.util.jar.*; |
|
import java.net.JarURLConnection; |
|
import sun.net.www.ParseUtil; |
|
|
|
/** |
|
* ExtCheck reports on clashes between a specified (target) |
|
* jar file and jar files already installed in the extensions |
|
* directory. |
|
* |
|
* @author Benedict Gomes |
|
* @since 1.2 |
|
*/ |
|
|
|
public class ExtCheck { |
|
|
|
private static final boolean DEBUG = false; |
|
|
|
// The following strings hold the values of the version variables |
|
|
|
private String targetSpecTitle; |
|
private String targetSpecVersion; |
|
private String targetSpecVendor; |
|
private String targetImplTitle; |
|
private String targetImplVersion; |
|
private String targetImplVendor; |
|
private String targetsealed; |
|
|
|
|
|
private boolean verboseFlag; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static ExtCheck create(File targetFile, boolean verbose) { |
|
return new ExtCheck(targetFile, verbose); |
|
} |
|
|
|
private ExtCheck(File targetFile, boolean verbose) { |
|
verboseFlag = verbose; |
|
investigateTarget(targetFile); |
|
} |
|
|
|
|
|
private void investigateTarget(File targetFile) { |
|
verboseMessage("Target file:" + targetFile); |
|
Manifest targetManifest = null; |
|
try { |
|
File canon = new File(targetFile.getCanonicalPath()); |
|
URL url = ParseUtil.fileToEncodedURL(canon); |
|
if (url != null){ |
|
JarLoader loader = new JarLoader(url); |
|
JarFile jarFile = loader.getJarFile(); |
|
targetManifest = jarFile.getManifest(); |
|
} |
|
} catch (MalformedURLException e){ |
|
error("Malformed URL "); |
|
} catch (IOException e) { |
|
error("IO Exception "); |
|
} |
|
if (targetManifest == null) |
|
error("No manifest available in "+targetFile); |
|
Attributes attr = targetManifest.getMainAttributes(); |
|
if (attr != null) { |
|
targetSpecTitle = attr.getValue(Name.SPECIFICATION_TITLE); |
|
targetSpecVersion = attr.getValue(Name.SPECIFICATION_VERSION); |
|
targetSpecVendor = attr.getValue(Name.SPECIFICATION_VENDOR); |
|
targetImplTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); |
|
targetImplVersion = attr.getValue(Name.IMPLEMENTATION_VERSION); |
|
targetImplVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); |
|
targetsealed = attr.getValue(Name.SEALED); |
|
} else { |
|
error("No attributes available in the manifest"); |
|
} |
|
if (targetSpecTitle == null) |
|
error("The target file does not have a specification title"); |
|
if (targetSpecVersion == null) |
|
error("The target file does not have a specification version"); |
|
verboseMessage("Specification title:" + targetSpecTitle); |
|
verboseMessage("Specification version:" + targetSpecVersion); |
|
if (targetSpecVendor != null) |
|
verboseMessage("Specification vendor:" + targetSpecVendor); |
|
if (targetImplVersion != null) |
|
verboseMessage("Implementation version:" + targetImplVersion); |
|
if (targetImplVendor != null) |
|
verboseMessage("Implementation vendor:" + targetImplVendor); |
|
verboseMessage(""); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
boolean checkInstalledAgainstTarget(){ |
|
String s = System.getProperty("java.ext.dirs"); |
|
File [] dirs; |
|
if (s != null) { |
|
StringTokenizer st = |
|
new StringTokenizer(s, File.pathSeparator); |
|
int count = st.countTokens(); |
|
dirs = new File[count]; |
|
for (int i = 0; i < count; i++) { |
|
dirs[i] = new File(st.nextToken()); |
|
} |
|
} else { |
|
dirs = new File[0]; |
|
} |
|
|
|
boolean result = true; |
|
for (int i = 0; i < dirs.length; i++) { |
|
String[] files = dirs[i].list(); |
|
if (files != null) { |
|
for (int j = 0; j < files.length; j++) { |
|
try { |
|
File f = new File(dirs[i],files[j]); |
|
File canon = new File(f.getCanonicalPath()); |
|
URL url = ParseUtil.fileToEncodedURL(canon); |
|
if (url != null){ |
|
result = result && checkURLRecursively(1,url); |
|
} |
|
} catch (MalformedURLException e){ |
|
error("Malformed URL"); |
|
} catch (IOException e) { |
|
error("IO Exception"); |
|
} |
|
} |
|
} |
|
} |
|
if (result) { |
|
generalMessage("No conflicting installed jar found."); |
|
} else { |
|
generalMessage("Conflicting installed jar found. " |
|
+ " Use -verbose for more information."); |
|
} |
|
return result; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean checkURLRecursively(int indent, URL url) |
|
throws IOException |
|
{ |
|
verboseMessage("Comparing with " + url); |
|
JarLoader jarloader = new JarLoader(url); |
|
JarFile j = jarloader.getJarFile(); |
|
Manifest man = j.getManifest(); |
|
if (man != null) { |
|
Attributes attr = man.getMainAttributes(); |
|
if (attr != null){ |
|
String title = attr.getValue(Name.SPECIFICATION_TITLE); |
|
String version = attr.getValue(Name.SPECIFICATION_VERSION); |
|
String vendor = attr.getValue(Name.SPECIFICATION_VENDOR); |
|
String implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE); |
|
String implVersion |
|
= attr.getValue(Name.IMPLEMENTATION_VERSION); |
|
String implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR); |
|
String sealed = attr.getValue(Name.SEALED); |
|
if (title != null){ |
|
if (title.equals(targetSpecTitle)){ |
|
if (version != null){ |
|
if (version.equals(targetSpecVersion) || |
|
isNotOlderThan(version,targetSpecVersion)){ |
|
verboseMessage(""); |
|
verboseMessage("CONFLICT DETECTED "); |
|
verboseMessage("Conflicting file:"+ url); |
|
verboseMessage("Installed Version:" + |
|
version); |
|
if (implTitle != null) |
|
verboseMessage("Implementation Title:"+ |
|
implTitle); |
|
if (implVersion != null) |
|
verboseMessage("Implementation Version:"+ |
|
implVersion); |
|
if (implVendor != null) |
|
verboseMessage("Implementation Vendor:"+ |
|
implVendor); |
|
return false; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
boolean result = true; |
|
URL[] loaderList = jarloader.getClassPath(); |
|
if (loaderList != null) { |
|
for(int i=0; i < loaderList.length; i++){ |
|
if (url != null){ |
|
boolean res = checkURLRecursively(indent+1,loaderList[i]); |
|
result = res && result; |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean isNotOlderThan(String already,String target) |
|
throws NumberFormatException |
|
{ |
|
if (already == null || already.length() < 1) { |
|
throw new NumberFormatException("Empty version string"); |
|
} |
|
|
|
|
|
StringTokenizer dtok = new StringTokenizer(target, ".", true); |
|
StringTokenizer stok = new StringTokenizer(already, ".", true); |
|
while (dtok.hasMoreTokens() || stok.hasMoreTokens()) { |
|
int dver; |
|
int sver; |
|
if (dtok.hasMoreTokens()) { |
|
dver = Integer.parseInt(dtok.nextToken()); |
|
} else |
|
dver = 0; |
|
|
|
if (stok.hasMoreTokens()) { |
|
sver = Integer.parseInt(stok.nextToken()); |
|
} else |
|
sver = 0; |
|
|
|
if (sver < dver) |
|
return false; |
|
if (sver > dver) |
|
return true; |
|
|
|
|
|
if (dtok.hasMoreTokens()) |
|
dtok.nextToken(); |
|
if (stok.hasMoreTokens()) |
|
stok.nextToken(); |
|
// Compare next component |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
void verboseMessage(String message){ |
|
if (verboseFlag) { |
|
System.err.println(message); |
|
} |
|
} |
|
|
|
void generalMessage(String message){ |
|
System.err.println(message); |
|
} |
|
|
|
|
|
|
|
*/ |
|
static void error(String message) throws RuntimeException { |
|
throw new RuntimeException(message); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static class JarLoader { |
|
private final URL base; |
|
private JarFile jar; |
|
private URL csu; |
|
|
|
|
|
|
|
*/ |
|
JarLoader(URL url) { |
|
String urlName = url + "!/"; |
|
URL tmpBaseURL = null; |
|
try { |
|
tmpBaseURL = new URL("jar","",urlName); |
|
jar = findJarFile(url); |
|
csu = url; |
|
} catch (MalformedURLException e) { |
|
ExtCheck.error("Malformed url "+urlName); |
|
} catch (IOException e) { |
|
ExtCheck.error("IO Exception occurred"); |
|
} |
|
base = tmpBaseURL; |
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
URL getBaseURL() { |
|
return base; |
|
} |
|
|
|
JarFile getJarFile() { |
|
return jar; |
|
} |
|
|
|
private JarFile findJarFile(URL url) throws IOException { |
|
|
|
if ("file".equals(url.getProtocol())) { |
|
String path = url.getFile().replace('/', File.separatorChar); |
|
File file = new File(path); |
|
if (!file.exists()) { |
|
throw new FileNotFoundException(path); |
|
} |
|
return new JarFile(path); |
|
} |
|
URLConnection uc = getBaseURL().openConnection(); |
|
|
|
return ((JarURLConnection)uc).getJarFile(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
URL[] getClassPath() throws IOException { |
|
Manifest man = jar.getManifest(); |
|
if (man != null) { |
|
Attributes attr = man.getMainAttributes(); |
|
if (attr != null) { |
|
String value = attr.getValue(Name.CLASS_PATH); |
|
if (value != null) { |
|
return parseClassPath(csu, value); |
|
} |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private URL[] parseClassPath(URL base, String value) |
|
throws MalformedURLException |
|
{ |
|
StringTokenizer st = new StringTokenizer(value); |
|
URL[] urls = new URL[st.countTokens()]; |
|
int i = 0; |
|
while (st.hasMoreTokens()) { |
|
String path = st.nextToken(); |
|
urls[i] = new URL(base, path); |
|
i++; |
|
} |
|
return urls; |
|
} |
|
} |
|
|
|
|
|
} |