Clover coverage report -
Coverage timestamp: Sun Apr 18 2004 21:32:30 EDT
file stats: LOC: 273   Methods: 9
NCLOC: 138   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
PluginManager.java 61.5% 65.6% 66.7% 64.6%
coverage coverage
 1   
 /*
 2   
  * SimplyHTML, a word processor based on Java, HTML and CSS
 3   
  * Copyright (C) 2002 Ulrich Hilger
 4   
  *
 5   
  * This program is free software; you can redistribute it and/or
 6   
  * modify it under the terms of the GNU General Public License
 7   
  * as published by the Free Software Foundation; either version 2
 8   
  * of the License, or (at your option) any later version.
 9   
  *
 10   
  * This program is distributed in the hope that it will be useful,
 11   
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13   
  * GNU General Public License for more details.
 14   
  *
 15   
  * You should have received a copy of the GNU General Public License
 16   
  * along with this program; if not, write to the Free Software
 17   
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18   
  */
 19   
 
 20   
 import java.awt.Frame;
 21   
 //import com.lightdev.app.shtm.Util;
 22   
 import java.util.Vector;
 23   
 import java.net.URLClassLoader;
 24   
 import java.net.URL;
 25   
 import java.util.Enumeration;
 26   
 import java.util.jar.JarFile;
 27   
 import java.util.jar.JarEntry;
 28   
 import java.io.File;
 29   
 import java.net.URI;
 30   
 import java.util.Hashtable;
 31   
 //import com.lightdev.app.shtm.FrmMain;
 32   
 //import javax.help.*;
 33   
 //import javax.help.event.*;
 34   
 
 35   
 /**
 36   
  * Finds and loads plug-ins of application SimplyHTML.
 37   
  *
 38   
  * @author Ulrich Hilger
 39   
  * @author Light Development
 40   
  * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
 41   
  * @author <a href="mailto:info@lightdev.com">info@lightdev.com</a>
 42   
  * @author published under the terms and conditions of the
 43   
  *      GNU General Public License,
 44   
  *      for details see file gpl.txt in the distribution
 45   
  *      package of this software
 46   
  *
 47   
  * @version stage 11, April 27, 2003
 48   
  */
 49   
 
 50   
 public class PluginManager {
 51   
 
 52   
   /** name of sub-package where plug-ins are stored */
 53   
   private String PLUGIN_PACKAGE = "installed";
 54   
 
 55   
   /** the class loader pointing to all plug-in locations (JARs) */
 56   
   private URLClassLoader loader;
 57   
 
 58   
   /** the class names of all loaded plug-ins */
 59   
   private Vector pluginClassNames = new Vector();
 60   
 
 61   
   /** the plug-in objects loaded by this <code>PluginManager</code> */
 62   
   private Hashtable loadedPlugins = new Hashtable();
 63   
 
 64   
   private Hashtable nameMap = new Hashtable();
 65   
 
 66   
   /** the URLs pointing to the classes in pluginClassNames */
 67   
   private Vector urls = new Vector();
 68   
 
 69   
   private FrmMain owner;
 70   
 
 71   
   /**
 72   
    * construct a new <code>PluginManager</code> and load
 73   
    * all available plug-ins.
 74   
    */
 75  75
   public PluginManager(Frame owner) {
 76  75
     this.owner = (FrmMain) owner;
 77   
   }
 78   
 
 79   
   /**
 80   
    * get all plug-ins loaded by this <code>PluginManager</code>
 81   
    */
 82  75
   public Enumeration plugins() {
 83  75
     return loadedPlugins.elements();
 84   
   }
 85   
 
 86  0
   public ClassLoader getPluginLoader() {
 87  0
     return loader;
 88   
   }
 89   
 
 90   
   /**
 91   
    * get a loaded plug-in by its GUI name.
 92   
    *
 93   
    * @param guiName  the GUI name of this plaug-in
 94   
    *
 95   
    * @return the plug-in having the given GUI name, or null of no plug-in
 96   
    * with that name is present
 97   
    */
 98  0
   public SHTMLPlugin pluginForName(String guiName) {
 99  0
     String intName = (String) nameMap.get(guiName);
 100  0
     return (SHTMLPlugin) loadedPlugins.get(intName);
 101   
   }
 102   
 
 103  0
   public Object[] getPluginNames() {
 104  0
     return nameMap.keySet().toArray();
 105   
   }
 106   
 
 107   
   /**
 108   
    * load all plug-ins found in the plug-in path
 109   
    */
 110  75
   public void loadPlugins() {
 111  75
     loadedPlugins.clear();
 112   
     //String pluginPrefix = this.getClass().getPackage().getName() +
 113   
     //              Util.CLASS_SEPARATOR + PLUGIN_PACKAGE + Util.CLASS_SEPARATOR;
 114  75
     String pluginPrefix = this.getClass().getName() +
 115   
                   Util.CLASS_SEPARATOR + /*PLUGIN_PACKAGE +*/ Util.CLASS_SEPARATOR;
 116   
     //System.out.println("pluginPrefix = "+ pluginPrefix);              
 117  75
     findPlugins(pluginPrefix.replace(Util.CLASS_SEPARATOR_CHAR,
 118   
                                      Util.URL_SEPARATOR_CHAR));
 119  75
     Enumeration cNames = pluginClassNames.elements();
 120  75
     Class cl;
 121  75
     Object o;
 122  75
     SHTMLPlugin p;
 123  75
     String intName;
 124  75
     while(cNames.hasMoreElements()) {
 125  0
       try {
 126  0
         String nextClass = (String) cNames.nextElement();
 127   
         //System.out.println("PluginManager loadPlugins loading " + pluginPrefix + nextClass /* pluginPrefix + (String) cNames.nextElement()*/);
 128  0
         cl = loader.loadClass(/*pluginPrefix +*/
 129   
                               /*(String) cNames.nextElement()*/ pluginPrefix + nextClass);
 130   
         //System.out.println("PluginManager loadPlugins calling newInstance ");
 131  0
         o = cl.newInstance();
 132  0
         if(o instanceof SHTMLPlugin) {
 133  0
           p = (SHTMLPlugin) o;
 134  0
           p.initPlugin(owner, null, null, null);
 135   
           //p.setOwner(owner);
 136   
           //p.initPluginActions();
 137  0
           intName = p.getInternalName();
 138  0
           loadedPlugins.put(intName, o);
 139  0
           nameMap.put(p.getGUIName(), intName);
 140   
         }
 141   
       }
 142   
       catch(Exception e) {
 143  0
         Util.errMsg(null, this.getClass().getName() + ".loadPlugins: " +
 144   
                     e.getMessage(), e);
 145   
       }
 146   
     }
 147   
   }
 148   
 
 149   
   /**
 150   
    * get a class loader for a given set of URLs
 151   
    * specifying one or more class paths
 152   
    *
 153   
    * @param urls  set of URLs specifying the class path(s)
 154   
    *
 155   
    * @return  the class loader
 156   
    */
 157  75
   private URLClassLoader createLoader(Vector urls) {
 158  75
     URL[] urlArray = new URL[urls.size()];
 159  75
     for(int i = 0; i < urls.size(); i++) {
 160  0
       urlArray[i] = (URL) urls.elementAt(i);
 161   
       //System.out.println("urlArray[" + i + "]=" + urlArray[i]);
 162   
     }
 163  75
     return new URLClassLoader(urlArray, this.getClass().getClassLoader());
 164   
   }
 165   
 
 166   
   /**
 167   
    * find plug-ins by looking for JARs inside a
 168   
    * given path and create a class loader for them.
 169   
    *
 170   
    * <p>JARs are searched in sub-package .plugin.installed
 171   
    * of the package this class resides in.</p>
 172   
    *
 173   
    * <p>On return of this method fields <code>loader</code> and
 174   
    * <code>pluginClassNames</code> are initialized and
 175   
    * filled accordingly.</p>
 176   
    *
 177   
    * @param pluginPath  the path to look for plug-in JAR files, e.g.
 178   
    * com/lightdev/app/shtm/plugin/installed/
 179   
    */
 180  75
   private void findPlugins(String pluginPath) {
 181  75
     String appPath = Util.getClassFilePath(this.getClass());
 182  75
     String filePath;
 183  75
     if(appPath.indexOf(":") < 0) {
 184  0
       filePath = "/" + appPath;
 185   
     }
 186   
     else {
 187  75
       filePath = appPath;
 188   
     }
 189   
     //System.out.println("PluginManager.findPlugins appPath=" + appPath + ", filePath=" + filePath);
 190  75
     pluginClassNames.clear();
 191  75
     urls.clear();
 192  75
     String fName;
 193  75
     try {
 194  75
       File plugindir = new File(filePath);//new URI(Util.FILE_PREFIX + Util.URL_SEPARATOR + appPath));
 195  75
       if(plugindir != null) {
 196  75
         File[] content = plugindir.listFiles();
 197  75
         if(content != null) {
 198  75
           for(int i = 0; i < content.length; i++) {
 199  22350
             if(content[i].isFile()) {
 200  21825
               fName = content[i].getName();
 201   
               //System.out.println("PluginManager.findPlugins fName=" + fName);
 202  21825
               if(fName.toLowerCase().endsWith("jhall.jar")) {
 203   
                 /*System.out.println("PluginManager.findPlugins adding URL " + Util.FILE_PREFIX +
 204   
                                   Util.URL_SEPARATOR + appPath + fName);*/
 205  0
                 urls.addElement(new URL(Util.FILE_PREFIX +
 206   
                                   Util.URL_SEPARATOR + appPath + fName));
 207   
               }
 208  21825
               if(fName.toLowerCase().endsWith("simplyhtml.jar")) {
 209   
                 /*System.out.println("PluginManager.findPlugins adding URL " + Util.FILE_PREFIX +
 210   
                                   Util.URL_SEPARATOR + appPath + fName);*/
 211  0
                 urls.addElement(new URL(Util.FILE_PREFIX +
 212   
                                   Util.URL_SEPARATOR + appPath + fName));
 213   
               }
 214  21825
               else if(fName.endsWith(Util.JAR_EXTENSION)) {
 215  750
                 readJar(appPath, pluginPath, content[i], fName);
 216   
               }
 217   
             }
 218   
           }
 219   
         }
 220   
       }
 221  75
       loader = createLoader(urls);
 222   
     }
 223   
     catch(Exception e) {
 224  0
       Util.errMsg(null, this.getClass().getName() + ".findPlugins: " +
 225   
                   e.getMessage(), e);
 226   
     }
 227   
   }
 228   
 
 229   
   /**
 230   
    * read a Java archive (JAR) file and look for classes within
 231   
    * a given package path inside the JAR file. Store class names and
 232   
    * their URLS for later use.
 233   
    *
 234   
    * <p>Some of the parameters required below could be extracted from
 235   
    * others passed to this method but as previous methods already determined
 236   
    * respective paramaters, it is faster to pass the existing values as
 237   
    * parameters than to re-build the values locally.</p>
 238   
    *
 239   
    * @param filePath  the absolute path pointing to the JAR file, e.g.
 240   
    *   file:/C:/Programs/SimplyHTML/
 241   
    * @param pluginPath  the path inside filePath pointing to potential plug-ins
 242   
    * @param jarFile  the file object referring to the JAR file to read
 243   
    * @param fileName  the name of the JAR file
 244   
    */
 245  750
   private void readJar(String filePath, String pluginPath, File jarFile,
 246   
                        String fileName)
 247   
   {
 248  750
     try {
 249  750
       Enumeration jarEntries = new JarFile(jarFile).entries();
 250  675
       JarEntry je;
 251  675
       String jeName;
 252  675
       while(jarEntries.hasMoreElements()) {
 253  34050
         je = (JarEntry) jarEntries.nextElement();
 254  34050
         jeName = je.getName();
 255  34050
         if(jeName.startsWith(pluginPath) &&
 256   
            !je.isDirectory() &&
 257   
            jeName.endsWith(Util.CLASS_EXT))
 258   
         {
 259   
           /*System.out.println("PluginManager.readJar adding URL " + Util.FILE_PREFIX +
 260   
                             Util.URL_SEPARATOR + filePath + fileName);*/
 261  0
           urls.addElement(new URL(Util.FILE_PREFIX +
 262   
                                   Util.URL_SEPARATOR + filePath + fileName));
 263  0
           pluginClassNames.addElement(jeName.substring(
 264   
               pluginPath.length(), jeName.indexOf(Util.CLASS_SEPARATOR)));
 265   
         }
 266   
       }
 267   
     }
 268   
     catch(Exception e) {
 269   
       /*Util.errMsg(null, this.getClass().getName() + ".readJar: " +
 270   
                   e.getMessage(), e);*/
 271   
     }
 272   
   }
 273   
 }