ExtCheck.java :  » 6.0-JDK-Modules-com.sun » tools » com » sun » tools » extcheck » Java Open Source

Java Open Source » 6.0 JDK Modules com.sun » tools 
tools » com » sun » tools » extcheck » ExtCheck.java
/*
 * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

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.
 *
 * @version 1.17 07/05/05
 * @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
    // for the target jar file
    private String targetSpecTitle;
    private String targetSpecVersion;
    private String targetSpecVendor;
    private String targetImplTitle;
    private String targetImplVersion;
    private String targetImplVendor;
    private String targetsealed;
    
    /* Flag to indicate whether extra information should be dumped to stdout */
    private boolean verboseFlag;

    /* 
     * Create a new instance of the jar reporting tool for a particular
     * targetFile.
     * @param targetFile is the file to compare against.
     * @param verbose indicates whether to dump filenames and manifest
     *                information (on conflict) to the standard output.
     */
    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("");
    }

    /**
     * Verify that none of the jar files in the install directory
     * has the same specification-title and the same or a newer 
     * specification-version. 
     *
     * @return Return true if the target jar file is newer 
     *        than any installed jar file with the same specification-title, 
     *        otherwise return false
     */
    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;
    }

    /**
     * Recursively verify that a jar file, and any urls mentioned
     * in its class path, do not conflict with the target jar file.
     *
     * @param indent is the current nesting level
     * @param url is the path to the jar file being checked.
     * @return true if there is no newer URL, otherwise false
     */
    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;
    }
      
    /** 
     *  See comment in method java.lang.Package.isCompatibleWith.
     *  Return true if already is not older than target. i.e. the
     *  target file may be superseded by a file already installed
     */
    private boolean isNotOlderThan(String already,String target)
  throws NumberFormatException
    {
      if (already == null || already.length() < 1) {
      throw new NumberFormatException("Empty version string");
  }

      // Until it matches scan and compare numbers
      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;    // Known to be incompatible
          if (sver > dver)
            return true;    // Known to be compatible

          // Check for and absorb separators
          if (dtok.hasMoreTokens())
            dtok.nextToken();
          if (stok.hasMoreTokens())
            stok.nextToken();
          // Compare next component
      }
      // All components numerically equal
  return true;
    }

    
    /**
     * Prints out message if the verboseFlag is set
     */
    void verboseMessage(String message){
  if (verboseFlag) {
      System.err.println(message);
  }
    }

    void generalMessage(String message){
  System.err.println(message);
    }

    /**
     * Print out the error message and exit from the program
     */
    static void error(String message){
  System.err.println(message);
  System.exit(-1);
    }


    /**
     * Inner class used to represent a loader of resources and classes
     * from a base URL. Somewhat modified version of code in 
     * sun.misc.URLClassPath.JarLoader
     */
    private static class JarLoader {
  private final URL base;
  private JarFile jar;
  private URL csu;

  /*
   * Creates a new Loader for the specified URL.
   */
  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;

  }

  /*
   * Returns the base URL for this Loader.
   */
  URL getBaseURL() {
      return base;
  }

  JarFile getJarFile() {
      return jar;
  }

  private JarFile findJarFile(URL url) throws IOException {
       // Optimize case where url refers to a local jar file
       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();
       //uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
       return ((JarURLConnection)uc).getJarFile();
   }


  /*
   * Returns the JAR file local class path, or null if none.
   */
  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;
  }

  /*
   * Parses value of the Class-Path manifest attribute and returns
   * an array of URLs relative to the specified base URL.
   */
  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;
  }
    }


}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.