Revize 00b3d224
Přidáno uživatelem Tomáš Šimandl před asi 6 roky(ů)
sources/src/main/java/cz/zcu/kiv/offscreen/modularization/IModule.java | ||
---|---|---|
1 |
package cz.zcu.kiv.offscreen.modularization; |
|
2 |
|
|
3 |
public interface IModule { |
|
4 |
|
|
5 |
String getRawJson(String file); |
|
6 |
} |
sources/src/main/java/cz/zcu/kiv/offscreen/modularization/ModuleLoader.java | ||
---|---|---|
1 |
package cz.zcu.kiv.offscreen.modularization; |
|
2 |
|
|
3 |
import com.sun.jndi.toolkit.url.Uri; |
|
4 |
import javafx.util.Pair; |
|
5 |
import org.apache.logging.log4j.LogManager; |
|
6 |
import org.apache.logging.log4j.Logger; |
|
7 |
|
|
8 |
import java.io.File; |
|
9 |
import java.io.FileInputStream; |
|
10 |
import java.io.FilenameFilter; |
|
11 |
import java.net.URI; |
|
12 |
import java.net.URISyntaxException; |
|
13 |
import java.net.URL; |
|
14 |
import java.net.URLClassLoader; |
|
15 |
import java.util.Arrays; |
|
16 |
import java.util.Optional; |
|
17 |
import java.util.Set; |
|
18 |
import java.util.jar.Attributes; |
|
19 |
import java.util.jar.JarInputStream; |
|
20 |
import java.util.jar.Manifest; |
|
21 |
import java.util.stream.Collectors; |
|
22 |
|
|
23 |
public class ModuleLoader { |
|
24 |
|
|
25 |
private static final Logger logger = LogManager.getLogger(); |
|
26 |
private static final FilenameFilter MODULE_FILTER = (file, name) -> name.contains(".jar"); |
|
27 |
private static final String MODULE_CLASS_IDENTIFIER = "Module-Class"; |
|
28 |
private static final String MODULE_NAME_IDENTIFIER = "Module-Name"; |
|
29 |
|
|
30 |
private final String modulesPath; |
|
31 |
|
|
32 |
public ModuleLoader(String modulesPath) { |
|
33 |
this.modulesPath = modulesPath; |
|
34 |
logger.info("Initializing new ModuleLoader with folder path: " + modulesPath); |
|
35 |
} |
|
36 |
|
|
37 |
public Set<Pair<String, IModule>> loadModules() { |
|
38 |
logger.info("Loading all modules from file."); |
|
39 |
final File[] modules = loadJarFiles(); |
|
40 |
return Arrays.stream(modules) |
|
41 |
.map(this::loadModule) |
|
42 |
.filter(Optional::isPresent) |
|
43 |
.map(Optional::get) |
|
44 |
.collect(Collectors.toSet()); |
|
45 |
} |
|
46 |
|
|
47 |
public Optional<File> getModulesFolder(){ |
|
48 |
|
|
49 |
final URL fileURL = getClass().getClassLoader().getResource(modulesPath); |
|
50 |
if (fileURL == null){ |
|
51 |
logger.warn("Can not open modules directory."); |
|
52 |
return Optional.empty(); |
|
53 |
} |
|
54 |
|
|
55 |
try { |
|
56 |
final File modulesFolder = new File(fileURL.toURI()); |
|
57 |
|
|
58 |
if (!modulesFolder.exists() || !modulesFolder.isDirectory()) { |
|
59 |
logger.warn("Modules folder is not exists or it is not a directory"); |
|
60 |
return Optional.empty(); |
|
61 |
} |
|
62 |
return Optional.of(modulesFolder); |
|
63 |
|
|
64 |
} catch (URISyntaxException e) { |
|
65 |
logger.warn("Can not open modules directory", e); |
|
66 |
return Optional.empty(); |
|
67 |
} |
|
68 |
} |
|
69 |
|
|
70 |
private File[] loadJarFiles() { |
|
71 |
|
|
72 |
Optional<File> folderOptional = getModulesFolder(); |
|
73 |
if(folderOptional.isPresent()){ |
|
74 |
logger.info(folderOptional.get().length() + " modules were read from file"); |
|
75 |
return folderOptional.get().listFiles(MODULE_FILTER); |
|
76 |
} |
|
77 |
return new File[0]; |
|
78 |
} |
|
79 |
|
|
80 |
private Optional<Pair<String, IModule>> loadModule(File moduleFile) { |
|
81 |
try { |
|
82 |
final JarInputStream jis = new JarInputStream(new FileInputStream(moduleFile)); |
|
83 |
final Manifest mf = jis.getManifest(); |
|
84 |
final Attributes attributes = mf.getMainAttributes(); |
|
85 |
final String moduleClassName = attributes.getValue(MODULE_CLASS_IDENTIFIER); |
|
86 |
final String moduleVisibleName = attributes.getValue(MODULE_NAME_IDENTIFIER); |
|
87 |
|
|
88 |
final ClassLoader loader = URLClassLoader.newInstance(new URL[]{moduleFile.toURI().toURL()}); |
|
89 |
final Class clazz = Class.forName(moduleClassName, true, loader); |
|
90 |
final IModule module = (IModule) clazz.asSubclass(IModule.class).newInstance(); |
|
91 |
|
|
92 |
return Optional.of(new Pair<>(moduleVisibleName, module)); |
|
93 |
|
|
94 |
} catch (Exception e) { |
|
95 |
logger.debug("Invalid module throw exception: ", e); |
|
96 |
return Optional.empty(); |
|
97 |
} |
|
98 |
} |
|
99 |
} |
sources/src/main/java/cz/zcu/kiv/offscreen/modularization/ModuleProvider.java | ||
---|---|---|
1 |
package cz.zcu.kiv.offscreen.modularization; |
|
2 |
|
|
3 |
import javafx.util.Pair; |
|
4 |
import org.apache.logging.log4j.LogManager; |
|
5 |
import org.apache.logging.log4j.Logger; |
|
6 |
|
|
7 |
import java.io.File; |
|
8 |
import java.io.IOException; |
|
9 |
import java.net.URISyntaxException; |
|
10 |
import java.net.URL; |
|
11 |
import java.nio.file.*; |
|
12 |
import java.util.HashMap; |
|
13 |
import java.util.Map; |
|
14 |
import java.util.Optional; |
|
15 |
import java.util.Set; |
|
16 |
import java.util.concurrent.*; |
|
17 |
|
|
18 |
public class ModuleProvider { |
|
19 |
|
|
20 |
private static final Logger logger = LogManager.getLogger(); |
|
21 |
private static final String MODULES_PATH = "modules"; |
|
22 |
private static ModuleProvider instance = null; |
|
23 |
|
|
24 |
private ConcurrentMap<String, Pair<String, IModule>> modules = new ConcurrentHashMap<>(); |
|
25 |
private final ModuleLoader loader; |
|
26 |
private boolean watch = true; |
|
27 |
|
|
28 |
|
|
29 |
public static ModuleProvider getInstance() { |
|
30 |
if (instance == null) { |
|
31 |
instance = new ModuleProvider(); |
|
32 |
} |
|
33 |
return instance; |
|
34 |
} |
|
35 |
|
|
36 |
private ModuleProvider() { |
|
37 |
this.loader = new ModuleLoader(MODULES_PATH); |
|
38 |
|
|
39 |
processModules(loader.loadModules()); |
|
40 |
|
|
41 |
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); |
|
42 |
Runnable task = this::initModulesWatcher; |
|
43 |
logger.debug("Scheduling Modules Watcher thread."); |
|
44 |
// task will be scheduled after 1 minute |
|
45 |
// When task ends (on failure) after one minute will be planed again |
|
46 |
executor.scheduleWithFixedDelay(task, 1, 1, TimeUnit.MINUTES); |
|
47 |
} |
|
48 |
|
|
49 |
private void initModulesWatcher() { |
|
50 |
try { |
|
51 |
logger.debug("Initializing new WatcherService for modules directory"); |
|
52 |
|
|
53 |
Optional<File> folderFileOptional = loader.getModulesFolder(); |
|
54 |
if (!folderFileOptional.isPresent()) { |
|
55 |
return; |
|
56 |
} |
|
57 |
|
|
58 |
Path path = folderFileOptional.get().toPath(); |
|
59 |
WatchService watcher = FileSystems.getDefault().newWatchService(); |
|
60 |
path.register(watcher, |
|
61 |
StandardWatchEventKinds.ENTRY_CREATE, |
|
62 |
StandardWatchEventKinds.ENTRY_DELETE, |
|
63 |
StandardWatchEventKinds.ENTRY_MODIFY); |
|
64 |
|
|
65 |
while (true) { |
|
66 |
WatchKey key = watcher.take(); |
|
67 |
logger.debug("Watcher events was detected"); |
|
68 |
|
|
69 |
for (WatchEvent<?> event : key.pollEvents()) { |
|
70 |
WatchEvent.Kind<?> kind = event.kind(); |
|
71 |
|
|
72 |
if (kind == StandardWatchEventKinds.OVERFLOW) { |
|
73 |
logger.debug("Overflow watcher event was detected"); |
|
74 |
continue; |
|
75 |
} |
|
76 |
|
|
77 |
processModules(loader.loadModules()); |
|
78 |
break; // watching only one folder and loading all files every loop => Only one iteration is needed. |
|
79 |
} |
|
80 |
|
|
81 |
if (!key.reset() || !watch) { |
|
82 |
logger.warn("Stopping modules directory watcher"); |
|
83 |
break; |
|
84 |
} |
|
85 |
} |
|
86 |
|
|
87 |
} catch (IOException | InterruptedException e) { |
|
88 |
logger.error("Modules directory watcher throw an exception: ", e); |
|
89 |
} |
|
90 |
} |
|
91 |
|
|
92 |
private void processModules(Set<Pair<String, IModule>> unprocessedModules) { |
|
93 |
Map<String, Pair<String, IModule>> localModules = new HashMap<>(); |
|
94 |
|
|
95 |
logger.info("Processing " + localModules.size() + " modules."); |
|
96 |
|
|
97 |
for (Pair<String, IModule> pair : unprocessedModules) { |
|
98 |
localModules.put(String.valueOf(pair.getKey().hashCode()), pair); |
|
99 |
} |
|
100 |
|
|
101 |
modules.clear(); |
|
102 |
modules.putAll(localModules); |
|
103 |
logger.debug("Modules were processed"); |
|
104 |
} |
|
105 |
|
|
106 |
public Map<String, Pair<String, IModule>> getModules() { |
|
107 |
return modules; |
|
108 |
} |
|
109 |
} |
sources/src/main/java/cz/zcu/kiv/offscreen/servlets/UploadFiles.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.offscreen.servlets; |
2 | 2 |
|
3 | 3 |
import com.google.common.base.Strings; |
4 |
import cz.zcu.kiv.offscreen.modularization.ModuleProvider; |
|
4 | 5 |
import cz.zcu.kiv.offscreen.storage.FileLoader; |
5 | 6 |
import cz.zcu.kiv.offscreen.user.DB; |
6 | 7 |
import cz.zcu.kiv.offscreen.user.Diagram; |
... | ... | |
40 | 41 |
|
41 | 42 |
List<Map<String, String>> publicDiagramList = diagram.getDiagramPublicList(); |
42 | 43 |
request.setAttribute("diagramsPublic", publicDiagramList); |
44 |
request.setAttribute("processingModules", ModuleProvider.getInstance().getModules()); |
|
43 | 45 |
|
44 | 46 |
// render |
45 | 47 |
RequestDispatcher rd = getServletContext().getRequestDispatcher("/uploadFiles.jsp"); |
sources/src/main/java/cz/zcu/kiv/offscreen/servlets/api/GetSessionDiagram.java | ||
---|---|---|
6 | 6 |
import cz.zcu.kiv.offscreen.graph.GraphManager; |
7 | 7 |
import cz.zcu.kiv.offscreen.graph.loader.GraphJSONDataLoader; |
8 | 8 |
import cz.zcu.kiv.offscreen.graph.loader.JSONConfigLoader; |
9 |
import cz.zcu.kiv.offscreen.modularization.IModule; |
|
10 |
import cz.zcu.kiv.offscreen.modularization.ModuleProvider; |
|
9 | 11 |
import cz.zcu.kiv.offscreen.servlets.BaseServlet; |
12 |
import javafx.util.Pair; |
|
10 | 13 |
import net.sf.json.JSONObject; |
11 | 14 |
import org.apache.logging.log4j.LogManager; |
12 | 15 |
import org.apache.logging.log4j.Logger; |
... | ... | |
47 | 50 |
|
48 | 51 |
String rawJson; |
49 | 52 |
|
50 |
switch (jsonType) { |
|
51 |
case "spade": |
|
52 |
logger.debug("Processing Spade json"); |
|
53 |
rawJson = convertSpadeToRawJson(jsonToDisplay); |
|
54 |
break; |
|
55 |
default: |
|
56 |
logger.debug("Processing Raw json"); |
|
57 |
rawJson = jsonToDisplay; |
|
53 |
if (jsonType.equals("raw")) { |
|
54 |
logger.debug("Processing Raw json"); |
|
55 |
rawJson = jsonToDisplay; |
|
56 |
} else { |
|
57 |
logger.debug("Processing json with module"); |
|
58 |
|
|
59 |
Pair<String, IModule> module = ModuleProvider.getInstance().getModules().get(jsonType); |
|
60 |
if (module == null){ |
|
61 |
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); |
|
62 |
logger.debug("No loader available for type: " + jsonType + ". Response BAD REQUEST"); |
|
63 |
return; |
|
64 |
} |
|
65 |
rawJson = module.getValue().getRawJson(jsonToDisplay); |
|
58 | 66 |
} |
59 | 67 |
|
60 | 68 |
JsonObject jsonObject = new JsonObject(); |
sources/src/main/webapp/uploadFiles.jsp | ||
---|---|---|
72 | 72 |
|
73 | 73 |
<div class="form-field"> |
74 | 74 |
Select type of data file:<br> |
75 |
<label for="spade"><input type="radio" name="jsonFileFormat" value="spade" id="spade" checked> Spade JSON</label><br> |
|
76 |
<label for="raw"><input type="radio" name="jsonFileFormat" value="raw" id="raw"> Raw JSON</label><br> |
|
75 |
<label for="raw"><input type="radio" name="jsonFileFormat" value="raw" id="raw" checked> Raw JSON</label><br> |
|
76 |
<c:forEach items="${processingModules}" var="module"> |
|
77 |
<label for="${module.key}"><input type="radio" name="jsonFileFormat" value="${module.key}" id="${module.key}">${module.value.key}</label><br> |
|
78 |
</c:forEach> |
|
77 | 79 |
</div> |
78 | 80 |
|
79 | 81 |
<button id="btnLoad" type="submit">Start visualization</button> |
Také k dispozici: Unified diff
Prepared application for loading json convertors from jar modules