java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ext/WikiSyntaxProcesor.java
changeset 197 40b7aa9126d0
parent 145 0efefbf5f8b6
child 202 8d141ea76a2d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ext/WikiSyntaxProcesor.java	Mon Nov 07 20:31:44 2011 +0100
     1.3 @@ -0,0 +1,130 @@
     1.4 +package cz.frantovo.nekurak.ext;
     1.5 +
     1.6 +import cz.frantovo.nekurak.dto.Komentar;
     1.7 +import cz.frantovo.nekurak.vyjimky.WikiSyntaxVyjimka;
     1.8 +import java.io.BufferedReader;
     1.9 +import java.io.IOException;
    1.10 +import java.io.InputStream;
    1.11 +import java.io.InputStreamReader;
    1.12 +import java.io.OutputStreamWriter;
    1.13 +import java.io.PrintStream;
    1.14 +import java.net.URL;
    1.15 +import java.net.URLConnection;
    1.16 +import java.net.URLEncoder;
    1.17 +import java.util.logging.Level;
    1.18 +import java.util.logging.Logger;
    1.19 +
    1.20 +/**
    1.21 + * Neprovádí vlastní interpretaci wiki syntaxe syntaxe, ale volá HTTP službu napsanou v PHP nebo samostatný proces v systému.
    1.22 + * TODO: použít webové služby, nebo něco lepšího než ruční práci s URL.
    1.23 + * @author fiki
    1.24 + */
    1.25 +public class WikiSyntaxProcesor {
    1.26 +
    1.27 +	/** TODO: parametrizovatelnost */
    1.28 +	private static final String URL_SLUZBY = "http://nekurak.net/texy/http/";
    1.29 +	private static final String KODOVANI = "UTF-8";
    1.30 +	private static final Logger log = Logger.getLogger(WikiSyntaxProcesor.class.getSimpleName());
    1.31 +	private String[] markdownPříkaz = new String[]{"sudo", "-u", "markdown", "/usr/bin/markdown"};
    1.32 +
    1.33 +	public String převeď(String text, Komentar.TYP syntaxe) throws WikiSyntaxVyjimka {
    1.34 +		switch (syntaxe) {
    1.35 +			case MARKDOWN:
    1.36 +				return převeďMarkdown(text);
    1.37 +			case TEXY:
    1.38 +				return převeďTexy(text);
    1.39 +			default:
    1.40 +				throw new WikiSyntaxVyjimka("Nepodporovaná wiki syntaxe.", null);
    1.41 +		}
    1.42 +	}
    1.43 +
    1.44 +	private String převeďMarkdown(String text) throws WikiSyntaxVyjimka {
    1.45 +		try {
    1.46 +			Runtime r = Runtime.getRuntime();
    1.47 +			Process p = r.exec(markdownPříkaz);
    1.48 +
    1.49 +			PrintStream processInput = new PrintStream(p.getOutputStream());
    1.50 +			processInput.print(text);
    1.51 +			processInput.close();
    1.52 +
    1.53 +			String errors = načtiProud(p.getErrorStream());
    1.54 +			String htmlFragment = načtiProud(p.getInputStream());
    1.55 +
    1.56 +			if (errors.length() == 0) {
    1.57 +				return htmlFragment;
    1.58 +			} else {
    1.59 +				throw new WikiSyntaxVyjimka("Markdown procesor vrátil chyby: " + errors, null);
    1.60 +			}
    1.61 +		} catch (Exception e) {
    1.62 +			throw new WikiSyntaxVyjimka("Chyba při transformaci Markdown → XHTML", e);
    1.63 +		}
    1.64 +	}
    1.65 +
    1.66 +	private String převeďTexy(String text) throws WikiSyntaxVyjimka {
    1.67 +		OutputStreamWriter wr = null;
    1.68 +		BufferedReader rd = null;
    1.69 +		try {
    1.70 +			URL url = new URL(URL_SLUZBY);
    1.71 +			URLConnection spojeni = url.openConnection();
    1.72 +			spojeni.setDoOutput(true);
    1.73 +
    1.74 +			/** Odešleme data */
    1.75 +			wr = new OutputStreamWriter(spojeni.getOutputStream());
    1.76 +			wr.write(URLEncoder.encode(text, KODOVANI));
    1.77 +			wr.flush();
    1.78 +
    1.79 +			/** Přijmeme odpověď */
    1.80 +			rd = new BufferedReader(new InputStreamReader(spojeni.getInputStream(), KODOVANI));
    1.81 +			StringBuilder vysledek = new StringBuilder();
    1.82 +			String radka;
    1.83 +			while ((radka = rd.readLine()) != null) {
    1.84 +				vysledek.append(radka);
    1.85 +			}
    1.86 +
    1.87 +			return vysledek.toString();
    1.88 +		} catch (Exception e) {
    1.89 +			throw new WikiSyntaxVyjimka("Chyba při zpracovávání textu: " + text, e);
    1.90 +		} finally {
    1.91 +			try {
    1.92 +				wr.close();
    1.93 +			} catch (IOException e) {
    1.94 +				log.log(Level.WARNING, "Selhalo zavírání OutputStreamWriteru", e);
    1.95 +			}
    1.96 +			try {
    1.97 +				rd.close();
    1.98 +			} catch (IOException e) {
    1.99 +				log.log(Level.WARNING, "Selhalo zavírání BufferedReaderu", e);
   1.100 +			}
   1.101 +		}
   1.102 +	}
   1.103 +
   1.104 +	/**
   1.105 +	 * Čte proud dat dokud to jde a výsledek pak vrátí jako text.
   1.106 +	 * @param proud vstupní proud
   1.107 +	 * @return obsah proudu jako text
   1.108 +	 * @throws IOException 
   1.109 +	 */
   1.110 +	public static String načtiProud(InputStream proud) throws IOException {
   1.111 +		StringBuilder výsledek = new StringBuilder();
   1.112 +		BufferedReader buf = new BufferedReader(new InputStreamReader(proud));
   1.113 +		while (true) {
   1.114 +			String radek = buf.readLine();
   1.115 +			if (radek == null) {
   1.116 +				break;
   1.117 +			} else {
   1.118 +				výsledek.append(radek);
   1.119 +				výsledek.append("\n");
   1.120 +			}
   1.121 +		}
   1.122 +		return výsledek.toString();
   1.123 +	}
   1.124 +
   1.125 +	/**
   1.126 +	 * Můžeme nastavit vlastní příkaz pro transformaci Markdown syntaxe.
   1.127 +	 * Ve výchozím nastavení se Markdown procesor volá přes sudo pod uživatelem markdown.
   1.128 +	 * @param markdownPříkaz první je příkaz, následují případné parametry
   1.129 +	 */
   1.130 +	public void setMarkdownPříkaz(String[] markdownPříkaz) {
   1.131 +		this.markdownPříkaz = markdownPříkaz;
   1.132 +	}
   1.133 +}