Revize 22d0b32a
Přidáno uživatelem Pavel Fidranský před asi 6 roky(ů)
sources/imiger-core/pom.xml | ||
---|---|---|
58 | 58 |
</build> |
59 | 59 |
|
60 | 60 |
<dependencies> |
61 |
<dependency> |
|
62 |
<groupId>cz.zcu.kiv</groupId> |
|
63 |
<artifactId>imiger-module</artifactId> |
|
64 |
<version>${project.version}</version> |
|
65 |
</dependency> |
|
61 | 66 |
<dependency> |
62 | 67 |
<groupId>cz.zcu.kiv</groupId> |
63 | 68 |
<artifactId>imiger-spade-converter</artifactId> |
sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/modularization/ModuleLoader.java | ||
---|---|---|
1 |
package cz.zcu.kiv.offscreen.modularization; |
|
2 |
|
|
3 |
import javafx.util.Pair; |
|
4 |
import org.apache.commons.io.FileUtils; |
|
5 |
import org.apache.commons.io.FilenameUtils; |
|
6 |
import org.apache.logging.log4j.LogManager; |
|
7 |
import org.apache.logging.log4j.Logger; |
|
8 |
|
|
9 |
import java.io.FileInputStream; |
|
10 |
import java.io.IOException; |
|
11 |
import java.net.URL; |
|
12 |
import java.net.URLClassLoader; |
|
13 |
import java.util.Arrays; |
|
14 |
import java.util.Optional; |
|
15 |
import java.util.Set; |
|
16 |
import java.util.jar.Attributes; |
|
17 |
import java.util.jar.JarInputStream; |
|
18 |
import java.util.jar.Manifest; |
|
19 |
import java.util.stream.Collectors; |
|
20 |
|
|
21 |
/** |
|
22 |
* @author Tomáš Šimandl |
|
23 |
*/ |
|
24 |
class ModuleLoader { |
|
25 |
|
|
26 |
private static final Logger logger = LogManager.getLogger(); |
|
27 |
/** Valid file extension of Java module. */ |
|
28 |
private static final String VALID_MODULE_EXTENSION = "jar"; |
|
29 |
/** Identification of section in manifest containing other information about the module. */ |
|
30 |
private static final String MODULE_SECTION_IDENTIFIER = "cz.zcu.kiv.imiger.plugin"; |
|
31 |
/** Identification of class name in modules manifest. */ |
|
32 |
private static final String MODULE_CLASS_IDENTIFIER = "Module-Class"; |
|
33 |
/** Identification of modules visible name in modules manifest. */ |
|
34 |
private static final String MODULE_NAME_IDENTIFIER = "Module-Name"; |
|
35 |
|
|
36 |
/** Name of method which must contains every module. */ |
|
37 |
private final String methodName; |
|
38 |
/** Class type of parameter to method which must contains every module. */ |
|
39 |
private final Class methodParamClass; |
|
40 |
|
|
41 |
|
|
42 |
/** |
|
43 |
* Only story input parameters |
|
44 |
* @param methodName Name of method which must contains every module. |
|
45 |
* @param methodParamClass Class type of parameter to method which must contains every module. |
|
46 |
*/ |
|
47 |
ModuleLoader(String methodName, Class methodParamClass) { |
|
48 |
this.methodName = methodName; |
|
49 |
this.methodParamClass = methodParamClass; |
|
50 |
logger.info("Initializing new ModuleLoader"); |
|
51 |
} |
|
52 |
|
|
53 |
/** |
|
54 |
* Method starts process of loading all modules from modules folder (defined in constructor). |
|
55 |
* @return set of loaded modules in Pair where key is: 'Visible name' and value: 'Class to be called'. |
|
56 |
*/ |
|
57 |
Set<Pair<String, Class>> loadModules() { |
|
58 |
logger.info("Loading all modules from file."); |
|
59 |
final URL[] resources = ((URLClassLoader) getClass().getClassLoader()).getURLs(); |
|
60 |
return Arrays.stream(resources) |
|
61 |
.filter(this::isJarFile) // remove resources which are not jar files |
|
62 |
.map(this::loadModule) // call method loadModule for every module |
|
63 |
.filter(Optional::isPresent) // remove modules which were not loaded |
|
64 |
.map(Optional::get) // extract modules from Optional class |
|
65 |
.collect(Collectors.toSet()); // return set of modules |
|
66 |
} |
|
67 |
|
|
68 |
/** |
|
69 |
* Checks if resource is a jar file by its extension. |
|
70 |
* |
|
71 |
* @param resourceUrl URL of the resource in local filesystem |
|
72 |
* @return true if the resource is a jar file, otherwise false |
|
73 |
*/ |
|
74 |
private boolean isJarFile(URL resourceUrl) { |
|
75 |
return FilenameUtils.getExtension(resourceUrl.getFile()).equals(VALID_MODULE_EXTENSION); |
|
76 |
} |
|
77 |
|
|
78 |
/** |
|
79 |
* Load one particular module given by input File containing opened jar file. |
|
80 |
* Method returns module in Optional in Pair where key is visible modules name and value is access Class from module. |
|
81 |
* |
|
82 |
* @param moduleUrl URL of the module in local filesystem |
|
83 |
* @return opened module or empty Optional where some error occurs. |
|
84 |
*/ |
|
85 |
private Optional<Pair<String, Class>> loadModule(URL moduleUrl) { |
|
86 |
JarInputStream jis = null; |
|
87 |
try { |
|
88 |
jis = new JarInputStream(new FileInputStream(FileUtils.toFile(moduleUrl))); |
|
89 |
final Manifest mf = jis.getManifest(); |
|
90 |
final Attributes attributes = mf.getAttributes(MODULE_SECTION_IDENTIFIER); |
|
91 |
if (attributes == null) { |
|
92 |
throw new NotModuleException(); |
|
93 |
} |
|
94 |
|
|
95 |
final String moduleClassName = attributes.getValue(MODULE_CLASS_IDENTIFIER); |
|
96 |
final String moduleVisibleName = attributes.getValue(MODULE_NAME_IDENTIFIER); |
|
97 |
|
|
98 |
final Class<?> clazz = Class.forName(moduleClassName, true, getClass().getClassLoader()); |
|
99 |
// checking if method exists, if not throw exception |
|
100 |
clazz.getMethod(methodName, methodParamClass); |
|
101 |
|
|
102 |
return Optional.of(new Pair<>(moduleVisibleName, clazz)); |
|
103 |
|
|
104 |
} catch (NotModuleException e) { |
|
105 |
return Optional.empty(); |
|
106 |
} catch (Exception e) { |
|
107 |
logger.debug("Invalid module throw exception: ", e); |
|
108 |
return Optional.empty(); |
|
109 |
} finally { |
|
110 |
try { |
|
111 |
if (jis != null) jis.close(); |
|
112 |
} catch (IOException e) { |
|
113 |
logger.error("Can not close opened jar file: ", e); |
|
114 |
} |
|
115 |
} |
|
116 |
} |
|
117 |
} |
sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/modularization/ModuleProvider.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.offscreen.modularization; |
2 | 2 |
|
3 |
import javafx.util.Pair;
|
|
3 |
import cz.zcu.kiv.imiger.spi.IModule;
|
|
4 | 4 |
import org.apache.logging.log4j.LogManager; |
5 | 5 |
import org.apache.logging.log4j.Logger; |
6 | 6 |
|
... | ... | |
8 | 8 |
import java.net.URISyntaxException; |
9 | 9 |
import java.nio.file.*; |
10 | 10 |
import java.util.HashMap; |
11 |
import java.util.Iterator; |
|
11 | 12 |
import java.util.Map; |
12 |
import java.util.Set;
|
|
13 |
import java.util.ServiceLoader;
|
|
13 | 14 |
import java.util.concurrent.*; |
14 | 15 |
|
15 | 16 |
/** |
... | ... | |
17 | 18 |
*/ |
18 | 19 |
public class ModuleProvider { |
19 | 20 |
|
20 |
/** Name of accessed method in every module. */ |
|
21 |
public static final String METHOD_NAME = "getRawJson"; |
|
22 |
/** Class of input parameter to accessed method in every module. */ |
|
23 |
public static final Class METHOD_PARAMETER_CLASS = String.class; |
|
24 |
|
|
25 | 21 |
private static final Logger logger = LogManager.getLogger(); |
26 | 22 |
/** Instance of this class used for singleton pattern. */ |
27 | 23 |
private static ModuleProvider instance = null; |
28 | 24 |
|
29 |
/** |
|
30 |
* Map containing actual loaded modules. Key is hash of visible name and value is pair of |
|
31 |
* visible name na accessed method. |
|
32 |
*/ |
|
33 |
private ConcurrentMap<String, Pair<String, Class>> modules = new ConcurrentHashMap<>(); |
|
34 |
/** Instance of class ModuleLoader. */ |
|
35 |
private final ModuleLoader loader; |
|
25 |
/** Queue containing actual loaded modules. */ |
|
26 |
private Map<String, IModule> modules = new ConcurrentHashMap<>(); |
|
27 |
/** Instance of ServiceLoader. */ |
|
28 |
private final ServiceLoader<IModule> loader; |
|
36 | 29 |
|
37 | 30 |
/** Instance of ScheduledExecutorService used for scheduling of module folder watcher. */ |
38 | 31 |
private ScheduledExecutorService executor; |
... | ... | |
60 | 53 |
* When watcher fails than is automatically starts new watcher after 5 minutes timeout. |
61 | 54 |
*/ |
62 | 55 |
private ModuleProvider() { |
63 |
this.loader = new ModuleLoader(METHOD_NAME, METHOD_PARAMETER_CLASS);
|
|
56 |
this.loader = ServiceLoader.load(IModule.class);
|
|
64 | 57 |
|
65 |
processModules(loader.loadModules());
|
|
58 |
processModules(loader.iterator());
|
|
66 | 59 |
|
67 | 60 |
executor = Executors.newSingleThreadScheduledExecutor(); |
68 | 61 |
Runnable task = this::initModulesWatcher; |
... | ... | |
120 | 113 |
continue; |
121 | 114 |
} |
122 | 115 |
|
123 |
processModules(loader.loadModules()); |
|
116 |
loader.reload(); |
|
117 |
processModules(loader.iterator()); |
|
124 | 118 |
break; // watching only one folder and loading all files every loop => Only one iteration is needed. |
125 | 119 |
} |
126 | 120 |
|
... | ... | |
142 | 136 |
* |
143 | 137 |
* @param unprocessedModules Set of loaded modules where first argument is visible name and second is accessible method. |
144 | 138 |
*/ |
145 |
private void processModules(Set<Pair<String, Class>> unprocessedModules) {
|
|
139 |
private void processModules(Iterator<IModule> unprocessedModules) {
|
|
146 | 140 |
long startTime = System.nanoTime(); |
147 |
Map<String, Pair<String, Class>> localModules = new HashMap<>();
|
|
141 |
Map<String, IModule> localModules = new HashMap<>();
|
|
148 | 142 |
|
149 |
logger.info("Processing " + unprocessedModules.size() + " modules.");
|
|
143 |
logger.info("Processing modules."); |
|
150 | 144 |
|
151 |
for (Pair<String, Class> pair : unprocessedModules) { |
|
152 |
localModules.put(String.valueOf(pair.getKey().hashCode()), pair); |
|
153 |
} |
|
145 |
unprocessedModules.forEachRemaining(module -> localModules.put(String.valueOf(module.getModuleName().hashCode()), module)); |
|
154 | 146 |
|
155 | 147 |
modules.clear(); |
156 | 148 |
modules.putAll(localModules); |
... | ... | |
163 | 155 |
* |
164 | 156 |
* @return all loaded modules. |
165 | 157 |
*/ |
166 |
public Map<String, Pair<String, Class>> getModules() {
|
|
158 |
public Map<String, IModule> getModules() {
|
|
167 | 159 |
return modules; |
168 | 160 |
} |
169 | 161 |
} |
sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/modularization/NotModuleException.java | ||
---|---|---|
1 |
package cz.zcu.kiv.offscreen.modularization; |
|
2 |
|
|
3 |
/** |
|
4 |
* Exception thrown when a jar file which is not a valid IMiGEr plugin is loaded. |
|
5 |
*/ |
|
6 |
class NotModuleException extends Exception { |
|
7 |
NotModuleException() { |
|
8 |
super("Jar file is not a valid IMiGEr plugin!"); |
|
9 |
} |
|
10 |
} |
sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/servlets/api/GetSessionDiagram.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.offscreen.servlets.api; |
2 | 2 |
|
3 | 3 |
import com.google.gson.JsonObject; |
4 |
import cz.zcu.kiv.imiger.spi.IModule; |
|
4 | 5 |
import cz.zcu.kiv.offscreen.modularization.ModuleProvider; |
5 | 6 |
import cz.zcu.kiv.offscreen.servlets.BaseServlet; |
6 |
import javafx.util.Pair; |
|
7 | 7 |
import org.apache.commons.lang3.StringUtils; |
8 | 8 |
import org.apache.logging.log4j.LogManager; |
9 | 9 |
import org.apache.logging.log4j.Logger; |
... | ... | |
11 | 11 |
import javax.servlet.http.HttpServletRequest; |
12 | 12 |
import javax.servlet.http.HttpServletResponse; |
13 | 13 |
import java.io.IOException; |
14 |
import java.lang.reflect.Method; |
|
15 | 14 |
import java.util.Optional; |
16 | 15 |
|
17 | 16 |
/** |
... | ... | |
85 | 84 |
private Optional<String> callModuleConverter(String type, String stringToConvert){ |
86 | 85 |
logger.debug("Processing json with module"); |
87 | 86 |
|
88 |
Pair<String, Class> module = ModuleProvider.getInstance().getModules().get(type);
|
|
89 |
if (module == null){ |
|
87 |
IModule module = ModuleProvider.getInstance().getModules().get(type);
|
|
88 |
if (module == null) {
|
|
90 | 89 |
logger.debug("No loader available for type: " + type + ". Response BAD REQUEST"); |
91 | 90 |
return Optional.empty(); |
92 | 91 |
} |
93 | 92 |
|
94 | 93 |
try { |
95 |
final Class<?> moduleClass = module.getValue(); |
|
96 |
// switching to class loader of module |
|
97 |
final ClassLoader appClassLoader = Thread.currentThread().getContextClassLoader(); |
|
98 |
Thread.currentThread().setContextClassLoader(moduleClass.getClassLoader()); |
|
94 |
String rawJson = String.valueOf(module.getRawJson(stringToConvert)); |
|
99 | 95 |
|
100 |
final Method moduleMethod = moduleClass.getMethod(ModuleProvider.METHOD_NAME, ModuleProvider.METHOD_PARAMETER_CLASS); |
|
101 |
String rawJson = String.valueOf(moduleMethod.invoke(moduleClass.newInstance(), stringToConvert)); |
|
102 |
|
|
103 |
// switching back to application class loader |
|
104 |
Thread.currentThread().setContextClassLoader(appClassLoader); |
|
105 |
|
|
106 |
if(StringUtils.isBlank(rawJson)){ |
|
96 |
if (StringUtils.isBlank(rawJson)){ |
|
107 | 97 |
return Optional.empty(); |
108 | 98 |
} else { |
109 | 99 |
return Optional.of(rawJson); |
110 | 100 |
} |
111 | 101 |
|
112 | 102 |
} catch (Exception e) { |
113 |
logger.error("Can not call convert method in module. Module name: " + module.getKey(), e);
|
|
103 |
logger.error("Can not call convert method in module. Module name: " + module.getModuleName(), e);
|
|
114 | 104 |
return Optional.empty(); |
115 | 105 |
} |
116 | 106 |
} |
sources/imiger-core/src/main/webapp/uploadFiles.jsp | ||
---|---|---|
74 | 74 |
Select type of data file:<br> |
75 | 75 |
<label for="raw"><input type="radio" name="fileFormat" value="raw" id="raw" checked> Raw JSON</label><br> |
76 | 76 |
<c:forEach items="${processingModules}" var="module"> |
77 |
<label for="${module.key}"><input type="radio" name="fileFormat" value="${module.key}" id="${module.key}"> ${module.value.key}</label><br>
|
|
77 |
<label for="${module.key}"><input type="radio" name="fileFormat" value="${module.key}" id="${module.key}"> ${module.value.moduleName}</label><br>
|
|
78 | 78 |
</c:forEach> |
79 | 79 |
</div> |
80 | 80 |
|
sources/imiger-module/src/main/java/cz/zcu/kiv/imiger/spi/IModule.java | ||
---|---|---|
1 |
package cz.zcu.kiv.imiger.spi; |
|
2 |
|
|
3 |
/** |
|
4 |
* Service Provider Interface (SPI) that must be implemented by all modules. |
|
5 |
*/ |
|
6 |
public interface IModule { |
|
7 |
/** |
|
8 |
* @return Display name of the module. |
|
9 |
*/ |
|
10 |
String getModuleName(); |
|
11 |
|
|
12 |
/** |
|
13 |
* Converts input string in any format to raw JSON processable by IMiGEr. |
|
14 |
* |
|
15 |
* @param stringToConvert String to be converted to raw JSON. |
|
16 |
* @return Raw JSON. |
|
17 |
*/ |
|
18 |
String getRawJson(String stringToConvert); |
|
19 |
} |
sources/imiger-plugin-template/pom.xml | ||
---|---|---|
26 | 26 |
<plugins> |
27 | 27 |
<plugin> |
28 | 28 |
<groupId>org.apache.maven.plugins</groupId> |
29 |
<artifactId>maven-assembly-plugin</artifactId> |
|
30 |
<configuration> |
|
31 |
<archive> |
|
32 |
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile> |
|
33 |
</archive> |
|
34 |
<descriptorRefs> |
|
35 |
<descriptorRef>jar-with-dependencies</descriptorRef> |
|
36 |
</descriptorRefs> |
|
37 |
</configuration> |
|
38 |
<executions> |
|
39 |
<execution> |
|
40 |
<id>make-assembly</id> <!-- this is used for inheritance merges --> |
|
41 |
<phase>package</phase> <!-- bind to the packaging phase --> |
|
42 |
<goals> |
|
43 |
<goal>single</goal> |
|
44 |
</goals> |
|
45 |
</execution> |
|
46 |
</executions> |
|
29 |
<artifactId>maven-jar-plugin</artifactId> |
|
30 |
<version>3.1.1</version> |
|
47 | 31 |
</plugin> |
48 | 32 |
</plugins> |
49 | 33 |
</build> |
sources/imiger-plugin-template/src/main/java/cz/zcu/kiv/imiger/plugin/template/Converter.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.imiger.plugin.template; |
2 | 2 |
|
3 | 3 |
import com.google.gson.Gson; |
4 |
import cz.zcu.kiv.imiger.spi.IModule; |
|
4 | 5 |
import cz.zcu.kiv.imiger.vo.Graph; |
5 | 6 |
|
6 |
public class Converter { |
|
7 |
public class Converter implements IModule { |
|
8 |
@Override |
|
9 |
public String getModuleName() { |
|
10 |
return "Module Template"; |
|
11 |
} |
|
7 | 12 |
|
8 | 13 |
/** |
9 | 14 |
* Convert input file to RAW JSON and return it. |
10 | 15 |
*/ |
16 |
@Override |
|
11 | 17 |
public String getRawJson(String inputFile) { |
12 |
|
|
13 | 18 |
Graph graph = new Graph(); |
14 | 19 |
return new Gson().toJson(graph); |
15 | 20 |
} |
sources/imiger-plugin-template/src/main/resources/META-INF/MANIFEST.MF | ||
---|---|---|
1 |
Manifest-Version: 1.0 |
|
2 |
Created-By: Apache Maven ${maven.version} |
|
3 |
Built-By: ${user.name} |
|
4 |
Build-Jdk: ${java.version} |
|
5 |
Module-Class: cz.zcu.kiv.imiger.plugin.template.Converter |
|
6 |
Module-Name: My Convertor |
sources/imiger-plugin-template/src/main/resources/META-INF/services/cz.zcu.kiv.imiger.spi.IModule | ||
---|---|---|
1 |
cz.zcu.kiv.imiger.plugin.template.Converter |
sources/imiger-plugin-template/src/test/java/PluginTest.java | ||
---|---|---|
1 |
import cz.zcu.kiv.imiger.spi.IModule; |
|
1 | 2 |
import org.junit.jupiter.api.Test; |
2 |
import org.junit.platform.commons.util.StringUtils; |
|
3 | 3 |
|
4 | 4 |
import java.io.File; |
5 |
import java.io.FileInputStream; |
|
6 |
import java.io.IOException; |
|
7 |
import java.lang.reflect.Method; |
|
5 |
import java.net.MalformedURLException; |
|
8 | 6 |
import java.net.URL; |
9 | 7 |
import java.net.URLClassLoader; |
10 |
import java.util.jar.Attributes; |
|
11 |
import java.util.jar.JarInputStream; |
|
12 |
import java.util.jar.Manifest; |
|
8 |
import java.util.Iterator; |
|
9 |
import java.util.ServiceLoader; |
|
13 | 10 |
|
14 |
import static org.junit.jupiter.api.Assertions.*;
|
|
11 |
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
15 | 12 |
|
16 | 13 |
/** |
17 | 14 |
* This class is only for testing integrity of Jar file. |
15 |
* <p> |
|
18 | 16 |
* Testing: |
19 |
* Jar file can be open
|
|
20 |
* Manifest contains Module-Name and it is not blank
|
|
21 |
* Manifest contains Module-Class and this class exists in Jar file
|
|
22 |
* Given class contains method 'String getRawJson(String)'
|
|
23 |
* |
|
24 |
* |
|
25 |
* !!! BEFORE USAGE PLEASE CHANGE VARIABLE 'ARCHIVE_WITH_DEPENDENCIES_PATH' !!!
|
|
17 |
* <ul>
|
|
18 |
* <li>Jar file exists
|
|
19 |
* <li>Jar file is valid service provider
|
|
20 |
* <li>Jar file contains at least one service implementing {@link cz.zcu.kiv.imiger.spi.IModule} interface
|
|
21 |
* </ul>
|
|
22 |
* <p>
|
|
23 |
* !!! BEFORE USAGE PLEASE CHANGE VARIABLE 'ARCHIVE_PATH' !!! |
|
26 | 24 |
*/ |
27 | 25 |
class PluginTest { |
28 | 26 |
|
29 |
private static final String ARCHIVE_WITH_DEPENDENCIES_PATH = "target\\imiger-plugin-template-1.0-SNAPSHOT-jar-with-dependencies.jar"; |
|
30 |
|
|
27 |
private static final String ARCHIVE_PATH = "target/imiger-plugin-template-1.0-SNAPSHOT.jar"; |
|
31 | 28 |
|
32 | 29 |
// ========================================= DO NOT CHANGE UNDER THIS LINE ========================================= |
33 | 30 |
|
34 |
private static final String MODULE_CLASS_IDENTIFIER = "Module-Class"; |
|
35 |
private static final String MODULE_NAME_IDENTIFIER = "Module-Name"; |
|
36 |
private static final String METHOD_NAME = "getRawJson"; |
|
37 |
private static final Class METHOD_PARAMETER_CLASS = String.class; |
|
38 |
|
|
39 | 31 |
@Test |
40 |
void integrityTest() { |
|
41 |
try { |
|
42 |
File jarFile = new File(ARCHIVE_WITH_DEPENDENCIES_PATH); |
|
43 |
|
|
44 |
JarInputStream jis = new JarInputStream(new FileInputStream(jarFile)); |
|
45 |
final Manifest mf = jis.getManifest(); |
|
46 |
final Attributes attributes = mf.getMainAttributes(); |
|
47 |
final String moduleClassName = attributes.getValue(MODULE_CLASS_IDENTIFIER); |
|
48 |
final String moduleVisibleName = attributes.getValue(MODULE_NAME_IDENTIFIER); |
|
49 |
|
|
50 |
assertFalse(StringUtils.isBlank(moduleClassName), "Blank module class name given by manifest attribute 'Module-Class'"); |
|
51 |
assertFalse(StringUtils.isBlank(moduleVisibleName), "Blank module visible name given by manifest attribute 'Module-Name'"); |
|
32 |
void integrityTest() throws MalformedURLException { |
|
33 |
File jarFile = new File(ARCHIVE_PATH); |
|
34 |
assertTrue(jarFile.exists(), "Jar file does not exist!"); |
|
52 | 35 |
|
53 |
final ClassLoader loader = URLClassLoader.newInstance(new URL[]{jarFile.toURI().toURL()}); |
|
54 |
final Class<?> clazz = Class.forName(moduleClassName, true, loader); |
|
55 |
// checking if method exists, if not throw exception |
|
56 |
Method method = clazz.getMethod(METHOD_NAME, METHOD_PARAMETER_CLASS); |
|
36 |
ServiceLoader<IModule> serviceLoader = ServiceLoader.load(IModule.class, new URLClassLoader(new URL[] { jarFile.toURI().toURL() })); |
|
37 |
Iterator<IModule> moduleIterator = serviceLoader.iterator(); |
|
57 | 38 |
|
58 |
|
|
59 |
assertEquals(String.class, method.getReturnType(), "Invalid method return type."); |
|
60 |
|
|
61 |
} catch (IOException e){ |
|
62 |
fail("Can not open given Jar file. Given path is probably incorrect."); |
|
63 |
} catch (ClassNotFoundException e) { |
|
64 |
fail("Class given by attribute 'Module-Class' in MANIFEST.MF was not found in Jar file."); |
|
65 |
} catch (NoSuchMethodException e) { |
|
66 |
fail("Class given by attribute 'Module-Class' in MANIFEST.MF do not contains method: String getRawJson(String)."); |
|
39 |
int modulesCount = 0; |
|
40 |
while (moduleIterator.hasNext()) { |
|
41 |
modulesCount++; |
|
42 |
moduleIterator.next(); |
|
67 | 43 |
} |
44 |
|
|
45 |
assertTrue(modulesCount > 0, "There should be at least one service provider in the Jar file!"); |
|
68 | 46 |
} |
69 | 47 |
} |
sources/imiger-spade-converter/pom.xml | ||
---|---|---|
21 | 21 |
<groupId>org.apache.maven.plugins</groupId> |
22 | 22 |
<artifactId>maven-jar-plugin</artifactId> |
23 | 23 |
<version>3.1.1</version> |
24 |
<configuration> |
|
25 |
<archive> |
|
26 |
<manifestSections> |
|
27 |
<manifestSection> |
|
28 |
<name>cz.zcu.kiv.imiger.plugin</name> |
|
29 |
<manifestEntries> |
|
30 |
<Module-Class>cz.zcu.kiv.imiger.plugin.spade.Spade</Module-Class> |
|
31 |
<Module-Name>Spade JSON</Module-Name> |
|
32 |
</manifestEntries> |
|
33 |
</manifestSection> |
|
34 |
</manifestSections> |
|
35 |
</archive> |
|
36 |
</configuration> |
|
37 | 24 |
</plugin> |
38 | 25 |
</plugins> |
39 | 26 |
</build> |
sources/imiger-spade-converter/src/main/java/cz/zcu/kiv/imiger/plugin/spade/Spade.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.imiger.plugin.spade; |
2 | 2 |
|
3 |
import cz.zcu.kiv.imiger.spi.IModule; |
|
3 | 4 |
import cz.zcu.kiv.imiger.vo.Graph; |
4 | 5 |
import cz.zcu.kiv.imiger.plugin.spade.graph.GraphManager; |
5 | 6 |
import cz.zcu.kiv.imiger.plugin.spade.graph.loader.GraphJSONDataLoader; |
6 | 7 |
import cz.zcu.kiv.imiger.plugin.spade.graph.loader.JSONConfigLoader; |
7 | 8 |
import net.sf.json.JSONObject; |
8 | 9 |
|
9 |
public class Spade { |
|
10 |
public class Spade implements IModule { |
|
11 |
@Override |
|
12 |
public String getModuleName() { |
|
13 |
return "Spade JSON"; |
|
14 |
} |
|
10 | 15 |
|
11 | 16 |
/** |
12 |
* Convert input spade JSON to RAW JSON and return it. |
|
17 |
* Convert input spade JSON to RAW JSON. |
|
18 |
* |
|
19 |
* @param file String to be converted to raw JSON. |
|
20 |
* @return Raw JSON. |
|
13 | 21 |
*/ |
22 |
@Override |
|
14 | 23 |
public String getRawJson(String file) { |
15 | 24 |
GraphManager graphManager = new GraphJSONDataLoader(file).loadData(); |
16 | 25 |
JSONConfigLoader configLoader = new JSONConfigLoader(graphManager); |
sources/imiger-spade-converter/src/main/resources/META-INF/services/cz.zcu.kiv.imiger.spi.IModule | ||
---|---|---|
1 |
cz.zcu.kiv.imiger.plugin.spade.Spade |
Také k dispozici: Unified diff
simplified modularization by using Java's native SPI