Skip to content
Commits on Source (16)
......@@ -3,3 +3,5 @@
.settings
target
maven-eclipse.xml
.idea/
*.iml
\ No newline at end of file
// ------------------------------------------------------------------
// Transitive dependencies of this project determined from the
// maven pom organized by organization.
// ------------------------------------------------------------------
Apache JAMES Mime4j Project
Release 0.9.0
-------------------
Fix MIME4J-262 without breaking compatibility with old code by deprecating MessageBuilder and adding Message.Builder
Message.Builder produce message for which the getDate method return null if and only if the message do not have a "Date"
header. Whereas MessageBuilder will produce message for which the getDate method never return null: if the message has
no "Date" header the returned value is "new Date()" result when the message has been instantiated
Release 0.7.2
-------------------
......
......@@ -23,30 +23,27 @@
<parent>
<artifactId>apache-mime4j-project</artifactId>
<groupId>org.apache.james</groupId>
<version>0.7.2</version>
<version>0.8.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>apache-mime4j</artifactId>
<packaging>pom</packaging>
<name>Apache JAMES Mime4j (Assembly)</name>
<name>Apache James :: Mime4j :: Assembly</name>
<dependencies>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-examples</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-benchmark</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
......@@ -65,41 +62,14 @@
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal> <!-- goals == mojos -->
<goal>attached</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>site-reports</id>
<build>
<pluginManagement>
<plugins>
<!--
Disable generation of technical reports for 'pom' project, because
of following problems:
- site-plugin configuration can't be overwritten yet
(https://jira.codehaus.org/browse/MSITE-484)
- cobertura-plugin fails with NPE
(http://jira.codehaus.org/browse/MCOBERTURA-148)
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<generateReports>false</generateReports>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
</project>
\ No newline at end of file
......@@ -23,25 +23,24 @@
<parent>
<artifactId>apache-mime4j-project</artifactId>
<groupId>org.apache.james</groupId>
<version>0.7.2</version>
<version>0.8.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>apache-mime4j-benchmark</artifactId>
<packaging>bundle</packaging>
<name>Apache JAMES Mime4j (Benchmarks)</name>
<name>Apache James :: Mime4j :: Benchmarks</name>
<description>Benchmarks for MIME4J stream based MIME message parser</description>
<dependencies>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-dom</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.james</groupId>
<artifactId>apache-mime4j-storage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
......@@ -50,8 +49,6 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<optional>false</optional>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
......@@ -28,7 +28,8 @@ import java.util.Random;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.james.mime4j.codec.Base64InputStream;
import org.apache.james.mime4j.codec.CodecUtil;
import org.apache.james.mime4j.codec.EncoderUtil;
import org.apache.james.mime4j.util.ContentUtil;
public class Base64InputStreamBench {
......@@ -47,7 +48,7 @@ public class Base64InputStreamBench {
for (int i = 0; i < 5; i++) {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new Base64InputStream(ed);
CodecUtil.copy(in, nullOut);
ContentUtil.copy(in, nullOut);
}
Thread.sleep(100);
......@@ -59,7 +60,7 @@ public class Base64InputStreamBench {
for (int i = 0; i < repetitions; i++) {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new Base64InputStream(ed);
CodecUtil.copy(in, nullOut);
ContentUtil.copy(in, nullOut);
}
long dt = System.currentTimeMillis() - t0;
......@@ -82,7 +83,7 @@ public class Base64InputStreamBench {
private static byte[] encode(byte[] data) throws IOException {
InputStream in = new ByteArrayInputStream(data);
ByteArrayOutputStream out = new ByteArrayOutputStream();
CodecUtil.encodeBase64(in, out);
EncoderUtil.encodeB(in, out);
return out.toByteArray();
}
......@@ -91,7 +92,7 @@ public class Base64InputStreamBench {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new Base64InputStream(ed);
ByteArrayOutputStream out = new ByteArrayOutputStream();
CodecUtil.copy(in, out);
ContentUtil.copy(in, out);
compare(data, out.toByteArray());
}
......
......@@ -24,7 +24,6 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.james.mime4j.codec.CodecUtil;
import org.apache.james.mime4j.dom.Header;
import org.apache.james.mime4j.dom.MessageBuilder;
import org.apache.james.mime4j.message.DefaultMessageBuilder;
......@@ -37,6 +36,7 @@ import org.apache.james.mime4j.storage.MemoryStorageProvider;
import org.apache.james.mime4j.stream.BodyDescriptor;
import org.apache.james.mime4j.stream.EntityState;
import org.apache.james.mime4j.stream.MimeTokenStream;
import org.apache.james.mime4j.util.ContentUtil;
public class LongMultipartReadBench {
......@@ -107,7 +107,7 @@ public class LongMultipartReadBench {
return null;
}
try {
CodecUtil.copy(instream, outstream);
ContentUtil.copy(instream, outstream);
} finally {
instream.close();
}
......
......@@ -27,8 +27,9 @@ import java.io.OutputStream;
import java.util.Random;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.james.mime4j.codec.CodecUtil;
import org.apache.james.mime4j.codec.EncoderUtil;
import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
import org.apache.james.mime4j.util.ContentUtil;
public class QuotedPrintableInputStreamBench {
......@@ -47,7 +48,7 @@ public class QuotedPrintableInputStreamBench {
for (int i = 0; i < 5; i++) {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new QuotedPrintableInputStream(ed);
CodecUtil.copy(in, nullOut);
ContentUtil.copy(in, nullOut);
}
Thread.sleep(100);
......@@ -59,7 +60,7 @@ public class QuotedPrintableInputStreamBench {
for (int i = 0; i < repetitions; i++) {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new QuotedPrintableInputStream(ed);
CodecUtil.copy(in, nullOut);
ContentUtil.copy(in, nullOut);
}
long dt = System.currentTimeMillis() - t0;
......@@ -82,7 +83,7 @@ public class QuotedPrintableInputStreamBench {
private static byte[] encode(byte[] data) throws IOException {
InputStream in = new ByteArrayInputStream(data);
ByteArrayOutputStream out = new ByteArrayOutputStream();
CodecUtil.encodeQuotedPrintableBinary(in, out);
EncoderUtil.encodeQBinary(in, out);
return out.toByteArray();
}
......@@ -91,7 +92,7 @@ public class QuotedPrintableInputStreamBench {
ByteArrayInputStream ed = new ByteArrayInputStream(encoded);
InputStream in = new QuotedPrintableInputStream(ed);
ByteArrayOutputStream out = new ByteArrayOutputStream();
CodecUtil.copy(in, out);
ContentUtil.copy(in, out);
compare(data, out.toByteArray());
}
......
......@@ -23,28 +23,24 @@
<parent>
<artifactId>apache-mime4j-project</artifactId>
<groupId>org.apache.james</groupId>
<version>0.7.2</version>
<version>0.8.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>apache-mime4j-core</artifactId>
<packaging>bundle</packaging>
<name>Apache JAMES Mime4j (Core)</name>
<name>Apache James :: Mime4j :: Core</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<type>jar</type>
<!-- Removed as a workaround for an unidentified M2 bug -->
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
......
/****************************************************************
* 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;
import java.nio.charset.Charset;
public final class Charsets {
public static final Charset US_ASCII = Charset.forName("US-ASCII");
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
public static final Charset UTF_8 = Charset.forName("UTF-8");
public static final Charset DEFAULT_CHARSET = US_ASCII;
}
......@@ -133,7 +133,6 @@ public class Base64InputStream extends InputStream {
}
private int read0(final byte[] buffer, final int off, final int len) throws IOException {
int from = off;
int to = off + len;
int index = off;
......@@ -148,7 +147,7 @@ public class Base64InputStream extends InputStream {
// eof or pad reached?
if (eof)
return index == from ? EOF : index - from;
return index == off ? EOF : index - off;
// decode into given buffer
......@@ -168,7 +167,7 @@ public class Base64InputStream extends InputStream {
handleUnexpectedEof(sextets);
}
return index == from ? EOF : index - from;
return index == off ? EOF : index - off;
} else if (n > 0) {
position = 0;
size = n;
......@@ -184,7 +183,7 @@ public class Base64InputStream extends InputStream {
if (value == BASE64_PAD) {
index = decodePad(data, sextets, buffer, index, to);
return index - from;
return index - off;
}
int decoded = BASE64_DECODE[value];
......@@ -226,7 +225,7 @@ public class Base64InputStream extends InputStream {
}
assert index == to;
return to - from;
return to - off;
}
}
}
......@@ -234,7 +233,7 @@ public class Base64InputStream extends InputStream {
assert sextets == 0;
assert index == to;
return to - from;
return to - off;
}
private int decodePad(int data, int sextets, final byte[] buffer,
......
......@@ -19,14 +19,14 @@
package org.apache.james.mime4j.codec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.james.mime4j.io.InputStreams;
import org.apache.james.mime4j.util.ByteArrayBuffer;
import org.apache.james.mime4j.util.CharsetUtil;
/**
......@@ -44,24 +44,23 @@ public class DecoderUtil {
* @return the decoded bytes.
*/
private static byte[] decodeQuotedPrintable(String s, DecodeMonitor monitor) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] bytes = s.getBytes("US-ASCII");
QuotedPrintableInputStream is = new QuotedPrintableInputStream(
new ByteArrayInputStream(bytes), monitor);
int b = 0;
InputStreams.createAscii(s), monitor);
try {
ByteArrayBuffer buf = new ByteArrayBuffer(s.length());
int b;
while ((b = is.read()) != -1) {
baos.write(b);
buf.append(b);
}
return buf.toByteArray();
} finally {
is.close();
}
} catch (IOException e) {
} catch (IOException ex) {
// This should never happen!
throw new IllegalStateException(e);
throw new Error(ex);
}
return baos.toByteArray();
}
/**
......@@ -72,24 +71,23 @@ public class DecoderUtil {
* @return the decoded bytes.
*/
private static byte[] decodeBase64(String s, DecodeMonitor monitor) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] bytes = s.getBytes("US-ASCII");
Base64InputStream is = new Base64InputStream(
new ByteArrayInputStream(bytes), monitor);
int b = 0;
InputStreams.createAscii(s), monitor);
try {
ByteArrayBuffer buf = new ByteArrayBuffer(s.length());
int b;
while ((b = is.read()) != -1) {
baos.write(b);
buf.append(b);
}
return buf.toByteArray();
} finally {
is.close();
}
} catch (IOException e) {
} catch (IOException ex) {
// This should never happen!
throw new IllegalStateException(e);
throw new Error(ex);
}
return baos.toByteArray();
}
/**
......@@ -142,6 +140,38 @@ public class DecoderUtil {
* @throws IllegalArgumentException only if the DecodeMonitor strategy throws it (Strict parsing)
*/
public static String decodeEncodedWords(String body, DecodeMonitor monitor) throws IllegalArgumentException {
return decodeEncodedWords(body, monitor, null);
}
/**
* Decodes a string containing encoded words as defined by RFC 2047. Encoded
* words have the form =?charset?enc?encoded-text?= where enc is either 'Q'
* or 'q' for quoted-printable and 'B' or 'b' for base64. Using fallback
* charset if charset in encoded words is invalid.
*
* @param body the string to decode
* @param fallback the fallback Charset to be used.
* @return the decoded string.
* @throws IllegalArgumentException only if the DecodeMonitor strategy throws it (Strict parsing)
*/
public static String decodeEncodedWords(String body, Charset fallback) throws IllegalArgumentException {
return decodeEncodedWords(body, null, fallback);
}
/**
* Decodes a string containing encoded words as defined by RFC 2047. Encoded
* words have the form =?charset?enc?encoded-text?= where enc is either 'Q'
* or 'q' for quoted-printable and 'B' or 'b' for base64. Using fallback
* charset if charset in encoded words is invalid.
*
* @param body the string to decode
* @param monitor the DecodeMonitor to be used.
* @param fallback the fallback Charset to be used.
* @return the decoded string.
* @throws IllegalArgumentException only if the DecodeMonitor strategy throws it (Strict parsing)
*/
public static String decodeEncodedWords(String body, DecodeMonitor monitor, Charset fallback)
throws IllegalArgumentException {
int tailIndex = 0;
boolean lastMatchValid = false;
......@@ -153,8 +183,8 @@ public class DecoderUtil {
String encoding = matcher.group(3);
String encodedText = matcher.group(4);
String decoded = null;
decoded = tryDecodeEncodedWord(mimeCharset, encoding, encodedText, monitor);
String decoded;
decoded = tryDecodeEncodedWord(mimeCharset, encoding, encodedText, monitor, fallback);
if (decoded == null) {
sb.append(matcher.group(0));
} else {
......@@ -178,12 +208,16 @@ public class DecoderUtil {
// return null on error
private static String tryDecodeEncodedWord(final String mimeCharset,
final String encoding, final String encodedText, final DecodeMonitor monitor) {
final String encoding, final String encodedText, final DecodeMonitor monitor, final Charset fallback) {
Charset charset = CharsetUtil.lookup(mimeCharset);
if (charset == null) {
if(fallback == null) {
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
"Mime charser '", mimeCharset, "' doesn't have a corresponding Java charset");
return null;
} else {
charset = fallback;
}
}
if (encodedText.length() == 0) {
......
......@@ -19,12 +19,17 @@
package org.apache.james.mime4j.codec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.BitSet;
import java.util.Locale;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.util.CharsetUtil;
import org.apache.james.mime4j.util.ContentUtil;
/**
* Static methods for encoding header field values. This includes encoded-words
......@@ -380,10 +385,8 @@ public class EncoderUtil {
: Q_RESTRICTED_CHARS;
StringBuilder sb = new StringBuilder();
final int end = bytes.length;
for (int idx = 0; idx < end; idx++) {
int v = bytes[idx] & 0xff;
for (byte aByte : bytes) {
int v = aByte & 0xff;
if (v == 32) {
sb.append('_');
} else if (!qChars.get(v)) {
......@@ -398,6 +401,47 @@ public class EncoderUtil {
return sb.toString();
}
/**
* Encodes the given stream using Quoted-Printable.
* This assumes that stream is binary and therefore escapes
* all line endings.
* @param in not null
* @param out not null
* @throws IOException
*/
public static void encodeQBinary(final InputStream in, final OutputStream out) throws IOException {
QuotedPrintableOutputStream qpOut = new QuotedPrintableOutputStream(out, true);
ContentUtil.copy(in, qpOut);
qpOut.close();
}
/**
* Encodes the given stream using Quoted-Printable.
* This assumes that stream is text and therefore does not escape
* all line endings.
* @param in not null
* @param out not null
* @throws IOException
*/
public static void encodeQ(final InputStream in, final OutputStream out) throws IOException {
QuotedPrintableOutputStream qpOut = new QuotedPrintableOutputStream(out, false);
ContentUtil.copy(in, qpOut);
qpOut.close();
}
/**
* Encodes the given stream using base64.
*
* @param in not null
* @param out not null
* @throws IOException if an I/O error occurs
*/
public static void encodeB(final InputStream in, final OutputStream out) throws IOException {
Base64OutputStream b64Out = new Base64OutputStream(out);
ContentUtil.copy(in, b64Out);
b64Out.close();
}
/**
* Tests whether the specified string is a token as defined in RFC 2045
* section 5.1.
......@@ -540,8 +584,8 @@ public class EncoderUtil {
int count = 0;
for (int idx = 0; idx < bytes.length; idx++) {
int v = bytes[idx] & 0xff;
for (byte aByte : bytes) {
int v = aByte & 0xff;
if (v == 32) {
count++;
} else if (!qChars.get(v)) {
......@@ -569,13 +613,13 @@ public class EncoderUtil {
for (int index = 0; index < len; index++) {
char ch = text.charAt(index);
if (ch > 0xff) {
return CharsetUtil.UTF_8;
return Charsets.UTF_8;
}
if (ch > 0x7f) {
ascii = false;
}
}
return ascii ? CharsetUtil.US_ASCII : CharsetUtil.ISO_8859_1;
return ascii ? Charsets.US_ASCII : Charsets.ISO_8859_1;
}
private static Encoding determineEncoding(byte[] bytes, Usage usage) {
......@@ -586,8 +630,8 @@ public class EncoderUtil {
: Q_RESTRICTED_CHARS;
int qEncoded = 0;
for (int i = 0; i < bytes.length; i++) {
int v = bytes[i] & 0xff;
for (byte aByte : bytes) {
int v = aByte & 0xff;
if (v != 32 && !qChars.get(v)) {
qEncoded++;
}
......
......@@ -45,6 +45,7 @@ public class QuotedPrintableInputStream extends InputStream {
private int pos = 0; // current index into encoded buffer
private int limit = 0; // current size of encoded buffer
private boolean lastWasCR = false;
private boolean closed;
private final DecodeMonitor monitor;
......@@ -141,7 +142,7 @@ public class QuotedPrintableInputStream extends InputStream {
blanks.clear();
} else if (blanks.length() > 0 && !keepblanks) {
StringBuilder sb = new StringBuilder(blanks.length() * 3);
for (int i = 0; i < blanks.length(); i++) sb.append(" "+blanks.byteAt(i));
for (int i = 0; i < blanks.length(); i++) sb.append(" ").append(blanks.byteAt(i));
if (monitor.warn("ignored blanks", sb.toString()))
throw new IOException("ignored blanks");
}
......@@ -157,7 +158,6 @@ public class QuotedPrintableInputStream extends InputStream {
private int read0(final byte[] buffer, final int off, final int len) throws IOException {
boolean eof = false;
int from = off;
int to = off + len;
int index = off;
......@@ -178,21 +178,22 @@ public class QuotedPrintableInputStream extends InputStream {
// end of stream?
if (limit - pos == 0 && eof) {
return index == from ? -1 : index - from;
return index == off ? -1 : index - off;
}
boolean lastWasCR = false;
while (pos < limit && index < to) {
int b = encoded[pos++] & 0xFF;
if (lastWasCR && b != LF) {
if (monitor.warn("Found CR without LF", "Leaving it as is"))
if (monitor.warn("Found CR without LF", "Leaving it as is")) {
throw new IOException("Found CR without LF");
}
index = transfer(CR, buffer, index, to, false);
} else if (!lastWasCR && b == LF) {
if (monitor.warn("Found LF without CR", "Translating to CRLF"))
if (monitor.warn("Found LF without CR", "Translating to CRLF")) {
throw new IOException("Found LF without CR");
}
}
if (b == CR) {
lastWasCR = true;
......@@ -236,6 +237,15 @@ public class QuotedPrintableInputStream extends InputStream {
}
} else if (Character.isWhitespace((char) b2)) {
// soft line break
int b3 = peek(0);
if (!(b2 == CR && b3 == LF)) {
if (monitor.warn("Found non-standard soft line break", "Translating to soft line break")) {
throw new IOException("Non-standard soft line break");
}
}
if (b3 == LF) {
lastWasCR = b2 == CR;
}
index = transfer(-1, buffer, index, to, true);
if (b2 != LF) {
blanks.append(b);
......@@ -258,11 +268,11 @@ public class QuotedPrintableInputStream extends InputStream {
} else if (Character.isWhitespace(b)) {
blanks.append(b);
} else {
index = transfer((int) b & 0xFF, buffer, index, to, true);
index = transfer(b & 0xFF, buffer, index, to, true);
}
}
}
return to - from;
return to - off;
}
/**
......
......@@ -58,7 +58,7 @@ public class QuotedPrintableOutputStream extends FilterOutputStream {
private boolean closed = false;
private byte[] singleByte = new byte[1];
private final byte[] singleByte = new byte[1];
public QuotedPrintableOutputStream(int bufsize, OutputStream out, boolean binary) {
super(out);
......
/****************************************************************
* 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.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* {@link InputStream} backed by byte array.
*/
class BinaryInputStream extends InputStream {
private final ByteBuffer bbuf;
BinaryInputStream(final ByteBuffer b) {
super();
this.bbuf = b;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
}
if (off < 0 || len < 0 || off + len > b.length) {
throw new IndexOutOfBoundsException();
}
if (len == 0) {
return 0;
}
if (this.bbuf.hasRemaining()) {
int chunk = Math.min(this.bbuf.remaining(), len);
this.bbuf.get(b, off, chunk);
return chunk;
} else {
return -1;
}
}
@Override
public int read() throws IOException {
if (this.bbuf.hasRemaining()) {
return this.bbuf.get() & 0xFF;
} else {
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.bbuf.hasRemaining()) {
this.bbuf.get();
n--;
skipped++;
}
return skipped;
}
@Override
public int available() throws IOException {
return this.bbuf.remaining();
}
@Override
public void close() throws IOException {
}
}
......@@ -137,7 +137,7 @@ public class BufferedLineReaderInputStream extends LineReaderInputStream {
@Override
public int read() throws IOException {
if (!readAllowed()) return -1;
int noRead = 0;
int noRead;
while (!hasBufferedData()) {
noRead = fillBuffer();
if (noRead == -1) {
......@@ -153,7 +153,7 @@ public class BufferedLineReaderInputStream extends LineReaderInputStream {
if (b == null) {
return 0;
}
int noRead = 0;
int noRead;
while (!hasBufferedData()) {
noRead = fillBuffer();
if (noRead == -1) {
......@@ -215,7 +215,7 @@ public class BufferedLineReaderInputStream extends LineReaderInputStream {
total += chunk;
}
if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
throw new MaxLineLimitException("Maximum line length limit exceeded");
throw new MaxLineLimitException("Maximum line length limit (" + this.maxLineLen +") exceeded");
}
}
if (total == 0 && bytesRead == -1) {
......
/****************************************************************
* 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.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import org.apache.james.mime4j.Charsets;
import org.apache.james.mime4j.util.ByteArrayBuffer;
/**
* Factory methods for {@link InputStream} instances backed by binary or textual data that attempt
* to minimize intermediate copying while streaming data.
*/
public final class InputStreams {
private InputStreams() {
}
public static InputStream create(final byte[] b, int off, int len) {
if (b == null) {
throw new IllegalArgumentException("Byte array may not be null");
}
return new BinaryInputStream(ByteBuffer.wrap(b, off, len));
}
public static InputStream create(final byte[] b) {
if (b == null) {
throw new IllegalArgumentException("Byte array may not be null");
}
return new BinaryInputStream(ByteBuffer.wrap(b));
}
public static InputStream create(final ByteArrayBuffer b) {
if (b == null) {
throw new IllegalArgumentException("Byte array may not be null");
}
return new BinaryInputStream(ByteBuffer.wrap(b.buffer(), 0, b.length()));
}
public static InputStream create(final ByteBuffer b) {
if (b == null) {
throw new IllegalArgumentException("Byte array may not be null");
}
return new BinaryInputStream(b);
}
public static InputStream createAscii(final CharSequence s) {
if (s == null) {
throw new IllegalArgumentException("CharSequence may not be null");
}
return new TextInputStream(s, Charsets.US_ASCII, 1024);
}
public static InputStream create(final CharSequence s, final Charset charset) {
if (s == null) {
throw new IllegalArgumentException("CharSequence may not be null");
}
return new TextInputStream(s, charset != null ? charset : Charsets.DEFAULT_CHARSET, 1024);
}
}
......@@ -92,7 +92,7 @@ public class LineReaderInputStreamAdaptor extends LineReaderInputStream {
dst.append(ch);
total++;
if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
throw new MaxLineLimitException("Maximum line length limit exceeded");
throw new MaxLineLimitException("Maximum line length limit ( "+ this.maxLineLen +") exceeded");
}
if (ch == '\n') {
break;
......@@ -120,11 +120,7 @@ public class LineReaderInputStreamAdaptor extends LineReaderInputStream {
@Override
public boolean unread(ByteArrayBuffer buf) {
if (bis != null) {
return bis.unread(buf);
} else {
return false;
}
return bis != null && bis.unread(buf);
}
@Override
......
......@@ -43,7 +43,7 @@ public class MimeBoundaryInputStream extends LineReaderInputStream {
private boolean lastPart;
private boolean completed;
private BufferedLineReaderInputStream buffer;
private final BufferedLineReaderInputStream buffer;
/**
* Store the first buffer length.
......