package fi.otavanopisto.muikku.plugins.data; import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.enterprise.inject.Any; import javax.enterprise.inject.Instance; import javax.inject.Inject; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import fi.otavanopisto.muikku.plugins.data.dao.ProcessedScriptDAO; public class DataPluginController { @Inject @Any private Instance<DataPluginScriptHandler> scriptHandlers; @Inject private ProcessedScriptDAO processedScriptDAO; public void processScripts(File file) throws ParserConfigurationException, SAXException, IOException { List<ScriptInfo> scriptInfos = new ArrayList<>(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(file); NodeList documentElementChildNodes = document.getDocumentElement().getChildNodes(); for (int i = 0, l = documentElementChildNodes.getLength(); i < l; i++) { Node item = documentElementChildNodes.item(i); if (item instanceof Element) { Element script = (Element) item; if ("script".equals(script.getTagName())) { Run run = Run.valueOf(script.getAttribute("run")); String url = script.getAttribute("url"); String handler = script.getAttribute("handler"); Map<String, String> parameters = new HashMap<String, String>(); if (!url.matches("[a-z]{1,}://.*")) { url = new File(file.getParent(), url).toURI().toString(); } NodeList scriptChildNodes = script.getChildNodes(); for (int j= 0, jl = scriptChildNodes.getLength(); j< jl; j++) { Node scriptChildItem = scriptChildNodes.item(j); if (scriptChildItem instanceof Element) { Element scriptChildElement = (Element) scriptChildItem; String name = scriptChildElement.getAttribute("name"); String value = scriptChildElement.getTextContent(); if (StringUtils.isBlank(name)) { // TODO: Proper error handling throw new RuntimeException("parameter element requires a name"); } parameters.put(name, value); } } if (run != null && StringUtils.isNotBlank(url) && StringUtils.isNotBlank(handler)) { scriptInfos.add(new ScriptInfo(url, run, handler, parameters)); } else { // TODO: Proper error handling throw new RuntimeException("Malformed 'script' element either run, url or handler element is missing"); } } else { // TODO: Proper error handling throw new RuntimeException("Expected 'script' element but found " + script.getTagName()); } } } for (ScriptInfo scriptInfo : scriptInfos) { switch (scriptInfo.getRun()) { case ALWAYS: runScript(scriptInfo); break; case ONCE: if (processedScriptDAO.findByUrl(scriptInfo.getUrl()) == null) { runScript(scriptInfo); processedScriptDAO.create(scriptInfo.getUrl()); } break; } } } public DataPluginScriptHandler getHandler(String names) { List<String> handlerNames = Arrays.asList(names.split("/")); Iterator<DataPluginScriptHandler> handlers = scriptHandlers.iterator(); while (handlers.hasNext()) { DataPluginScriptHandler handler = handlers.next(); if (handlerNames.contains(handler.getName())) return handler; } return null; } private void runScript(ScriptInfo scriptInfo) { DataPluginScriptHandler scriptHandler = getHandler(scriptInfo.getHandler()); if (scriptHandler == null) { // TODO: Proper error handling throw new RuntimeException("Could not find script handler '" + scriptInfo.getHandler() + "'"); } try { scriptHandler.executeScript(scriptInfo.getUrl(), scriptInfo.getParameters()); } catch (IOException | SQLException e) { // TODO: Proper error handling throw new RuntimeException("Failed to execute script '" + scriptInfo.getUrl() + "': " + e.getMessage()); } } private enum Run { ONCE, ALWAYS } private class ScriptInfo { public ScriptInfo(String url, Run run, String handler, Map<String, String> parameters) { this.url = url; this.run = run; this.handler = handler; this.parameters = parameters; } public Map<String, String> getParameters() { return parameters; } public String getHandler() { return handler; } public Run getRun() { return run; } public String getUrl() { return url; } private Run run; private String url; private String handler; private Map<String, String> parameters; } }