Package jsynoptic.ui

Source Code of jsynoptic.ui.PluginLookup

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Nicolas Brodu
*
* $Id: PluginLookup.java,v 1.10 2007/03/28 16:05:16 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/

package jsynoptic.ui;

import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;

import jsynoptic.base.Plugin;
import simtools.ui.BasicMessageWriter;
import simtools.ui.CheckBoxList;
import simtools.ui.ResourceFinder;

/**
* This class contains utilities to get/set dynamically the class path and the native library path
* It is strongly dependent on Sun's JDK implementation.
* Patches to support other JVMs welcome :) 
*/
public class PluginLookup {
 
 
  /**
   * A looger to dump error or warning messages in a soket, an output stream, a file...
   */
  static Logger _logger = simtools.util.LogConfigurator.getLogger(PluginLookup.class.getName());

 
  /** Resources */
  public static BasicMessageWriter messageWriter = ResourceFinder
  .getMessages(JSynoptic.class);


  protected static void testElement(Class theClass, String name, Vector results) {
    if (name.equals("jsynoptic.base.Plugin")) return; // do not add base class!
    try {
      if (theClass.isAssignableFrom(Class.forName(name))) {
        if (!results.contains(name)) results.add(name); // avoid duplicates
      }
    } catch (Throwable t) {
    }
  }


  protected static void searchJar(Class theClass, JarFile j, Vector results) throws IOException {
    Enumeration e = j.entries();
    while (e.hasMoreElements()) {
      JarEntry je =(JarEntry)e.nextElement();
      if (je.isDirectory()) continue;
      String entry = je.getName();
      if (!entry.endsWith(".class")) continue;
      entry = entry.substring(0,entry.length()-6); // removes .class
      entry = entry.replace('\\','/');
      entry = entry.replace('/','.');
      testElement(theClass, entry,results);
    }
  }

  protected static void searchFile(Class theClass, File d, Vector results, String prefix) {
    File[] list = d.listFiles();
    if (list==null) { // was a file!
      list = new File[] {d};
    }
    for (int i=0; i<list.length; ++i) {
      if (list[i].isDirectory() && (list[i].getName()!=".") && (list[i].getName()!="..")) {
        searchFile(theClass, list[i],results,prefix.equals("")?list[i].getName():prefix+"."+list[i].getName());
        continue;
      }
      String name = list[i].getName();
      if (!name.endsWith(".class")) continue;
      name = name.substring(0,name.length()-6); // removes .class
      testElement(theClass, prefix+"."+name,results);
    }
  }


