/** * XML Web generátor – program na generování webových stránek * Copyright © 2012 František Kučera (frantovo.cz) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package cz.frantovo.xmlWebGenerator.makra; import static cz.frantovo.xmlWebGenerator.NástrojeCLI.načtiProud; import static cz.frantovo.xmlWebGenerator.Funkce.spojText; import static cz.frantovo.xmlWebGenerator.Xmlns.*; import java.io.ByteArrayInputStream; import java.io.File; import java.io.PrintStream; import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Document; import org.w3c.dom.Node; /** * Provedeme skript a do stránky vložíme jeho výstup. * * @author František Kučera (frantovo.cz) */ public class Skriptování { private enum FORMÁT { xml, xhtml, text } /** * klíč = jazyk – např. bash * hodnota = interpret – např. /bin/bash */ private static final Map interpreti; static { Map podporovanýJazyk = new HashMap(); podporovanýJazyk.put("bash", "/bin/bash"); podporovanýJazyk.put("perl", "/usr/bin/perl"); podporovanýJazyk.put("php", "/usr/bin/php"); podporovanýJazyk.put("python", "/usr/bin/python"); interpreti = Collections.unmodifiableMap(podporovanýJazyk); } /** * TODO: podporovat i složitější scénáře (např. kompilaci), * než jen vložení do souboru a přidání správného záhlaví. * * @param skriptText skript k vykonání * @param skriptSoubor cesta k souboru se skriptem/programem * @param jazyk programovací jazyk * @param výstupníFormát text (výchozí) | xml (v tom případě kontrolujeme validitu) * @param uriStránky URI aktuálně generované stránky → proměnná prostředí * @param nadpisStránky nadpis stránky → proměnná prostředí * @param perexStránky perex stránky → proměnná prostředí * @return výstup příkazu buď jako textový řetězec nebo jako XML (DOMSource) */ public static Source interpretuj(String[] skriptText, String skriptSoubor, String jazyk, String výstupníFormát, String uriStránky, String nadpisStránky, String perexStránky) throws Exception { String výstupSkriptu = získejVýstupSkriptu(spojText(skriptText), skriptSoubor, jazyk, uriStránky, nadpisStránky, perexStránky); return vyrobXml(výstupSkriptu, zjistiFormát(výstupníFormát)); } private static String získejVýstupSkriptu(String skriptText, String skriptSoubor, String jazyk, String uriStránky, String nadpisStránky, String perexStránky) throws Exception { try { if (isNeprázdný(skriptSoubor)) { System.err.println("\tInterpretuji skript ze souboru: " + skriptSoubor); } else { System.err.println("\tInterpretuji skript v jazyce: " + jazyk); } File souborStránky = new File(new URI(uriStránky)); File f; if (isNeprázdný(skriptText)) { /** Skript je zadán uvnitř elementu přímo ve stránce */ String interpret = interpreti.get(jazyk); if (interpret == null) { throw new Exception("Neznámý skriptovací jazyk: " + jazyk); } f = File.createTempFile("xml-web-generátor-", ".skript"); f.deleteOnExit(); f.setExecutable(true); PrintStream ps = new PrintStream(f); ps.print("#!"); ps.println(interpret); ps.println(); ps.print(skriptText); ps.close(); } else if (isNeprázdný(skriptSoubor)) { /** Skript/program je uložen v externím souboru */ if (skriptSoubor.startsWith(File.separator)) { /** absolutní cesta */ f = new File(skriptSoubor); } else { /** relativní cesta */ f = new File(souborStránky.getParent(), File.separatorChar + skriptSoubor); } if (!f.canExecute()) { throw new Exception("Soubor se skriptem není spustitelný → nastavte: chmod +x " + f); } } else { throw new Exception("Musí být vyplněn text skriptu, nebo cesta k souboru."); } String[] prostředí = new String[]{ "LANG=" + System.getenv("LANG"), "USER=" + System.getenv("USER"), "XWG_SKRIPTOVANI_JAVA=" + "šablona" + File.separator + "funkce" + File.separator + "src" + File.separator + Skriptování.class.getName().replaceAll("\\.", File.separator) + ".java", "XWG_STRANKA_URI=" + uriStránky, // env:URI aktuálně zpracovávané stránky "XWG_STRANKA_SOUBOR=" + souborStránky.getAbsolutePath(), // env:absolutní cesta k souboru "XWG_STRANKA_NADPIS=" + nadpisStránky, // env:nadpis stránky "XWG_STRANKA_PEREX=" + perexStránky // env:perex stránky }; Runtime r = Runtime.getRuntime(); Process p = r.exec(new String[]{f.getAbsolutePath()}, prostředí); String výsledek = načtiProud(p.getInputStream()); String chyby = načtiProud(p.getErrorStream()); p.waitFor(); if (p.exitValue() == 0) { if (chyby.length() > 0) { System.err.println("--- Chybový výstup skriptu -----"); System.err.println(chyby); System.err.println("--------------------------------"); System.err.println("Nicméně skript skončil úspěšně, takže pokračujeme dál."); } return výsledek.trim(); } else { System.err.println("--- Standardní výstup skriptu: -----"); System.err.println(výsledek); System.err.println("--- Cyhbový výstup skriptu: ---------"); System.err.println(chyby); System.err.println("--------------------------------------"); throw new Exception("Návratová hodnota: " + p.exitValue()); } } catch (Exception e) { System.err.println("Došlo k chybě při vykonávání skriptu."); System.err.println("--------"); System.err.println(skriptText); System.err.println("--------"); e.printStackTrace(System.err); throw e; } } private static boolean isNeprázdný(String s) { return !(s == null || s.trim().isEmpty()); } private static FORMÁT zjistiFormát(String výstupníFormát) { try { return FORMÁT.valueOf(výstupníFormát); } catch (NullPointerException e) { return FORMÁT.text; } catch (IllegalArgumentException e) { return FORMÁT.text; } } /** * @param zadání výstup vygenerovaný skriptem * @param xmlFormát formát zadání: true = xml fragment | false = prostý text * @return xml fragment nebo prostý text zabalený do html/body * @throws Exception */ private static Source vyrobXml(String zadání, FORMÁT formát) throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document d; if (formát == FORMÁT.text) { d = db.newDocument(); Node html = d.createElementNS(XHTML, "html"); Node body = d.createElementNS(XHTML, "body"); Node text = d.createTextNode(zadání); body.appendChild(text); html.appendChild(body); d.appendChild(html); } else { if (formát == FORMÁT.xhtml) { zadání = "" + zadání + ""; } try { d = db.parse(new ByteArrayInputStream(zadání.getBytes())); } catch (Exception e) { System.err.println("Chyba: Skript vrátil neplatné XML."); throw e; } } return new DOMSource(d); } }