Skip to content

Commit a344950

Browse files
quentingodeauCrim
authored andcommitted
Fix issue #159 to allow custom formatter uploading (#164)
1 parent 8b3d3cd commit a344950

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/controller/configuration/messageformat/MessageFormatController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public String create(
226226

227227
// Attempt to load jar?
228228
try {
229-
deserializerLoader.getPlugin(tempFilename, messageFormatForm.getClasspath());
229+
deserializerLoader.checkPlugin(tempFilename, messageFormatForm.getClasspath());
230230
} catch (final LoaderException exception) {
231231
// If we had issues, remove the temp location
232232
Files.delete(Paths.get(jarPath));

kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/plugin/PluginFactory.java

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
package org.sourcelab.kafka.webview.ui.manager.plugin;
2626

27+
import java.io.IOException;
2728
import org.sourcelab.kafka.webview.ui.manager.plugin.exception.LoaderException;
2829
import org.sourcelab.kafka.webview.ui.manager.plugin.exception.UnableToFindClassException;
2930
import org.sourcelab.kafka.webview.ui.manager.plugin.exception.WrongImplementationException;
3031

3132
import java.lang.reflect.InvocationTargetException;
3233
import java.net.MalformedURLException;
3334
import java.net.URL;
35+
import java.net.URLClassLoader;
3436
import java.nio.file.Path;
3537
import java.nio.file.Paths;
3638

@@ -84,16 +86,16 @@ public Class<? extends T> getPluginClass(final String classpath) throws LoaderEx
8486
*/
8587
public Class<? extends T> getPluginClass(final String jarName, final String classpath) throws LoaderException {
8688
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();
8991
final ClassLoader pluginClassLoader = new PluginClassLoader(jarUrl, getClass().getClassLoader());
9092
//final ClassLoader pluginClassLoader = new PluginClassLoader(jarUrl);
9193
return getPluginClass(pluginClassLoader, classpath);
9294
} catch (MalformedURLException exception) {
9395
throw new LoaderException("Unable to load jar " + jarName, exception);
9496
}
9597
}
96-
98+
9799
/**
98100
* Internal method to load the given classpath using the given ClassLoader.
99101
* @return Class instance.
@@ -139,12 +141,51 @@ public T getPlugin(final String jarName, final String classpath) throws LoaderEx
139141
throw new LoaderException(errorMsg, e);
140142
}
141143
}
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+
}
142183

143184
/**
144185
* Get the full path on disk to the given Jar file.
145186
* @param jarName Jar to lookup full path to.
146187
*/
147188
public Path getPathForJar(final String jarName) {
148-
return Paths.get(jarDirectory + "/", jarName).toAbsolutePath();
189+
return Paths.get(jarDirectory, jarName).toAbsolutePath();
149190
}
150191
}

kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/plugin/UploadManager.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
package org.sourcelab.kafka.webview.ui.manager.plugin;
2626

27+
import java.io.BufferedInputStream;
2728
import org.slf4j.Logger;
2829
import org.slf4j.LoggerFactory;
2930
import org.springframework.web.multipart.MultipartFile;
@@ -156,8 +157,9 @@ private String handleFileUpload(final MultipartFile file, final String outFileNa
156157
}
157158

158159
// Get the file and save it somewhere
159-
final byte[] bytes = file.getBytes();
160-
Files.write(fullOutputPath, bytes);
160+
try (BufferedInputStream in = new BufferedInputStream(file.getInputStream())) {
161+
Files.copy(in, fullOutputPath);
162+
}
161163

162164
return fullOutputPath.toString();
163165
}

0 commit comments

Comments
 (0)