diff -r d843b4fee5dc -r a788bf0e1080 src/org/sonews/storage/DrupalMessage.java --- a/src/org/sonews/storage/DrupalMessage.java Thu Oct 20 09:59:04 2011 +0200 +++ b/src/org/sonews/storage/DrupalMessage.java Thu Oct 20 10:50:58 2011 +0200 @@ -43,6 +43,7 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -76,7 +77,7 @@ * @param rs ResultSet containing message data. No {@link ResultSet#next()} will be called, just values from current row will be read. * @param constructBody true if whole message should be constructed | false if we need only message headers (body will be dummy). */ - public DrupalMessage(ResultSet rs, String myDomain, boolean constructBody) throws SQLException, UnsupportedEncodingException, MessagingException { + public DrupalMessage(ResultSet rs, String myDomain, boolean constructBody) throws SQLException, UnsupportedEncodingException, MessagingException, TransformerException, IOException { super(Session.getDefaultInstance(System.getProperties())); groupID = rs.getLong("group_id"); @@ -99,7 +100,13 @@ /** XHTML part */ MimeBodyPart htmlPart = new MimeBodyPart(); - String xhtmlText = readXhtmlText(rs); + String xhtmlText = readXhtmlText( + rs.getString("text"), + rs.getString("subject"), + rs.getInt("parent_id"), + rs.getString("urlBase"), + rs.getString("wwwRead"), + rs.getString("wwwPost")); htmlPart.setContent(xhtmlText, XHTML_CONTENT_TYPE); /** Plain text part */ @@ -172,60 +179,72 @@ } } - private String readXhtmlText(ResultSet rs) { + private String readXhtmlText(String text, String subject, long parentId, String urlBase, String wwwRead, String wwwPost) throws TransformerException, IOException { /** * TODO: * - znovupoužívat XSL transformér * - používat cache, ukládat si vygenerované články */ + String inputText = makeSimpleXHTML(text); + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer paragraphTransformer = tf.newTransformer(new StreamSource(Resource.getAsStream("helpers/mimeXhtmlPart-make-paragraphs.xsl"))); + + String paragraphedText; + boolean tidyWasUsed = false; try { - String inputText = makeSimpleXHTML(rs.getString("text")); + StringReader input = new StringReader(inputText); + StringWriter output = new StringWriter(2 * inputText.length()); + paragraphTransformer.transform(new StreamSource(input), new StreamResult(output)); + paragraphedText = output.toString(); + } catch (Exception e) { + log.log(Level.FINER, "HTML input was shitty – Tidy had to be called.", e); + StringReader input = new StringReader(tidyXhtml(inputText)); + StringWriter output = new StringWriter(2 * inputText.length()); + paragraphTransformer.transform(new StreamSource(input), new StreamResult(output)); + paragraphedText = output.toString(); + tidyWasUsed = true; + } - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer paragraphTransformer = tf.newTransformer(new StreamSource(Resource.getAsStream("helpers/mimeXhtmlPart-make-paragraphs.xsl"))); + Transformer xhtmlTransformer = tf.newTransformer(new StreamSource(Resource.getAsStream("helpers/mimeXhtmlPart.xsl"))); + xhtmlTransformer.setParameter("isRoot", (parentId == 0)); + xhtmlTransformer.setParameter("title", subject); + xhtmlTransformer.setParameter("urlBase", urlBase); + xhtmlTransformer.setParameter("wwwRead", wwwRead); + xhtmlTransformer.setParameter("wwwPost", wwwPost); + xhtmlTransformer.setParameter("headComment", String.format("Drupal-NNTP bridge. Transformed: %1$tc. Tidy had to be used: %2$b", new Date(), tidyWasUsed)); + StringReader input = new StringReader(paragraphedText); + StringWriter output = new StringWriter(2 * paragraphedText.length()); + xhtmlTransformer.transform(new StreamSource(input), new StreamResult(output)); - String paragraphedText; - boolean tidyWasUsed = false; - try { - StringReader input = new StringReader(inputText); - StringWriter output = new StringWriter(2 * inputText.length()); - paragraphTransformer.transform(new StreamSource(input), new StreamResult(output)); - paragraphedText = output.toString(); - } catch (Exception e) { - log.log(Level.FINER, "HTML input was shitty – Tidy had to be called.", e); - StringReader input = new StringReader(tidyXhtml(inputText)); - StringWriter output = new StringWriter(2 * inputText.length()); - paragraphTransformer.transform(new StreamSource(input), new StreamResult(output)); - paragraphedText = output.toString(); - tidyWasUsed = true; - } - - Transformer xhtmlTransformer = tf.newTransformer(new StreamSource(Resource.getAsStream("helpers/mimeXhtmlPart.xsl"))); - xhtmlTransformer.setParameter("isRoot", (rs.getInt("parent_id") == 0)); - xhtmlTransformer.setParameter("title", rs.getString("subject")); - xhtmlTransformer.setParameter("urlBase", rs.getString("urlBase")); - xhtmlTransformer.setParameter("wwwRead", rs.getString("wwwRead")); - xhtmlTransformer.setParameter("wwwPost", rs.getString("wwwPost")); - xhtmlTransformer.setParameter("headComment", String.format("Drupal-NNTP bridge. Transformed: %1$tc. Tidy had to be used: %2$b", new Date(), tidyWasUsed)); - StringReader input = new StringReader(paragraphedText); - StringWriter output = new StringWriter(2 * paragraphedText.length()); - xhtmlTransformer.transform(new StreamSource(input), new StreamResult(output)); - - return output.toString(); - } catch (Exception e) { - /** - * TODO: lepší ošetření chyby - */ - log.log(Level.WARNING, "Error while transforming article to XHTML", e); - return makeSimpleXHTML("
Při transformaci příspěvku bohužel došlo k chybě.
"); - } + return output.toString(); } + /** + * Does not parse XML works just with text. + * @param body XHTML fragment that should be put between <body> and </body> + * @return simple XHTML document (body wrapped in html and body tags) + */ private static String makeSimpleXHTML(String body) { return "" + body + ""; } /** + * Does not parse XML works just with text. + * @param xhtml whole XHTML page + * @return content between <body> and </body> tags. + */ + private static String makeFragmentXHTML(String xhtml) { + final String startTag = ""; + final String endTag = ""; + + int start = xhtml.indexOf(startTag) + startTag.length(); + int end = xhtml.lastIndexOf(endTag); + + return xhtml.substring(start, end); + } + + /** * TODO: refaktorovat, přesunout */ private static String tidyXhtml(String inputText) throws IOException { @@ -425,4 +444,33 @@ writeTo(baos, skipHeaders.toArray(new String[skipHeaders.size()])); return baos.toByteArray(); } + + /** + * Transforms message content to valid XHTML and strips html and body tags. + * When receiving message from user through NNTP + * this method is used to get text that should be saved into databse. + * @return XHTML fragment – content between <body> and </body> tags. + */ + public String getBodyXhtmlFragment() throws StorageBackendException { + /** + * TODO: podporovat i zprávy přímo v HTML a multipart. + */ + try { + Object c = getContent(); + if (isMimeType("text/plain") && c instanceof String) { + String xhtml = readXhtmlText( + (String) c, + getSubject(), + getParentID(), + null, + null, + null); + return makeFragmentXHTML(xhtml); + } else { + throw new StorageBackendException("Only text/plain messages are supported for now – post it as plain text please."); + } + } catch (Exception e) { + throw new StorageBackendException(e); + } + } }