java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ext/WikiSyntaxProcesor.java
author František Kučera <franta-hg@frantovo.cz>
Mon Nov 07 20:31:44 2011 +0100 (2011-11-07)
changeset 197 40b7aa9126d0
parent 145 java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ext/Texy.java@0efefbf5f8b6
child 202 8d141ea76a2d
permissions -rw-r--r--
Podpora Markdown syntaxe pro komentáře.
     1 package cz.frantovo.nekurak.ext;
     2 
     3 import cz.frantovo.nekurak.dto.Komentar;
     4 import cz.frantovo.nekurak.vyjimky.WikiSyntaxVyjimka;
     5 import java.io.BufferedReader;
     6 import java.io.IOException;
     7 import java.io.InputStream;
     8 import java.io.InputStreamReader;
     9 import java.io.OutputStreamWriter;
    10 import java.io.PrintStream;
    11 import java.net.URL;
    12 import java.net.URLConnection;
    13 import java.net.URLEncoder;
    14 import java.util.logging.Level;
    15 import java.util.logging.Logger;
    16 
    17 /**
    18  * Neprovádí vlastní interpretaci wiki syntaxe syntaxe, ale volá HTTP službu napsanou v PHP nebo samostatný proces v systému.
    19  * TODO: použít webové služby, nebo něco lepšího než ruční práci s URL.
    20  * @author fiki
    21  */
    22 public class WikiSyntaxProcesor {
    23 
    24 	/** TODO: parametrizovatelnost */
    25 	private static final String URL_SLUZBY = "http://nekurak.net/texy/http/";
    26 	private static final String KODOVANI = "UTF-8";
    27 	private static final Logger log = Logger.getLogger(WikiSyntaxProcesor.class.getSimpleName());
    28 	private String[] markdownPříkaz = new String[]{"sudo", "-u", "markdown", "/usr/bin/markdown"};
    29 
    30 	public String převeď(String text, Komentar.TYP syntaxe) throws WikiSyntaxVyjimka {
    31 		switch (syntaxe) {
    32 			case MARKDOWN:
    33 				return převeďMarkdown(text);
    34 			case TEXY:
    35 				return převeďTexy(text);
    36 			default:
    37 				throw new WikiSyntaxVyjimka("Nepodporovaná wiki syntaxe.", null);
    38 		}
    39 	}
    40 
    41 	private String převeďMarkdown(String text) throws WikiSyntaxVyjimka {
    42 		try {
    43 			Runtime r = Runtime.getRuntime();
    44 			Process p = r.exec(markdownPříkaz);
    45 
    46 			PrintStream processInput = new PrintStream(p.getOutputStream());
    47 			processInput.print(text);
    48 			processInput.close();
    49 
    50 			String errors = načtiProud(p.getErrorStream());
    51 			String htmlFragment = načtiProud(p.getInputStream());
    52 
    53 			if (errors.length() == 0) {
    54 				return htmlFragment;
    55 			} else {
    56 				throw new WikiSyntaxVyjimka("Markdown procesor vrátil chyby: " + errors, null);
    57 			}
    58 		} catch (Exception e) {
    59 			throw new WikiSyntaxVyjimka("Chyba při transformaci Markdown → XHTML", e);
    60 		}
    61 	}
    62 
    63 	private String převeďTexy(String text) throws WikiSyntaxVyjimka {
    64 		OutputStreamWriter wr = null;
    65 		BufferedReader rd = null;
    66 		try {
    67 			URL url = new URL(URL_SLUZBY);
    68 			URLConnection spojeni = url.openConnection();
    69 			spojeni.setDoOutput(true);
    70 
    71 			/** Odešleme data */
    72 			wr = new OutputStreamWriter(spojeni.getOutputStream());
    73 			wr.write(URLEncoder.encode(text, KODOVANI));
    74 			wr.flush();
    75 
    76 			/** Přijmeme odpověď */
    77 			rd = new BufferedReader(new InputStreamReader(spojeni.getInputStream(), KODOVANI));
    78 			StringBuilder vysledek = new StringBuilder();
    79 			String radka;
    80 			while ((radka = rd.readLine()) != null) {
    81 				vysledek.append(radka);
    82 			}
    83 
    84 			return vysledek.toString();
    85 		} catch (Exception e) {
    86 			throw new WikiSyntaxVyjimka("Chyba při zpracovávání textu: " + text, e);
    87 		} finally {
    88 			try {
    89 				wr.close();
    90 			} catch (IOException e) {
    91 				log.log(Level.WARNING, "Selhalo zavírání OutputStreamWriteru", e);
    92 			}
    93 			try {
    94 				rd.close();
    95 			} catch (IOException e) {
    96 				log.log(Level.WARNING, "Selhalo zavírání BufferedReaderu", e);
    97 			}
    98 		}
    99 	}
   100 
   101 	/**
   102 	 * Čte proud dat dokud to jde a výsledek pak vrátí jako text.
   103 	 * @param proud vstupní proud
   104 	 * @return obsah proudu jako text
   105 	 * @throws IOException 
   106 	 */
   107 	public static String načtiProud(InputStream proud) throws IOException {
   108 		StringBuilder výsledek = new StringBuilder();
   109 		BufferedReader buf = new BufferedReader(new InputStreamReader(proud));
   110 		while (true) {
   111 			String radek = buf.readLine();
   112 			if (radek == null) {
   113 				break;
   114 			} else {
   115 				výsledek.append(radek);
   116 				výsledek.append("\n");
   117 			}
   118 		}
   119 		return výsledek.toString();
   120 	}
   121 
   122 	/**
   123 	 * Můžeme nastavit vlastní příkaz pro transformaci Markdown syntaxe.
   124 	 * Ve výchozím nastavení se Markdown procesor volá přes sudo pod uživatelem markdown.
   125 	 * @param markdownPříkaz první je příkaz, následují případné parametry
   126 	 */
   127 	public void setMarkdownPříkaz(String[] markdownPříkaz) {
   128 		this.markdownPříkaz = markdownPříkaz;
   129 	}
   130 }