|
24 | 24 |
|
25 | 25 | package org.sourcelab.kafka.webview.ui.manager.plugin; |
26 | 26 |
|
| 27 | +import java.io.IOException; |
27 | 28 | import org.sourcelab.kafka.webview.ui.manager.plugin.exception.LoaderException; |
28 | 29 | import org.sourcelab.kafka.webview.ui.manager.plugin.exception.UnableToFindClassException; |
29 | 30 | import org.sourcelab.kafka.webview.ui.manager.plugin.exception.WrongImplementationException; |
30 | 31 |
|
31 | 32 | import java.lang.reflect.InvocationTargetException; |
32 | 33 | import java.net.MalformedURLException; |
33 | 34 | import java.net.URL; |
| 35 | +import java.net.URLClassLoader; |
34 | 36 | import java.nio.file.Path; |
35 | 37 | import java.nio.file.Paths; |
36 | 38 |
|
@@ -84,16 +86,16 @@ public Class<? extends T> getPluginClass(final String classpath) throws LoaderEx |
84 | 86 | */ |
85 | 87 | public Class<? extends T> getPluginClass(final String jarName, final String classpath) throws LoaderException { |
86 | 88 | try { |
87 | | - final String absolutePath = getPathForJar(jarName).toString(); |
88 | | - final URL jarUrl = new URL("file://" + absolutePath); |
| 89 | + final Path absolutePath = getPathForJar(jarName); |
| 90 | + final URL jarUrl = absolutePath.toUri().toURL(); |
89 | 91 | final ClassLoader pluginClassLoader = new PluginClassLoader(jarUrl, getClass().getClassLoader()); |
90 | 92 | //final ClassLoader pluginClassLoader = new PluginClassLoader(jarUrl); |
91 | 93 | return getPluginClass(pluginClassLoader, classpath); |
92 | 94 | } catch (MalformedURLException exception) { |
93 | 95 | throw new LoaderException("Unable to load jar " + jarName, exception); |
94 | 96 | } |
95 | 97 | } |
96 | | - |
| 98 | + |
97 | 99 | /** |
98 | 100 | * Internal method to load the given classpath using the given ClassLoader. |
99 | 101 | * @return Class instance. |
@@ -139,12 +141,51 @@ public T getPlugin(final String jarName, final String classpath) throws LoaderEx |
139 | 141 | throw new LoaderException(errorMsg, e); |
140 | 142 | } |
141 | 143 | } |
| 144 | + |
| 145 | + /** |
| 146 | + * Check if instance of the class given at the classpath can be load from the given Jar. |
| 147 | + * @param jarName Jar to load the class from |
| 148 | + * @param classpath Classpath to class. |
| 149 | + * @throws LoaderException LoaderException When we run into issues. |
| 150 | + */ |
| 151 | + public void checkPlugin(final String jarName, final String classpath) throws LoaderException { |
| 152 | + try { |
| 153 | + final Path absolutePath = getPathForJar(jarName); |
| 154 | + final URL jarUrl = absolutePath.toUri().toURL(); |
| 155 | + // Windows issue, URLClassLoader open file so if we need to delete them |
| 156 | + // (that the case for new uploaded file) then the close must be explicitly call. |
| 157 | + // More information available here: |
| 158 | + // https://docs.oracle.com/javase/8/docs/technotes/guides/net/ClassLoader.html |
| 159 | + try (URLClassLoader pluginClassLoader = new PluginClassLoader(jarUrl, getClass().getClassLoader())) { |
| 160 | + Class<? extends T> pluginClass = getPluginClass(pluginClassLoader, classpath); |
| 161 | + pluginClass.getDeclaredConstructor().newInstance(); |
| 162 | + } |
| 163 | + } catch (MalformedURLException exception) { |
| 164 | + throw new LoaderException("Unable to load jar " + jarName, exception); |
| 165 | + } catch (IOException exception) { |
| 166 | + throw new LoaderException("Unable to load jar " + jarName, exception); |
| 167 | + } catch (final NoClassDefFoundError e) { |
| 168 | + // Typically this happens if the uploaded JAR references some dependency that was |
| 169 | + // not package in the JAR. Attempt to provide a useful error msg. |
| 170 | + final String errorMsg = e.getMessage() |
| 171 | + + " - Does your JAR include all of its required dependencies? " |
| 172 | + + "See https://github.com/SourceLabOrg/kafka-webview-examples#packaging-a-jar"; |
| 173 | + throw new LoaderException(errorMsg, e); |
| 174 | + } catch (final InstantiationException | IllegalAccessException e) { |
| 175 | + throw new LoaderException(e.getMessage(), e); |
| 176 | + } catch (final NoSuchMethodException | InvocationTargetException e) { |
| 177 | + // Typically this happens if referenced class in the uploaded JAR has no default constructor. |
| 178 | + final String errorMsg = e.getMessage() |
| 179 | + + " - Does your class contain a default no argument constructor?"; |
| 180 | + throw new LoaderException(errorMsg, e); |
| 181 | + } |
| 182 | + } |
142 | 183 |
|
143 | 184 | /** |
144 | 185 | * Get the full path on disk to the given Jar file. |
145 | 186 | * @param jarName Jar to lookup full path to. |
146 | 187 | */ |
147 | 188 | public Path getPathForJar(final String jarName) { |
148 | | - return Paths.get(jarDirectory + "/", jarName).toAbsolutePath(); |
| 189 | + return Paths.get(jarDirectory, jarName).toAbsolutePath(); |
149 | 190 | } |
150 | 191 | } |
0 commit comments