  /**
   * Public method to search for all implementors of a given class object, in the classpath
   */
  public static Vector search(Class theClass) {
    Vector entries = new Vector();
    URL[] urls = sysloader.getURLs();

    int i = 0;
    for (i=0; i<urls.length; ++i) {
        String elt;
        try {
            elt = URLDecoder.decode(urls[i].getPath(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            elt = urls[i].getPath();
        }
        search(theClass,elt,entries);
    }
   
    return entries;
  }

 
  public static Vector search(String dirOrJar, Vector entries) {
    return search(Plugin.class, dirOrJar, entries);
  }
 
  public static Vector search(Class theClass, String dirOrJar, Vector entries) {
    JarFile j;
    if (dirOrJar.endsWith(".jar") || dirOrJar.endsWith("jsynoptic") || dirOrJar.endsWith("jsynoptic.exe")) {
      try {
        j = new JarFile(dirOrJar);
      } catch (IOException e) {
        j = null;
      }
    } else j=null;
   
    if (j!=null) {
      try {
        searchJar(theClass,j,entries);
        j.close();
      } catch (IOException e) {
      }
    }
    else searchFile(theClass,new File(dirOrJar),entries,"");
    return entries;
  }

  public static Vector lookup() {
    Vector entries = new Vector();
    URL[] urls = sysloader.getURLs();
    for (int i=0; i<urls.length; ++i) {
        String elt;
        try {
            elt = URLDecoder.decode(urls[i].getPath(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            elt = urls[i].getPath();
        }
        search(elt,entries);
    }
    return entries;
  }

  private static final Class[] parameters = new Class[]{URL.class};
 
  protected static String separator = System.getProperty("path.separator");
  protected static URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
  protected static Class sysclass = URLClassLoader.class;

  /**
   * Adds the given string to the classpath.
   * A great thanks to java forum user 8025 = antony_miguel for dynamic classpath modification
   */ 
  public static void addClassPath(String s) {
    if (s==null) return;
    addClassPath(new File(s));   
  }
 
  /**
   * Adds the given file to the classpath.
   * A great thanks to java forum user 8025 = antony_miguel for dynamic classpath modification
   */ 
  public static void addClassPath(File f) {
    if (f==null) return;
    try {
      addClassPath(f.toURL());
    } catch (MalformedURLException e) {
      return;
    }
  }
 
  /**
   * Adds the given URL to the classpath.
   * A great thanks to java forum user 8025 = antony_miguel for dynamic classpath modification
   */ 
  public static void addClassPath(URL url) {

    // Only add the URL if it does not exist yet
    URL[] urls = sysloader.getURLs();
    for (int i=0; i<urls.length; ++i) if (urls[i].equals(url)) return;
   
    try {
      Method method = sysclass.getDeclaredMethod("addURL",parameters);
      method.setAccessible(true);
      method.invoke(sysloader,new Object[]{ url });
    } catch (Throwable t) {
      //t.printStackTrace();
    }//end try catch

  }

  /**
   * Adds the given local path to the native library paths
   */ 
  public static void addNativePath(File localPath) {

      try {
        Field field;
            field = ClassLoader.class.getDeclaredField("usr_paths");
            field.setAccessible(true);
            String[] libs = (String[])field.get(null);
        // Only add the path if it does not exist yet
            for (int i=0; i<libs.length; ++i) if (localPath.equals(new File(libs[i]))) return;
            // OK, add the path
            String[] newlibs = new String[libs.length+1];
            for (int i=0; i<libs.length; ++i) newlibs[i] = libs[i];
            newlibs[libs.length] = localPath.getAbsolutePath();
            field.set(null, newlibs);
        } catch (SecurityException e) {
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
  }
 
  /** Helper function to determine if a given file is a dynamic native library */
  public static boolean isNativeLibrary(File f) {
      String name = f.getName();
      if (name.endsWith(".so") || name.endsWith(".dll") || name.endsWith(".jnilib"))
          return true;
      return false;
  }

  /**
   * This method tries to automatically add the plugin paths
   * It looks for the main class is in the classpath
   * Then it adds the content of the "plugins" sirectory sibling to the core one, if it exists
   * I also adds all sub-directories found inside it as class directories, and
   * all jars found in the subdirectories in the class path too.
   */
  public static void addPluginPaths() {
    addPluginPaths(false, null);
  }
 
  /**
   * This method tries to add the plugin paths
   * It looks for the main class is in the classpath
   * Then it adds the content of the "plugins" sirectory sibling to the core one, if it exists
   * I also adds all sub-directories found inside it as class directories, and
   * all jars found in the subdirectories in the class path too.
   * @param userChoice if true then the user can confirm the selected paths
   * @param parentWindow the owner for the dialog box displayed in interactive mode
   * @return false if user selects cancel
   */
  public static boolean addPluginPaths(boolean userChoice, Window parentWindow) {
    Vector nativePaths=new Vector();
    Vector classPaths=new Vector();
   
    // first look for the Run class location
    Vector entries = new Vector();
    URL[] urls = sysloader.getURLs();

    int i = 0;
    String elt = "";
    for (i=0; i<urls.length; ++i) {
      try {
          elt = URLDecoder.decode(urls[i].getPath(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
          elt = urls[i].getPath();
      }
      search(Run.class,elt,entries);
      if (!entries.isEmpty()) break;
    }
   
    // if found then add the paths and jars wrt this location
    if (i<urls.length) {
      File parent = new File(elt).getParentFile();
      if (parent!=null) {
        // first add all jar siblings
        // Also tests if parent contains libraries => add to native path
          boolean nativePath = false;
        File[] siblings = parent.listFiles();
        if (siblings!=null) for(int j=0; j<siblings.length; ++j) {
          if (siblings[j].getName().endsWith(".jar")){
            classPaths.add(siblings[j]);
          }
          if ((!nativePath) && isNativeLibrary(siblings[j])) nativePath = true;
        }
        if (nativePath){
          nativePaths.add(parent);
        }
        // then try to find a "plugins" directory, here or parent sibling
        File plugs = new File(parent,"plugins");
        if ((!plugs.exists()) && (parent.getParentFile()!=null)) {
          plugs = new File(parent.getParentFile(),"plugins");
          // Also tries to find a lib/jsynoptic directory, for unix bin/... lib/...
          if (!plugs.exists()) {
            plugs = new File(parent,"lib");
            if (!plugs.exists()) {
              plugs = new File(parent.getParentFile(),"lib"); // now in lib dir
              if (!plugs.exists()) plugs = new File(parent,"ext"); // special for eclipse workspace
            }
          }
        }
        // Consider the plugins directory as classpath
        // Consider the plugins directory sub-directories as classpath too, or go to subdirectory
        // "jsynoptic" if it exists first
        // Add all jar founds
        if (plugs.exists()) {
          classPaths.add(plugs);
          // Go to subdirectory jsynoptic if it exists (in case of plugin dir is lib/jsynoptic)
          // Also, on unix systems, don't add the whole system lib path as native libs : if
          // the user wants that, (s)he should do it with LD_LIBRARY_PATH
          File[] reps = plugs.listFiles();
          if (reps!=null) for(int j=0; j<reps.length; ++j) {
            if (reps[j].getName().equalsIgnoreCase("jsynoptic")) {
              plugs = reps[j];
              classPaths.add(plugs);
              reps = plugs.listFiles();
              break;
            }
          }
            nativePath = false;
          if (reps!=null) for(int j=0; j<reps.length; ++j) {
            File[] maybejars = reps[j].listFiles();
            if (maybejars!=null) {
                boolean native2 = false;
                classPaths.add(reps[j]); // Was a directory => add as classpath
              for(int k=0; k<maybejars.length; ++k) {
                if (maybejars[k].getName().endsWith(".jar")){
                  classPaths.add(maybejars[k]);
                }
                if ((!native2) && isNativeLibrary(maybejars[k])) native2 = true;
              }
              if (native2) addNativePath(reps[j]);
            // Also add jar files and check for native libraries
            } else {
                if (reps[j].getName().endsWith(".jar")){
                  classPaths.add(reps[j]);
                }
              if ((!nativePath) && isNativeLibrary(reps[j])) nativePath = true;
            }
          }
          if (nativePath){
            nativePaths.add(parent);
          }
        }
      }
     
    }
   
    // Now the system directories are added. Also add the user directory
    // See simtools.ui.UserProperties ans jsynoptic.ui.Run for consistency
    String productName = "jsynoptic";
    String home = System.getProperty(productName + ".home", System.getProperty("user.home", ""));
    File file = new File(home, "." + productName);
    if (file.isDirectory()) {
      classPaths.add(file);
        File[] reps = file.listFiles();
        boolean nativePath = false;
        if (reps!=null) for(int j=0; j<reps.length; ++j) {
            File[] maybejars = reps[j].listFiles();
            if (maybejars!=null) {
            boolean native2 = false;
            classPaths.add(reps[j]); // Was a directory => add as classpath
                for(int k=0; k<maybejars.length; ++k) {
                    if (maybejars[k].getName().endsWith(".jar")){
                      classPaths.add(maybejars[k]);
                    }
            if ((!native2) && isNativeLibrary(maybejars[k])) native2 = true;
                }
          if (native2) addNativePath(reps[j]);
          // Also add jar files and check for native libraries
        } else {
            if (reps[j].getName().endsWith(".jar")){
              classPaths.add(reps[j]);
            }
          if ((!nativePath) && isNativeLibrary(reps[j])) nativePath = true;
        }
        }
      if (nativePath){
        nativePaths.add(file);
      }
    }
   
    // remove duplicates
    for(int ic=0;ic<classPaths.size();ic++){
      for(int jc=ic+1;jc<classPaths.size();jc++){
        if(classPaths.get(ic).equals(classPaths.get(jc))){
          classPaths.remove(jc);
        }
      }
    }
    for(int in=0;in<nativePaths.size();in++){
      for(int jn=in+1;jn<nativePaths.size();jn++){
        if(nativePaths.get(in).equals(nativePaths.get(jn))){
          nativePaths.remove(jn);
        }
      }
    }
   
   
    // check wrt user
    boolean canceled=false;
    if(userChoice){
      String[] files=new String[classPaths.size()];
      boolean[] checked=new boolean[classPaths.size()];
      for(int k=0;k<classPaths.size();k++){
        files[k]=((File)classPaths.get(k)).getAbsolutePath();
        checked[k]=true;
      }
      boolean[] res=CheckBoxList.openDialog(
          messageWriter.print0args("confirmPluginsPath"),
          parentWindow, files, checked);
      if(res==null){
        canceled=true;
      }
      else{
        for(int k=classPaths.size()-1;k>=0;k--){
          if(!res[k]){
            classPaths.remove(k);
          }
        }
      }   
    }
   
    if(!canceled){
   
      // set the pathes
      for(int ic=0;ic<classPaths.size();ic++){
        addClassPath((File)classPaths.get(ic));
      }
      // Remark : the native path is not yet confirmed by the user
      for(int ic=0;ic<nativePaths.size();ic++){
        addNativePath((File)nativePaths.get(ic));
      }
    }
   
    return !canceled;
  }

  public static String getClassPath() {
    String ret = null;
    URL[] urls = sysloader.getURLs();
    for (int i=0; i<urls.length; ++i) {
      if (ret==null) ret = "";
      else ret += separator;
      try {
          ret += URLDecoder.decode(urls[i].getPath(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
          ret += urls[i].getPath();
      }
    }
    return ret;
  }

  public static String getNativePath() {
        String ret = null;
      try {
        Field field;
            field = ClassLoader.class.getDeclaredField("usr_paths");
            field.setAccessible(true);
            String[] libs = (String[])field.get(null);
        for (int i=0; i<libs.length; ++i) {
          if (ret==null) ret = "";
          else ret += separator;
          ret += libs[i];
        }
        } catch (SecurityException e) {
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    return ret;
  }
 
  public static void main(String args[]) {
    Vector entries = new Vector();
    URL[] urls = sysloader.getURLs();
    for (int i=0; i<urls.length; ++i) {
        String elt;
        try {
            elt = URLDecoder.decode(urls[i].getPath(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            elt = urls[i].getPath();
        }
        //String elt = urls[i].getPath();
      _logger.fine("searching: "+elt);
      search(elt,entries);
    }
    //entries = search(LookAndFeel.class);
    _logger.fine("Found: ");
    for (int i=0; i<entries.size(); ++i) _logger.fine(entries.get(i).toString());
   
    _logger.fine("Looking for plugin dirs");
    addPluginPaths();

    entries = new Vector();
    urls = sysloader.getURLs();
    for (int i=0; i<urls.length; ++i) {
      String elt;
      try {
                elt = URLDecoder.decode(urls[i].getPath(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                elt = urls[i].getPath();
            }
      _logger.fine("searching: "+elt);
      search(elt,entries);
    }
    //entries = search(LookAndFeel.class);
    _logger.fine("Found: ");
    for (int i=0; i<entries.size(); ++i) _logger.fine(entries.get(i).toString());
   
    _logger.fine("Native path: "+getNativePath());
   
  }

}
TOP

Related Classes of jsynoptic.ui.PluginLookup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.