Return-Path: X-Original-To: apmail-clerezza-commits-archive@www.apache.org Delivered-To: apmail-clerezza-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1756FF3ED for ; Sun, 24 Mar 2013 13:56:23 +0000 (UTC) Received: (qmail 31125 invoked by uid 500); 24 Mar 2013 13:56:23 -0000 Delivered-To: apmail-clerezza-commits-archive@clerezza.apache.org Received: (qmail 31090 invoked by uid 500); 24 Mar 2013 13:56:22 -0000 Mailing-List: contact commits-help@clerezza.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@clerezza.apache.org Delivered-To: mailing list commits@clerezza.apache.org Received: (qmail 31083 invoked by uid 99); 24 Mar 2013 13:56:22 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 24 Mar 2013 13:56:22 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 24 Mar 2013 13:56:16 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C5E6F23888FE; Sun, 24 Mar 2013 13:55:49 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1460378 - in /clerezza/trunk/platform.xhtml2html: ./ src/main/java/org/apache/clerezza/platform/xhtml2html/ src/test/java/org/apache/clerezza/platform/xhtml2html/ Date: Sun, 24 Mar 2013 13:55:49 -0000 To: commits@clerezza.apache.org From: reto@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130324135549.C5E6F23888FE@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: reto Date: Sun Mar 24 13:55:48 2013 New Revision: 1460378 URL: http://svn.apache.org/r1460378 Log: CLEREZZA-759: ported to use servlet filters rather than wrhapi Added: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingOutputStream.java - copied, changed from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingByteChannel.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringOutputStream.java - copied, changed from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringByteChannel.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsOutputStream.java - copied, changed from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannel.java Removed: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingByteChannel.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringByteChannel.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannel.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlConvertingBody.java Modified: clerezza/trunk/platform.xhtml2html/pom.xml clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedRequest.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedResponse.java clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlFilter.java clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/DocTypeSettingByteChannelTest.java clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannelTest.java Modified: clerezza/trunk/platform.xhtml2html/pom.xml URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/pom.xml?rev=1460378&r1=1460377&r2=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/pom.xml (original) +++ clerezza/trunk/platform.xhtml2html/pom.xml Sun Mar 24 13:55:48 2013 @@ -1,4 +1,5 @@ - +--> + 4.0.0 clerezza @@ -30,14 +32,14 @@ bundle 0.6-SNAPSHOT Clerezza - Filter for browsers that do not support XHTML - Provides a wrhapi filter that changes the content-type of the + Provides a servlet filter that changes the content-type of the response from application/xhtml+xml to text/html - org.wymiwyg - wrhapi - 0.9 + javax.servlet + servlet-api + 2.5 org.osgi Copied: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingOutputStream.java (from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingByteChannel.java) URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingOutputStream.java?p2=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingOutputStream.java&p1=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingByteChannel.java&r1=1459696&r2=1460378&rev=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingByteChannel.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/ContentLengthSettingOutputStream.java Sun Mar 24 13:55:48 2013 @@ -19,58 +19,68 @@ package org.apache.clerezza.platform.xhtml2html; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import org.wymiwyg.wrhapi.HandlerException; +import java.io.OutputStream; +import javax.servlet.ServletOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Triggers the CONTENT-LENGTH header to be set in the wrapped response when the - * first bytes are written to the WritableByteChannel and the content - * (to be written to the channel) will not to be converted from xhtml to html. - * + * first bytes are written to the + * WritableByteChannel and the content (to be written to the + * channel) will not to be converted from xhtml to html. + * * @author mir */ -class ContentLengthSettingByteChannel implements WritableByteChannel { +class ContentLengthSettingOutputStream extends ServletOutputStream { - final static private Logger logger = LoggerFactory.getLogger(ContentLengthSettingByteChannel.class); + final static private Logger logger = LoggerFactory.getLogger(ContentLengthSettingOutputStream.class); private WrappedResponse wrappedResponse; - private WritableByteChannel wrappedByteChannel; + private OutputStream base; private boolean contetLengthIsSet = false; + int charCount = 0; - ContentLengthSettingByteChannel(WritableByteChannel byteChannel, + ContentLengthSettingOutputStream(OutputStream base, WrappedResponse wrappedResponse) { - this.wrappedByteChannel = byteChannel; + this.base = base; this.wrappedResponse = wrappedResponse; } @Override - public int write(ByteBuffer bb) throws IOException { - if (!contetLengthIsSet && bb.remaining() > 0) { - try { - wrappedResponse.setContentLengthIfNoConversion(); - contetLengthIsSet = true; - } catch (HandlerException ex) { - logger.error("Exception {}", ex.toString(), ex); - } + public void write(int b) throws IOException { + if (!contetLengthIsSet) { + wrappedResponse.setContentLengthIfNoConversion(); + contetLengthIsSet = true; } - return wrappedByteChannel.write(bb); + base.write(b); } - + /** + * This does was the abstract superclass would be expected to do + */ @Override - public boolean isOpen() { - return wrappedByteChannel.isOpen(); - - + public void write(byte b[]) throws IOException { + write(b, 0, b.length); + } + /** + * This does was the abstract superclass would be expected to do + */ + @Override + public void write(byte b[], int off, int len) throws IOException { + for (int i = off; i < (off + len); i++) { + write(b[i]); + } + } + @Override + public void flush() throws IOException { + super.flush(); } @Override public void close() throws IOException { - wrappedByteChannel.close(); - - + super.close(); } + + } Copied: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringOutputStream.java (from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringByteChannel.java) URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringOutputStream.java?p2=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringOutputStream.java&p1=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringByteChannel.java&r1=1459696&r2=1460378&rev=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringByteChannel.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/DocTypeFilteringOutputStream.java Sun Mar 24 13:55:48 2013 @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.clerezza.platform.xhtml2html; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; @@ -28,17 +28,16 @@ import java.nio.channels.WritableByteCha * * @author mir */ -class DocTypeFilteringByteChannel implements WritableByteChannel { - +class DocTypeFilteringOutputStream extends OutputStream { + private final static byte[] DOCTYPE_DEF_BYTES = " ".getBytes(); private final static byte[] DOCTYPE_TAG_BYTES = "'; private final static byte SPACE = ' '; private final static byte NEXTLINE = '\n'; private final static byte CARRIAGE_RETURN = '\r'; - private WritableByteChannel wrappedByteChannel; private boolean doctypeWritten = false; private int arrayPosition = 0; private ByteArrayOutputStream cachedBytes = new ByteArrayOutputStream(); @@ -47,96 +46,95 @@ class DocTypeFilteringByteChannel implem private boolean isNotADoctypeDef = false; private boolean hasHtmlTag = false; private boolean lookingForHtmlTag = true; - - public DocTypeFilteringByteChannel(WritableByteChannel byteChannel, + private OutputStream wrapped; + + public DocTypeFilteringOutputStream(OutputStream wrapped, ResponseStatusInfo wrappedResponse) { - this.wrappedByteChannel = byteChannel; + this.wrapped = wrapped; this.wrappedResponse = wrappedResponse; - } + } @Override - public int write(ByteBuffer byteBuffer) throws IOException { + public void write(int b) throws IOException { if (!doctypeWritten && wrappedResponse.convertXhtml2Html()) { - int initialRemaining = byteBuffer.remaining(); - while (byteBuffer.remaining() > 0) { - byte b = byteBuffer.get(); - cachedBytes.write(b); - if (arrayPosition == 0 && - (b == SPACE || b == NEXTLINE || b == CARRIAGE_RETURN)) { - continue; - } - if (arrayPosition == (DOCTYPE_TAG_BYTES.length - 1) && - DOCTYPE_TAG_BYTES[arrayPosition] == b) { - writeEverythingAndSetDoctypeWrittenToTrue(byteBuffer); - break; + + cachedBytes.write(b); + if (arrayPosition == 0 + && (b == SPACE || b == NEXTLINE || b == CARRIAGE_RETURN)) { + return; + } + if (arrayPosition == (DOCTYPE_TAG_BYTES.length - 1) + && DOCTYPE_TAG_BYTES[arrayPosition] == b) { + writeEverythingAndSetDoctypeWrittenToTrue(b); + return; + } + if (arrayPosition < XML_DECLARATION_BYTES.length + && XML_DECLARATION_BYTES[arrayPosition] != b) { + isXmlDeclaration = false; + } + + if (lookingForHtmlTag) { + if (arrayPosition < HTML_TAG_BYTES.length + && HTML_TAG_BYTES[arrayPosition] != b) { + lookingForHtmlTag = false; } - if (arrayPosition < XML_DECLARATION_BYTES.length - && XML_DECLARATION_BYTES[arrayPosition] != b) { - isXmlDeclaration = false; + if (arrayPosition >= HTML_TAG_BYTES.length) { + hasHtmlTag = true; } + } - if (lookingForHtmlTag) { - if (arrayPosition < HTML_TAG_BYTES.length - && HTML_TAG_BYTES[arrayPosition] != b) { - lookingForHtmlTag = false; - } - if (arrayPosition >= HTML_TAG_BYTES.length) { - hasHtmlTag = true; - } - } - - if (arrayPosition >= XML_DECLARATION_BYTES.length && isXmlDeclaration) { - if (b == GREATER_THAN) { - arrayPosition = 0; - isNotADoctypeDef = false; - lookingForHtmlTag = true; - cachedBytes.reset(); // dump XML Declaration - } - continue; + if (arrayPosition >= XML_DECLARATION_BYTES.length && isXmlDeclaration) { + if (b == GREATER_THAN) { + arrayPosition = 0; + isNotADoctypeDef = false; + lookingForHtmlTag = true; + cachedBytes.reset(); // dump XML Declaration } - if (DOCTYPE_TAG_BYTES[arrayPosition] != b || isNotADoctypeDef) { - isNotADoctypeDef = true; - if (!isXmlDeclaration && hasHtmlTag) { - writeToWrappedChannel(DOCTYPE_DEF_BYTES); - writeEverythingAndSetDoctypeWrittenToTrue(byteBuffer); - break; - } else if (!isXmlDeclaration && !hasHtmlTag && !lookingForHtmlTag){ - writeEverythingAndSetDoctypeWrittenToTrue(byteBuffer); - break; - } + return; + } + if (DOCTYPE_TAG_BYTES[arrayPosition] != b || isNotADoctypeDef) { + isNotADoctypeDef = true; + if (!isXmlDeclaration && hasHtmlTag) { + writeToWrappedChannel(DOCTYPE_DEF_BYTES); + writeEverythingAndSetDoctypeWrittenToTrue(b); + return; + } else if (!isXmlDeclaration && !hasHtmlTag && !lookingForHtmlTag) { + writeEverythingAndSetDoctypeWrittenToTrue(b); + return; } - arrayPosition++; } - return initialRemaining - byteBuffer.remaining(); + arrayPosition++; + } else { - return wrappedByteChannel.write(byteBuffer); + wrapped.write(b); } } - private void writeEverythingAndSetDoctypeWrittenToTrue(ByteBuffer byteBuffer) throws IOException { + private void writeEverythingAndSetDoctypeWrittenToTrue(int b) throws IOException { writeToWrappedChannel(cachedBytes.toByteArray()); - wrappedByteChannel.write(byteBuffer); + //wrapped.write(b); doctypeWritten = true; } @Override - public boolean isOpen() { - return wrappedByteChannel.isOpen(); + public void flush() + throws IOException { + if (!doctypeWritten) { + writeToWrappedChannel(cachedBytes.toByteArray()); + } + wrapped.flush(); } - + @Override public void close() throws IOException { if (!doctypeWritten) { writeToWrappedChannel(cachedBytes.toByteArray()); } - wrappedByteChannel.close(); + wrapped.close(); } private void writeToWrappedChannel(byte[] byteArray) throws IOException { - ByteBuffer buf = ByteBuffer.wrap(byteArray); - while (buf.remaining() > 0) { - wrappedByteChannel.write(buf); - } + wrapped.write(byteArray); } } Copied: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsOutputStream.java (from r1459696, clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannel.java) URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsOutputStream.java?p2=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsOutputStream.java&p1=clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannel.java&r1=1459696&r2=1460378&rev=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsByteChannel.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/SelfClosing2ClosingTagsOutputStream.java Sun Mar 24 13:55:48 2013 @@ -16,32 +16,27 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.clerezza.platform.xhtml2html; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.WritableByteChannel; import java.util.Arrays; +import javax.servlet.ServletOutputStream; /** * Changes self-closing tags to tags with closing tags. Self-closing tags that * are allowed in HTML are left unchanged. The allowed self-closing tags are: * area, base, basefont, br, hr, input img, link and meta. - * + * * @author mir */ -class SelfClosing2ClosingTagsByteChannel implements WritableByteChannel { - - +class SelfClosing2ClosingTagsOutputStream extends ServletOutputStream { + private final static byte SPACE = " ".getBytes()[0]; private final static byte SLASH = "/".getBytes()[0]; private final static byte LESS_THAN = "<".getBytes()[0]; private final static byte GREATER_THAN = ">".getBytes()[0]; - private static byte[][] allowedTagNamesBytes = { "area".getBytes(), "base".getBytes(), @@ -53,96 +48,111 @@ class SelfClosing2ClosingTagsByteChannel "link".getBytes(), "meta".getBytes() }; - - private WritableByteChannel wrappedByteChannel; + private OutputStream wrapped; private ResponseStatusInfo responseStatusInfo; - private ByteArrayOutputStream tagNameStream = new ByteArrayOutputStream(); - private OutputStream bytes = new ByteArrayOutputStream(); + //private OutputStream bytes = new ByteArrayOutputStream(); - private enum Status {SEARCH_TAG, DETERMINE_IF_IS_OPENING_TAG, READ_TAG_NAME, - SEARCH_SLASH,SEARCH_GREATER_THAN, FOUND} - + private enum Status { + + SEARCH_TAG, DETERMINE_IF_IS_OPENING_TAG, READ_TAG_NAME, + SEARCH_SLASH, SEARCH_GREATER_THAN, FOUND + } private Status status = Status.SEARCH_TAG; - - public SelfClosing2ClosingTagsByteChannel(WritableByteChannel byteChannel, + + public SelfClosing2ClosingTagsOutputStream(OutputStream wrapped, ResponseStatusInfo responseStatusInfo) { - this.wrappedByteChannel = byteChannel; + this.wrapped = wrapped; this.responseStatusInfo = responseStatusInfo; - bytes = Channels.newOutputStream(wrappedByteChannel); - } + } @Override - public int write(ByteBuffer byteBuffer) throws IOException { + public void write(int b) throws IOException { if (responseStatusInfo.convertXhtml2Html()) { - int bytesWritten = byteBuffer.remaining(); - while (byteBuffer.remaining() > 0) { - byte b = byteBuffer.get(); - switch (status) { - case SEARCH_TAG: - if (b == LESS_THAN) { - status = Status.DETERMINE_IF_IS_OPENING_TAG; - } - break; - case DETERMINE_IF_IS_OPENING_TAG: - if (b != SLASH) { - status = Status.READ_TAG_NAME; - } else { - status = Status.SEARCH_TAG; - break; - } - case READ_TAG_NAME: - if (b == SPACE) { - status = Status.SEARCH_SLASH; - } else if (b == GREATER_THAN) { - reset(); - } else if (b == SLASH) { - status = Status.SEARCH_GREATER_THAN; - continue; - } else { - tagNameStream.write(b); - } - break; - case SEARCH_SLASH: - if (b == SLASH) { - status = Status.SEARCH_GREATER_THAN; - continue; - } - if (b == GREATER_THAN) { - reset(); - } - break; + switch (status) { + case SEARCH_TAG: + if (b == LESS_THAN) { + status = Status.DETERMINE_IF_IS_OPENING_TAG; + } + break; - case SEARCH_GREATER_THAN: - if (b == GREATER_THAN) { - status = Status.FOUND; - } else { - bytes.write(SLASH); // write the slash that we didn't write when we found it - status = Status.SEARCH_SLASH; - } + case DETERMINE_IF_IS_OPENING_TAG: + if (b != SLASH) { + status = Status.READ_TAG_NAME; + } else { + status = Status.SEARCH_TAG; break; - } - if (status == Status.FOUND) { - byte[] tagNameBytes = tagNameStream.toByteArray(); - if (isAllowedTagName(tagNameBytes)) { - bytes.write(SLASH); - bytes.write(GREATER_THAN); + } + case READ_TAG_NAME: + if (b == SPACE) { + status = Status.SEARCH_SLASH; + } else if (b == GREATER_THAN) { + reset(); + } else if (b == SLASH) { + status = Status.SEARCH_GREATER_THAN; + return; } else { - bytes.write(GREATER_THAN); - bytes.write(LESS_THAN); - bytes.write(SLASH); - bytes.write(tagNameBytes); - bytes.write(GREATER_THAN); + tagNameStream.write(b); } - reset(); + break; + case SEARCH_SLASH: + if (b == SLASH) { + status = Status.SEARCH_GREATER_THAN; + return; + } + if (b == GREATER_THAN) { + reset(); + } + break; + + case SEARCH_GREATER_THAN: + if (b == GREATER_THAN) { + status = Status.FOUND; + } else { + wrapped.write(SLASH); // write the slash that we didn't write when we found it + status = Status.SEARCH_SLASH; + } + break; + } + if (status == Status.FOUND) { + byte[] tagNameBytes = tagNameStream.toByteArray(); + if (isAllowedTagName(tagNameBytes)) { + wrapped.write(SLASH); + wrapped.write(GREATER_THAN); } else { - bytes.write(b); + wrapped.write(GREATER_THAN); + wrapped.write(LESS_THAN); + wrapped.write(SLASH); + wrapped.write(tagNameBytes); + wrapped.write(GREATER_THAN); } + reset(); + } else { + wrapped.write(b); } - return bytesWritten - byteBuffer.remaining(); + } else { - return wrappedByteChannel.write(byteBuffer); + wrapped.write(b); + flush(); + } + } + + /** + * This does was the abstract superclass would be expected to do + */ + @Override + public void write(byte b[]) throws IOException { + write(b, 0, b.length); + } + + /** + * This does was the abstract superclass would be expected to do + */ + @Override + public void write(byte b[], int off, int len) throws IOException { + for (int i = off; i < (off + len); i++) { + write(b[i]); } } @@ -150,7 +160,7 @@ class SelfClosing2ClosingTagsByteChannel tagNameStream.reset(); status = Status.SEARCH_TAG; } - + private boolean isAllowedTagName(byte[] tagNameBytes) { for (int i = 0; i < allowedTagNamesBytes.length; i++) { byte[] allowedTagNameBytes = allowedTagNamesBytes[i]; @@ -162,12 +172,12 @@ class SelfClosing2ClosingTagsByteChannel } @Override - public boolean isOpen() { - return wrappedByteChannel.isOpen(); + public void flush() throws IOException { + wrapped.flush(); } @Override - public void close() throws IOException { - wrappedByteChannel.close(); + public void close() throws IOException { + wrapped.close(); } } Modified: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedRequest.java URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedRequest.java?rev=1460378&r1=1460377&r2=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedRequest.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedRequest.java Sun Mar 24 13:55:48 2013 @@ -19,36 +19,43 @@ package org.apache.clerezza.platform.xhtml2html; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; -import org.wymiwyg.wrhapi.HandlerException; -import org.wymiwyg.wrhapi.HeaderName; -import org.wymiwyg.wrhapi.Request; -import org.wymiwyg.wrhapi.util.RequestWrapper; +import java.util.Vector; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; /** * Sets the accept-header to text/html, application/xhtml+xml;q=.9,*\/*;q=.1 * * @author rbn */ -class WrappedRequest extends RequestWrapper { +class WrappedRequest extends HttpServletRequestWrapper { + public static final String NEW_ACCCEPT = "text/html, application/xhtml+xml;q=.9, */*;q=.1"; - public WrappedRequest(Request request) { + public WrappedRequest(HttpServletRequest request) { super(request); } @Override - public String[] getHeaderValues(HeaderName headerName) throws HandlerException { - if (headerName.equals(HeaderName.ACCEPT)) { + public Enumeration getHeaders(String headerName) { + if ("Accept".equalsIgnoreCase(headerName)) { + Vector newList = new Vector(); + newList.add(NEW_ACCCEPT); + return newList.elements(); + } else { + return super.getHeaders(headerName); + } + } + @Override + public String getHeader(String headerName) { + if ("Accept".equalsIgnoreCase(headerName)) { List newList = new ArrayList(); - newList.add("text/html"); - newList.add("application/xhtml+xml;q=.9"); - newList.add("*/*;q=.1"); - return newList.toArray(new String[newList.size()]); + return NEW_ACCCEPT; } else { - return super.getHeaderValues(headerName); + return super.getHeader(headerName); } } - } Modified: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedResponse.java URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedResponse.java?rev=1460378&r1=1460377&r2=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedResponse.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/WrappedResponse.java Sun Mar 24 13:55:48 2013 @@ -18,80 +18,143 @@ */ package org.apache.clerezza.platform.xhtml2html; -import java.util.ArrayList; -import java.util.List; -import org.wymiwyg.wrhapi.HandlerException; -import org.wymiwyg.wrhapi.HeaderName; -import org.wymiwyg.wrhapi.MessageBody; -import org.wymiwyg.wrhapi.Response; -import org.wymiwyg.wrhapi.util.ResponseWrapper; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * * @author rbn */ -class WrappedResponse extends ResponseWrapper implements ResponseStatusInfo { +class WrappedResponse extends HttpServletResponseWrapper implements ResponseStatusInfo { + private String XHTML_TYPE = "application/xhtml+xml"; private String HTML_TYPE = "text/html"; private boolean convertXhtml2Html = false; - private List contentLengths = new ArrayList(); + private String contentLength = null; + private final Logger log = LoggerFactory.getLogger(WrappedResponse.class); - public WrappedResponse(Response response) { + public WrappedResponse(HttpServletResponse response) { super(response); } + //stupid servlet redundanny + @Override + public void setContentLength(int value) { + if (convertXhtml2Html) { + // do nothing + } else { + contentLength = Integer.toString(value); + } + } + @Override - public void addHeader(HeaderName headerName, Object value) throws HandlerException { - if (headerName.equals(HeaderName.CONTENT_LENGTH)) { + public void setContentType(String type) { + if (type.startsWith(XHTML_TYPE)) { + super.setHeader("Content-Type", HTML_TYPE + type.substring(XHTML_TYPE.length())); + convertXhtml2Html = true; + } else { + log.info("The original media type is "+type+" and is not being changed"); + super.setContentType(type); + } + + } + + @Override + public void setHeader(String headerName, String value) { + if ("Content-Length".equalsIgnoreCase(headerName)) { if (convertXhtml2Html) { // do nothing } else { - contentLengths.add(value); + contentLength = value; } return; } - String stringValue = value.toString(); - if (headerName.equals(HeaderName.CONTENT_TYPE) && value.toString().startsWith(XHTML_TYPE)) { - super.addHeader(headerName, HTML_TYPE+stringValue.substring(XHTML_TYPE.length())); - convertXhtml2Html = true; - } else { - super.addHeader(headerName, value); + + if ("Content-Type".equalsIgnoreCase(headerName)) { + setContentType(value); + return; } + super.setHeader(headerName, value); } @Override - public void setHeader(HeaderName headerName, Object value) throws HandlerException { - if (headerName.equals(HeaderName.CONTENT_LENGTH)) { + public void addHeader(String headerName, String value) { + if ("Content-Length".equalsIgnoreCase(headerName)) { if (convertXhtml2Html) { // do nothing } else { - contentLengths.clear(); - contentLengths.add(value); + contentLength = value; } return; } - String stringValue = value.toString(); - if (headerName.equals(HeaderName.CONTENT_TYPE) && stringValue.startsWith(XHTML_TYPE)) { - super.setHeader(headerName, HTML_TYPE+stringValue.substring(XHTML_TYPE.length())); - convertXhtml2Html = true; + if ("Content-Type".equalsIgnoreCase(headerName) && value.startsWith(XHTML_TYPE)) { + //more than one conten-type hearders make no sense + setContentType(value); } else { - super.setHeader(headerName, value); + super.addHeader(headerName, value); } } @Override - public void setBody(MessageBody body) throws HandlerException { - super.setBody(new Xhtml2HtmlConvertingBody(body, this)); + public ServletOutputStream getOutputStream() throws IOException { + //return new ContentLengthSettingByteChannel(super.getOutputStream(), this); + return new ContentLengthSettingOutputStream(new DocTypeFilteringOutputStream( + new SelfClosing2ClosingTagsOutputStream( + super.getOutputStream(), this), this), this); + } + + @Override + public PrintWriter getWriter() throws IOException { + //this doesn't work, data is truncated + //return new PrintWriter(new OutputStreamWriter(getOutputStream(), "utf-8"), true); + final OutputStream stream = getOutputStream(); + return new PrintWriter(new Writer() { + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + + for (int i = 0; i < len; i++) { + char ch = cbuf[off+i]; + if (ch > 127) { + byte[] bytes = (""+ch).getBytes("utf-8"); + for (byte b : bytes) { + stream.write(b); + } + } else { + stream.write(ch); + } + } + } + + @Override + public void flush() throws IOException { + stream.flush(); + } + + @Override + public void close() throws IOException { + stream.close();; + } + }, true); + } + @Override public boolean convertXhtml2Html() { return convertXhtml2Html; } - void setContentLengthIfNoConversion() throws HandlerException { - if (contentLengths.size() > 0 && !convertXhtml2Html) { - super.setHeader(HeaderName.CONTENT_LENGTH, contentLengths.toArray()); + void setContentLengthIfNoConversion() { + if ((contentLength != null) && !convertXhtml2Html) { + super.setHeader("Content-Length", contentLength); } } } Modified: clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlFilter.java URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlFilter.java?rev=1460378&r1=1460377&r2=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlFilter.java (original) +++ clerezza/trunk/platform.xhtml2html/src/main/java/org/apache/clerezza/platform/xhtml2html/Xhtml2HtmlFilter.java Sun Mar 24 13:55:48 2013 @@ -18,45 +18,46 @@ */ package org.apache.clerezza.platform.xhtml2html; -import java.util.Iterator; +import java.io.IOException; +import java.util.Enumeration; import java.util.regex.Pattern; import javax.activation.MimeType; import javax.activation.MimeTypeParseException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.osgi.service.component.ComponentContext; -import org.wymiwyg.wrhapi.Handler; -import org.wymiwyg.wrhapi.HandlerException; -import org.wymiwyg.wrhapi.HeaderName; -import org.wymiwyg.wrhapi.Request; -import org.wymiwyg.wrhapi.Response; -import org.wymiwyg.wrhapi.filter.Filter; -import org.wymiwyg.wrhapi.util.AcceptHeaderEntry; -import org.wymiwyg.wrhapi.util.EnhancedRequest; /** - * This Filter acts on client agents matching a pattern defined by the - * service property pattern, it changes the returhned content type - * from application/xhtml+xml to application/html and adds application/xhtml+xml - * to the accept header. + * This Filter acts on client agents matching a pattern defined by the service + * property + * pattern, it changes the returhned content type from + * application/xhtml+xml to application/html and adds application/xhtml+xml to + * the accept header. * - * - * @scr.component - * @scr.service interface="org.wymiwyg.wrhapi.filter.Filter" - * @scr.property name="pattern" - * values.name=".*MSIE.*" - * - * @author rbn */ -@Component +@Component(immediate=true) @Service(Filter.class) -@Property(name="pattern", value={".*MSIE.*", ""}) +@Properties(value = { + @Property(name="pattern",value=".*"), + @Property(name = "service.ranking", intValue = Integer.MAX_VALUE), + @Property(name = "agent-pattern", value = {".*MSIE.*", ""}) +}) public class Xhtml2HtmlFilter implements Filter { private Pattern[] patterns; final MimeType xhtmlMimeType; final MimeType htmlMimeType; + { try { xhtmlMimeType = new MimeType("application", "xhtml+xml"); @@ -66,22 +67,13 @@ public class Xhtml2HtmlFilter implements } } - @Override - public void handle(Request request, Response response, Handler handler) - throws HandlerException { - if (!isApplicable(request)) { - handler.handle(request, response); - } else { - handler.handle(new WrappedRequest(request), new WrappedResponse(response)); - } - } - - private boolean isApplicable(final Request request) throws HandlerException { + private boolean isApplicable(final HttpServletRequest request) { if (htmlPreferredInAccept(request)) { return true; } - final String[] userAgentStrings = request.getHeaderValues(HeaderName.USER_AGENT); - for (final String userAgentString : userAgentStrings) { + final Enumeration userAgentStrings = request.getHeaders("User-Agent"); + while (userAgentStrings.hasMoreElements()) { + final String userAgentString = userAgentStrings.nextElement(); for (final Pattern pattern : patterns) { if (pattern.matcher(userAgentString).matches()) { return true; @@ -91,15 +83,15 @@ public class Xhtml2HtmlFilter implements return false; } - private boolean htmlPreferredInAccept(Request request) throws HandlerException { - EnhancedRequest ehRequest = new EnhancedRequest(request); - Iterator iter = ehRequest.getAccept(); - while (iter.hasNext()) { - AcceptHeaderEntry entry = iter.next(); - if (entry.getRange().match(xhtmlMimeType)) { + private boolean htmlPreferredInAccept(HttpServletRequest request) { + Enumeration accepts = request.getHeaders("Accept"); + //TODO parse geader + while (accepts.hasMoreElements()) { + final String accept = accepts.nextElement(); + if (accept.startsWith("application/xhtml+xml")) { return false; } - if (entry.getRange().match(htmlMimeType)) { + if (accept.startsWith("text/html")) { return true; } } @@ -108,13 +100,29 @@ public class Xhtml2HtmlFilter implements protected void activate(ComponentContext context) throws Exception { final String[] patternStrings = (String[]) context.getProperties(). - get("pattern"); + get("agent-pattern"); patterns = new Pattern[patternStrings.length]; - for(int i = 0; i < patternStrings.length; i++) { + for (int i = 0; i < patternStrings.length; i++) { patterns[i] = Pattern.compile(patternStrings[i]); } } + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + @Override + public void doFilter(ServletRequest request, + ServletResponse response, FilterChain chain) throws IOException, ServletException { + if (!isApplicable((HttpServletRequest)request)) { + chain.doFilter(request, response); + } else { + chain.doFilter(new WrappedRequest((HttpServletRequest)request), + new WrappedResponse((HttpServletResponse)response)); + } + } + @Override + public void destroy() { + } } Modified: clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/DocTypeSettingByteChannelTest.java URL: http://svn.apache.org/viewvc/clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/DocTypeSettingByteChannelTest.java?rev=1460378&r1=1460377&r2=1460378&view=diff ============================================================================== --- clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/DocTypeSettingByteChannelTest.java (original) +++ clerezza/trunk/platform.xhtml2html/src/test/java/org/apache/clerezza/platform/xhtml2html/DocTypeSettingByteChannelTest.java Sun Mar 24 13:55:48 2013 @@ -20,6 +20,7 @@ package org.apache.clerezza.platform.xhtml2html; import java.io.ByteArrayOutputStream; +import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; @@ -38,11 +39,24 @@ public class DocTypeSettingByteChannelTe "\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - channel.write(ByteBuffer.wrap(someHtml.getBytes(UTF8))); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtml.getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); - Assert.assertTrue(resultString.startsWith("\n" + + "\n" + + "hello" + + "\n" + + ""; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtml.getBytes(UTF8)); + final String resultString = new String(baos.toByteArray(), UTF8); + Assert.assertTrue(resultString.startsWith("" + - "\n" + + "\n" + "\n" + "hello" + "\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - int bytesWritten = channel.write(ByteBuffer.wrap(someHtml.substring(0, 20).getBytes(UTF8))); - bytesWritten += channel.write(ByteBuffer.wrap(someHtml.substring(20).getBytes(UTF8))); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtml.substring(0, 20).getBytes(UTF8)); + channel.write(someHtml.substring(20).getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); - Assert.assertEquals(someHtml.length(), bytesWritten); + //Assert.assertEquals(someHtml.length(), bytesWritten); Assert.assertTrue(resultString.contains("\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - channel.write(ByteBuffer.wrap(someHtml.getBytes(UTF8))); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtml.getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); Assert.assertTrue(resultString.contains("\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - channel.write(ByteBuffer.wrap(someHtml.getBytes(UTF8))); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtml.getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); Assert.assertTrue(resultString.startsWith("\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); + final OutputStream channel = createDocTypeFilteringByteChannel(baos); final byte[] bytes = someHtml.getBytes(UTF8); for (int i = 0; i < bytes.length; i++) { - ByteBuffer buf = ByteBuffer.allocate(1); - buf.put(bytes[i]); - buf.rewind(); - channel.write(buf); + channel.write(bytes[i]); } final String resultString = new String(baos.toByteArray(), UTF8); Assert.assertTrue(resultString.startsWith("\n"; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - channel.write(ByteBuffer.wrap(someHtmlSnippet.getBytes(UTF8))); + final DocTypeFilteringOutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtmlSnippet.getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); Assert.assertEquals(someHtmlSnippet, resultString); } @@ -149,8 +160,8 @@ public class DocTypeSettingByteChannelTe "hello" + "\n"; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = createDocTypeFilteringByteChannel(baos); - channel.write(ByteBuffer.wrap(someHtmlSnippet.getBytes(UTF8))); + final DocTypeFilteringOutputStream channel = createDocTypeFilteringByteChannel(baos); + channel.write(someHtmlSnippet.getBytes(UTF8)); final String resultString = new String(baos.toByteArray(), UTF8); /* The test fails iff the ?xml is at another position than 0, not * if its removed*/ @@ -160,8 +171,8 @@ public class DocTypeSettingByteChannelTe Assert.assertFalse(resultString.contains("\n" + ""; final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final WritableByteChannel channel = new SelfClosing2ClosingTagsByteChannel(Channels.newChannel(baos), + final OutputStream channel = new SelfClosing2ClosingTagsOutputStream(baos, new ResponseStatusInfo() { @Override @@ -76,8 +74,8 @@ public class SelfClosing2ClosingTagsByte } }); - int bytesWritten = channel.write(ByteBuffer.wrap(someHtml.getBytes(UTF8))); - Assert.assertEquals(someHtml.length(), bytesWritten); + channel.write(someHtml.getBytes(UTF8)); + // Assert.assertEquals(someHtml.length(), bytesWritten); final String resultString = new String(baos.toByteArray(), UTF8); Assert.assertEquals(expectedHtml, resultString); }