Ignore:
Timestamp:
08/01/19 12:11:21 (5 years ago)
Author:
pharms
Message:

Update to java 11

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-plugin-core/src/main/java/de/ugoe/cs/autoquest/plugin/PluginLoader.java

    r2232 r2260  
    1616 
    1717import java.io.File; 
    18 import java.io.FileInputStream; 
    19 import java.io.FileNotFoundException; 
    2018import java.io.FilenameFilter; 
    21 import java.io.IOException; 
    2219import java.lang.reflect.InvocationTargetException; 
    23 import java.lang.reflect.Method; 
    2420import java.net.MalformedURLException; 
    2521import java.net.URL; 
     
    2824import java.util.Collections; 
    2925import java.util.LinkedList; 
    30 import java.util.jar.JarInputStream; 
    31 import java.util.jar.Manifest; 
     26import java.util.List; 
    3227 
    3328/** 
    3429 * <p> 
    35  * This class provides the functionality to load AutoQUEST plug-ins from a 
    36  * pre-defined folder. 
     30 * This class provides the functionality to load AutoQUEST plug-ins from a pre-defined folder. 
    3731 * </p> 
    3832 *  
     
    4034 * @version 1.0 
    4135 */ 
    42 public class PluginLoader { 
    43  
    44         /** 
    45          * <p> 
    46          * Handle of the plug-in directory. 
    47          * </p> 
    48          */ 
    49         private final File pluginDir; 
    50  
    51         /** 
    52          * <p> 
    53          * Collection of the loaded plug-ins. 
    54          * </p> 
    55          */ 
    56         private final Collection<AutoQUESTPlugin> plugins; 
    57  
    58         /** 
    59          * <p> 
    60          * Constructor. Creates a new PluginLoader that can load plug-ins the 
    61          * defined directory. 
    62          * </p> 
    63          *  
    64          * @param pluginDir 
    65          *            handle of the directory; in case the handle is 
    66          *            <code>null</code> or does not describe a directory, an 
    67          *            {@link IllegalArgumentException} is thrown 
    68          */ 
    69         public PluginLoader(File pluginDir) { 
    70                 if (pluginDir == null) { 
    71                         throw new IllegalArgumentException( 
    72                                         "Parameter pluginDir must not be null!"); 
    73                 } 
    74                 if (!pluginDir.isDirectory()) { 
    75                         throw new IllegalArgumentException("File " + pluginDir.getPath() 
    76                                         + " is not a directory"); 
    77                 } 
    78                 this.pluginDir = pluginDir; 
    79                 plugins = new LinkedList<AutoQUESTPlugin>(); 
    80         } 
    81  
    82         /** 
    83          * <p> 
    84          * Loads plug-ins from {@link #pluginDir}. 
    85          * </p> 
    86          *  
    87          * @throws PluginLoaderException 
    88          *             thrown if there is a problem loading a plug-in or updating 
    89          *             the classpath 
    90          */ 
    91         public void load() throws PluginLoaderException { 
    92                 File[] jarFiles = pluginDir.listFiles(new FilenameFilter() { 
    93                         @Override 
    94                         public boolean accept(File dir, String name) { 
    95                                 return checkNameConformity(name); 
    96                         } 
    97                 }); 
    98  
    99                 if (jarFiles != null) { 
    100                         for (File jarFile : jarFiles) { 
    101                                 updateClassLoader(jarFile); 
    102  
    103                                 String pluginName = jarFile.getName().split("-")[2]; 
    104                                 String pluginClassName = "de.ugoe.cs.autoquest.plugin." + pluginName 
    105                                                 + "." + pluginName.toUpperCase() + "Plugin"; 
    106  
    107                                 Class<?> pluginClass = null; 
    108                                 try { 
    109                                         pluginClass = Class.forName(pluginClassName); 
    110                                 } catch (ClassNotFoundException e) { 
    111                                         throw new PluginLoaderException("No class '" + pluginClassName 
    112                                                         + "' found in " + pluginDir + "/" + jarFile.getName()); 
    113                                 } 
    114                                 try { 
    115                                         AutoQUESTPlugin pluginObject = (AutoQUESTPlugin) pluginClass 
    116                                                         .newInstance(); 
    117                                         plugins.add(pluginObject); 
    118                                 } catch (InstantiationException e) { 
    119                                         throw new PluginLoaderException("Could not instantiate " 
    120                                                         + pluginClassName); 
    121                                 } catch (IllegalAccessException e) { 
    122                                         throw new PluginLoaderException("Could not access " 
    123                                                         + pluginClassName); 
    124                                 } catch (ClassCastException e) { 
    125                                         throw new PluginLoaderException("Class " + pluginClassName 
    126                                                         + " not instance of AutoQUESTPlugin"); 
    127                                 } 
    128                         } 
    129                 } 
    130         } 
    131  
    132         /** 
    133          * <p> 
    134          * Retrieves the classpath from a Jar file's MANIFEST. 
    135          * </p> 
    136          */ 
    137         protected String[] getClassPathFromJar(File jarFile) { 
    138                 String[] classPath; 
    139  
    140                 JarInputStream jarInputStream = null; 
    141                 Manifest manifest = null; 
    142                 try { 
    143                     FileInputStream fileStream = new FileInputStream(jarFile); 
    144                     try { 
    145                         jarInputStream = new JarInputStream(fileStream); 
    146                         manifest = jarInputStream.getManifest(); 
    147                     } finally { 
    148                         jarInputStream.close(); 
    149                         fileStream.close(); 
    150                     } 
    151                 } catch (FileNotFoundException e) { 
    152                         throw new AssertionError( 
    153                                         "FileNotFoundException should be impossible!"); 
    154                 } catch (IOException e) { 
    155                         throw new PluginLoaderException(e); 
    156                 } 
    157  
    158                 String jarClassPath = manifest.getMainAttributes().getValue( 
    159                                 "Class-Path"); 
    160  
    161                 if (jarClassPath != null) { 
    162                         String[] jarClassPathElements = jarClassPath.split(" "); 
    163                         classPath = new String[jarClassPathElements.length]; 
    164                         for (int i = 0; i < jarClassPathElements.length; i++) { 
    165                                 classPath[i] = "file:" 
    166                                                 + jarFile.getParentFile().getAbsolutePath() + "/" 
    167                                                 + jarClassPathElements[i]; 
    168                         } 
    169                         try { 
    170                                 jarInputStream.close(); 
    171                         } catch (IOException e) { 
    172                                 throw new PluginLoaderException(e); 
    173                         } 
    174                 } else { 
    175                         classPath = new String[] {}; 
    176                 } 
    177                 return classPath; 
    178         } 
    179  
    180         /** 
    181          * <p> 
    182          * Updates the classpath of the {@link ClassLoader} to include the plug-in 
    183          * jar as well as further libraries required by the plug-in jar as defined 
    184          * in the <code>Class-Path</code> section of its manifest. 
    185          * </p> 
    186          *  
    187          * @param jarFile 
    188          *            handle of the plug-in jar file 
    189          * @throws PluginLoaderException 
    190          *             thrown if there is a problem updating the class loader or 
    191          *             loading the plug-in jar 
    192          */ 
    193         private void updateClassLoader(File jarFile) throws PluginLoaderException { 
    194                 String[] classPath = getClassPathFromJar(jarFile); 
    195                 URLClassLoader classLoader = (URLClassLoader) ClassLoader 
    196                                 .getSystemClassLoader(); 
    197                 Method method; 
    198  
    199                 try { 
    200                         method = URLClassLoader.class.getDeclaredMethod("addURL", 
    201                                         new Class[] { URL.class }); 
    202                 } catch (SecurityException e) { 
    203                         throw new PluginLoaderException( 
    204                                         "addURL method of URLClassLoader not accessible via reflection."); 
    205                 } catch (NoSuchMethodException e) { 
    206                         throw new AssertionError( 
    207                                         "URLClassLoader does not have addURL method. Should be impossible!!"); 
    208                 } 
    209                 method.setAccessible(true); 
    210  
    211                 try { 
    212                         method.invoke( 
    213                                         classLoader, 
    214                                         new Object[] { new URL("file:" + jarFile.getAbsoluteFile()) }); 
    215                         for (String element : classPath) { 
    216                                 method.invoke(classLoader, new Object[] { new URL(element) }); 
    217                         } 
    218                 } catch (IllegalArgumentException e) { 
    219                         throw new AssertionError( 
    220                                         "Illegal arguments for addURL method. Should be impossible!!"); 
    221                 } catch (MalformedURLException e) { 
    222                         throw new PluginLoaderException(e); 
    223                 } catch (IllegalAccessException e) { 
    224                         throw new PluginLoaderException( 
    225                                         "addURL method of URLClassLoader not accessible via reflection."); 
    226                 } catch (InvocationTargetException e) { 
    227                         throw new PluginLoaderException(e); 
    228                 } 
    229         } 
    230  
    231         /** 
    232          * <p> 
    233          * Checks if the name of a file indicates that it defines a AutoQUEST plug-in. 
    234          * The structure of valid plug-in filenames is 
    235          * <code>autoquest-plugin-%PLUGIN_NAME%-version.jar</code>, where 
    236          * <code>%PLUGIN_NAME%</code> is replaced by the name of the plug-in. Note 
    237          * that plug-in names must not contain any dashes. 
    238          * </p> 
    239          *  
    240          * @param filename 
    241          *            filename that is checked 
    242          * @return true if filename matches pattern of AutoQUEST plug-in; false 
    243          *         otherwise 
    244          */ 
    245         protected boolean checkNameConformity(String filename) { 
    246                 if (filename == null) { 
    247                         return false; 
    248                 } 
    249                 return filename.startsWith("autoquest-plugin-") && !filename.startsWith("autoquest-plugin-core") 
    250                                 && 
    251                                 ((filename.split("-").length == 4 && filename.endsWith(".jar")) || 
    252                                   filename.split("-").length == 5 && filename.endsWith("SNAPSHOT.jar") || 
    253                                   filename.split("-").length == 6 && filename.endsWith(".jar")); 
    254         } 
    255          
    256         public Collection<AutoQUESTPlugin> getPlugins() { 
    257                 return Collections.unmodifiableCollection(plugins); 
    258         } 
     36public class PluginLoader implements AutoCloseable { 
     37 
     38    /** 
     39     * <p> 
     40     * Handle of the plug-in directory. 
     41     * </p> 
     42     */ 
     43    private final File pluginDir; 
     44 
     45    /** 
     46     * <p> 
     47     * Collection of the loaded plug-ins. 
     48     * </p> 
     49     */ 
     50    private final Collection<AutoQUESTPlugin> plugins; 
     51     
     52    /** 
     53     * <p> 
     54     * the class loaders instantiated internally 
     55     * </p> 
     56     */ 
     57    private List<URLClassLoader> instantiatedClassLoaders = new LinkedList<>(); 
     58 
     59    /** 
     60     * <p> 
     61     * Constructor. Creates a new PluginLoader that can load plug-ins the defined directory. 
     62     * </p> 
     63     *  
     64     * @param pluginDir 
     65     *            handle of the directory; in case the handle is <code>null</code> or does not 
     66     *            describe a directory, an {@link IllegalArgumentException} is thrown 
     67     */ 
     68    public PluginLoader(File pluginDir) { 
     69        if (pluginDir == null) { 
     70            throw new IllegalArgumentException("Parameter pluginDir must not be null!"); 
     71        } 
     72        if (!pluginDir.isDirectory()) { 
     73            throw new IllegalArgumentException("File " + pluginDir.getPath() + 
     74                " is not a directory"); 
     75        } 
     76        this.pluginDir = pluginDir; 
     77        plugins = new LinkedList<AutoQUESTPlugin>(); 
     78    } 
     79 
     80    /** 
     81     * <p> 
     82     * Loads plug-ins from {@link #pluginDir}. 
     83     * </p> 
     84     *  
     85     * @throws PluginLoaderException 
     86     *             thrown if there is a problem loading a plug-in or updating the classpath 
     87     */ 
     88    public void load() throws PluginLoaderException { 
     89        File[] jarFiles = pluginDir.listFiles(new FilenameFilter() { 
     90            @Override 
     91            public boolean accept(File dir, String name) { 
     92                return checkNameConformity(name); 
     93            } 
     94        }); 
     95 
     96        if (jarFiles != null) { 
     97            for (File jarFile : jarFiles) { 
     98                updateClassLoader(jarFile); 
     99 
     100                String pluginName = jarFile.getName().split("-")[2]; 
     101                String pluginClassName = "de.ugoe.cs.autoquest.plugin." + pluginName + "." + 
     102                    pluginName.toUpperCase() + "Plugin"; 
     103 
     104                Class<?> pluginClass = null; 
     105                try { 
     106                    pluginClass = Class.forName(pluginClassName); 
     107                } 
     108                catch (ClassNotFoundException e) { 
     109                    throw new PluginLoaderException("No class '" + pluginClassName + "' found in " + 
     110                        pluginDir + "/" + jarFile.getName()); 
     111                } 
     112                try { 
     113                    AutoQUESTPlugin pluginObject = 
     114                        (AutoQUESTPlugin) pluginClass.getDeclaredConstructor().newInstance(); 
     115                    plugins.add(pluginObject); 
     116                } 
     117                catch (InstantiationException e) { 
     118                    throw new PluginLoaderException("Could not instantiate " + pluginClassName); 
     119                } 
     120                catch (IllegalAccessException e) { 
     121                    throw new PluginLoaderException("Could not access " + pluginClassName); 
     122                } 
     123                catch (ClassCastException e) { 
     124                    throw new PluginLoaderException("Class " + pluginClassName + 
     125                        " not instance of AutoQUESTPlugin"); 
     126                } 
     127                catch (IllegalArgumentException e) { 
     128                    // TODO Auto-generated catch block 
     129                    e.printStackTrace(); 
     130                } 
     131                catch (InvocationTargetException e) { 
     132                    // TODO Auto-generated catch block 
     133                    e.printStackTrace(); 
     134                } 
     135                catch (NoSuchMethodException e) { 
     136                    // TODO Auto-generated catch block 
     137                    e.printStackTrace(); 
     138                } 
     139                catch (SecurityException e) { 
     140                    // TODO Auto-generated catch block 
     141                    e.printStackTrace(); 
     142                } 
     143            } 
     144        } 
     145    } 
     146 
     147    /** 
     148     * <p> 
     149     * Retrieves the classpath from a Jar file's MANIFEST. 
     150     * </p> 
     151     */ 
     152    /* 
     153     * protected String[] getClassPathFromJar(File jarFile) { String[] classPath; 
     154     *  
     155     * JarInputStream jarInputStream = null; Manifest manifest = null; try { FileInputStream 
     156     * fileStream = new FileInputStream(jarFile); try { jarInputStream = new 
     157     * JarInputStream(fileStream); manifest = jarInputStream.getManifest(); } finally { 
     158     * jarInputStream.close(); fileStream.close(); } } catch (FileNotFoundException e) { throw new 
     159     * AssertionError( "FileNotFoundException should be impossible!"); } catch (IOException e) { 
     160     * throw new PluginLoaderException(e); } 
     161     *  
     162     * String jarClassPath = manifest.getMainAttributes().getValue( "Class-Path"); 
     163     *  
     164     * if (jarClassPath != null) { String[] jarClassPathElements = jarClassPath.split(" "); 
     165     * classPath = new String[jarClassPathElements.length]; for (int i = 0; i < 
     166     * jarClassPathElements.length; i++) { classPath[i] = "file:" + 
     167     * jarFile.getParentFile().getAbsolutePath() + "/" + jarClassPathElements[i]; } try { 
     168     * jarInputStream.close(); } catch (IOException e) { throw new PluginLoaderException(e); } } 
     169     * else { classPath = new String[] {}; } return classPath; } 
     170     */ 
     171 
     172    /** 
     173     * <p> 
     174     * Updates the classpath of the {@link ClassLoader} to include the plug-in jar as well as 
     175     * further libraries required by the plug-in jar as defined in the <code>Class-Path</code> 
     176     * section of its manifest. 
     177     * </p> 
     178     *  
     179     * @param jarFile 
     180     *            handle of the plug-in jar file 
     181     * @throws PluginLoaderException 
     182     *             thrown if there is a problem updating the class loader or loading the plug-in jar 
     183     */ 
     184    private void updateClassLoader(File jarFile) throws PluginLoaderException { 
     185        // String[] classPath = getClassPathFromJar(jarFile); 
     186 
     187        try { 
     188            URLClassLoader loader = new URLClassLoader(new URL[] 
     189                { new URL("file:" + jarFile.getAbsoluteFile()) }, 
     190                                                    ClassLoader.getSystemClassLoader()); 
     191             
     192            instantiatedClassLoaders.add(loader); 
     193        } 
     194        catch (MalformedURLException e) { 
     195            throw new PluginLoaderException(e); 
     196        } 
     197    } 
     198 
     199    /** 
     200     * <p> 
     201     * Checks if the name of a file indicates that it defines a AutoQUEST plug-in. The structure of 
     202     * valid plug-in filenames is <code>autoquest-plugin-%PLUGIN_NAME%-version.jar</code>, where 
     203     * <code>%PLUGIN_NAME%</code> is replaced by the name of the plug-in. Note that plug-in names 
     204     * must not contain any dashes. 
     205     * </p> 
     206     *  
     207     * @param filename 
     208     *            filename that is checked 
     209     * @return true if filename matches pattern of AutoQUEST plug-in; false otherwise 
     210     */ 
     211    protected boolean checkNameConformity(String filename) { 
     212        if (filename == null) { 
     213            return false; 
     214        } 
     215        return filename.startsWith("autoquest-plugin-") && 
     216            !filename.startsWith("autoquest-plugin-core") && 
     217            ((filename.split("-").length == 4 && filename.endsWith(".jar")) || 
     218                filename.split("-").length == 5 && filename.endsWith("SNAPSHOT.jar") || 
     219                filename.split("-").length == 6 && filename.endsWith(".jar")); 
     220    } 
     221 
     222    public Collection<AutoQUESTPlugin> getPlugins() { 
     223        return Collections.unmodifiableCollection(plugins); 
     224    } 
     225 
     226    @Override 
     227    public void close() throws Exception { 
     228        for (URLClassLoader loader : instantiatedClassLoaders) { 
     229            loader.close(); 
     230        } 
     231    } 
     232 
    259233} 
Note: See TracChangeset for help on using the changeset viewer.