james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Norman Maurer <norman.mau...@googlemail.com>
Subject Re: svn commit: r1227867 - in /james/mime4j/trunk/dom/src: main/java/org/apache/james/mime4j/message/ test/java/org/apache/james/mime4j/message/
Date Sat, 07 Jan 2012 08:54:21 GMT
Hi Oleg,

wouldnt it better be called CharSequenceInputStream?

Bye
Norman


Am 05.01.2012 um 23:13 schrieb olegk@apache.org:

> Author: olegk
> Date: Thu Jan  5 22:13:00 2012
> New Revision: 1227867
> 
> URL: http://svn.apache.org/viewvc?rev=1227867&view=rev
> Log:
> More efficient implementation of TextBody backed by a String; body content can be streamed
without convering the string to a byte array
> 
> Added:
>    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
  (with props)
>    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
  (with props)
>    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
  (with props)
> Modified:
>    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
> 
> Modified: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
> URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java?rev=1227867&r1=1227866&r2=1227867&view=diff
> ==============================================================================
> --- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
(original)
> +++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/BasicBodyFactory.java
Thu Jan  5 22:13:00 2012
> @@ -23,6 +23,8 @@ import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.io.UnsupportedEncodingException;
> +import java.nio.charset.Charset;
> +import java.nio.charset.UnsupportedCharsetException;
> 
> import org.apache.james.mime4j.dom.BinaryBody;
> import org.apache.james.mime4j.dom.TextBody;
> @@ -33,8 +35,6 @@ import org.apache.james.mime4j.util.Char
>  */
> public class BasicBodyFactory implements BodyFactory {
> 
> -    private static String DEFAULT_CHARSET = CharsetUtil.DEFAULT_CHARSET.name();
> -
>     public BinaryBody binaryBody(final InputStream is) throws IOException {
>         return new BasicBinaryBody(bufferContent(is));
>     }
> @@ -60,11 +60,23 @@ public class BasicBodyFactory implements
>         if (text == null) {
>             throw new IllegalArgumentException("Text may not be null");
>         }
> -        return new BasicTextBody(text.getBytes(mimeCharset), mimeCharset);
> +        Charset charset = Charset.forName(mimeCharset);
> +        try {
> +            return new StringBody(text, charset);
> +        } catch (UnsupportedCharsetException ex) {
> +            throw new UnsupportedEncodingException(ex.getMessage());
> +        }
> +    }
> +
> +    public TextBody textBody(final String text, final Charset charset) {
> +        if (text == null) {
> +            throw new IllegalArgumentException("Text may not be null");
> +        }
> +        return new StringBody(text, charset);
>     }
> 
> -    public TextBody textBody(final String text) throws UnsupportedEncodingException
{
> -        return textBody(text, DEFAULT_CHARSET);
> +    public TextBody textBody(final String text) {
> +        return textBody(text, CharsetUtil.DEFAULT_CHARSET);
>     }
> 
>     public BinaryBody binaryBody(final byte[] buf) {
> 
> Added: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
> URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java?rev=1227867&view=auto
> ==============================================================================
> --- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
(added)
> +++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
Thu Jan  5 22:13:00 2012
> @@ -0,0 +1,62 @@
> +/****************************************************************
> + * 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.james.mime4j.message;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.io.Reader;
> +import java.io.StringReader;
> +import java.nio.charset.Charset;
> +
> +import org.apache.james.mime4j.dom.SingleBody;
> +import org.apache.james.mime4j.dom.TextBody;
> +
> +class StringBody extends TextBody {
> +
> +    private final String content;
> +    private final Charset charset;
> +
> +    StringBody(final String content, final Charset charset) {
> +        super();
> +        this.content = content;
> +        this.charset = charset;
> +    }
> +
> +    @Override
> +    public String getMimeCharset() {
> +        return this.charset.name();
> +    }
> +
> +    @Override
> +    public Reader getReader() throws IOException {
> +        return new StringReader(this.content);
> +    }
> +
> +    @Override
> +    public InputStream getInputStream() throws IOException {
> +        return new StringInputStream(this.content, this.charset, 2048);
> +    }
> +
> +    @Override
> +    public SingleBody copy() {
> +        return new StringBody(this.content, this.charset);
> +    }
> +
> +}
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
> ------------------------------------------------------------------------------
>    svn:executable = *
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Revision
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringBody.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
> 
> Added: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
> URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java?rev=1227867&view=auto
> ==============================================================================
> --- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
(added)
> +++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
Thu Jan  5 22:13:00 2012
> @@ -0,0 +1,150 @@
> +/****************************************************************
> + * 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.james.mime4j.message;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.nio.ByteBuffer;
> +import java.nio.CharBuffer;
> +import java.nio.charset.Charset;
> +import java.nio.charset.CharsetEncoder;
> +import java.nio.charset.CoderResult;
> +import java.nio.charset.CodingErrorAction;
> +
> +class StringInputStream extends InputStream {
> +
> +    private final CharsetEncoder encoder;
> +    private final CharBuffer cbuf;
> +    private final ByteBuffer bbuf;
> +
> +    private int mark;
> +
> +    StringInputStream(final CharSequence s, final Charset charset, int bufferSize) {
> +        super();
> +        this.encoder = charset.newEncoder()
> +            .onMalformedInput(CodingErrorAction.REPLACE)
> +            .onUnmappableCharacter(CodingErrorAction.REPLACE);
> +        this.bbuf = ByteBuffer.allocate(124);
> +        this.bbuf.flip();
> +        this.cbuf = CharBuffer.wrap(s);
> +        this.mark = -1;
> +    }
> +
> +    StringInputStream(final CharSequence s, final Charset charset) {
> +        this(s, charset, 2048);
> +    }
> +
> +    private void fillBuffer() throws IOException {
> +        this.bbuf.compact();
> +        CoderResult result = this.encoder.encode(this.cbuf, this.bbuf, true);
> +        if (result.isError()) {
> +            result.throwException();
> +        }
> +        this.bbuf.flip();
> +    }
> +
> +    @Override
> +    public int read(byte[] b, int off, int len) throws IOException {
> +        if (b == null) {
> +            throw new NullPointerException("Byte array is null");
> +        }
> +        if (len < 0 || (off + len) > b.length) {
> +            throw new IndexOutOfBoundsException("Array Size=" + b.length +
> +                    ", offset=" + off + ", length=" + len);
> +        }
> +        if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining()) {
> +            return -1;
> +        }
> +        int bytesRead = 0;
> +        while (len > 0) {
> +            if (this.bbuf.hasRemaining()) {
> +                int chunk = Math.min(this.bbuf.remaining(), len);
> +                this.bbuf.get(b, off, chunk);
> +                off += chunk;
> +                len -= chunk;
> +                bytesRead += chunk;
> +            } else {
> +                fillBuffer();
> +                if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining())
{
> +                    break;
> +                }
> +            }
> +        }
> +        return bytesRead == 0 && !this.cbuf.hasRemaining() ? -1 : bytesRead;
> +    }
> +
> +    @Override
> +    public int read() throws IOException {
> +        for (;;) {
> +            if (this.bbuf.hasRemaining()) {
> +                return this.bbuf.get() & 0xFF;
> +            } else {
> +                fillBuffer();
> +                if (!this.bbuf.hasRemaining() && !this.cbuf.hasRemaining())
{
> +                    return -1;
> +                }
> +            }
> +        }
> +    }
> +
> +    @Override
> +    public int read(byte[] b) throws IOException {
> +        return read(b, 0, b.length);
> +    }
> +
> +    @Override
> +    public long skip(long n) throws IOException {
> +        int skipped = 0;
> +        while (n > 0 && this.cbuf.hasRemaining()) {
> +            this.cbuf.get();
> +            n--;
> +            skipped++;
> +        }
> +        return skipped;
> +    }
> +
> +    @Override
> +    public int available() throws IOException {
> +        return this.cbuf.remaining();
> +    }
> +
> +    @Override
> +    public void close() throws IOException {
> +    }
> +
> +    @Override
> +    public void mark(int readlimit) {
> +        this.mark = this.cbuf.position();
> +    }
> +
> +    @Override
> +    public void reset() throws IOException {
> +        if (this.mark != -1) {
> +            this.cbuf.position(this.mark);
> +            this.mark = -1;
> +        }
> +    }
> +
> +    @Override
> +    public boolean markSupported() {
> +        return true;
> +    }
> +
> +}
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
> ------------------------------------------------------------------------------
>    svn:executable = *
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Revision
> 
> Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/message/StringInputStream.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
> 
> Added: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
> URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java?rev=1227867&view=auto
> ==============================================================================
> --- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
(added)
> +++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
Thu Jan  5 22:13:00 2012
> @@ -0,0 +1,129 @@
> +/****************************************************************
> + * 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.james.mime4j.message;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.security.SecureRandom;
> +
> +import org.apache.james.mime4j.util.CharsetUtil;
> +
> +import junit.framework.TestCase;
> +
> +public class StringInputStreamTest extends TestCase {
> +
> +    private static final String SWISS_GERMAN_HELLO = "Gr\374ezi_z\344m\344";
> +    private static final String RUSSIAN_HELLO = "\u0412\u0441\u0435\u043C_\u043F\u0440\u0438\u0432\u0435\u0442";
> +    private static final String TEST_STRING = "Hello and stuff " + SWISS_GERMAN_HELLO
+ " " +  RUSSIAN_HELLO;
> +    private static final String LARGE_TEST_STRING;
> +
> +    static {
> +        StringBuilder buffer = new StringBuilder();
> +        for (int i=0; i<100; i++) {
> +            buffer.append(TEST_STRING);
> +        }
> +        LARGE_TEST_STRING = buffer.toString();
> +    }
> +
> +    private static void singleByteReadTest(final String testString) throws IOException
{
> +        byte[] bytes = testString.getBytes(CharsetUtil.UTF_8.name());
> +        InputStream in = new StringInputStream(testString, CharsetUtil.UTF_8);
> +        for (byte b : bytes) {
> +            int read = in.read();
> +            assertTrue(read >= 0);
> +            assertTrue(read <= 255);
> +            assertEquals(b, (byte)read);
> +        }
> +        assertEquals(-1, in.read());
> +    }
> +
> +    private static void bufferedReadTest(final String testString) throws IOException
{
> +        SecureRandom rnd = new SecureRandom();
> +        byte[] expected = testString.getBytes(CharsetUtil.UTF_8.name());
> +        InputStream in = new StringInputStream(testString, CharsetUtil.UTF_8);
> +        byte[] buffer = new byte[128];
> +        int offset = 0;
> +        while (true) {
> +            int bufferOffset = rnd.nextInt(64);
> +            int bufferLength = rnd.nextInt(64);
> +            int read = in.read(buffer, bufferOffset, bufferLength);
> +            if (read == -1) {
> +                assertEquals(offset, expected.length);
> +                break;
> +            } else {
> +                assertTrue(read <= bufferLength);
> +                while (read > 0) {
> +                    assertTrue(offset < expected.length);
> +                    assertEquals(expected[offset], buffer[bufferOffset]);
> +                    offset++;
> +                    bufferOffset++;
> +                    read--;
> +                }
> +            }
> +        }
> +    }
> +
> +    public void testSingleByteRead() throws IOException {
> +        singleByteReadTest(TEST_STRING);
> +    }
> +
> +    public void testLargeSingleByteRead() throws IOException {
> +        singleByteReadTest(LARGE_TEST_STRING);
> +    }
> +
> +    public void testBufferedRead() throws IOException {
> +        bufferedReadTest(TEST_STRING);
> +    }
> +
> +    public void testLargeBufferedRead() throws IOException {
> +        bufferedReadTest(LARGE_TEST_STRING);
> +    }
> +
> +    public void testReadZero() throws Exception {
> +        InputStream r = new StringInputStream("test", CharsetUtil.UTF_8);
> +        byte[] bytes = new byte[30];
> +        assertEquals(0, r.read(bytes, 0, 0));
> +    }
> +
> +    public void testSkip() throws Exception {
> +        InputStream r = new StringInputStream("test", CharsetUtil.UTF_8);
> +        r.skip(1);
> +        r.skip(2);
> +        assertEquals('t', r.read());
> +        r.skip(100);
> +        assertEquals(-1, r.read());
> +    }
> +
> +    public void testMarkReset() throws Exception {
> +        InputStream r = new StringInputStream("test", CharsetUtil.UTF_8);
> +        r.skip(2);
> +        r.mark(0);
> +        assertEquals('s', r.read());
> +        assertEquals('t', r.read());
> +        assertEquals(-1, r.read());
> +        r.reset();
> +        assertEquals('s', r.read());
> +        assertEquals('t', r.read());
> +        assertEquals(-1, r.read());
> +        r.reset();
> +        r.reset();
> +    }
> +
> +}
> 
> Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
> 
> Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
> ------------------------------------------------------------------------------
>    svn:executable = *
> 
> Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Revision
> 
> Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/message/StringInputStreamTest.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
> 
> 

Mime
View raw message