You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2016/05/09 22:04:45 UTC

svn commit: r1743065 - in /webservices/axiom/trunk/aspects/core-aspects/src: main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java

Author: veithen
Date: Mon May  9 22:04:45 2016
New Revision: 1743065

URL: http://svn.apache.org/viewvc?rev=1743065&view=rev
Log:
Add some infrastructure to simplify conversion of unmappable characters into character references.

Added:
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java   (with props)
    webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java   (with props)

Added: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java?rev=1743065&view=auto
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java (added)
+++ webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java Mon May  9 22:04:45 2016
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.core.stream.serializer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+final class OutputStreamXmlWriter extends XmlWriter {
+    private final OutputStream out;
+    private final CharBuffer encoderIn;
+    private final ByteBuffer encoderOut;
+    private final CharsetEncoder encoder;
+    private CharBuffer characterReferenceBuffer;
+
+    OutputStreamXmlWriter(OutputStream out, Charset charset) {
+        this.out = out;
+        encoderIn = CharBuffer.allocate(4096);
+        encoderOut = ByteBuffer.allocate(4096);
+        encoder = charset.newEncoder();
+    }
+
+    private void flushEncodingOut() throws IOException {
+        out.write(encoderOut.array(), 0, encoderOut.position());
+        encoderOut.clear();
+    }
+
+    private void flushEncodingIn(boolean force) throws IOException {
+        if (force || !encoderIn.hasRemaining()) {
+            encoderIn.flip();
+            while (true) {
+                CoderResult coderResult = encoder.encode(encoderIn, encoderOut, false);
+                if (coderResult.isUnderflow()) {
+                    encoderIn.compact();
+                    break;
+                } else if (coderResult.isOverflow()) {
+                    flushEncodingOut();
+                } else if (coderResult.isUnmappable()) {
+                    // Note that we can't use writeCharacterReference here because we are still
+                    // processing the encoderIn buffer
+                    switch (coderResult.length()) {
+                        case 1:
+                            insertCharacterReference(encoderIn.get());
+                            break;
+                        case 2:
+                            throw new UnsupportedOperationException("TODO");
+                        default:
+                            throw new IllegalStateException();
+                    }
+                } else {
+                    throw new IOException("Malformed character sequence");
+                }
+            }
+        }
+    }
+
+    private void insertCharacterReference(int codePoint) throws IOException {
+        CharBuffer buffer = characterReferenceBuffer;
+        if (characterReferenceBuffer == null) {
+            buffer = characterReferenceBuffer = CharBuffer.allocate(16);
+        } else {
+            buffer.clear();
+        }
+        buffer.put("&#");
+        // TODO: optimize this
+        buffer.put(Integer.toString(codePoint));
+        buffer.put(';');
+        buffer.flip();
+        while (true) {
+            CoderResult coderResult = encoder.encode(buffer, encoderOut, false);
+            if (coderResult.isUnderflow()) {
+                break;
+            } else if (coderResult.isOverflow()) {
+                flushEncodingOut();
+            } else {
+                throw new IllegalStateException();
+            }
+        }
+    }
+
+    @Override
+    void write(char c) throws IOException {
+        flushEncodingIn(false);
+        encoderIn.put(c);
+    }
+
+    @Override
+    void write(String src) throws IOException {
+        int offset = 0;
+        int length = src.length();
+        while (length > 0) {
+            flushEncodingIn(false);
+            int c = Math.min(length, encoderIn.remaining());
+            encoderIn.put(src, offset, length);
+            offset += c;
+            length -= c;
+        }
+    }
+
+    @Override
+    void write(char[] src, int offset, int length) throws IOException {
+        while (length > 0) {
+            flushEncodingIn(false);
+            int c = Math.min(length, encoderIn.remaining());
+            encoderIn.put(src, offset, length);
+            offset += c;
+            length -= c;
+        }
+    }
+
+    @Override
+    void flushBuffer() throws IOException {
+        flushEncodingIn(true);
+        flushEncodingOut();
+    }
+}

Propchange: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java?rev=1743065&view=auto
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java (added)
+++ webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java Mon May  9 22:04:45 2016
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.core.stream.serializer;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
+
+import org.junit.Test;
+
+public class OutputStreamXmlWriterTest {
+    @Test
+    public void test() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        XmlWriter writer = new OutputStreamXmlWriter(baos, Charset.forName("iso-8859-1"));
+        writer.write("abc\u20ACdef");
+        writer.flushBuffer();
+        assertThat(baos.toString("iso-8859-1")).isEqualTo("abc€def");
+    }
+}

Propchange: webservices/axiom/trunk/aspects/core-aspects/src/test/java/org/apache/axiom/core/stream/serializer/OutputStreamXmlWriterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native