You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mime4j-dev@james.apache.org by ol...@apache.org on 2009/02/04 13:17:29 UTC

svn commit: r740712 - in /james/mime4j/trunk/src: main/java/org/apache/james/mime4j/field/address/ main/java/org/apache/james/mime4j/io/ main/java/org/apache/james/mime4j/parser/ test/java/org/apache/james/mime4j/io/ test/java/org/apache/james/mime4j/p...

Author: olegk
Date: Wed Feb  4 12:17:29 2009
New Revision: 740712

URL: http://svn.apache.org/viewvc?rev=740712&view=rev
Log:
MIME4J-93: RootInputStream degrades performance by 50%

* RootInputStream functionality repalced with an optional LineNumberSource interface
* RootInputStream#truncate logic moved to BufferedLineReaderInputStream

Contributed by Markus Wiederkehr
Reviewed by Oleg Kalnichevski

Added:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberInputStream.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberSource.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java   (with props)
Removed:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/RootInputStream.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/RootInputStreamTest.java
Modified:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/BufferedLineReaderInputStream.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java Wed Feb  4 12:17:29 2009
@@ -28,6 +28,8 @@
  */
 public abstract class Address implements Serializable {
 
+    private static final long serialVersionUID = 634090661990433426L;
+
     /**
      * Adds any mailboxes represented by this address into the given List. Note
      * that this method has default (package) access, so a doAddMailboxesTo

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/BufferedLineReaderInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/BufferedLineReaderInputStream.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/BufferedLineReaderInputStream.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/BufferedLineReaderInputStream.java Wed Feb  4 12:17:29 2009
@@ -30,6 +30,8 @@
  */
 public class BufferedLineReaderInputStream extends LineReaderInputStream {
 
+    private boolean truncated;
+    
     private byte[] buffer;
     
     private int bufpos;
@@ -52,6 +54,7 @@
         this.bufpos = 0;
         this.buflen = 0;
         this.maxLineLen = maxLineLen;
+        this.truncated = false;
     }
 
     public BufferedLineReaderInputStream(
@@ -101,8 +104,16 @@
         return this.bufpos < this.buflen;
     }
 
+    public void truncate() {
+        clear();
+        this.truncated = true;
+    }
+    
     @Override
     public int read() throws IOException {
+        if (this.truncated) {
+            return -1;
+        }
         int noRead = 0;
         while (!hasBufferedData()) {
             noRead = fillBuffer();
@@ -115,6 +126,9 @@
     
     @Override
     public int read(final byte[] b, int off, int len) throws IOException {
+        if (this.truncated) {
+            return -1;
+        }
         if (b == null) {
             return 0;
         }
@@ -136,6 +150,9 @@
     
     @Override
     public int read(final byte[] b) throws IOException {
+        if (this.truncated) {
+            return -1;
+        }
         if (b == null) {
             return 0;
         }
@@ -153,6 +170,9 @@
         if (dst == null) {
             throw new IllegalArgumentException("Buffer may not be null");
         }
+        if (this.truncated) {
+            return -1;
+        }
         int total = 0;
         boolean found = false;
         int bytesRead = 0;

Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberInputStream.java?rev=740712&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberInputStream.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberInputStream.java Wed Feb  4 12:17:29 2009
@@ -0,0 +1,67 @@
+/****************************************************************
+ * 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.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * <code>InputStream</code> used by the parser to wrap the original user
+ * supplied stream. This stream keeps track of the current line number.
+ */
+public class LineNumberInputStream extends FilterInputStream implements
+        LineNumberSource {
+    private int lineNumber = 1;
+
+    /**
+     * Creates a new <code>LineNumberInputStream</code>.
+     * 
+     * @param is
+     *            the stream to read from.
+     */
+    public LineNumberInputStream(InputStream is) {
+        super(is);
+    }
+
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
+    @Override
+    public int read() throws IOException {
+        int b = in.read();
+        if (b == '\n') {
+            lineNumber++;
+        }
+        return b;
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        int n = in.read(b, off, len);
+        for (int i = off; i < off + n; i++) {
+            if (b[i] == '\n') {
+                lineNumber++;
+            }
+        }
+        return n;
+    }
+}

Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberSource.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberSource.java?rev=740712&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberSource.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/io/LineNumberSource.java Wed Feb  4 12:17:29 2009
@@ -0,0 +1,30 @@
+/****************************************************************
+ * 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.io;
+
+public interface LineNumberSource {
+    /**
+     * Gets the current line number starting at 1 (the number of
+     * <code>\r\n</code> read so far plus 1).
+     * 
+     * @return the current line number.
+     */
+    int getLineNumber();
+}

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java Wed Feb  4 12:17:29 2009
@@ -117,6 +117,10 @@
         return result;
     }
 
+    /**
+     * Returns the current line number or <code>-1</code> if line number
+     * information is not available.
+     */
     protected abstract int getLineNumber();
     
     protected abstract LineReaderInputStream getDataStream();
@@ -308,15 +312,18 @@
      * or for logging
      */
     protected String message(Event event) {
-        String preamble = "Line " + getLineNumber() + ": ";
         final String message;
         if (event == null) {
             message = "Event is unexpectedly null.";
         } else {
             message = event.toString();
         }
-        final String result = preamble + message;
-        return result;
+
+        int lineNumber = getLineNumber();
+        if (lineNumber <= 0)
+            return message;
+        else
+            return "Line " + lineNumber + ": " + message;
     }
     
     /**

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java Wed Feb  4 12:17:29 2009
@@ -28,10 +28,10 @@
 import org.apache.james.mime4j.descriptor.BodyDescriptor;
 import org.apache.james.mime4j.io.BufferedLineReaderInputStream;
 import org.apache.james.mime4j.io.LimitedInputStream;
+import org.apache.james.mime4j.io.LineNumberSource;
 import org.apache.james.mime4j.io.LineReaderInputStream;
 import org.apache.james.mime4j.io.LineReaderInputStreamAdaptor;
 import org.apache.james.mime4j.io.MimeBoundaryInputStream;
-import org.apache.james.mime4j.io.RootInputStream;
 import org.apache.james.mime4j.util.MimeUtil;
 
 public class MimeEntity extends AbstractEntity {
@@ -45,7 +45,7 @@
      */
     private static final int T_IN_MESSAGE = -3;
 
-    private final RootInputStream rootStream;
+    private final LineNumberSource lineSource;
     private final BufferedLineReaderInputStream inbuffer;
     
     private int recursionMode;
@@ -56,14 +56,14 @@
     private byte[] tmpbuf;
     
     public MimeEntity(
-            RootInputStream rootStream,
+            LineNumberSource lineSource,
             BufferedLineReaderInputStream inbuffer,
             BodyDescriptor parent, 
             int startState, 
             int endState,
             MimeEntityConfig config) {
         super(parent, startState, endState, config);
-        this.rootStream = rootStream;
+        this.lineSource = lineSource;
         this.inbuffer = inbuffer;
         this.dataStream = new LineReaderInputStreamAdaptor(
                 inbuffer,
@@ -72,12 +72,12 @@
     }
 
     public MimeEntity(
-            RootInputStream rootStream,
+            LineNumberSource lineSource,
             BufferedLineReaderInputStream inbuffer,
             BodyDescriptor parent, 
             int startState, 
             int endState) {
-        this(rootStream, inbuffer, parent, startState, endState, 
+        this(lineSource, inbuffer, parent, startState, endState, 
                 new MimeEntityConfig());
     }
 
@@ -99,7 +99,10 @@
     
     @Override
     protected int getLineNumber() {
-        return rootStream.getLineNumber();
+        if (lineSource == null)
+            return -1;
+        else
+            return lineSource.getLineNumber();
     }
     
     @Override
@@ -255,7 +258,7 @@
             return message;
         } else {
             MimeEntity message = new MimeEntity(
-                    rootStream, 
+                    lineSource, 
                     new BufferedLineReaderInputStream(
                             instream, 
                             4 * 1024,
@@ -279,7 +282,7 @@
                     4 * 1024,
                     config.getMaxLineLen());
             MimeEntity mimeentity = new MimeEntity(
-                    rootStream, 
+                    lineSource, 
                     stream,
                     body, 
                     EntityStates.T_START_BODYPART, 

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java Wed Feb  4 12:17:29 2009
@@ -31,6 +31,7 @@
     private int maxLineLen;
     private int maxHeaderCount;
     private long maxContentLen;
+    private boolean countLineNumbers;
     
     public MimeEntityConfig() {
         this.maximalBodyDescriptor = false;
@@ -38,6 +39,7 @@
         this.maxLineLen = 1000;
         this.maxHeaderCount = 1000;
         this.maxContentLen = -1;
+        this.countLineNumbers = false;
     }
     
     public boolean isMaximalBodyDescriptor() {
@@ -137,6 +139,26 @@
         return maxContentLen;
     }
 
+    /**
+     * Defines whether the parser should count line numbers. If enabled line
+     * numbers are included in the debug output.
+     * 
+     * @param countLineNumbers
+     *            value of the line number counting mode.
+     */
+    public void setCountLineNumbers(boolean countLineNumbers) {
+        this.countLineNumbers = countLineNumbers;
+    }
+
+    /**
+     * Returns the value of the line number counting mode.
+     * 
+     * @return value of the line number counting mode.
+     */
+    public boolean isCountLineNumbers() {
+        return countLineNumbers;
+    }
+
     @Override
     public MimeEntityConfig clone() {
         try {
@@ -149,15 +171,11 @@
     
     @Override
     public String toString() {
-        StringBuilder buffer = new StringBuilder(128);
-        buffer.append("[max body descriptor: ");
-        buffer.append(Boolean.toString(this.maximalBodyDescriptor));
-        buffer.append("][strict parsing: ");
-        buffer.append(Boolean.toString(this.strictParsing));
-        buffer.append("][max header length: ");
-        buffer.append(Integer.toString(this.maxLineLen));
-        buffer.append("]");
-        return buffer.toString();
+        return "[max body descriptor: " + maximalBodyDescriptor
+                + ", strict parsing: " + strictParsing + ", max line length: "
+                + maxLineLen + ", max header count: " + maxHeaderCount
+                + ", max content length: " + maxContentLen
+                + ", count line numbers: " + countLineNumbers + "]";
     }
     
 }

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java Wed Feb  4 12:17:29 2009
@@ -33,7 +33,8 @@
 import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
 import org.apache.james.mime4j.descriptor.BodyDescriptor;
 import org.apache.james.mime4j.io.BufferedLineReaderInputStream;
-import org.apache.james.mime4j.io.RootInputStream;
+import org.apache.james.mime4j.io.LineNumberInputStream;
+import org.apache.james.mime4j.io.LineNumberSource;
 import org.apache.james.mime4j.util.CharsetUtil;
 import org.apache.james.mime4j.util.MimeUtil;
 
@@ -106,7 +107,6 @@
     private EntityStateMachine currentStateMachine;
     private int recursionMode = M_RECURSE;
     private BufferedLineReaderInputStream inbuffer;
-    private RootInputStream rootInputStream;
     
     /**
      * Constructs a standard (lax) stream.
@@ -149,9 +149,16 @@
 
     private void doParse(InputStream stream, String contentType) {
         entities.clear();
-        rootInputStream = new RootInputStream(stream);
+
+        LineNumberSource lineSource = null;
+        if (config.isCountLineNumbers()) {
+            LineNumberInputStream lineInput = new LineNumberInputStream(stream);
+            lineSource = lineInput;
+            stream = lineInput;
+        }
+
         inbuffer = new BufferedLineReaderInputStream(
-                rootInputStream, 
+                stream, 
                 4 * 1024,
                 config.getMaxLineLen());
         switch (recursionMode) {
@@ -164,7 +171,7 @@
             // expected to be called only at start of paring
         case M_RECURSE:
             MimeEntity mimeentity = new MimeEntity(
-                    rootInputStream,
+                    lineSource,
                     inbuffer,
                     null, 
                     T_START_MESSAGE, 
@@ -234,8 +241,7 @@
      * {@link ContentHandler#startMessage()}, etc.
      */
     public void stop() {
-        inbuffer.clear();
-        rootInputStream.truncate();
+        inbuffer.truncate();
     }
 
     /**

Added: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java?rev=740712&view=auto
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java (added)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java Wed Feb  4 12:17:29 2009
@@ -0,0 +1,81 @@
+/****************************************************************
+ * 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.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.apache.james.mime4j.io.LineNumberInputStream;
+
+import junit.framework.TestCase;
+
+public class LineNumberInputStreamTest extends TestCase {
+    /**
+     * Tests that reading single bytes updates the line number appropriately.
+     */
+    public void testReadSingleByte() throws IOException {
+        String s = "Yada\r\nyada\r\nyada\r\n";
+        LineNumberInputStream is = new LineNumberInputStream(
+                new ByteArrayInputStream(s.getBytes()));
+
+        for (int i = 0; i < 6; i++) {
+            assertEquals(1, is.getLineNumber());
+            is.read();
+        }
+
+        for (int i = 6; i < 12; i++) {
+            assertEquals(2, is.getLineNumber());
+            is.read();
+        }
+
+        for (int i = 12; i < 18; i++) {
+            assertEquals(3, is.getLineNumber());
+            is.read();
+        }
+
+        assertEquals(4, is.getLineNumber());
+        assertEquals(-1, is.read());
+    }
+
+    /**
+     * Tests that reading multiple bytes at once updates the line number
+     * appropriately.
+     */
+    public void testReadManyBytes() throws IOException {
+        String s = "Yada\r\nyada\r\nyada\r\n";
+        LineNumberInputStream is = new LineNumberInputStream(
+                new ByteArrayInputStream(s.getBytes()));
+
+        byte[] buf = new byte[4];
+        assertEquals(1, is.getLineNumber());
+        is.read(buf);
+        assertEquals(1, is.getLineNumber());
+        is.read(buf);
+        assertEquals(2, is.getLineNumber());
+        is.read(buf);
+        assertEquals(3, is.getLineNumber());
+        is.read(buf);
+        assertEquals(3, is.getLineNumber());
+        is.read(buf);
+        assertEquals(4, is.getLineNumber());
+
+        assertEquals(-1, is.read());
+    }
+}

Propchange: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/io/LineNumberInputStreamTest.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java?rev=740712&r1=740711&r2=740712&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java Wed Feb  4 12:17:29 2009
@@ -26,7 +26,7 @@
 import org.apache.james.mime4j.io.BufferedLineReaderInputStream;
 import org.apache.james.mime4j.io.MaxHeaderLimitException;
 import org.apache.james.mime4j.io.MaxLineLimitException;
-import org.apache.james.mime4j.io.RootInputStream;
+import org.apache.james.mime4j.io.LineNumberInputStream;
 import org.apache.james.mime4j.parser.EntityStateMachine;
 import org.apache.james.mime4j.parser.EntityStates;
 import org.apache.james.mime4j.parser.MimeEntity;
@@ -47,11 +47,11 @@
             "a very important message";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 12); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 12); 
         
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -134,11 +134,11 @@
             "Goodbye!";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 24); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 24); 
         
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -247,11 +247,11 @@
             "Goodbye!";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 24); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 24); 
         
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -344,13 +344,13 @@
             "a very important message";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 12); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 12); 
         
         MimeEntityConfig config = new MimeEntityConfig();
         config.setMaxLineLen(50);
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -398,13 +398,13 @@
             "a very important message";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 12); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 12); 
         
         MimeEntityConfig config = new MimeEntityConfig();
         config.setMaxLineLen(50);
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -456,13 +456,13 @@
             "a very important message";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 12); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 12); 
         
         MimeEntityConfig config = new MimeEntityConfig();
         config.setMaxHeaderCount(20);
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,
@@ -504,13 +504,13 @@
             "DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS DoS\r\n";
         byte[] raw = message.getBytes("US-ASCII");
         ByteArrayInputStream instream = new ByteArrayInputStream(raw);
-        RootInputStream rootStream = new RootInputStream(instream); 
-        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(rootStream, 12); 
+        LineNumberInputStream lineInput = new LineNumberInputStream(instream); 
+        BufferedLineReaderInputStream rawstream = new BufferedLineReaderInputStream(lineInput, 12); 
         
         MimeEntityConfig config = new MimeEntityConfig();
         config.setMaxContentLen(100);
         MimeEntity entity = new MimeEntity(
-                rootStream,
+                lineInput,
                 rawstream,
                 null,
                 EntityStates.T_START_MESSAGE,