Source:
<code>public static String textToHtml(String text) { if (text.length() > MAX_SMART_HTMLIFY_MESSAGE_LENGTH) { return simpleTextToHtml(text); } StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); boolean isStartOfLine = true; int spaces = 0; int quoteDepth = 0; int quotesThisLine = 0; for (int index = 0; index < text.length(); index++) { char c = text.charAt(index); if (isStartOfLine) { switch (c) { case ' ': spaces++; break; case '>': quotesThisLine++; spaces = 0; break; case '\n': appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = true; quotesThisLine = 0; break; default: isStartOfLine = false; appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = false; break; } } else { appendchar(buff, c); if (c == '\n') { isStartOfLine = true; quotesThisLine = 0; } } } if (quoteDepth > 0) { for (int i = quoteDepth; i > 0; i--) { buff.append(HTML_BLOCKQUOTE_END); } } text = buff.toString(); text = text.replaceAll( "\\Q" + HTML_NEWLINE + "\\E((\\Q" + HTML_NEWLINE + "\\E)+?)\\Q" + HTML_BLOCKQUOTE_END + "\\E", HTML_BLOCKQUOTE_END + "$1" ); <START> text = ASCII_VERSION_OF_HR.matcher(text).replaceAll("<hr />"); <END> StringBuffer sb = new StringBuffer(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); sb.append(htmlifyMessageHeader()); linkifyText(text, sb); sb.append(htmlifyMessageFooter()); text = sb.toString(); text = text.replaceAll("<gt>", "&gt;"); return text; }</code><technical_language>generate valid XHTML. Please change <hr></technical_language>

Target:
public static String textToHtml(String text) { if (text.length() > MAX_SMART_HTMLIFY_MESSAGE_LENGTH) { return simpleTextToHtml(text); } StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); boolean isStartOfLine = true; int spaces = 0; int quoteDepth = 0; int quotesThisLine = 0; for (int index = 0; index < text.length(); index++) { char c = text.charAt(index); if (isStartOfLine) { switch (c) { case ' ': spaces++; break; case '>': quotesThisLine++; spaces = 0; break; case '\n': appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = true; quotesThisLine = 0; break; default: isStartOfLine = false; appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = false; break; } } else { appendchar(buff, c); if (c == '\n') { isStartOfLine = true; quotesThisLine = 0; } } } if (quoteDepth > 0) { for (int i = quoteDepth; i > 0; i--) { buff.append(HTML_BLOCKQUOTE_END); } } text = buff.toString(); text = text.replaceAll( "\\Q" + HTML_NEWLINE + "\\E((\\Q" + HTML_NEWLINE + "\\E)+?)\\Q" + HTML_BLOCKQUOTE_END + "\\E", HTML_BLOCKQUOTE_END + "$1" ); text = text.replaceAll("\\s*([-=_]{30,}+)\\s*", "<hr />"); StringBuffer sb = new StringBuffer(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); sb.append(htmlifyMessageHeader()); linkifyText(text, sb); sb.append(htmlifyMessageFooter()); text = sb.toString(); text = text.replaceAll("<gt>", "&gt;"); return text; }