mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-27 11:42:16 -05:00
Start building using a JAR of MIME4J
This commit is contained in:
parent
eb6e48c7bd
commit
7b2cd531ca
BIN
libs/apache-mime4j-core-0.7-SNAPSHOT.jar
Normal file
BIN
libs/apache-mime4j-core-0.7-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
libs/apache-mime4j-dom-0.7-SNAPSHOT.jar
Normal file
BIN
libs/apache-mime4j-dom-0.7-SNAPSHOT.jar
Normal file
Binary file not shown.
@ -1,65 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* MIME processing exception.
|
||||
* <p>
|
||||
* A <code>MimeException</code> may be thrown by a {@link org.apache.james.mime4j.parser.ContentHandler} to
|
||||
* indicate that it has failed to process a message event and that no further
|
||||
* events should be generated.
|
||||
* <p>
|
||||
* <code>MimeException</code> also gets thrown by the parser to indicate MIME
|
||||
* protocol errors, e.g. if a message boundary is too long or a header field
|
||||
* cannot be parsed.
|
||||
*/
|
||||
public class MimeException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 8352821278714188542L;
|
||||
|
||||
/**
|
||||
* Constructs a new MIME exception with the specified detail message.
|
||||
*
|
||||
* @param message detail message
|
||||
*/
|
||||
public MimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MIME exception with the specified cause.
|
||||
*
|
||||
* @param cause cause of the exception
|
||||
*/
|
||||
public MimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MIME exception with the specified detail message and cause.
|
||||
*
|
||||
* @param message detail message
|
||||
* @param cause cause of the exception
|
||||
*/
|
||||
public MimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.io.IOException;
|
||||
|
||||
/**
|
||||
* A wrapper class based on {@link IOException} for MIME protocol exceptions.
|
||||
* <p>
|
||||
* This exception is used to signal a <code>MimeException</code> in methods
|
||||
* that only permit <code>IOException</code> to be thrown.
|
||||
* <p>
|
||||
* The cause of a <code>MimeIOException</code> is always a
|
||||
* <code>MimeException</code> therefore.
|
||||
*/
|
||||
public class MimeIOException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 5393613459533735409L;
|
||||
|
||||
/**
|
||||
* Constructs an IO exception based on {@link MimeException}.
|
||||
*
|
||||
* @param cause the cause.
|
||||
*/
|
||||
public MimeIOException(MimeException cause) {
|
||||
super(cause == null ? null : cause.getMessage());
|
||||
initCause(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>MimeException</code> that caused this
|
||||
* <code>MimeIOException</code>.
|
||||
*
|
||||
* @return the cause of this <code>MimeIOException</code>.
|
||||
*/
|
||||
@Override
|
||||
public MimeException getCause() {
|
||||
return (MimeException) super.getCause();
|
||||
}
|
||||
|
||||
}
|
@ -1,286 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.james.mime4j.util.ByteArrayBuffer;
|
||||
|
||||
/**
|
||||
* Performs Base-64 decoding on an underlying stream.
|
||||
*/
|
||||
public class Base64InputStream extends InputStream {
|
||||
private static final int ENCODED_BUFFER_SIZE = 1536;
|
||||
|
||||
private static final int[] BASE64_DECODE = new int[256];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < 256; i++)
|
||||
BASE64_DECODE[i] = -1;
|
||||
for (int i = 0; i < Base64OutputStream.BASE64_TABLE.length; i++)
|
||||
BASE64_DECODE[Base64OutputStream.BASE64_TABLE[i] & 0xff] = i;
|
||||
}
|
||||
|
||||
private static final byte BASE64_PAD = '=';
|
||||
|
||||
private static final int EOF = -1;
|
||||
|
||||
private final byte[] singleByte = new byte[1];
|
||||
|
||||
private final InputStream in;
|
||||
private final byte[] encoded;
|
||||
private final ByteArrayBuffer decodedBuf;
|
||||
|
||||
private int position = 0; // current index into encoded buffer
|
||||
private int size = 0; // current size of encoded buffer
|
||||
|
||||
private boolean closed = false;
|
||||
private boolean eof; // end of file or pad character reached
|
||||
|
||||
private final DecodeMonitor monitor;
|
||||
|
||||
public Base64InputStream(InputStream in, DecodeMonitor monitor) {
|
||||
this(ENCODED_BUFFER_SIZE, in, monitor);
|
||||
}
|
||||
|
||||
protected Base64InputStream(int bufsize, InputStream in, DecodeMonitor monitor) {
|
||||
if (in == null)
|
||||
throw new IllegalArgumentException();
|
||||
this.encoded = new byte[bufsize];
|
||||
this.decodedBuf = new ByteArrayBuffer(512);
|
||||
this.in = in;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
public Base64InputStream(InputStream in) {
|
||||
this(in, false);
|
||||
}
|
||||
|
||||
public Base64InputStream(InputStream in, boolean strict) {
|
||||
this(ENCODED_BUFFER_SIZE, in, strict ? DecodeMonitor.STRICT : DecodeMonitor.SILENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Stream has been closed");
|
||||
|
||||
while (true) {
|
||||
int bytes = read0(singleByte, 0, 1);
|
||||
if (bytes == EOF)
|
||||
return EOF;
|
||||
|
||||
if (bytes == 1)
|
||||
return singleByte[0] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer) throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Stream has been closed");
|
||||
|
||||
if (buffer == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
if (buffer.length == 0)
|
||||
return 0;
|
||||
|
||||
return read0(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Stream has been closed");
|
||||
|
||||
if (buffer == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
if (offset < 0 || length < 0 || offset + length > buffer.length)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
return read0(buffer, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
closed = true;
|
||||
}
|
||||
|
||||
private int read0(final byte[] buffer, final int off, final int len) throws IOException {
|
||||
int from = off;
|
||||
int to = off + len;
|
||||
int index = off;
|
||||
|
||||
// check if a previous invocation left decoded content
|
||||
if (decodedBuf.length() > 0) {
|
||||
int chunk = Math.min(decodedBuf.length(), len);
|
||||
System.arraycopy(decodedBuf.buffer(), 0, buffer, index, chunk);
|
||||
decodedBuf.remove(0, chunk);
|
||||
index += chunk;
|
||||
}
|
||||
|
||||
// eof or pad reached?
|
||||
|
||||
if (eof)
|
||||
return index == from ? EOF : index - from;
|
||||
|
||||
// decode into given buffer
|
||||
|
||||
int data = 0; // holds decoded data; up to four sextets
|
||||
int sextets = 0; // number of sextets
|
||||
|
||||
while (index < to) {
|
||||
// make sure buffer not empty
|
||||
|
||||
while (position == size) {
|
||||
int n = in.read(encoded, 0, encoded.length);
|
||||
if (n == EOF) {
|
||||
eof = true;
|
||||
|
||||
if (sextets != 0) {
|
||||
// error in encoded data
|
||||
handleUnexpectedEof(sextets);
|
||||
}
|
||||
|
||||
return index == from ? EOF : index - from;
|
||||
} else if (n > 0) {
|
||||
position = 0;
|
||||
size = n;
|
||||
} else {
|
||||
assert n == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// decode buffer
|
||||
|
||||
while (position < size && index < to) {
|
||||
int value = encoded[position++] & 0xff;
|
||||
|
||||
if (value == BASE64_PAD) {
|
||||
index = decodePad(data, sextets, buffer, index, to);
|
||||
return index - from;
|
||||
}
|
||||
|
||||
int decoded = BASE64_DECODE[value];
|
||||
if (decoded < 0) { // -1: not a base64 char
|
||||
if (value != 0x0D && value != 0x0A && value != 0x20) {
|
||||
if (monitor.warn("Unexpected base64 byte: "+(byte) value, "ignoring."))
|
||||
throw new IOException("Unexpected base64 byte");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
data = (data << 6) | decoded;
|
||||
sextets++;
|
||||
|
||||
if (sextets == 4) {
|
||||
sextets = 0;
|
||||
|
||||
byte b1 = (byte) (data >>> 16);
|
||||
byte b2 = (byte) (data >>> 8);
|
||||
byte b3 = (byte) data;
|
||||
|
||||
if (index < to - 2) {
|
||||
buffer[index++] = b1;
|
||||
buffer[index++] = b2;
|
||||
buffer[index++] = b3;
|
||||
} else {
|
||||
if (index < to - 1) {
|
||||
buffer[index++] = b1;
|
||||
buffer[index++] = b2;
|
||||
decodedBuf.append(b3);
|
||||
} else if (index < to) {
|
||||
buffer[index++] = b1;
|
||||
decodedBuf.append(b2);
|
||||
decodedBuf.append(b3);
|
||||
} else {
|
||||
decodedBuf.append(b1);
|
||||
decodedBuf.append(b2);
|
||||
decodedBuf.append(b3);
|
||||
}
|
||||
|
||||
assert index == to;
|
||||
return to - from;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert sextets == 0;
|
||||
assert index == to;
|
||||
return to - from;
|
||||
}
|
||||
|
||||
private int decodePad(int data, int sextets, final byte[] buffer,
|
||||
int index, final int end) throws IOException {
|
||||
eof = true;
|
||||
|
||||
if (sextets == 2) {
|
||||
// one byte encoded as "XY=="
|
||||
|
||||
byte b = (byte) (data >>> 4);
|
||||
if (index < end) {
|
||||
buffer[index++] = b;
|
||||
} else {
|
||||
decodedBuf.append(b);
|
||||
}
|
||||
} else if (sextets == 3) {
|
||||
// two bytes encoded as "XYZ="
|
||||
|
||||
byte b1 = (byte) (data >>> 10);
|
||||
byte b2 = (byte) ((data >>> 2) & 0xFF);
|
||||
|
||||
if (index < end - 1) {
|
||||
buffer[index++] = b1;
|
||||
buffer[index++] = b2;
|
||||
} else if (index < end) {
|
||||
buffer[index++] = b1;
|
||||
decodedBuf.append(b2);
|
||||
} else {
|
||||
decodedBuf.append(b1);
|
||||
decodedBuf.append(b2);
|
||||
}
|
||||
} else {
|
||||
// error in encoded data
|
||||
handleUnexpecedPad(sextets);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private void handleUnexpectedEof(int sextets) throws IOException {
|
||||
if (monitor.warn("Unexpected end of BASE64 stream", "dropping " + sextets + " sextet(s)"))
|
||||
throw new IOException("Unexpected end of BASE64 stream");
|
||||
}
|
||||
|
||||
private void handleUnexpecedPad(int sextets) throws IOException {
|
||||
if (monitor.warn("Unexpected padding character", "dropping " + sextets + " sextet(s)"))
|
||||
throw new IOException("Unexpected padding character");
|
||||
}
|
||||
}
|
@ -1,321 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite>
|
||||
* from RFC 2045 <cite>Multipurpose Internet Mail Extensions (MIME) Part One:
|
||||
* Format of Internet Message Bodies</cite> by Freed and Borenstein.
|
||||
* <p>
|
||||
* Code is based on Base64 and Base64OutputStream code from Commons-Codec 1.4.
|
||||
*
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
|
||||
*/
|
||||
public class Base64OutputStream extends FilterOutputStream {
|
||||
|
||||
// Default line length per RFC 2045 section 6.8.
|
||||
private static final int DEFAULT_LINE_LENGTH = 76;
|
||||
|
||||
// CRLF line separator per RFC 2045 section 2.1.
|
||||
private static final byte[] CRLF_SEPARATOR = { '\r', '\n' };
|
||||
|
||||
// This array is a lookup table that translates 6-bit positive integer index
|
||||
// values into their "Base64 Alphabet" equivalents as specified in Table 1
|
||||
// of RFC 2045.
|
||||
static final byte[] BASE64_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F',
|
||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
|
||||
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', '+', '/' };
|
||||
|
||||
// Byte used to pad output.
|
||||
private static final byte BASE64_PAD = '=';
|
||||
|
||||
// This set contains all base64 characters including the pad character. Used
|
||||
// solely to check if a line separator contains any of these characters.
|
||||
private static final Set<Byte> BASE64_CHARS = new HashSet<Byte>();
|
||||
|
||||
static {
|
||||
for (byte b : BASE64_TABLE) {
|
||||
BASE64_CHARS.add(b);
|
||||
}
|
||||
BASE64_CHARS.add(BASE64_PAD);
|
||||
}
|
||||
|
||||
// Mask used to extract 6 bits
|
||||
private static final int MASK_6BITS = 0x3f;
|
||||
|
||||
private static final int ENCODED_BUFFER_SIZE = 2048;
|
||||
|
||||
private final byte[] singleByte = new byte[1];
|
||||
|
||||
private final int lineLength;
|
||||
private final byte[] lineSeparator;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private final byte[] encoded;
|
||||
private int position = 0;
|
||||
|
||||
private int data = 0;
|
||||
private int modulus = 0;
|
||||
|
||||
private int linePosition = 0;
|
||||
|
||||
/**
|
||||
* Creates a <code>Base64OutputStream</code> that writes the encoded data
|
||||
* to the given output stream using the default line length (76) and line
|
||||
* separator (CRLF).
|
||||
*
|
||||
* @param out
|
||||
* underlying output stream.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out) {
|
||||
this(out, DEFAULT_LINE_LENGTH, CRLF_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Base64OutputStream</code> that writes the encoded data
|
||||
* to the given output stream using the given line length and the default
|
||||
* line separator (CRLF).
|
||||
* <p>
|
||||
* The given line length will be rounded up to the nearest multiple of 4. If
|
||||
* the line length is zero then the output will not be split into lines.
|
||||
*
|
||||
* @param out
|
||||
* underlying output stream.
|
||||
* @param lineLength
|
||||
* desired line length.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out, int lineLength) {
|
||||
this(out, lineLength, CRLF_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Base64OutputStream</code> that writes the encoded data
|
||||
* to the given output stream using the given line length and line
|
||||
* separator.
|
||||
* <p>
|
||||
* The given line length will be rounded up to the nearest multiple of 4. If
|
||||
* the line length is zero then the output will not be split into lines and
|
||||
* the line separator is ignored.
|
||||
* <p>
|
||||
* The line separator must not include characters from the BASE64 alphabet
|
||||
* (including the padding character <code>=</code>).
|
||||
*
|
||||
* @param out
|
||||
* underlying output stream.
|
||||
* @param lineLength
|
||||
* desired line length.
|
||||
* @param lineSeparator
|
||||
* line separator to use.
|
||||
*/
|
||||
public Base64OutputStream(OutputStream out, int lineLength,
|
||||
byte[] lineSeparator) {
|
||||
super(out);
|
||||
|
||||
if (out == null)
|
||||
throw new IllegalArgumentException();
|
||||
if (lineLength < 0)
|
||||
throw new IllegalArgumentException();
|
||||
checkLineSeparator(lineSeparator);
|
||||
|
||||
this.lineLength = lineLength;
|
||||
this.lineSeparator = new byte[lineSeparator.length];
|
||||
System.arraycopy(lineSeparator, 0, this.lineSeparator, 0,
|
||||
lineSeparator.length);
|
||||
|
||||
this.encoded = new byte[ENCODED_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(final int b) throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Base64OutputStream has been closed");
|
||||
|
||||
singleByte[0] = (byte) b;
|
||||
write0(singleByte, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(final byte[] buffer) throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Base64OutputStream has been closed");
|
||||
|
||||
if (buffer == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
if (buffer.length == 0)
|
||||
return;
|
||||
|
||||
write0(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(final byte[] buffer, final int offset,
|
||||
final int length) throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Base64OutputStream has been closed");
|
||||
|
||||
if (buffer == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
if (offset < 0 || length < 0 || offset + length > buffer.length)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
write0(buffer, offset, offset + length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Base64OutputStream has been closed");
|
||||
|
||||
flush0();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
closed = true;
|
||||
close0();
|
||||
}
|
||||
|
||||
private void write0(final byte[] buffer, final int from, final int to)
|
||||
throws IOException {
|
||||
for (int i = from; i < to; i++) {
|
||||
data = (data << 8) | (buffer[i] & 0xff);
|
||||
|
||||
if (++modulus == 3) {
|
||||
modulus = 0;
|
||||
|
||||
// write line separator if necessary
|
||||
|
||||
if (lineLength > 0 && linePosition >= lineLength) {
|
||||
// writeLineSeparator() inlined for performance reasons
|
||||
|
||||
linePosition = 0;
|
||||
|
||||
if (encoded.length - position < lineSeparator.length)
|
||||
flush0();
|
||||
|
||||
for (byte ls : lineSeparator)
|
||||
encoded[position++] = ls;
|
||||
}
|
||||
|
||||
// encode data into 4 bytes
|
||||
|
||||
if (encoded.length - position < 4)
|
||||
flush0();
|
||||
|
||||
encoded[position++] = BASE64_TABLE[(data >> 18) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[(data >> 12) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[(data >> 6) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[data & MASK_6BITS];
|
||||
|
||||
linePosition += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void flush0() throws IOException {
|
||||
if (position > 0) {
|
||||
out.write(encoded, 0, position);
|
||||
position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void close0() throws IOException {
|
||||
if (modulus != 0)
|
||||
writePad();
|
||||
|
||||
// write line separator at the end of the encoded data
|
||||
|
||||
if (lineLength > 0 && linePosition > 0) {
|
||||
writeLineSeparator();
|
||||
}
|
||||
|
||||
flush0();
|
||||
}
|
||||
|
||||
private void writePad() throws IOException {
|
||||
// write line separator if necessary
|
||||
|
||||
if (lineLength > 0 && linePosition >= lineLength) {
|
||||
writeLineSeparator();
|
||||
}
|
||||
|
||||
// encode data into 4 bytes
|
||||
|
||||
if (encoded.length - position < 4)
|
||||
flush0();
|
||||
|
||||
if (modulus == 1) {
|
||||
encoded[position++] = BASE64_TABLE[(data >> 2) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[(data << 4) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_PAD;
|
||||
encoded[position++] = BASE64_PAD;
|
||||
} else {
|
||||
assert modulus == 2;
|
||||
encoded[position++] = BASE64_TABLE[(data >> 10) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[(data >> 4) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_TABLE[(data << 2) & MASK_6BITS];
|
||||
encoded[position++] = BASE64_PAD;
|
||||
}
|
||||
|
||||
linePosition += 4;
|
||||
}
|
||||
|
||||
private void writeLineSeparator() throws IOException {
|
||||
linePosition = 0;
|
||||
|
||||
if (encoded.length - position < lineSeparator.length)
|
||||
flush0();
|
||||
|
||||
for (byte ls : lineSeparator)
|
||||
encoded[position++] = ls;
|
||||
}
|
||||
|
||||
private void checkLineSeparator(byte[] lineSeparator) {
|
||||
if (lineSeparator.length > ENCODED_BUFFER_SIZE)
|
||||
throw new IllegalArgumentException("line separator length exceeds "
|
||||
+ ENCODED_BUFFER_SIZE);
|
||||
|
||||
for (byte b : lineSeparator) {
|
||||
if (BASE64_CHARS.contains(b)) {
|
||||
throw new IllegalArgumentException(
|
||||
"line separator must not contain base64 character '"
|
||||
+ (char) (b & 0xff) + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Utility methods related to codecs.
|
||||
*/
|
||||
public class CodecUtil {
|
||||
|
||||
static final int DEFAULT_ENCODING_BUFFER_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* Copies the contents of one stream to the other.
|
||||
* @param in not null
|
||||
* @param out not null
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void copy(final InputStream in, final OutputStream out) throws IOException {
|
||||
final byte[] buffer = new byte[DEFAULT_ENCODING_BUFFER_SIZE];
|
||||
int inputLength;
|
||||
while (-1 != (inputLength = in.read(buffer))) {
|
||||
out.write(buffer, 0, inputLength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 encodeQuotedPrintableBinary(final InputStream in, final OutputStream out) throws IOException {
|
||||
QuotedPrintableOutputStream qpOut = new QuotedPrintableOutputStream(out, true);
|
||||
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 encodeQuotedPrintable(final InputStream in, final OutputStream out) throws IOException {
|
||||
QuotedPrintableOutputStream qpOut = new QuotedPrintableOutputStream(out, false);
|
||||
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 encodeBase64(final InputStream in, final OutputStream out) throws IOException {
|
||||
Base64OutputStream b64Out = new Base64OutputStream(out);
|
||||
copy(in, b64Out);
|
||||
b64Out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given stream in a Quoted-Printable encoder.
|
||||
* @param out not null
|
||||
* @return encoding outputstream
|
||||
* @throws IOException
|
||||
*/
|
||||
public static OutputStream wrapQuotedPrintable(final OutputStream out, boolean binary) throws IOException {
|
||||
return new QuotedPrintableOutputStream(out, binary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given stream in a Base64 encoder.
|
||||
* @param out not null
|
||||
* @return encoding outputstream
|
||||
* @throws IOException
|
||||
*/
|
||||
public static OutputStream wrapBase64(final OutputStream out) throws IOException {
|
||||
return new Base64OutputStream(out);
|
||||
}
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to drive how decoder/parser should deal with malformed
|
||||
* and unexpected data.
|
||||
*
|
||||
* 2 basic implementations are provided:
|
||||
* STRICT return "true" on any occourence.
|
||||
* SILENT ignores any problem.
|
||||
*
|
||||
* @see org.apache.james.mime4j.field.LoggingMonitor for an example
|
||||
* about logging malformations via Commons-logging.
|
||||
*/
|
||||
public class DecodeMonitor {
|
||||
|
||||
/**
|
||||
* The STRICT monitor throws an exception on every event.
|
||||
*/
|
||||
public static final DecodeMonitor STRICT = new DecodeMonitor() {
|
||||
|
||||
@Override
|
||||
public boolean warn(String error, String dropDesc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListening() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The SILENT monitor ignore requests.
|
||||
*/
|
||||
public static final DecodeMonitor SILENT = new DecodeMonitor();
|
||||
|
||||
public boolean warn(String error, String dropDesc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isListening() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.james.mime4j.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Static methods for decoding strings, byte arrays and encoded words.
|
||||
*/
|
||||
public class DecoderUtil {
|
||||
|
||||
private static final Pattern PATTERN_ENCODED_WORD = Pattern.compile(
|
||||
"(.*?)=\\?([^\\?]+?)\\?(\\w)\\?([^\\?]+?)\\?=", Pattern.DOTALL);
|
||||
|
||||
/**
|
||||
* Decodes a string containing quoted-printable encoded data.
|
||||
*
|
||||
* @param s the string to decode.
|
||||
* @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;
|
||||
while ((b = is.read()) != -1) {
|
||||
baos.write(b);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// This should never happen!
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a string containing base64 encoded data.
|
||||
*
|
||||
* @param s the string to decode.
|
||||
* @param monitor
|
||||
* @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;
|
||||
while ((b = is.read()) != -1) {
|
||||
baos.write(b);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// This should never happen!
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an encoded text encoded with the 'B' encoding (described in
|
||||
* RFC 2047) found in a header field body.
|
||||
*
|
||||
* @param encodedText the encoded text to decode.
|
||||
* @param charset the Java charset to use.
|
||||
* @param monitor
|
||||
* @return the decoded string.
|
||||
* @throws UnsupportedEncodingException if the given Java charset isn't
|
||||
* supported.
|
||||
*/
|
||||
static String decodeB(String encodedText, String charset, DecodeMonitor monitor)
|
||||
throws UnsupportedEncodingException {
|
||||
byte[] decodedBytes = decodeBase64(encodedText, monitor);
|
||||
return new String(decodedBytes, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an encoded text encoded with the 'Q' encoding (described in
|
||||
* RFC 2047) found in a header field body.
|
||||
*
|
||||
* @param encodedText the encoded text to decode.
|
||||
* @param charset the Java charset to use.
|
||||
* @return the decoded string.
|
||||
* @throws UnsupportedEncodingException if the given Java charset isn't
|
||||
* supported.
|
||||
*/
|
||||
static String decodeQ(String encodedText, String charset, DecodeMonitor monitor)
|
||||
throws UnsupportedEncodingException {
|
||||
encodedText = replaceUnderscores(encodedText);
|
||||
|
||||
byte[] decodedBytes = decodeQuotedPrintable(encodedText, monitor);
|
||||
return new String(decodedBytes, charset);
|
||||
}
|
||||
|
||||
static String decodeEncodedWords(String body) {
|
||||
return decodeEncodedWords(body, DecodeMonitor.SILENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param body the string to decode
|
||||
* @param monitor the DecodeMonitor 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) throws IllegalArgumentException {
|
||||
int tailIndex = 0;
|
||||
boolean lastMatchValid = false;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Matcher matcher = PATTERN_ENCODED_WORD.matcher(body); matcher.find();) {
|
||||
String separator = matcher.group(1);
|
||||
String mimeCharset = matcher.group(2);
|
||||
String encoding = matcher.group(3);
|
||||
String encodedText = matcher.group(4);
|
||||
|
||||
String decoded = null;
|
||||
decoded = tryDecodeEncodedWord(mimeCharset, encoding, encodedText, monitor);
|
||||
if (decoded == null) {
|
||||
sb.append(matcher.group(0));
|
||||
} else {
|
||||
if (!lastMatchValid || !CharsetUtil.isWhitespace(separator)) {
|
||||
sb.append(separator);
|
||||
}
|
||||
sb.append(decoded);
|
||||
}
|
||||
|
||||
tailIndex = matcher.end();
|
||||
lastMatchValid = decoded != null;
|
||||
}
|
||||
|
||||
if (tailIndex == 0) {
|
||||
return body;
|
||||
} else {
|
||||
sb.append(body.substring(tailIndex));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// return null on error
|
||||
private static String tryDecodeEncodedWord(final String mimeCharset,
|
||||
final String encoding, final String encodedText, DecodeMonitor monitor) throws IllegalArgumentException {
|
||||
String charset = CharsetUtil.toJavaCharset(mimeCharset);
|
||||
if (charset == null) {
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Mime charser '", mimeCharset, "' doesn't have a corresponding Java charset");
|
||||
return null;
|
||||
} else if (!CharsetUtil.isDecodingSupported(charset)) {
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Current JDK doesn't support decoding of charset '", charset,
|
||||
"' - MIME charset '", mimeCharset, "' in encoded word");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (encodedText.length() == 0) {
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Missing encoded text in encoded word");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (encoding.equalsIgnoreCase("Q")) {
|
||||
return DecoderUtil.decodeQ(encodedText, charset, monitor);
|
||||
} else if (encoding.equalsIgnoreCase("B")) {
|
||||
return DecoderUtil.decodeB(encodedText, charset, monitor);
|
||||
} else {
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Warning: Unknown encoding in encoded word");
|
||||
return null;
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// should not happen because of isDecodingSupported check above
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Unsupported encoding (", e.getMessage(), ") in encoded word");
|
||||
return null;
|
||||
} catch (RuntimeException e) {
|
||||
monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded",
|
||||
"Could not decode (", e.getMessage(), ") encoded word");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void monitor(DecodeMonitor monitor, String mimeCharset, String encoding,
|
||||
String encodedText, String dropDesc, String... strings) throws IllegalArgumentException {
|
||||
if (monitor.isListening()) {
|
||||
String encodedWord = recombine(mimeCharset, encoding, encodedText);
|
||||
StringBuilder text = new StringBuilder();
|
||||
for (String str : strings) {
|
||||
text.append(str);
|
||||
}
|
||||
text.append(" (");
|
||||
text.append(encodedWord);
|
||||
text.append(")");
|
||||
String exceptionDesc = text.toString();
|
||||
if (monitor.warn(exceptionDesc, dropDesc))
|
||||
throw new IllegalArgumentException(text.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static String recombine(final String mimeCharset,
|
||||
final String encoding, final String encodedText) {
|
||||
return "=?" + mimeCharset + "?" + encoding + "?" + encodedText + "?=";
|
||||
}
|
||||
|
||||
// Replace _ with =20
|
||||
private static String replaceUnderscores(String str) {
|
||||
// probably faster than String#replace(CharSequence, CharSequence)
|
||||
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c == '_') {
|
||||
sb.append("=20");
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,609 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.BitSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.james.mime4j.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Static methods for encoding header field values. This includes encoded-words
|
||||
* as defined in <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC 2047</a>
|
||||
* or display-names of an e-mail address, for example.
|
||||
*/
|
||||
public class EncoderUtil {
|
||||
private static final byte[] BASE64_TABLE = Base64OutputStream.BASE64_TABLE;
|
||||
private static final char BASE64_PAD = '=';
|
||||
|
||||
private static final BitSet Q_REGULAR_CHARS = initChars("=_?");
|
||||
|
||||
private static final BitSet Q_RESTRICTED_CHARS = initChars("=_?\"#$%&'(),.:;<>@[\\]^`{|}~");
|
||||
|
||||
private static final int MAX_USED_CHARACTERS = 50;
|
||||
|
||||
private static final String ENC_WORD_PREFIX = "=?";
|
||||
private static final String ENC_WORD_SUFFIX = "?=";
|
||||
|
||||
private static final int ENCODED_WORD_MAX_LENGTH = 75; // RFC 2047
|
||||
|
||||
private static final BitSet TOKEN_CHARS = initChars("()<>@,;:\\\"/[]?=");
|
||||
|
||||
private static final BitSet ATEXT_CHARS = initChars("()<>@.,;:\\\"[]");
|
||||
|
||||
private static BitSet initChars(String specials) {
|
||||
BitSet bs = new BitSet(128);
|
||||
for (char ch = 33; ch < 127; ch++) {
|
||||
if (specials.indexOf(ch) == -1) {
|
||||
bs.set(ch);
|
||||
}
|
||||
}
|
||||
return bs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects one of the two encodings specified in RFC 2047.
|
||||
*/
|
||||
public enum Encoding {
|
||||
/** The B encoding (identical to base64 defined in RFC 2045). */
|
||||
B,
|
||||
/** The Q encoding (similar to quoted-printable defined in RFC 2045). */
|
||||
Q
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the intended usage of an encoded word.
|
||||
*/
|
||||
public enum Usage {
|
||||
/**
|
||||
* Encoded word is used to replace a 'text' token in any Subject or
|
||||
* Comments header field.
|
||||
*/
|
||||
TEXT_TOKEN,
|
||||
/**
|
||||
* Encoded word is used to replace a 'word' entity within a 'phrase',
|
||||
* for example, one that precedes an address in a From, To, or Cc
|
||||
* header.
|
||||
*/
|
||||
WORD_ENTITY
|
||||
}
|
||||
|
||||
private EncoderUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the display-name portion of an address. See <a
|
||||
* href='http://www.faqs.org/rfcs/rfc5322.html'>RFC 5322</a> section 3.4
|
||||
* and <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC 2047</a> section
|
||||
* 5.3. The specified string should not be folded.
|
||||
*
|
||||
* @param displayName
|
||||
* display-name to encode.
|
||||
* @return encoded display-name.
|
||||
*/
|
||||
public static String encodeAddressDisplayName(String displayName) {
|
||||
// display-name = phrase
|
||||
// phrase = 1*( encoded-word / word )
|
||||
// word = atom / quoted-string
|
||||
// atom = [CFWS] 1*atext [CFWS]
|
||||
// CFWS = comment or folding white space
|
||||
|
||||
if (isAtomPhrase(displayName)) {
|
||||
return displayName;
|
||||
} else if (hasToBeEncoded(displayName, 0)) {
|
||||
return encodeEncodedWord(displayName, Usage.WORD_ENTITY);
|
||||
} else {
|
||||
return quote(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the local part of an address specification as described in RFC
|
||||
* 5322 section 3.4.1. Leading and trailing CFWS should have been removed
|
||||
* before calling this method. The specified string should not contain any
|
||||
* illegal (control or non-ASCII) characters.
|
||||
*
|
||||
* @param localPart
|
||||
* the local part to encode
|
||||
* @return the encoded local part.
|
||||
*/
|
||||
public static String encodeAddressLocalPart(String localPart) {
|
||||
// local-part = dot-atom / quoted-string
|
||||
// dot-atom = [CFWS] dot-atom-text [CFWS]
|
||||
// CFWS = comment or folding white space
|
||||
|
||||
if (isDotAtomText(localPart)) {
|
||||
return localPart;
|
||||
} else {
|
||||
return quote(localPart);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified strings into a header parameter as described in RFC
|
||||
* 2045 section 5.1 and RFC 2183 section 2. The specified strings should not
|
||||
* contain any illegal (control or non-ASCII) characters.
|
||||
*
|
||||
* @param name
|
||||
* parameter name.
|
||||
* @param value
|
||||
* parameter value.
|
||||
* @return encoded result.
|
||||
*/
|
||||
public static String encodeHeaderParameter(String name, String value) {
|
||||
name = name.toLowerCase(Locale.US);
|
||||
|
||||
// value := token / quoted-string
|
||||
if (isToken(value)) {
|
||||
return name + "=" + value;
|
||||
} else {
|
||||
return name + "=" + quote(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method that encodes the specified text into an encoded-word if
|
||||
* the text has to be encoded.
|
||||
*
|
||||
* @param text
|
||||
* text to encode.
|
||||
* @param usage
|
||||
* whether the encoded-word is to be used to replace a text token
|
||||
* or a word entity (see RFC 822).
|
||||
* @param usedCharacters
|
||||
* number of characters already used up (<code>0 <= usedCharacters <= 50</code>).
|
||||
* @return the specified text if encoding is not necessary or an encoded
|
||||
* word or a sequence of encoded words otherwise.
|
||||
*/
|
||||
public static String encodeIfNecessary(String text, Usage usage,
|
||||
int usedCharacters) {
|
||||
if (hasToBeEncoded(text, usedCharacters))
|
||||
return encodeEncodedWord(text, usage, usedCharacters);
|
||||
else
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string has to encoded into an encoded-word.
|
||||
* Returns <code>true</code> if the text contains characters that don't
|
||||
* fall into the printable ASCII character set or if the text contains a
|
||||
* 'word' (sequence of non-whitespace characters) longer than 77 characters
|
||||
* (including characters already used up in the line).
|
||||
*
|
||||
* @param text
|
||||
* text to analyze.
|
||||
* @param usedCharacters
|
||||
* number of characters already used up (<code>0 <= usedCharacters <= 50</code>).
|
||||
* @return <code>true</code> if the specified text has to be encoded into
|
||||
* an encoded-word, <code>false</code> otherwise.
|
||||
*/
|
||||
public static boolean hasToBeEncoded(String text, int usedCharacters) {
|
||||
if (text == null)
|
||||
throw new IllegalArgumentException();
|
||||
if (usedCharacters < 0 || usedCharacters > MAX_USED_CHARACTERS)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
int nonWhiteSpaceCount = usedCharacters;
|
||||
|
||||
for (int idx = 0; idx < text.length(); idx++) {
|
||||
char ch = text.charAt(idx);
|
||||
if (ch == '\t' || ch == ' ') {
|
||||
nonWhiteSpaceCount = 0;
|
||||
} else {
|
||||
nonWhiteSpaceCount++;
|
||||
if (nonWhiteSpaceCount > 77) {
|
||||
// Line cannot be folded into multiple lines with no more
|
||||
// than 78 characters each. Encoding as encoded-words makes
|
||||
// that possible. One character has to be reserved for
|
||||
// folding white space; that leaves 77 characters.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch < 32 || ch >= 127) {
|
||||
// non-printable ascii character has to be encoded
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified text into an encoded word or a sequence of encoded
|
||||
* words separated by space. The text is separated into a sequence of
|
||||
* encoded words if it does not fit in a single one.
|
||||
* <p>
|
||||
* The charset to encode the specified text into a byte array and the
|
||||
* encoding to use for the encoded-word are detected automatically.
|
||||
* <p>
|
||||
* This method assumes that zero characters have already been used up in the
|
||||
* current line.
|
||||
*
|
||||
* @param text
|
||||
* text to encode.
|
||||
* @param usage
|
||||
* whether the encoded-word is to be used to replace a text token
|
||||
* or a word entity (see RFC 822).
|
||||
* @return the encoded word (or sequence of encoded words if the given text
|
||||
* does not fit in a single encoded word).
|
||||
* @see #hasToBeEncoded(String, int)
|
||||
*/
|
||||
public static String encodeEncodedWord(String text, Usage usage) {
|
||||
return encodeEncodedWord(text, usage, 0, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified text into an encoded word or a sequence of encoded
|
||||
* words separated by space. The text is separated into a sequence of
|
||||
* encoded words if it does not fit in a single one.
|
||||
* <p>
|
||||
* The charset to encode the specified text into a byte array and the
|
||||
* encoding to use for the encoded-word are detected automatically.
|
||||
*
|
||||
* @param text
|
||||
* text to encode.
|
||||
* @param usage
|
||||
* whether the encoded-word is to be used to replace a text token
|
||||
* or a word entity (see RFC 822).
|
||||
* @param usedCharacters
|
||||
* number of characters already used up (<code>0 <= usedCharacters <= 50</code>).
|
||||
* @return the encoded word (or sequence of encoded words if the given text
|
||||
* does not fit in a single encoded word).
|
||||
* @see #hasToBeEncoded(String, int)
|
||||
*/
|
||||
public static String encodeEncodedWord(String text, Usage usage,
|
||||
int usedCharacters) {
|
||||
return encodeEncodedWord(text, usage, usedCharacters, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified text into an encoded word or a sequence of encoded
|
||||
* words separated by space. The text is separated into a sequence of
|
||||
* encoded words if it does not fit in a single one.
|
||||
*
|
||||
* @param text
|
||||
* text to encode.
|
||||
* @param usage
|
||||
* whether the encoded-word is to be used to replace a text token
|
||||
* or a word entity (see RFC 822).
|
||||
* @param usedCharacters
|
||||
* number of characters already used up (<code>0 <= usedCharacters <= 50</code>).
|
||||
* @param charset
|
||||
* the Java charset that should be used to encode the specified
|
||||
* string into a byte array. A suitable charset is detected
|
||||
* automatically if this parameter is <code>null</code>.
|
||||
* @param encoding
|
||||
* the encoding to use for the encoded-word (either B or Q). A
|
||||
* suitable encoding is automatically chosen if this parameter is
|
||||
* <code>null</code>.
|
||||
* @return the encoded word (or sequence of encoded words if the given text
|
||||
* does not fit in a single encoded word).
|
||||
* @see #hasToBeEncoded(String, int)
|
||||
*/
|
||||
public static String encodeEncodedWord(String text, Usage usage,
|
||||
int usedCharacters, Charset charset, Encoding encoding) {
|
||||
if (text == null)
|
||||
throw new IllegalArgumentException();
|
||||
if (usedCharacters < 0 || usedCharacters > MAX_USED_CHARACTERS)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
if (charset == null)
|
||||
charset = determineCharset(text);
|
||||
|
||||
String mimeCharset = CharsetUtil.toMimeCharset(charset.name());
|
||||
if (mimeCharset == null) {
|
||||
// cannot happen if charset was originally null
|
||||
throw new IllegalArgumentException("Unsupported charset");
|
||||
}
|
||||
|
||||
byte[] bytes = encode(text, charset);
|
||||
|
||||
if (encoding == null)
|
||||
encoding = determineEncoding(bytes, usage);
|
||||
|
||||
if (encoding == Encoding.B) {
|
||||
String prefix = ENC_WORD_PREFIX + mimeCharset + "?B?";
|
||||
return encodeB(prefix, text, usedCharacters, charset, bytes);
|
||||
} else {
|
||||
String prefix = ENC_WORD_PREFIX + mimeCharset + "?Q?";
|
||||
return encodeQ(prefix, text, usage, usedCharacters, charset, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified byte array using the B encoding defined in RFC
|
||||
* 2047.
|
||||
*
|
||||
* @param bytes
|
||||
* byte array to encode.
|
||||
* @return encoded string.
|
||||
*/
|
||||
public static String encodeB(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int idx = 0;
|
||||
final int end = bytes.length;
|
||||
for (; idx < end - 2; idx += 3) {
|
||||
int data = (bytes[idx] & 0xff) << 16 | (bytes[idx + 1] & 0xff) << 8
|
||||
| bytes[idx + 2] & 0xff;
|
||||
sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data >> 6 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data & 0x3f]);
|
||||
}
|
||||
|
||||
if (idx == end - 2) {
|
||||
int data = (bytes[idx] & 0xff) << 16 | (bytes[idx + 1] & 0xff) << 8;
|
||||
sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data >> 6 & 0x3f]);
|
||||
sb.append(BASE64_PAD);
|
||||
|
||||
} else if (idx == end - 1) {
|
||||
int data = (bytes[idx] & 0xff) << 16;
|
||||
sb.append((char) BASE64_TABLE[data >> 18 & 0x3f]);
|
||||
sb.append((char) BASE64_TABLE[data >> 12 & 0x3f]);
|
||||
sb.append(BASE64_PAD);
|
||||
sb.append(BASE64_PAD);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the specified byte array using the Q encoding defined in RFC
|
||||
* 2047.
|
||||
*
|
||||
* @param bytes
|
||||
* byte array to encode.
|
||||
* @param usage
|
||||
* whether the encoded-word is to be used to replace a text token
|
||||
* or a word entity (see RFC 822).
|
||||
* @return encoded string.
|
||||
*/
|
||||
public static String encodeQ(byte[] bytes, Usage usage) {
|
||||
BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS
|
||||
: Q_RESTRICTED_CHARS;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
final int end = bytes.length;
|
||||
for (int idx = 0; idx < end; idx++) {
|
||||
int v = bytes[idx] & 0xff;
|
||||
if (v == 32) {
|
||||
sb.append('_');
|
||||
} else if (!qChars.get(v)) {
|
||||
sb.append('=');
|
||||
sb.append(hexDigit(v >>> 4));
|
||||
sb.append(hexDigit(v & 0xf));
|
||||
} else {
|
||||
sb.append((char) v);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the specified string is a token as defined in RFC 2045
|
||||
* section 5.1.
|
||||
*
|
||||
* @param str
|
||||
* string to test.
|
||||
* @return <code>true</code> if the specified string is a RFC 2045 token,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public static boolean isToken(String str) {
|
||||
// token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials>
|
||||
// tspecials := "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" /
|
||||
// <"> / "/" / "[" / "]" / "?" / "="
|
||||
// CTL := 0.- 31., 127.
|
||||
|
||||
final int length = str.length();
|
||||
if (length == 0)
|
||||
return false;
|
||||
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
char ch = str.charAt(idx);
|
||||
if (!TOKEN_CHARS.get(ch))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isAtomPhrase(String str) {
|
||||
// atom = [CFWS] 1*atext [CFWS]
|
||||
|
||||
boolean containsAText = false;
|
||||
|
||||
final int length = str.length();
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
char ch = str.charAt(idx);
|
||||
if (ATEXT_CHARS.get(ch)) {
|
||||
containsAText = true;
|
||||
} else if (!CharsetUtil.isWhitespace(ch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return containsAText;
|
||||
}
|
||||
|
||||
// RFC 5322 section 3.2.3
|
||||
private static boolean isDotAtomText(String str) {
|
||||
// dot-atom-text = 1*atext *("." 1*atext)
|
||||
// atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" /
|
||||
// "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
|
||||
|
||||
char prev = '.';
|
||||
|
||||
final int length = str.length();
|
||||
if (length == 0)
|
||||
return false;
|
||||
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
char ch = str.charAt(idx);
|
||||
|
||||
if (ch == '.') {
|
||||
if (prev == '.' || idx == length - 1)
|
||||
return false;
|
||||
} else {
|
||||
if (!ATEXT_CHARS.get(ch))
|
||||
return false;
|
||||
}
|
||||
|
||||
prev = ch;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// RFC 5322 section 3.2.4
|
||||
private static String quote(String str) {
|
||||
// quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS]
|
||||
// qcontent = qtext / quoted-pair
|
||||
// qtext = %d33 / %d35-91 / %d93-126
|
||||
// quoted-pair = ("\" (VCHAR / WSP))
|
||||
// VCHAR = %x21-7E
|
||||
// DQUOTE = %x22
|
||||
|
||||
String escaped = str.replaceAll("[\\\\\"]", "\\\\$0");
|
||||
return "\"" + escaped + "\"";
|
||||
}
|
||||
|
||||
private static String encodeB(String prefix, String text,
|
||||
int usedCharacters, Charset charset, byte[] bytes) {
|
||||
int encodedLength = bEncodedLength(bytes);
|
||||
|
||||
int totalLength = prefix.length() + encodedLength
|
||||
+ ENC_WORD_SUFFIX.length();
|
||||
if (totalLength <= ENCODED_WORD_MAX_LENGTH - usedCharacters) {
|
||||
return prefix + encodeB(bytes) + ENC_WORD_SUFFIX;
|
||||
} else {
|
||||
String part1 = text.substring(0, text.length() / 2);
|
||||
byte[] bytes1 = encode(part1, charset);
|
||||
String word1 = encodeB(prefix, part1, usedCharacters, charset,
|
||||
bytes1);
|
||||
|
||||
String part2 = text.substring(text.length() / 2);
|
||||
byte[] bytes2 = encode(part2, charset);
|
||||
String word2 = encodeB(prefix, part2, 0, charset, bytes2);
|
||||
|
||||
return word1 + " " + word2;
|
||||
}
|
||||
}
|
||||
|
||||
private static int bEncodedLength(byte[] bytes) {
|
||||
return (bytes.length + 2) / 3 * 4;
|
||||
}
|
||||
|
||||
private static String encodeQ(String prefix, String text, Usage usage,
|
||||
int usedCharacters, Charset charset, byte[] bytes) {
|
||||
int encodedLength = qEncodedLength(bytes, usage);
|
||||
|
||||
int totalLength = prefix.length() + encodedLength
|
||||
+ ENC_WORD_SUFFIX.length();
|
||||
if (totalLength <= ENCODED_WORD_MAX_LENGTH - usedCharacters) {
|
||||
return prefix + encodeQ(bytes, usage) + ENC_WORD_SUFFIX;
|
||||
} else {
|
||||
String part1 = text.substring(0, text.length() / 2);
|
||||
byte[] bytes1 = encode(part1, charset);
|
||||
String word1 = encodeQ(prefix, part1, usage, usedCharacters,
|
||||
charset, bytes1);
|
||||
|
||||
String part2 = text.substring(text.length() / 2);
|
||||
byte[] bytes2 = encode(part2, charset);
|
||||
String word2 = encodeQ(prefix, part2, usage, 0, charset, bytes2);
|
||||
|
||||
return word1 + " " + word2;
|
||||
}
|
||||
}
|
||||
|
||||
private static int qEncodedLength(byte[] bytes, Usage usage) {
|
||||
BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS
|
||||
: Q_RESTRICTED_CHARS;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int idx = 0; idx < bytes.length; idx++) {
|
||||
int v = bytes[idx] & 0xff;
|
||||
if (v == 32) {
|
||||
count++;
|
||||
} else if (!qChars.get(v)) {
|
||||
count += 3;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private static byte[] encode(String text, Charset charset) {
|
||||
ByteBuffer buffer = charset.encode(text);
|
||||
byte[] bytes = new byte[buffer.limit()];
|
||||
buffer.get(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static Charset determineCharset(String text) {
|
||||
// it is an important property of iso-8859-1 that it directly maps
|
||||
// unicode code points 0000 to 00ff to byte values 00 to ff.
|
||||
boolean ascii = true;
|
||||
final int len = text.length();
|
||||
for (int index = 0; index < len; index++) {
|
||||
char ch = text.charAt(index);
|
||||
if (ch > 0xff) {
|
||||
return CharsetUtil.UTF_8;
|
||||
}
|
||||
if (ch > 0x7f) {
|
||||
ascii = false;
|
||||
}
|
||||
}
|
||||
return ascii ? CharsetUtil.US_ASCII : CharsetUtil.ISO_8859_1;
|
||||
}
|
||||
|
||||
private static Encoding determineEncoding(byte[] bytes, Usage usage) {
|
||||
if (bytes.length == 0)
|
||||
return Encoding.Q;
|
||||
|
||||
BitSet qChars = usage == Usage.TEXT_TOKEN ? Q_REGULAR_CHARS
|
||||
: Q_RESTRICTED_CHARS;
|
||||
|
||||
int qEncoded = 0;
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
int v = bytes[i] & 0xff;
|
||||
if (v != 32 && !qChars.get(v)) {
|
||||
qEncoded++;
|
||||
}
|
||||
}
|
||||
|
||||
int percentage = qEncoded * 100 / bytes.length;
|
||||
return percentage > 30 ? Encoding.B : Encoding.Q;
|
||||
}
|
||||
|
||||
private static char hexDigit(int i) {
|
||||
return i < 10 ? (char) (i + '0') : (char) (i - 10 + 'A');
|
||||
}
|
||||
}
|
@ -1,309 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.james.mime4j.util.ByteArrayBuffer;
|
||||
|
||||
/**
|
||||
* Performs Quoted-Printable decoding on an underlying stream.
|
||||
*/
|
||||
public class QuotedPrintableInputStream extends InputStream {
|
||||
|
||||
private static final int DEFAULT_BUFFER_SIZE = 1024 * 2;
|
||||
|
||||
private static final byte EQ = 0x3D;
|
||||
private static final byte CR = 0x0D;
|
||||
private static final byte LF = 0x0A;
|
||||
|
||||
private final byte[] singleByte = new byte[1];
|
||||
|
||||
private final InputStream in;
|
||||
private final ByteArrayBuffer decodedBuf;
|
||||
private final ByteArrayBuffer blanks;
|
||||
|
||||
private final byte[] encoded;
|
||||
private int pos = 0; // current index into encoded buffer
|
||||
private int limit = 0; // current size of encoded buffer
|
||||
|
||||
private boolean closed;
|
||||
|
||||
private final DecodeMonitor monitor;
|
||||
|
||||
public QuotedPrintableInputStream(final InputStream in, DecodeMonitor monitor) {
|
||||
this(DEFAULT_BUFFER_SIZE, in, monitor);
|
||||
}
|
||||
|
||||
protected QuotedPrintableInputStream(final int bufsize, final InputStream in, DecodeMonitor monitor) {
|
||||
super();
|
||||
this.in = in;
|
||||
this.encoded = new byte[bufsize];
|
||||
this.decodedBuf = new ByteArrayBuffer(512);
|
||||
this.blanks = new ByteArrayBuffer(512);
|
||||
this.closed = false;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
protected QuotedPrintableInputStream(final int bufsize, final InputStream in, boolean strict) {
|
||||
this(bufsize, in, strict ? DecodeMonitor.STRICT : DecodeMonitor.SILENT);
|
||||
}
|
||||
|
||||
public QuotedPrintableInputStream(final InputStream in, boolean strict) {
|
||||
this(DEFAULT_BUFFER_SIZE, in, strict);
|
||||
}
|
||||
|
||||
public QuotedPrintableInputStream(final InputStream in) {
|
||||
this(in, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates Quoted-Printable coded content. This method does NOT close
|
||||
* the underlying input stream.
|
||||
*
|
||||
* @throws IOException on I/O errors.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
private int fillBuffer() throws IOException {
|
||||
// Compact buffer if needed
|
||||
if (pos < limit) {
|
||||
System.arraycopy(encoded, pos, encoded, 0, limit - pos);
|
||||
limit -= pos;
|
||||
pos = 0;
|
||||
} else {
|
||||
limit = 0;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
int capacity = encoded.length - limit;
|
||||
if (capacity > 0) {
|
||||
int bytesRead = in.read(encoded, limit, capacity);
|
||||
if (bytesRead > 0) {
|
||||
limit += bytesRead;
|
||||
}
|
||||
return bytesRead;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int getnext() {
|
||||
if (pos < limit) {
|
||||
byte b = encoded[pos];
|
||||
pos++;
|
||||
return b & 0xFF;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private int peek(int i) {
|
||||
if (pos + i < limit) {
|
||||
return encoded[pos + i] & 0xFF;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private int transfer(
|
||||
final int b, final byte[] buffer, final int from, final int to, boolean keepblanks) throws IOException {
|
||||
int index = from;
|
||||
if (keepblanks && blanks.length() > 0) {
|
||||
int chunk = Math.min(blanks.length(), to - index);
|
||||
System.arraycopy(blanks.buffer(), 0, buffer, index, chunk);
|
||||
index += chunk;
|
||||
int remaining = blanks.length() - chunk;
|
||||
if (remaining > 0) {
|
||||
decodedBuf.append(blanks.buffer(), chunk, remaining);
|
||||
}
|
||||
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));
|
||||
if (monitor.warn("ignored blanks", sb.toString()))
|
||||
throw new IOException("ignored blanks");
|
||||
}
|
||||
if (b != -1) {
|
||||
if (index < to) {
|
||||
buffer[index++] = (byte) b;
|
||||
} else {
|
||||
decodedBuf.append(b);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// check if a previous invocation left decoded content
|
||||
if (decodedBuf.length() > 0) {
|
||||
int chunk = Math.min(decodedBuf.length(), to - index);
|
||||
System.arraycopy(decodedBuf.buffer(), 0, buffer, index, chunk);
|
||||
decodedBuf.remove(0, chunk);
|
||||
index += chunk;
|
||||
}
|
||||
|
||||
while (index < to) {
|
||||
|
||||
if (limit - pos < 3) {
|
||||
int bytesRead = fillBuffer();
|
||||
eof = bytesRead == -1;
|
||||
}
|
||||
|
||||
// end of stream?
|
||||
if (limit - pos == 0 && eof) {
|
||||
return index == from ? -1 : index - from;
|
||||
}
|
||||
|
||||
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"))
|
||||
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"))
|
||||
throw new IOException("Found LF without CR");
|
||||
}
|
||||
|
||||
if (b == CR) {
|
||||
lastWasCR = true;
|
||||
continue;
|
||||
} else {
|
||||
lastWasCR = false;
|
||||
}
|
||||
|
||||
if (b == LF) {
|
||||
// at end of line
|
||||
if (blanks.length() == 0) {
|
||||
index = transfer(CR, buffer, index, to, false);
|
||||
index = transfer(LF, buffer, index, to, false);
|
||||
} else {
|
||||
if (blanks.byteAt(0) != EQ) {
|
||||
// hard line break
|
||||
index = transfer(CR, buffer, index, to, false);
|
||||
index = transfer(LF, buffer, index, to, false);
|
||||
}
|
||||
}
|
||||
blanks.clear();
|
||||
} else if (b == EQ) {
|
||||
if (limit - pos < 2 && !eof) {
|
||||
// not enough buffered data
|
||||
pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
// found special char '='
|
||||
int b2 = getnext();
|
||||
if (b2 == EQ) {
|
||||
index = transfer(b2, buffer, index, to, true);
|
||||
// deal with '==\r\n' brokenness
|
||||
int bb1 = peek(0);
|
||||
int bb2 = peek(1);
|
||||
if (bb1 == LF || (bb1 == CR && bb2 == LF)) {
|
||||
monitor.warn("Unexpected ==EOL encountered", "== 0x"+bb1+" 0x"+bb2);
|
||||
blanks.append(b2);
|
||||
} else {
|
||||
monitor.warn("Unexpected == encountered", "==");
|
||||
}
|
||||
} else if (Character.isWhitespace((char) b2)) {
|
||||
// soft line break
|
||||
index = transfer(-1, buffer, index, to, true);
|
||||
if (b2 != LF) {
|
||||
blanks.append(b);
|
||||
blanks.append(b2);
|
||||
}
|
||||
} else {
|
||||
int b3 = getnext();
|
||||
int upper = convert(b2);
|
||||
int lower = convert(b3);
|
||||
if (upper < 0 || lower < 0) {
|
||||
monitor.warn("Malformed encoded value encountered", "leaving "+((char) EQ)+((char) b2)+((char) b3)+" as is");
|
||||
// TODO see MIME4J-160
|
||||
index = transfer(EQ, buffer, index, to, true);
|
||||
index = transfer(b2, buffer, index, to, false);
|
||||
index = transfer(b3, buffer, index, to, false);
|
||||
} else {
|
||||
index = transfer((upper << 4) | lower, buffer, index, to, true);
|
||||
}
|
||||
}
|
||||
} else if (Character.isWhitespace(b)) {
|
||||
blanks.append(b);
|
||||
} else {
|
||||
index = transfer((int) b & 0xFF, buffer, index, to, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return to - from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts '0' => 0, 'A' => 10, etc.
|
||||
* @param c ASCII character value.
|
||||
* @return Numeric value of hexadecimal character.
|
||||
*/
|
||||
private int convert(int c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return (c - '0');
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
return (0xA + (c - 'A'));
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
return (0xA + (c - 'a'));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
for (;;) {
|
||||
int bytes = read(singleByte, 0, 1);
|
||||
if (bytes == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (bytes == 1) {
|
||||
return singleByte[0] & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
return read0(b, off, len);
|
||||
}
|
||||
|
||||
}
|
@ -1,233 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.codec;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Performs Quoted-Printable encoding on an underlying stream.
|
||||
*/
|
||||
public class QuotedPrintableOutputStream extends FilterOutputStream {
|
||||
|
||||
private static final int DEFAULT_BUFFER_SIZE = 1024 * 3;
|
||||
|
||||
private static final byte TB = 0x09;
|
||||
private static final byte SP = 0x20;
|
||||
private static final byte EQ = 0x3D;
|
||||
private static final byte CR = 0x0D;
|
||||
private static final byte LF = 0x0A;
|
||||
private static final byte QUOTED_PRINTABLE_LAST_PLAIN = 0x7E;
|
||||
private static final int QUOTED_PRINTABLE_MAX_LINE_LENGTH = 76;
|
||||
private static final int QUOTED_PRINTABLE_OCTETS_PER_ESCAPE = 3;
|
||||
private static final byte[] HEX_DIGITS = {
|
||||
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
|
||||
private final byte[] outBuffer;
|
||||
private final boolean binary;
|
||||
|
||||
private boolean pendingSpace;
|
||||
private boolean pendingTab;
|
||||
private boolean pendingCR;
|
||||
private int nextSoftBreak;
|
||||
private int outputIndex;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private byte[] singleByte = new byte[1];
|
||||
|
||||
public QuotedPrintableOutputStream(int bufsize, OutputStream out, boolean binary) {
|
||||
super(out);
|
||||
this.outBuffer = new byte[bufsize];
|
||||
this.binary = binary;
|
||||
this.pendingSpace = false;
|
||||
this.pendingTab = false;
|
||||
this.pendingCR = false;
|
||||
this.outputIndex = 0;
|
||||
this.nextSoftBreak = QUOTED_PRINTABLE_MAX_LINE_LENGTH + 1;
|
||||
}
|
||||
|
||||
public QuotedPrintableOutputStream(OutputStream out, boolean binary) {
|
||||
this(DEFAULT_BUFFER_SIZE, out, binary);
|
||||
}
|
||||
|
||||
private void encodeChunk(byte[] buffer, int off, int len) throws IOException {
|
||||
for (int inputIndex = off; inputIndex < len + off; inputIndex++) {
|
||||
encode(buffer[inputIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
private void completeEncoding() throws IOException {
|
||||
writePending();
|
||||
flushOutput();
|
||||
}
|
||||
|
||||
private void writePending() throws IOException {
|
||||
if (pendingSpace) {
|
||||
plain(SP);
|
||||
} else if (pendingTab) {
|
||||
plain(TB);
|
||||
} else if (pendingCR) {
|
||||
plain(CR);
|
||||
}
|
||||
clearPending();
|
||||
}
|
||||
|
||||
private void clearPending() throws IOException {
|
||||
pendingSpace = false;
|
||||
pendingTab = false;
|
||||
pendingCR = false;
|
||||
}
|
||||
|
||||
private void encode(byte next) throws IOException {
|
||||
if (next == LF) {
|
||||
if (binary) {
|
||||
writePending();
|
||||
escape(next);
|
||||
} else {
|
||||
if (pendingCR) {
|
||||
// Expect either space or tab pending
|
||||
// but not both
|
||||
if (pendingSpace) {
|
||||
escape(SP);
|
||||
} else if (pendingTab) {
|
||||
escape(TB);
|
||||
}
|
||||
lineBreak();
|
||||
clearPending();
|
||||
} else {
|
||||
writePending();
|
||||
plain(next);
|
||||
}
|
||||
}
|
||||
} else if (next == CR) {
|
||||
if (binary) {
|
||||
escape(next);
|
||||
} else {
|
||||
pendingCR = true;
|
||||
}
|
||||
} else {
|
||||
writePending();
|
||||
if (next == SP) {
|
||||
if (binary) {
|
||||
escape(next);
|
||||
} else {
|
||||
pendingSpace = true;
|
||||
}
|
||||
} else if (next == TB) {
|
||||
if (binary) {
|
||||
escape(next);
|
||||
} else {
|
||||
pendingTab = true;
|
||||
}
|
||||
} else if (next < SP) {
|
||||
escape(next);
|
||||
} else if (next > QUOTED_PRINTABLE_LAST_PLAIN) {
|
||||
escape(next);
|
||||
} else if (next == EQ) {
|
||||
escape(next);
|
||||
} else {
|
||||
plain(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void plain(byte next) throws IOException {
|
||||
if (--nextSoftBreak <= 1) {
|
||||
softBreak();
|
||||
}
|
||||
write(next);
|
||||
}
|
||||
|
||||
private void escape(byte next) throws IOException {
|
||||
if (--nextSoftBreak <= QUOTED_PRINTABLE_OCTETS_PER_ESCAPE) {
|
||||
softBreak();
|
||||
}
|
||||
|
||||
int nextUnsigned = next & 0xff;
|
||||
|
||||
write(EQ);
|
||||
--nextSoftBreak;
|
||||
write(HEX_DIGITS[nextUnsigned >> 4]);
|
||||
--nextSoftBreak;
|
||||
write(HEX_DIGITS[nextUnsigned % 0x10]);
|
||||
}
|
||||
|
||||
private void write(byte next) throws IOException {
|
||||
outBuffer[outputIndex++] = next;
|
||||
if (outputIndex >= outBuffer.length) {
|
||||
flushOutput();
|
||||
}
|
||||
}
|
||||
|
||||
private void softBreak() throws IOException {
|
||||
write(EQ);
|
||||
lineBreak();
|
||||
}
|
||||
|
||||
private void lineBreak() throws IOException {
|
||||
write(CR);
|
||||
write(LF);
|
||||
nextSoftBreak = QUOTED_PRINTABLE_MAX_LINE_LENGTH;
|
||||
}
|
||||
|
||||
void flushOutput() throws IOException {
|
||||
if (outputIndex < outBuffer.length) {
|
||||
out.write(outBuffer, 0, outputIndex);
|
||||
} else {
|
||||
out.write(outBuffer);
|
||||
}
|
||||
outputIndex = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed)
|
||||
return;
|
||||
|
||||
try {
|
||||
completeEncoding();
|
||||
// do not close the wrapped stream
|
||||
} finally {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
flushOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
singleByte[0] = (byte) b;
|
||||
this.write(singleByte, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
encodeChunk(b, off, len);
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
/**
|
||||
* A body containing binary data.
|
||||
*/
|
||||
public abstract class BinaryBody extends SingleBody {
|
||||
|
||||
/**
|
||||
* Sole constructor.
|
||||
*/
|
||||
protected BinaryBody() {
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
/**
|
||||
* Encapsulates the body of an entity (see RFC 2045).
|
||||
* <p>
|
||||
* A body can be a {@link Message}, a {@link Multipart} or a {@link SingleBody}.
|
||||
* This interface should not be implemented directly by classes other than
|
||||
* those.
|
||||
*/
|
||||
public interface Body extends Disposable {
|
||||
|
||||
/**
|
||||
* Gets the parent of this body.
|
||||
*
|
||||
* @return the parent.
|
||||
*/
|
||||
Entity getParent();
|
||||
|
||||
/**
|
||||
* Sets the parent of this body.
|
||||
*
|
||||
* @param parent
|
||||
* the parent.
|
||||
*/
|
||||
void setParent(Entity parent);
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
/**
|
||||
* A <tt>Disposable</tt> is an object that should be disposed of explicitly
|
||||
* when it is no longer needed.
|
||||
*
|
||||
* The dispose method is invoked to release resources that the object is
|
||||
* holding (such as open files).
|
||||
*/
|
||||
public interface Disposable {
|
||||
/**
|
||||
* Free any resources this object is holding and prepares this object
|
||||
* for garbage collection. Once an object has been disposed of it can no
|
||||
* longer be used.
|
||||
*/
|
||||
void dispose();
|
||||
}
|
@ -1,550 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.james.mime4j.dom.field.ContentDispositionField;
|
||||
import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
|
||||
import org.apache.james.mime4j.dom.field.ContentTypeField;
|
||||
import org.apache.james.mime4j.dom.field.Field;
|
||||
import org.apache.james.mime4j.dom.field.FieldName;
|
||||
|
||||
/**
|
||||
* MIME entity. An entity has a header and a body (see RFC 2045).
|
||||
*/
|
||||
public abstract class Entity implements Disposable {
|
||||
private Header header = null;
|
||||
private Body body = null;
|
||||
private Entity parent = null;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Entity</code>. Typically invoked implicitly by a
|
||||
* subclass constructor.
|
||||
*/
|
||||
protected Entity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parent entity of this entity.
|
||||
* Returns <code>null</code> if this is the root entity.
|
||||
*
|
||||
* @return the parent or <code>null</code>.
|
||||
*/
|
||||
public Entity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent entity of this entity.
|
||||
*
|
||||
* @param parent the parent entity or <code>null</code> if
|
||||
* this will be the root entity.
|
||||
*/
|
||||
public void setParent(Entity parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity header.
|
||||
*
|
||||
* @return the header.
|
||||
*/
|
||||
public Header getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity header.
|
||||
*
|
||||
* @param header the header.
|
||||
*/
|
||||
public void setHeader(Header header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the body of this entity.
|
||||
*
|
||||
* @return the body,
|
||||
*/
|
||||
public Body getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the body of this entity.
|
||||
*
|
||||
* @param body the body.
|
||||
* @throws IllegalStateException if the body has already been set.
|
||||
*/
|
||||
public void setBody(Body body) {
|
||||
if (this.body != null)
|
||||
throw new IllegalStateException("body already set");
|
||||
|
||||
this.body = body;
|
||||
body.setParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns the body of this entity. The removed body may be
|
||||
* attached to another entity. If it is no longer needed it should be
|
||||
* {@link Disposable#dispose() disposed} of.
|
||||
*
|
||||
* @return the removed body or <code>null</code> if no body was set.
|
||||
*/
|
||||
public Body removeBody() {
|
||||
if (body == null)
|
||||
return null;
|
||||
|
||||
Body body = this.body;
|
||||
this.body = null;
|
||||
body.setParent(null);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified message as body of this entity and the content type to
|
||||
* "message/rfc822". A <code>Header</code> is created if this
|
||||
* entity does not already have one.
|
||||
*
|
||||
* @param message
|
||||
* the message to set as body.
|
||||
*/
|
||||
public void setMessage(Message message) {
|
||||
setBody(message, "message/rfc822", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified multipart as body of this entity. Also sets the
|
||||
* content type accordingly and creates a message boundary string. A
|
||||
* <code>Header</code> is created if this entity does not already have
|
||||
* one.
|
||||
*
|
||||
* @param multipart
|
||||
* the multipart to set as body.
|
||||
*/
|
||||
public void setMultipart(Multipart multipart) {
|
||||
String mimeType = "multipart/" + multipart.getSubType();
|
||||
Map<String, String> parameters = Collections.singletonMap("boundary",
|
||||
newUniqueBoundary());
|
||||
|
||||
setBody(multipart, mimeType, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified multipart as body of this entity. Also sets the
|
||||
* content type accordingly and creates a message boundary string. A
|
||||
* <code>Header</code> is created if this entity does not already have
|
||||
* one.
|
||||
*
|
||||
* @param multipart
|
||||
* the multipart to set as body.
|
||||
* @param parameters
|
||||
* additional parameters for the Content-Type header field.
|
||||
*/
|
||||
public void setMultipart(Multipart multipart, Map<String, String> parameters) {
|
||||
String mimeType = "multipart/" + multipart.getSubType();
|
||||
if (!parameters.containsKey("boundary")) {
|
||||
parameters = new HashMap<String, String>(parameters);
|
||||
parameters.put("boundary", newUniqueBoundary());
|
||||
}
|
||||
|
||||
setBody(multipart, mimeType, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified <code>TextBody</code> as body of this entity and the
|
||||
* content type to "text/plain". A <code>Header</code> is
|
||||
* created if this entity does not already have one.
|
||||
*
|
||||
* @param textBody
|
||||
* the <code>TextBody</code> to set as body.
|
||||
* @see org.apache.james.mime4j.message.BodyFactory#textBody(String)
|
||||
*/
|
||||
public void setText(TextBody textBody) {
|
||||
setText(textBody, "plain");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified <code>TextBody</code> as body of this entity. Also
|
||||
* sets the content type according to the specified sub-type. A
|
||||
* <code>Header</code> is created if this entity does not already have
|
||||
* one.
|
||||
*
|
||||
* @param textBody
|
||||
* the <code>TextBody</code> to set as body.
|
||||
* @param subtype
|
||||
* the text subtype (e.g. "plain", "html" or
|
||||
* "xml").
|
||||
* @see org.apache.james.mime4j.message.BodyFactory#textBody(String)
|
||||
*/
|
||||
public void setText(TextBody textBody, String subtype) {
|
||||
String mimeType = "text/" + subtype;
|
||||
|
||||
Map<String, String> parameters = null;
|
||||
String mimeCharset = textBody.getMimeCharset();
|
||||
if (mimeCharset != null && !mimeCharset.equalsIgnoreCase("us-ascii")) {
|
||||
parameters = Collections.singletonMap("charset", mimeCharset);
|
||||
}
|
||||
|
||||
setBody(textBody, mimeType, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the body of this entity and sets the content-type to the specified
|
||||
* value. A <code>Header</code> is created if this entity does not already
|
||||
* have one.
|
||||
*
|
||||
* @param body
|
||||
* the body.
|
||||
* @param mimeType
|
||||
* the MIME media type of the specified body
|
||||
* ("type/subtype").
|
||||
*/
|
||||
public void setBody(Body body, String mimeType) {
|
||||
setBody(body, mimeType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the body of this entity and sets the content-type to the specified
|
||||
* value. A <code>Header</code> is created if this entity does not already
|
||||
* have one.
|
||||
*
|
||||
* @param body
|
||||
* the body.
|
||||
* @param mimeType
|
||||
* the MIME media type of the specified body
|
||||
* ("type/subtype").
|
||||
* @param parameters
|
||||
* additional parameters for the Content-Type header field.
|
||||
*/
|
||||
public void setBody(Body body, String mimeType,
|
||||
Map<String, String> parameters) {
|
||||
setBody(body);
|
||||
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentType(mimeType, parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the MIME type of this <code>Entity</code>. The MIME type
|
||||
* is derived by looking at the parent's Content-Type field if no
|
||||
* Content-Type field is set for this <code>Entity</code>.
|
||||
*
|
||||
* @return the MIME type.
|
||||
*/
|
||||
public String getMimeType() {
|
||||
ContentTypeField child =
|
||||
getContentTypeField();
|
||||
ContentTypeField parent = getParent() != null
|
||||
? (ContentTypeField) getParent().getHeader().
|
||||
getField(FieldName.CONTENT_TYPE)
|
||||
: null;
|
||||
|
||||
return calcMimeType(child, parent);
|
||||
}
|
||||
|
||||
private ContentTypeField getContentTypeField() {
|
||||
return (ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the MIME character set encoding of this <code>Entity</code>.
|
||||
*
|
||||
* @return the MIME character set encoding.
|
||||
*/
|
||||
public String getCharset() {
|
||||
return calcCharset((ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the transfer encoding of this <code>Entity</code>.
|
||||
*
|
||||
* @return the transfer encoding.
|
||||
*/
|
||||
public String getContentTransferEncoding() {
|
||||
ContentTransferEncodingField f = (ContentTransferEncodingField)
|
||||
getHeader().getField(FieldName.CONTENT_TRANSFER_ENCODING);
|
||||
|
||||
return calcTransferEncoding(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transfer encoding of this <code>Entity</code> to the specified
|
||||
* value.
|
||||
*
|
||||
* @param contentTransferEncoding
|
||||
* transfer encoding to use.
|
||||
*/
|
||||
public void setContentTransferEncoding(String contentTransferEncoding) {
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentTransferEncoding(contentTransferEncoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the disposition type of the content disposition of this
|
||||
* <code>Entity</code>.
|
||||
*
|
||||
* @return the disposition type or <code>null</code> if no disposition
|
||||
* type has been set.
|
||||
*/
|
||||
public String getDispositionType() {
|
||||
ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getDispositionType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content disposition of this <code>Entity</code> to the
|
||||
* specified disposition type. No filename, size or date parameters
|
||||
* are included in the content disposition.
|
||||
*
|
||||
* @param dispositionType
|
||||
* disposition type value (usually <code>inline</code> or
|
||||
* <code>attachment</code>).
|
||||
*/
|
||||
public void setContentDisposition(String dispositionType) {
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentDisposition(dispositionType, null, -1, null,
|
||||
null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content disposition of this <code>Entity</code> to the
|
||||
* specified disposition type and filename. No size or date parameters are
|
||||
* included in the content disposition.
|
||||
*
|
||||
* @param dispositionType
|
||||
* disposition type value (usually <code>inline</code> or
|
||||
* <code>attachment</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
*/
|
||||
public void setContentDisposition(String dispositionType, String filename) {
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentDisposition(dispositionType, filename, -1,
|
||||
null, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content disposition of this <code>Entity</code> to the
|
||||
* specified values. No date parameters are included in the content
|
||||
* disposition.
|
||||
*
|
||||
* @param dispositionType
|
||||
* disposition type value (usually <code>inline</code> or
|
||||
* <code>attachment</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param size
|
||||
* size parameter value or <code>-1</code> if the parameter
|
||||
* should not be included.
|
||||
*/
|
||||
public void setContentDisposition(String dispositionType, String filename,
|
||||
long size) {
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentDisposition(dispositionType, filename, size,
|
||||
null, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content disposition of this <code>Entity</code> to the
|
||||
* specified values.
|
||||
*
|
||||
* @param dispositionType
|
||||
* disposition type value (usually <code>inline</code> or
|
||||
* <code>attachment</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param size
|
||||
* size parameter value or <code>-1</code> if the parameter
|
||||
* should not be included.
|
||||
* @param creationDate
|
||||
* creation-date parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param modificationDate
|
||||
* modification-date parameter value or <code>null</code> if
|
||||
* the parameter should not be included.
|
||||
* @param readDate
|
||||
* read-date parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
*/
|
||||
public void setContentDisposition(String dispositionType, String filename,
|
||||
long size, Date creationDate, Date modificationDate, Date readDate) {
|
||||
Header header = obtainHeader();
|
||||
header.setField(newContentDisposition(dispositionType, filename, size,
|
||||
creationDate, modificationDate, readDate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename parameter of the content disposition of this
|
||||
* <code>Entity</code>.
|
||||
*
|
||||
* @return the filename parameter of the content disposition or
|
||||
* <code>null</code> if the filename has not been set.
|
||||
*/
|
||||
public String getFilename() {
|
||||
ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getFilename();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filename parameter of the content disposition of this
|
||||
* <code>Entity</code> to the specified value. If this entity does not
|
||||
* have a content disposition header field a new one with disposition type
|
||||
* <code>attachment</code> is created.
|
||||
*
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should be removed.
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
Header header = obtainHeader();
|
||||
ContentDispositionField field = (ContentDispositionField) header
|
||||
.getField(FieldName.CONTENT_DISPOSITION);
|
||||
if (field == null) {
|
||||
if (filename != null) {
|
||||
header.setField(newContentDisposition(
|
||||
ContentDispositionField.DISPOSITION_TYPE_ATTACHMENT,
|
||||
filename, -1, null, null, null));
|
||||
}
|
||||
} else {
|
||||
String dispositionType = field.getDispositionType();
|
||||
Map<String, String> parameters = new HashMap<String, String>(field
|
||||
.getParameters());
|
||||
if (filename == null) {
|
||||
parameters.remove(ContentDispositionField.PARAM_FILENAME);
|
||||
} else {
|
||||
parameters
|
||||
.put(ContentDispositionField.PARAM_FILENAME, filename);
|
||||
}
|
||||
header.setField(newContentDisposition(dispositionType, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the MIME type of this <code>Entity</code> matches the
|
||||
* given one. MIME types are case-insensitive.
|
||||
*
|
||||
* @param type the MIME type to match against.
|
||||
* @return <code>true</code> on match, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isMimeType(String type) {
|
||||
return getMimeType().equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the MIME type of this <code>Entity</code> is
|
||||
* <code>multipart/*</code>. Since multipart-entities must have
|
||||
* a boundary parameter in the <code>Content-Type</code> field this
|
||||
* method returns <code>false</code> if no boundary exists.
|
||||
*
|
||||
* @return <code>true</code> on match, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isMultipart() {
|
||||
ContentTypeField f = getContentTypeField();
|
||||
return f != null
|
||||
&& f.getBoundary() != null
|
||||
&& getMimeType().startsWith(
|
||||
ContentTypeField.TYPE_MULTIPART_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes of the body of this entity. Note that the dispose call does not
|
||||
* get forwarded to the parent entity of this Entity.
|
||||
*
|
||||
* Subclasses that need to free resources should override this method and
|
||||
* invoke super.dispose().
|
||||
*
|
||||
* @see org.apache.james.mime4j.dom.Disposable#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
if (body != null) {
|
||||
body.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the header of this entity. Creates and sets a new header if this
|
||||
* entity's header is currently <code>null</code>.
|
||||
*
|
||||
* @return the header of this entity; never <code>null</code>.
|
||||
*/
|
||||
Header obtainHeader() {
|
||||
if (header == null) {
|
||||
header = new Header();
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the header field with the specified name.
|
||||
*
|
||||
* @param <F>
|
||||
* concrete field type.
|
||||
* @param fieldName
|
||||
* name of the field to retrieve.
|
||||
* @return the header field or <code>null</code> if this entity has no
|
||||
* header or the header contains no such field.
|
||||
*/
|
||||
<F extends Field> F obtainField(String fieldName) {
|
||||
Header header = getHeader();
|
||||
if (header == null)
|
||||
return null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
F field = (F) header.getField(fieldName);
|
||||
return field;
|
||||
}
|
||||
|
||||
protected abstract String newUniqueBoundary();
|
||||
|
||||
protected abstract ContentDispositionField newContentDisposition(
|
||||
String dispositionType, String filename, long size,
|
||||
Date creationDate, Date modificationDate, Date readDate);
|
||||
|
||||
protected abstract ContentDispositionField newContentDisposition(
|
||||
String dispositionType, Map<String, String> parameters);
|
||||
|
||||
protected abstract ContentTypeField newContentType(String mimeType,
|
||||
Map<String, String> parameters);
|
||||
|
||||
protected abstract ContentTransferEncodingField newContentTransferEncoding(
|
||||
String contentTransferEncoding);
|
||||
|
||||
protected abstract String calcMimeType(ContentTypeField child, ContentTypeField parent);
|
||||
|
||||
protected abstract String calcTransferEncoding(ContentTransferEncodingField f);
|
||||
|
||||
protected abstract String calcCharset(ContentTypeField contentType);
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.james.mime4j.dom.field.Field;
|
||||
|
||||
/**
|
||||
* The header of an entity (see RFC 2045).
|
||||
*/
|
||||
public class Header implements Iterable<Field> {
|
||||
|
||||
private List<Field> fields = new LinkedList<Field>();
|
||||
private Map<String, List<Field>> fieldMap = new HashMap<String, List<Field>>();
|
||||
|
||||
/**
|
||||
* Creates a new empty <code>Header</code>.
|
||||
*/
|
||||
public Header() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Header</code> from the specified
|
||||
* <code>Header</code>. The <code>Header</code> instance is initialized
|
||||
* with a copy of the list of {@link Field}s of the specified
|
||||
* <code>Header</code>. The <code>Field</code> objects are not copied
|
||||
* because they are immutable and can safely be shared between headers.
|
||||
*
|
||||
* @param other
|
||||
* header to copy.
|
||||
*/
|
||||
public Header(Header other) {
|
||||
for (Field otherField : other.fields) {
|
||||
addField(otherField);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to the end of the list of fields.
|
||||
*
|
||||
* @param field the field to add.
|
||||
*/
|
||||
public void addField(Field field) {
|
||||
List<Field> values = fieldMap.get(field.getName().toLowerCase());
|
||||
if (values == null) {
|
||||
values = new LinkedList<Field>();
|
||||
fieldMap.put(field.getName().toLowerCase(), values);
|
||||
}
|
||||
values.add(field);
|
||||
fields.add(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fields of this header. The returned list will not be
|
||||
* modifiable.
|
||||
*
|
||||
* @return the list of <code>Field</code> objects.
|
||||
*/
|
||||
public List<Field> getFields() {
|
||||
return Collections.unmodifiableList(fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a <code>Field</code> given a field name. If there are multiple
|
||||
* such fields defined in this header the first one will be returned.
|
||||
*
|
||||
* @param name the field name (e.g. From, Subject).
|
||||
* @return the field or <code>null</code> if none found.
|
||||
*/
|
||||
public Field getField(String name) {
|
||||
List<Field> l = fieldMap.get(name.toLowerCase());
|
||||
if (l != null && !l.isEmpty()) {
|
||||
return l.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all <code>Field</code>s having the specified field name.
|
||||
*
|
||||
* @param name the field name (e.g. From, Subject).
|
||||
* @return the list of fields.
|
||||
*/
|
||||
public List<Field> getFields(final String name) {
|
||||
final String lowerCaseName = name.toLowerCase();
|
||||
final List<Field> l = fieldMap.get(lowerCaseName);
|
||||
final List<Field> results;
|
||||
if (l == null || l.isEmpty()) {
|
||||
results = Collections.emptyList();
|
||||
} else {
|
||||
results = Collections.unmodifiableList(l);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the list of fields of this header.
|
||||
*
|
||||
* @return an iterator.
|
||||
*/
|
||||
public Iterator<Field> iterator() {
|
||||
return Collections.unmodifiableList(fields).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all <code>Field</code>s having the specified field name.
|
||||
*
|
||||
* @param name
|
||||
* the field name (e.g. From, Subject).
|
||||
* @return number of fields removed.
|
||||
*/
|
||||
public int removeFields(String name) {
|
||||
final String lowerCaseName = name.toLowerCase();
|
||||
List<Field> removed = fieldMap.remove(lowerCaseName);
|
||||
if (removed == null || removed.isEmpty())
|
||||
return 0;
|
||||
|
||||
for (Iterator<Field> iterator = fields.iterator(); iterator.hasNext();) {
|
||||
Field field = iterator.next();
|
||||
if (field.getName().equalsIgnoreCase(name))
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
return removed.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or replaces a field. This method is useful for header fields such as
|
||||
* Subject or Message-ID that should not occur more than once in a message.
|
||||
*
|
||||
* If this <code>Header</code> does not already contain a header field of
|
||||
* the same name as the given field then it is added to the end of the list
|
||||
* of fields (same behavior as {@link #addField(Field)}). Otherwise the
|
||||
* first occurrence of a field with the same name is replaced by the given
|
||||
* field and all further occurrences are removed.
|
||||
*
|
||||
* @param field the field to set.
|
||||
*/
|
||||
public void setField(Field field) {
|
||||
final String lowerCaseName = field.getName().toLowerCase();
|
||||
List<Field> l = fieldMap.get(lowerCaseName);
|
||||
if (l == null || l.isEmpty()) {
|
||||
addField(field);
|
||||
return;
|
||||
}
|
||||
|
||||
l.clear();
|
||||
l.add(field);
|
||||
|
||||
int firstOccurrence = -1;
|
||||
int index = 0;
|
||||
for (Iterator<Field> iterator = fields.iterator(); iterator.hasNext(); index++) {
|
||||
Field f = iterator.next();
|
||||
if (f.getName().equalsIgnoreCase(field.getName())) {
|
||||
iterator.remove();
|
||||
|
||||
if (firstOccurrence == -1)
|
||||
firstOccurrence = index;
|
||||
}
|
||||
}
|
||||
|
||||
fields.add(firstOccurrence, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Header Object as String representation. Each headerline is
|
||||
* seperated by "\r\n"
|
||||
*
|
||||
* @return headers
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder(128);
|
||||
for (Field field : fields) {
|
||||
str.append(field.toString());
|
||||
str.append("\r\n");
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,512 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.james.mime4j.dom.address.Address;
|
||||
import org.apache.james.mime4j.dom.address.AddressList;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
import org.apache.james.mime4j.dom.address.MailboxList;
|
||||
import org.apache.james.mime4j.dom.field.AddressListField;
|
||||
import org.apache.james.mime4j.dom.field.DateTimeField;
|
||||
import org.apache.james.mime4j.dom.field.Field;
|
||||
import org.apache.james.mime4j.dom.field.FieldName;
|
||||
import org.apache.james.mime4j.dom.field.MailboxField;
|
||||
import org.apache.james.mime4j.dom.field.MailboxListField;
|
||||
import org.apache.james.mime4j.dom.field.UnstructuredField;
|
||||
|
||||
public abstract class Message extends Entity implements Body {
|
||||
|
||||
/**
|
||||
* Write the content to the given output stream using the
|
||||
* {@link org.apache.james.mime4j.message.MessageWriter#DEFAULT default} message writer.
|
||||
*
|
||||
* @param out
|
||||
* the output stream to write to.
|
||||
* @throws IOException
|
||||
* in case of an I/O error
|
||||
* @see org.apache.james.mime4j.message.MessageWriter
|
||||
*/
|
||||
public abstract void writeTo(OutputStream out) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Message-ID</i> header field of this message
|
||||
* or <code>null</code> if it is not present.
|
||||
*
|
||||
* @return the identifier of this message.
|
||||
*/
|
||||
public String getMessageId() {
|
||||
Field field = obtainField(FieldName.MESSAGE_ID);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and sets a new <i>Message-ID</i> header field for this message.
|
||||
* A <code>Header</code> is created if this message does not already have
|
||||
* one.
|
||||
*
|
||||
* @param hostname
|
||||
* host name to be included in the identifier or
|
||||
* <code>null</code> if no host name should be included.
|
||||
*/
|
||||
public void createMessageId(String hostname) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
header.setField(newMessageId(hostname));
|
||||
}
|
||||
|
||||
protected abstract Field newMessageId(String hostname);
|
||||
|
||||
/**
|
||||
* Returns the (decoded) value of the <i>Subject</i> header field of this
|
||||
* message or <code>null</code> if it is not present.
|
||||
*
|
||||
* @return the subject of this message.
|
||||
*/
|
||||
public String getSubject() {
|
||||
UnstructuredField field = obtainField(FieldName.SUBJECT);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Subject</i> header field for this message. The specified
|
||||
* string may contain non-ASCII characters, in which case it gets encoded as
|
||||
* an 'encoded-word' automatically. A <code>Header</code> is created if
|
||||
* this message does not already have one.
|
||||
*
|
||||
* @param subject
|
||||
* subject to set or <code>null</code> to remove the subject
|
||||
* header field.
|
||||
*/
|
||||
public void setSubject(String subject) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
if (subject == null) {
|
||||
header.removeFields(FieldName.SUBJECT);
|
||||
} else {
|
||||
header.setField(newSubject(subject));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Date</i> header field of this message as
|
||||
* <code>Date</code> object or <code>null</code> if it is not present.
|
||||
*
|
||||
* @return the date of this message.
|
||||
*/
|
||||
public Date getDate() {
|
||||
DateTimeField dateField = obtainField(FieldName.DATE);
|
||||
if (dateField == null)
|
||||
return null;
|
||||
|
||||
return dateField.getDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Date</i> header field for this message. This method uses the
|
||||
* default <code>TimeZone</code> of this host to encode the specified
|
||||
* <code>Date</code> object into a string.
|
||||
*
|
||||
* @param date
|
||||
* date to set or <code>null</code> to remove the date header
|
||||
* field.
|
||||
*/
|
||||
public void setDate(Date date) {
|
||||
setDate(date, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Date</i> header field for this message. The specified
|
||||
* <code>TimeZone</code> is used to encode the specified <code>Date</code>
|
||||
* object into a string.
|
||||
*
|
||||
* @param date
|
||||
* date to set or <code>null</code> to remove the date header
|
||||
* field.
|
||||
* @param zone
|
||||
* a time zone.
|
||||
*/
|
||||
public void setDate(Date date, TimeZone zone) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
if (date == null) {
|
||||
header.removeFields(FieldName.DATE);
|
||||
} else {
|
||||
header.setField(newDate(date, zone));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Sender</i> header field of this message as
|
||||
* <code>Mailbox</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return the sender of this message.
|
||||
*/
|
||||
public Mailbox getSender() {
|
||||
return getMailbox(FieldName.SENDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Sender</i> header field of this message to the specified
|
||||
* mailbox address.
|
||||
*
|
||||
* @param sender
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setSender(Mailbox sender) {
|
||||
setMailbox(FieldName.SENDER, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>From</i> header field of this message as
|
||||
* <code>MailboxList</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return value of the from field of this message.
|
||||
*/
|
||||
public MailboxList getFrom() {
|
||||
return getMailboxList(FieldName.FROM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>From</i> header field of this message to the specified
|
||||
* mailbox address.
|
||||
*
|
||||
* @param from
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setFrom(Mailbox from) {
|
||||
setMailboxList(FieldName.FROM, from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>From</i> header field of this message to the specified
|
||||
* mailbox addresses.
|
||||
*
|
||||
* @param from
|
||||
* addresses to set or <code>null</code> or no arguments to
|
||||
* remove the header field.
|
||||
*/
|
||||
public void setFrom(Mailbox... from) {
|
||||
setMailboxList(FieldName.FROM, from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>From</i> header field of this message to the specified
|
||||
* mailbox addresses.
|
||||
*
|
||||
* @param from
|
||||
* addresses to set or <code>null</code> or an empty collection
|
||||
* to remove the header field.
|
||||
*/
|
||||
public void setFrom(Collection<Mailbox> from) {
|
||||
setMailboxList(FieldName.FROM, from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>To</i> header field of this message as
|
||||
* <code>AddressList</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return value of the to field of this message.
|
||||
*/
|
||||
public AddressList getTo() {
|
||||
return getAddressList(FieldName.TO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>To</i> header field of this message to the specified
|
||||
* address.
|
||||
*
|
||||
* @param to
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setTo(Address to) {
|
||||
setAddressList(FieldName.TO, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>To</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param to
|
||||
* addresses to set or <code>null</code> or no arguments to
|
||||
* remove the header field.
|
||||
*/
|
||||
public void setTo(Address... to) {
|
||||
setAddressList(FieldName.TO, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>To</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param to
|
||||
* addresses to set or <code>null</code> or an empty collection
|
||||
* to remove the header field.
|
||||
*/
|
||||
public void setTo(Collection<Address> to) {
|
||||
setAddressList(FieldName.TO, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Cc</i> header field of this message as
|
||||
* <code>AddressList</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return value of the cc field of this message.
|
||||
*/
|
||||
public AddressList getCc() {
|
||||
return getAddressList(FieldName.CC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Cc</i> header field of this message to the specified
|
||||
* address.
|
||||
*
|
||||
* @param cc
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setCc(Address cc) {
|
||||
setAddressList(FieldName.CC, cc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Cc</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param cc
|
||||
* addresses to set or <code>null</code> or no arguments to
|
||||
* remove the header field.
|
||||
*/
|
||||
public void setCc(Address... cc) {
|
||||
setAddressList(FieldName.CC, cc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Cc</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param cc
|
||||
* addresses to set or <code>null</code> or an empty collection
|
||||
* to remove the header field.
|
||||
*/
|
||||
public void setCc(Collection<Address> cc) {
|
||||
setAddressList(FieldName.CC, cc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Bcc</i> header field of this message as
|
||||
* <code>AddressList</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return value of the bcc field of this message.
|
||||
*/
|
||||
public AddressList getBcc() {
|
||||
return getAddressList(FieldName.BCC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Bcc</i> header field of this message to the specified
|
||||
* address.
|
||||
*
|
||||
* @param bcc
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setBcc(Address bcc) {
|
||||
setAddressList(FieldName.BCC, bcc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Bcc</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param bcc
|
||||
* addresses to set or <code>null</code> or no arguments to
|
||||
* remove the header field.
|
||||
*/
|
||||
public void setBcc(Address... bcc) {
|
||||
setAddressList(FieldName.BCC, bcc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Bcc</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param bcc
|
||||
* addresses to set or <code>null</code> or an empty collection
|
||||
* to remove the header field.
|
||||
*/
|
||||
public void setBcc(Collection<Address> bcc) {
|
||||
setAddressList(FieldName.BCC, bcc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the <i>Reply-To</i> header field of this message as
|
||||
* <code>AddressList</code> object or <code>null</code> if it is not
|
||||
* present.
|
||||
*
|
||||
* @return value of the reply to field of this message.
|
||||
*/
|
||||
public AddressList getReplyTo() {
|
||||
return getAddressList(FieldName.REPLY_TO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Reply-To</i> header field of this message to the specified
|
||||
* address.
|
||||
*
|
||||
* @param replyTo
|
||||
* address to set or <code>null</code> to remove the header
|
||||
* field.
|
||||
*/
|
||||
public void setReplyTo(Address replyTo) {
|
||||
setAddressList(FieldName.REPLY_TO, replyTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Reply-To</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param replyTo
|
||||
* addresses to set or <code>null</code> or no arguments to
|
||||
* remove the header field.
|
||||
*/
|
||||
public void setReplyTo(Address... replyTo) {
|
||||
setAddressList(FieldName.REPLY_TO, replyTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <i>Reply-To</i> header field of this message to the specified
|
||||
* addresses.
|
||||
*
|
||||
* @param replyTo
|
||||
* addresses to set or <code>null</code> or an empty collection
|
||||
* to remove the header field.
|
||||
*/
|
||||
public void setReplyTo(Collection<Address> replyTo) {
|
||||
setAddressList(FieldName.REPLY_TO, replyTo);
|
||||
}
|
||||
|
||||
private Mailbox getMailbox(String fieldName) {
|
||||
MailboxField field = obtainField(fieldName);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getMailbox();
|
||||
}
|
||||
|
||||
private void setMailbox(String fieldName, Mailbox mailbox) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
if (mailbox == null) {
|
||||
header.removeFields(fieldName);
|
||||
} else {
|
||||
header.setField(newMailbox(fieldName, mailbox));
|
||||
}
|
||||
}
|
||||
|
||||
private MailboxList getMailboxList(String fieldName) {
|
||||
MailboxListField field = obtainField(fieldName);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getMailboxList();
|
||||
}
|
||||
|
||||
private void setMailboxList(String fieldName, Mailbox mailbox) {
|
||||
setMailboxList(fieldName, mailbox == null ? null : Collections
|
||||
.singleton(mailbox));
|
||||
}
|
||||
|
||||
private void setMailboxList(String fieldName, Mailbox... mailboxes) {
|
||||
setMailboxList(fieldName, mailboxes == null ? null : Arrays
|
||||
.asList(mailboxes));
|
||||
}
|
||||
|
||||
private void setMailboxList(String fieldName, Collection<Mailbox> mailboxes) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
if (mailboxes == null || mailboxes.isEmpty()) {
|
||||
header.removeFields(fieldName);
|
||||
} else {
|
||||
header.setField(newMailboxList(fieldName, mailboxes));
|
||||
}
|
||||
}
|
||||
|
||||
private AddressList getAddressList(String fieldName) {
|
||||
AddressListField field = obtainField(fieldName);
|
||||
if (field == null)
|
||||
return null;
|
||||
|
||||
return field.getAddressList();
|
||||
}
|
||||
|
||||
private void setAddressList(String fieldName, Address address) {
|
||||
setAddressList(fieldName, address == null ? null : Collections
|
||||
.singleton(address));
|
||||
}
|
||||
|
||||
private void setAddressList(String fieldName, Address... addresses) {
|
||||
setAddressList(fieldName, addresses == null ? null : Arrays
|
||||
.asList(addresses));
|
||||
}
|
||||
|
||||
private void setAddressList(String fieldName, Collection<Address> addresses) {
|
||||
Header header = obtainHeader();
|
||||
|
||||
if (addresses == null || addresses.isEmpty()) {
|
||||
header.removeFields(fieldName);
|
||||
} else {
|
||||
header.setField(newAddressList(fieldName, addresses));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AddressListField newAddressList(String fieldName, Collection<Address> addresses);
|
||||
|
||||
protected abstract UnstructuredField newSubject(String subject);
|
||||
|
||||
protected abstract DateTimeField newDate(Date date, TimeZone zone);
|
||||
|
||||
protected abstract MailboxField newMailbox(String fieldName, Mailbox mailbox);
|
||||
|
||||
protected abstract MailboxListField newMailboxList(String fieldName, Collection<Mailbox> mailboxes);
|
||||
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.james.mime4j.MimeException;
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
|
||||
/**
|
||||
* Defines the API to obtain Message instances from a mime stream.
|
||||
*/
|
||||
public abstract class MessageBuilder {
|
||||
|
||||
public abstract Message newMessage();
|
||||
|
||||
public abstract Message newMessage(Message source);
|
||||
|
||||
public abstract Message parse(InputStream source) throws MimeException, IOException;
|
||||
|
||||
public abstract void setDecodeMonitor(
|
||||
DecodeMonitor decodeMonitor);
|
||||
|
||||
public abstract void setContentDecoding(boolean contentDecoding);
|
||||
|
||||
public abstract void setFlatMode();
|
||||
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import org.apache.james.mime4j.MimeException;
|
||||
|
||||
/**
|
||||
* A MessageBuilderFactory is used to create EntityBuilder instances.
|
||||
*
|
||||
* MessageBuilderFactory.newInstance() is used to get access to an implementation
|
||||
* of MessageBuilderFactory.
|
||||
* Then the method newMessageBuilder is used to create a new EntityBuilder object.
|
||||
*/
|
||||
public abstract class MessageBuilderFactory {
|
||||
|
||||
public abstract MessageBuilder newMessageBuilder() throws MimeException;
|
||||
|
||||
public static MessageBuilderFactory newInstance() throws MimeException {
|
||||
return ServiceLoader.load(MessageBuilderFactory.class);
|
||||
}
|
||||
|
||||
public abstract void setAttribute(String name, Object value) throws IllegalArgumentException;
|
||||
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a MIME multipart body (see RFC 2045).A multipart body has a
|
||||
* ordered list of body parts. The multipart body also has a preamble and
|
||||
* epilogue. The preamble consists of whatever characters appear before the
|
||||
* first body part while the epilogue consists of whatever characters come after
|
||||
* the last body part.
|
||||
*/
|
||||
public abstract class Multipart implements Body {
|
||||
|
||||
protected List<Entity> bodyParts = new LinkedList<Entity>();
|
||||
private Entity parent = null;
|
||||
|
||||
private String subType;
|
||||
|
||||
/**
|
||||
* Creates a new empty <code>Multipart</code> instance.
|
||||
*/
|
||||
public Multipart(String subType) {
|
||||
this.subType = subType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the multipart sub-type. E.g. <code>alternative</code> (the
|
||||
* default) or <code>parallel</code>. See RFC 2045 for common sub-types
|
||||
* and their meaning.
|
||||
*
|
||||
* @return the multipart sub-type.
|
||||
*/
|
||||
public String getSubType() {
|
||||
return subType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the multipart sub-type. E.g. <code>alternative</code> or
|
||||
* <code>parallel</code>. See RFC 2045 for common sub-types and their
|
||||
* meaning.
|
||||
*
|
||||
* @param subType
|
||||
* the sub-type.
|
||||
*/
|
||||
public void setSubType(String subType) {
|
||||
this.subType = subType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.Body#getParent()
|
||||
*/
|
||||
public Entity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.Body#setParent(org.apache.james.mime4j.dom.Entity)
|
||||
*/
|
||||
public void setParent(Entity parent) {
|
||||
this.parent = parent;
|
||||
for (Entity bodyPart : bodyParts) {
|
||||
bodyPart.setParent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of body parts.
|
||||
*
|
||||
* @return number of <code>Entity</code> objects.
|
||||
*/
|
||||
public int getCount() {
|
||||
return bodyParts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of body parts. The list is immutable.
|
||||
*
|
||||
* @return the list of <code>Entity</code> objects.
|
||||
*/
|
||||
public List<Entity> getBodyParts() {
|
||||
return Collections.unmodifiableList(bodyParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of body parts.
|
||||
*
|
||||
* @param bodyParts
|
||||
* the new list of <code>Entity</code> objects.
|
||||
*/
|
||||
public void setBodyParts(List<Entity> bodyParts) {
|
||||
this.bodyParts = bodyParts;
|
||||
for (Entity bodyPart : bodyParts) {
|
||||
bodyPart.setParent(parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a body part to the end of the list of body parts.
|
||||
*
|
||||
* @param bodyPart
|
||||
* the body part.
|
||||
*/
|
||||
public void addBodyPart(Entity bodyPart) {
|
||||
if (bodyPart == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
bodyParts.add(bodyPart);
|
||||
bodyPart.setParent(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a body part at the specified position in the list of body parts.
|
||||
*
|
||||
* @param bodyPart
|
||||
* the body part.
|
||||
* @param index
|
||||
* index at which the specified body part is to be inserted.
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the index is out of range (index < 0 || index >
|
||||
* getCount()).
|
||||
*/
|
||||
public void addBodyPart(Entity bodyPart, int index) {
|
||||
if (bodyPart == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
bodyParts.add(index, bodyPart);
|
||||
bodyPart.setParent(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the body part at the specified position in the list of body
|
||||
* parts.
|
||||
*
|
||||
* @param index
|
||||
* index of the body part to be removed.
|
||||
* @return the removed body part.
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the index is out of range (index < 0 || index >=
|
||||
* getCount()).
|
||||
*/
|
||||
public Entity removeBodyPart(int index) {
|
||||
Entity bodyPart = bodyParts.remove(index);
|
||||
bodyPart.setParent(null);
|
||||
return bodyPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the body part at the specified position in the list of body
|
||||
* parts with the specified body part.
|
||||
*
|
||||
* @param bodyPart
|
||||
* body part to be stored at the specified position.
|
||||
* @param index
|
||||
* index of body part to replace.
|
||||
* @return the replaced body part.
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if the index is out of range (index < 0 || index >=
|
||||
* getCount()).
|
||||
*/
|
||||
public Entity replaceBodyPart(Entity bodyPart, int index) {
|
||||
if (bodyPart == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
Entity replacedEntity = bodyParts.set(index, bodyPart);
|
||||
if (bodyPart == replacedEntity)
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot replace body part with itself");
|
||||
|
||||
bodyPart.setParent(parent);
|
||||
replacedEntity.setParent(null);
|
||||
|
||||
return replacedEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the preamble or null if the message has no preamble.
|
||||
*
|
||||
* @return the preamble.
|
||||
*/
|
||||
public abstract String getPreamble();
|
||||
|
||||
/**
|
||||
* Sets the preamble with a value or null to remove the preamble.
|
||||
*
|
||||
* @param preamble
|
||||
* the preamble.
|
||||
*/
|
||||
public abstract void setPreamble(String preamble);
|
||||
|
||||
/**
|
||||
* Gets the epilogue or null if the message has no epilogue
|
||||
*
|
||||
* @return the epilogue.
|
||||
*/
|
||||
public abstract String getEpilogue();
|
||||
|
||||
/**
|
||||
* Sets the epilogue value, or remove it if the value passed is null.
|
||||
*
|
||||
* @param epilogue
|
||||
* the epilogue.
|
||||
*/
|
||||
public abstract void setEpilogue(String epilogue);
|
||||
|
||||
/**
|
||||
* Disposes of the BodyParts of this Multipart. Note that the dispose call
|
||||
* does not get forwarded to the parent entity of this Multipart.
|
||||
*
|
||||
* @see org.apache.james.mime4j.dom.Disposable#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
for (Entity bodyPart : bodyParts) {
|
||||
bodyPart.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* Utility class to load Service Providers (SPI).
|
||||
* This will deprecated as soon as mime4j will be upgraded to Java6
|
||||
* as Java6 has javax.util.ServiceLoader as a core class.
|
||||
*/
|
||||
class ServiceLoader {
|
||||
|
||||
private ServiceLoader() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Service Provider for the given interface/class (SPI).
|
||||
*/
|
||||
static <T> T load(Class<T> spiClass) {
|
||||
String spiResURI = "META-INF/services/" + spiClass.getName();
|
||||
ClassLoader classLoader = spiClass.getClassLoader();
|
||||
Enumeration<URL> resources;
|
||||
try {
|
||||
resources = classLoader.getResources(spiResURI);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (resources.hasMoreElements()) {
|
||||
URL resource = resources.nextElement();
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(resource
|
||||
.openStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
int cmtIdx = line.indexOf('#');
|
||||
if (cmtIdx != -1) {
|
||||
line = line.substring(0, cmtIdx);
|
||||
line = line.trim();
|
||||
}
|
||||
|
||||
if (line.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> implClass;
|
||||
try {
|
||||
implClass = classLoader.loadClass(line);
|
||||
|
||||
if (spiClass.isAssignableFrom(implClass)) {
|
||||
Object impl = implClass.newInstance();
|
||||
return spiClass.cast(impl);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract implementation of a single message body; that is, a body that does
|
||||
* not contain (directly or indirectly) any other child bodies. It also provides
|
||||
* the parent functionality required by bodies.
|
||||
*/
|
||||
public abstract class SingleBody implements Body {
|
||||
|
||||
private Entity parent = null;
|
||||
|
||||
/**
|
||||
* Sole constructor.
|
||||
*/
|
||||
protected SingleBody() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.Body#getParent()
|
||||
*/
|
||||
public Entity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.Body#setParent(org.apache.james.mime4j.dom.Entity)
|
||||
*/
|
||||
public void setParent(Entity parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a <code>InputStream</code> which reads the bytes of the body.
|
||||
*
|
||||
* @return the stream, transfer decoded
|
||||
* @throws IOException
|
||||
* on I/O errors.
|
||||
*/
|
||||
public abstract InputStream getInputStream() throws IOException;
|
||||
|
||||
/**
|
||||
* Writes this single body to the given stream. The default implementation copies
|
||||
* the input stream obtained by {@link #getInputStream()} to the specified output
|
||||
* stream. May be overwritten by a subclass to improve performance.
|
||||
*
|
||||
* @param out
|
||||
* the stream to write to.
|
||||
* @throws IOException
|
||||
* in case of an I/O error
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
if (out == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
InputStream in = getInputStream();
|
||||
SingleBody.copy(in, out);
|
||||
in.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this <code>SingleBody</code> (optional operation).
|
||||
* <p>
|
||||
* The general contract of this method is as follows:
|
||||
* <ul>
|
||||
* <li>Invoking {@link #getParent()} on the copy returns <code>null</code>.
|
||||
* That means that the copy is detached from the parent entity of this
|
||||
* <code>SingleBody</code>. The copy may get attached to a different
|
||||
* entity later on.</li>
|
||||
* <li>The underlying content does not have to be copied. Instead it may be
|
||||
* shared between multiple copies of a <code>SingleBody</code>.</li>
|
||||
* <li>If the underlying content is shared by multiple copies the
|
||||
* implementation has to make sure that the content gets deleted when the
|
||||
* last copy gets disposed of (and not before that).</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This implementation always throws an
|
||||
* <code>UnsupportedOperationException</code>.
|
||||
*
|
||||
* @return a copy of this <code>SingleBody</code>.
|
||||
* @throws UnsupportedOperationException
|
||||
* if the <code>copy</code> operation is not supported by this
|
||||
* single body.
|
||||
*/
|
||||
public SingleBody copy() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should override this method if they have allocated resources
|
||||
* that need to be freed explicitly (e.g. cannot be simply reclaimed by the
|
||||
* garbage collector).
|
||||
*
|
||||
* The default implementation of this method does nothing.
|
||||
*
|
||||
* @see org.apache.james.mime4j.dom.Disposable#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
static final int DEFAULT_ENCODING_BUFFER_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* Copies the contents of one stream to the other.
|
||||
* @param in not null
|
||||
* @param out not null
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void copy(final InputStream in, final OutputStream out) throws IOException {
|
||||
final byte[] buffer = new byte[DEFAULT_ENCODING_BUFFER_SIZE];
|
||||
int inputLength;
|
||||
while (-1 != (inputLength = in.read(buffer))) {
|
||||
out.write(buffer, 0, inputLength);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Encapsulates the contents of a <code>text/*</code> entity body.
|
||||
*/
|
||||
public abstract class TextBody extends SingleBody {
|
||||
|
||||
/**
|
||||
* Sole constructor.
|
||||
*/
|
||||
protected TextBody() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MIME charset of this text body.
|
||||
*
|
||||
* @return the MIME charset.
|
||||
*/
|
||||
public abstract String getMimeCharset();
|
||||
|
||||
/**
|
||||
* Gets a <code>Reader</code> which may be used to read out the contents
|
||||
* of this body.
|
||||
*
|
||||
* @return the <code>Reader</code>.
|
||||
* @throws IOException
|
||||
* on I/O errors.
|
||||
*/
|
||||
public abstract Reader getReader() throws IOException;
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The abstract base for classes that represent RFC2822 addresses. This includes
|
||||
* groups and mailboxes.
|
||||
*/
|
||||
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
|
||||
* method is needed to allow the behavior to be overridden by subclasses.
|
||||
*/
|
||||
final void addMailboxesTo(List<Mailbox> results) {
|
||||
doAddMailboxesTo(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any mailboxes represented by this address into the given List. Must
|
||||
* be overridden by concrete subclasses.
|
||||
*/
|
||||
protected abstract void doAddMailboxesTo(List<Mailbox> results);
|
||||
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An immutable, random-access list of Address objects.
|
||||
*/
|
||||
public class AddressList extends AbstractList<Address> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<? extends Address> addresses;
|
||||
|
||||
/**
|
||||
* @param addresses
|
||||
* A List that contains only Address objects.
|
||||
* @param dontCopy
|
||||
* true iff it is not possible for the addresses list to be
|
||||
* modified by someone else.
|
||||
*/
|
||||
public AddressList(List<? extends Address> addresses, boolean dontCopy) {
|
||||
if (addresses != null)
|
||||
this.addresses = dontCopy ? addresses : new ArrayList<Address>(
|
||||
addresses);
|
||||
else
|
||||
this.addresses = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of elements in this list.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return addresses.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an address.
|
||||
*/
|
||||
@Override
|
||||
public Address get(int index) {
|
||||
return addresses.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flat list of all mailboxes represented in this address list.
|
||||
* Use this if you don't care about grouping.
|
||||
*/
|
||||
public MailboxList flatten() {
|
||||
// in the common case, all addresses are mailboxes
|
||||
boolean groupDetected = false;
|
||||
for (Address addr : addresses) {
|
||||
if (!(addr instanceof Mailbox)) {
|
||||
groupDetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupDetected) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Mailbox> mailboxes = (List<Mailbox>) addresses;
|
||||
return new MailboxList(mailboxes, true);
|
||||
}
|
||||
|
||||
List<Mailbox> results = new ArrayList<Mailbox>();
|
||||
for (Address addr : addresses) {
|
||||
addr.addMailboxesTo(results);
|
||||
}
|
||||
|
||||
// copy-on-construct this time, because subclasses
|
||||
// could have held onto a reference to the results
|
||||
return new MailboxList(results, false);
|
||||
}
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An immutable, random-access list of Strings (that are supposedly domain names
|
||||
* or domain literals).
|
||||
*/
|
||||
public class DomainList extends AbstractList<String> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<String> domains;
|
||||
|
||||
/**
|
||||
* @param domains
|
||||
* A List that contains only String objects.
|
||||
* @param dontCopy
|
||||
* true iff it is not possible for the domains list to be
|
||||
* modified by someone else.
|
||||
*/
|
||||
public DomainList(List<String> domains, boolean dontCopy) {
|
||||
if (domains != null)
|
||||
this.domains = dontCopy ? domains : new ArrayList<String>(domains);
|
||||
else
|
||||
this.domains = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of elements in this list.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return domains.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the domain name or domain literal at the specified index.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If index is < 0 or >= size().
|
||||
*/
|
||||
@Override
|
||||
public String get(int index) {
|
||||
return domains.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of domains formatted as a route string (not including
|
||||
* the trailing ':').
|
||||
*/
|
||||
public String toRouteString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (String domain : domains) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
|
||||
sb.append("@");
|
||||
sb.append(domain);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toRouteString();
|
||||
}
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A named group of zero or more mailboxes.
|
||||
*/
|
||||
public class Group extends Address {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String name;
|
||||
private final MailboxList mailboxList;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The group name.
|
||||
* @param mailboxes
|
||||
* The mailboxes in this group.
|
||||
*/
|
||||
public Group(String name, MailboxList mailboxes) {
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException();
|
||||
if (mailboxes == null)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
this.name = name;
|
||||
this.mailboxList = mailboxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The group name.
|
||||
* @param mailboxes
|
||||
* The mailboxes in this group.
|
||||
*/
|
||||
public Group(String name, Mailbox... mailboxes) {
|
||||
this(name, new MailboxList(Arrays.asList(mailboxes), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The group name.
|
||||
* @param mailboxes
|
||||
* The mailboxes in this group.
|
||||
*/
|
||||
public Group(String name, Collection<Mailbox> mailboxes) {
|
||||
this(name, new MailboxList(new ArrayList<Mailbox>(mailboxes), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the group name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mailboxes in this group.
|
||||
*/
|
||||
public MailboxList getMailboxes() {
|
||||
return mailboxList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAddMailboxesTo(List<Mailbox> results) {
|
||||
for (Mailbox mailbox : mailboxList) {
|
||||
results.add(mailbox);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
sb.append(':');
|
||||
boolean first = true;
|
||||
for (Mailbox mailbox : mailboxList) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(' ');
|
||||
sb.append(mailbox);
|
||||
}
|
||||
sb.append(";");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.james.mime4j.util.LangUtils;
|
||||
|
||||
/**
|
||||
* Represents a single e-mail address.
|
||||
*/
|
||||
public class Mailbox extends Address {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final DomainList EMPTY_ROUTE_LIST = new DomainList(
|
||||
Collections.<String> emptyList(), true);
|
||||
|
||||
private final String name;
|
||||
private final DomainList route;
|
||||
private final String localPart;
|
||||
private final String domain;
|
||||
|
||||
/**
|
||||
* Creates a named mailbox with a route. Routes are obsolete.
|
||||
*
|
||||
* @param name
|
||||
* the name of the e-mail address. May be <code>null</code>.
|
||||
* @param route
|
||||
* The zero or more domains that make up the route. May be
|
||||
* <code>null</code>.
|
||||
* @param localPart
|
||||
* The part of the e-mail address to the left of the "@".
|
||||
* @param domain
|
||||
* The part of the e-mail address to the right of the "@".
|
||||
*/
|
||||
public Mailbox(String name, DomainList route, String localPart,
|
||||
String domain) {
|
||||
if (localPart == null || localPart.length() == 0)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
this.name = name == null || name.length() == 0 ? null : name;
|
||||
this.route = route == null ? EMPTY_ROUTE_LIST : route;
|
||||
this.localPart = localPart;
|
||||
this.domain = domain == null || domain.length() == 0 ? null : domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a named mailbox based on an unnamed mailbox. Package private;
|
||||
* internally used by Builder.
|
||||
*/
|
||||
Mailbox(String name, Mailbox baseMailbox) {
|
||||
this(name, baseMailbox.getRoute(), baseMailbox.getLocalPart(),
|
||||
baseMailbox.getDomain());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unnamed mailbox without a route. Routes are obsolete.
|
||||
*
|
||||
* @param localPart
|
||||
* The part of the e-mail address to the left of the "@".
|
||||
* @param domain
|
||||
* The part of the e-mail address to the right of the "@".
|
||||
*/
|
||||
public Mailbox(String localPart, String domain) {
|
||||
this(null, null, localPart, domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an unnamed mailbox with a route. Routes are obsolete.
|
||||
*
|
||||
* @param route
|
||||
* The zero or more domains that make up the route. May be
|
||||
* <code>null</code>.
|
||||
* @param localPart
|
||||
* The part of the e-mail address to the left of the "@".
|
||||
* @param domain
|
||||
* The part of the e-mail address to the right of the "@".
|
||||
*/
|
||||
public Mailbox(DomainList route, String localPart, String domain) {
|
||||
this(null, route, localPart, domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a named mailbox without a route. Routes are obsolete.
|
||||
*
|
||||
* @param name
|
||||
* the name of the e-mail address. May be <code>null</code>.
|
||||
* @param localPart
|
||||
* The part of the e-mail address to the left of the "@".
|
||||
* @param domain
|
||||
* The part of the e-mail address to the right of the "@".
|
||||
*/
|
||||
public Mailbox(String name, String localPart, String domain) {
|
||||
this(name, null, localPart, domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the mailbox or <code>null</code> if it does not
|
||||
* have a name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route list. If the mailbox does not have a route an empty
|
||||
* domain list is returned.
|
||||
*/
|
||||
public DomainList getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the left part of the e-mail address (before "@").
|
||||
*/
|
||||
public String getLocalPart() {
|
||||
return localPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the right part of the e-mail address (after "@").
|
||||
*/
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address in the form <i>localPart@domain</i>.
|
||||
*
|
||||
* @return the address part of this mailbox.
|
||||
*/
|
||||
public String getAddress() {
|
||||
if (domain == null) {
|
||||
return localPart;
|
||||
} else {
|
||||
return localPart + '@' + domain;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void doAddMailboxesTo(List<Mailbox> results) {
|
||||
results.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = LangUtils.HASH_SEED;
|
||||
hash = LangUtils.hashCode(hash, this.localPart);
|
||||
hash = LangUtils.hashCode(hash, this.domain != null ?
|
||||
this.domain.toLowerCase(Locale.US) : null);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this mailbox.
|
||||
* <p>
|
||||
* An object is considered to be equal to this mailbox if it is an instance
|
||||
* of class <code>Mailbox</code> that holds the same address as this one.
|
||||
* The domain is considered to be case-insensitive but the local-part is not
|
||||
* (because of RFC 5321: <cite>the local-part of a mailbox MUST BE treated
|
||||
* as case sensitive</cite>).
|
||||
*
|
||||
* @param obj
|
||||
* the object to test for equality.
|
||||
* @return <code>true</code> if the specified object is a
|
||||
* <code>Mailbox</code> that holds the same address as this one.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (!(obj instanceof Mailbox))
|
||||
return false;
|
||||
Mailbox that = (Mailbox) obj;
|
||||
return LangUtils.equals(this.localPart, that.localPart) &&
|
||||
LangUtils.equalsIgnoreCase(this.domain, that.domain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAddress();
|
||||
}
|
||||
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.address;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An immutable, random-access list of Mailbox objects.
|
||||
*/
|
||||
public class MailboxList extends AbstractList<Mailbox> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Mailbox> mailboxes;
|
||||
|
||||
/**
|
||||
* @param mailboxes
|
||||
* A List that contains only Mailbox objects.
|
||||
* @param dontCopy
|
||||
* true iff it is not possible for the mailboxes list to be
|
||||
* modified by someone else.
|
||||
*/
|
||||
public MailboxList(List<Mailbox> mailboxes, boolean dontCopy) {
|
||||
if (mailboxes != null)
|
||||
this.mailboxes = dontCopy ? mailboxes : new ArrayList<Mailbox>(
|
||||
mailboxes);
|
||||
else
|
||||
this.mailboxes = Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of elements in this list.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return mailboxes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an address.
|
||||
*/
|
||||
@Override
|
||||
public Mailbox get(int index) {
|
||||
return mailboxes.get(index);
|
||||
}
|
||||
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.datetime;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class DateTime {
|
||||
private final Date date;
|
||||
private final int year;
|
||||
private final int month;
|
||||
private final int day;
|
||||
private final int hour;
|
||||
private final int minute;
|
||||
private final int second;
|
||||
private final int timeZone;
|
||||
|
||||
public DateTime(String yearString, int month, int day, int hour, int minute, int second, int timeZone) {
|
||||
this.year = convertToYear(yearString);
|
||||
this.date = convertToDate(year, month, day, hour, minute, second, timeZone);
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
this.hour = hour;
|
||||
this.minute = minute;
|
||||
this.second = second;
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
private int convertToYear(String yearString) {
|
||||
int year = Integer.parseInt(yearString);
|
||||
switch (yearString.length()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (year >= 0 && year < 50)
|
||||
return 2000 + year;
|
||||
else
|
||||
return 1900 + year;
|
||||
case 3:
|
||||
return 1900 + year;
|
||||
default:
|
||||
return year;
|
||||
}
|
||||
}
|
||||
|
||||
public static Date convertToDate(int year, int month, int day, int hour, int minute, int second, int timeZone) {
|
||||
Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT+0"));
|
||||
c.set(year, month - 1, day, hour, minute, second);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
if (timeZone != Integer.MIN_VALUE) {
|
||||
int minutes = ((timeZone / 100) * 60) + timeZone % 100;
|
||||
c.add(Calendar.MINUTE, -1 * minutes);
|
||||
}
|
||||
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
public int getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public int getHour() {
|
||||
return hour;
|
||||
}
|
||||
|
||||
public int getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
public int getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public int getTimeZone() {
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
public void print() {
|
||||
System.out.println(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getYear() + " " + getMonth() + " " + getDay() + "; " + getHour() + " " + getMinute() + " " + getSecond() + " " + getTimeZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int PRIME = 31;
|
||||
int result = 1;
|
||||
result = PRIME * result + ((date == null) ? 0 : date.hashCode());
|
||||
result = PRIME * result + day;
|
||||
result = PRIME * result + hour;
|
||||
result = PRIME * result + minute;
|
||||
result = PRIME * result + month;
|
||||
result = PRIME * result + second;
|
||||
result = PRIME * result + timeZone;
|
||||
result = PRIME * result + year;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final DateTime other = (DateTime) obj;
|
||||
if (date == null) {
|
||||
if (other.date != null)
|
||||
return false;
|
||||
} else if (!date.equals(other.date))
|
||||
return false;
|
||||
if (day != other.day)
|
||||
return false;
|
||||
if (hour != other.hour)
|
||||
return false;
|
||||
if (minute != other.minute)
|
||||
return false;
|
||||
if (month != other.month)
|
||||
return false;
|
||||
if (second != other.second)
|
||||
return false;
|
||||
if (timeZone != other.timeZone)
|
||||
return false;
|
||||
if (year != other.year)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import org.apache.james.mime4j.dom.address.AddressList;
|
||||
|
||||
public interface AddressListField extends ParsedField {
|
||||
|
||||
AddressList getAddressList();
|
||||
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package org.apache.james.mime4j.dom.field;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ContentDispositionField extends ParsedField {
|
||||
|
||||
/** The <code>inline</code> disposition type. */
|
||||
public static final String DISPOSITION_TYPE_INLINE = "inline";
|
||||
/** The <code>attachment</code> disposition type. */
|
||||
public static final String DISPOSITION_TYPE_ATTACHMENT = "attachment";
|
||||
/** The name of the <code>filename</code> parameter. */
|
||||
public static final String PARAM_FILENAME = "filename";
|
||||
/** The name of the <code>creation-date</code> parameter. */
|
||||
public static final String PARAM_CREATION_DATE = "creation-date";
|
||||
/** The name of the <code>modification-date</code> parameter. */
|
||||
public static final String PARAM_MODIFICATION_DATE = "modification-date";
|
||||
/** The name of the <code>read-date</code> parameter. */
|
||||
public static final String PARAM_READ_DATE = "read-date";
|
||||
/** The name of the <code>size</code> parameter. */
|
||||
public static final String PARAM_SIZE = "size";
|
||||
|
||||
/**
|
||||
* Gets the disposition type defined in this Content-Disposition field.
|
||||
*
|
||||
* @return the disposition type or an empty string if not set.
|
||||
*/
|
||||
String getDispositionType();
|
||||
|
||||
/**
|
||||
* Gets the value of a parameter. Parameter names are case-insensitive.
|
||||
*
|
||||
* @param name
|
||||
* the name of the parameter to get.
|
||||
* @return the parameter value or <code>null</code> if not set.
|
||||
*/
|
||||
String getParameter(String name);
|
||||
|
||||
/**
|
||||
* Gets all parameters.
|
||||
*
|
||||
* @return the parameters.
|
||||
*/
|
||||
Map<String, String> getParameters();
|
||||
|
||||
/**
|
||||
* Determines if the disposition type of this field matches the given one.
|
||||
*
|
||||
* @param dispositionType
|
||||
* the disposition type to match against.
|
||||
* @return <code>true</code> if the disposition type of this field
|
||||
* matches, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isDispositionType(String dispositionType);
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the disposition type of this field is
|
||||
* <i>inline</i>, <code>false</code> otherwise.
|
||||
*
|
||||
* @return <code>true</code> if the disposition type of this field is
|
||||
* <i>inline</i>, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isInline();
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the disposition type of this field is
|
||||
* <i>attachment</i>, <code>false</code> otherwise.
|
||||
*
|
||||
* @return <code>true</code> if the disposition type of this field is
|
||||
* <i>attachment</i>, <code>false</code> otherwise.
|
||||
*/
|
||||
public abstract boolean isAttachment();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>filename</code> parameter if set.
|
||||
*
|
||||
* @return the <code>filename</code> parameter value or <code>null</code>
|
||||
* if not set.
|
||||
*/
|
||||
String getFilename();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>creation-date</code> parameter if set and
|
||||
* valid.
|
||||
*
|
||||
* @return the <code>creation-date</code> parameter value or
|
||||
* <code>null</code> if not set or invalid.
|
||||
*/
|
||||
Date getCreationDate();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>modification-date</code> parameter if set
|
||||
* and valid.
|
||||
*
|
||||
* @return the <code>modification-date</code> parameter value or
|
||||
* <code>null</code> if not set or invalid.
|
||||
*/
|
||||
Date getModificationDate();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>read-date</code> parameter if set and
|
||||
* valid.
|
||||
*
|
||||
* @return the <code>read-date</code> parameter value or <code>null</code>
|
||||
* if not set or invalid.
|
||||
*/
|
||||
Date getReadDate();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>size</code> parameter if set and valid.
|
||||
*
|
||||
* @return the <code>size</code> parameter value or <code>-1</code> if
|
||||
* not set or invalid.
|
||||
*/
|
||||
long getSize();
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
public interface ContentTransferEncodingField extends ParsedField {
|
||||
|
||||
/**
|
||||
* Gets the encoding defined in this field.
|
||||
*
|
||||
* @return the encoding or an empty string if not set.
|
||||
*/
|
||||
String getEncoding();
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ContentTypeField extends ParsedField {
|
||||
|
||||
/** The prefix of all <code>multipart</code> MIME types. */
|
||||
public static final String TYPE_MULTIPART_PREFIX = "multipart/";
|
||||
/** The <code>multipart/digest</code> MIME type. */
|
||||
public static final String TYPE_MULTIPART_DIGEST = "multipart/digest";
|
||||
/** The <code>text/plain</code> MIME type. */
|
||||
public static final String TYPE_TEXT_PLAIN = "text/plain";
|
||||
/** The <code>message/rfc822</code> MIME type. */
|
||||
public static final String TYPE_MESSAGE_RFC822 = "message/rfc822";
|
||||
/** The name of the <code>boundary</code> parameter. */
|
||||
public static final String PARAM_BOUNDARY = "boundary";
|
||||
/** The name of the <code>charset</code> parameter. */
|
||||
public static final String PARAM_CHARSET = "charset";
|
||||
|
||||
/**
|
||||
* Gets the MIME type defined in this Content-Type field.
|
||||
*
|
||||
* @return the MIME type or an empty string if not set.
|
||||
*/
|
||||
String getMimeType();
|
||||
|
||||
/**
|
||||
* Gets the value of a parameter. Parameter names are case-insensitive.
|
||||
*
|
||||
* @param name
|
||||
* the name of the parameter to get.
|
||||
* @return the parameter value or <code>null</code> if not set.
|
||||
*/
|
||||
String getParameter(String name);
|
||||
|
||||
/**
|
||||
* Gets all parameters.
|
||||
*
|
||||
* @return the parameters.
|
||||
*/
|
||||
Map<String, String> getParameters();
|
||||
|
||||
/**
|
||||
* Determines if the MIME type of this field matches the given one.
|
||||
*
|
||||
* @param mimeType
|
||||
* the MIME type to match against.
|
||||
* @return <code>true</code> if the MIME type of this field matches,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isMimeType(String mimeType);
|
||||
|
||||
/**
|
||||
* Determines if the MIME type of this field is <code>multipart/*</code>.
|
||||
*
|
||||
* @return <code>true</code> if this field is has a
|
||||
* <code>multipart/*</code> MIME type, <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
boolean isMultipart();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>boundary</code> parameter if set.
|
||||
*
|
||||
* @return the <code>boundary</code> parameter value or <code>null</code>
|
||||
* if not set.
|
||||
*/
|
||||
String getBoundary();
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>charset</code> parameter if set.
|
||||
*
|
||||
* @return the <code>charset</code> parameter value or <code>null</code>
|
||||
* if not set.
|
||||
*/
|
||||
String getCharset();
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package org.apache.james.mime4j.dom.field;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface DateTimeField extends ParsedField {
|
||||
|
||||
Date getDate();
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract MIME field.
|
||||
*/
|
||||
public interface Field {
|
||||
|
||||
/**
|
||||
* Gets the name of the field (<code>Subject</code>, <code>From</code>, etc).
|
||||
*
|
||||
* @return the field name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the unparsed and possibly encoded (see RFC 2047) field body string.
|
||||
*
|
||||
* @return the unparsed field body string.
|
||||
*/
|
||||
String getBody();
|
||||
|
||||
/**
|
||||
* Writes the original raw field bytes to an output stream.
|
||||
* The output is folded, the last CRLF is not included.
|
||||
* @throws IOException
|
||||
*/
|
||||
void writeTo(OutputStream out) throws IOException;
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
/**
|
||||
* Constants for common header field names.
|
||||
*/
|
||||
public class FieldName {
|
||||
|
||||
public static final String CONTENT_DISPOSITION = "Content-Disposition";
|
||||
public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
|
||||
public static final String CONTENT_TYPE = "Content-Type";
|
||||
|
||||
public static final String DATE = "Date";
|
||||
public static final String MESSAGE_ID = "Message-ID";
|
||||
public static final String SUBJECT = "Subject";
|
||||
|
||||
public static final String FROM = "From";
|
||||
public static final String SENDER = "Sender";
|
||||
public static final String TO = "To";
|
||||
public static final String CC = "Cc";
|
||||
public static final String BCC = "Bcc";
|
||||
public static final String REPLY_TO = "Reply-To";
|
||||
|
||||
public static final String RESENT_DATE = "Resent-Date";
|
||||
|
||||
public static final String RESENT_FROM = "Resent-From";
|
||||
public static final String RESENT_SENDER = "Resent-Sender";
|
||||
public static final String RESENT_TO = "Resent-To";
|
||||
public static final String RESENT_CC = "Resent-Cc";
|
||||
public static final String RESENT_BCC = "Resent-Bcc";
|
||||
|
||||
private FieldName() {
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
|
||||
public interface MailboxField extends ParsedField {
|
||||
|
||||
Mailbox getMailbox();
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import org.apache.james.mime4j.dom.address.MailboxList;
|
||||
|
||||
public interface MailboxListField extends ParsedField {
|
||||
|
||||
MailboxList getMailboxList();
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
import org.apache.james.mime4j.MimeException;
|
||||
|
||||
/**
|
||||
* This exception is thrown when parse errors are encountered.
|
||||
*/
|
||||
public class ParseException extends MimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs a new parse exception with the specified detail message.
|
||||
*
|
||||
* @param message
|
||||
* detail message
|
||||
*/
|
||||
protected ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parse exception with the specified cause.
|
||||
*
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
protected ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parse exception with the specified detail message and
|
||||
* cause.
|
||||
*
|
||||
* @param message
|
||||
* detail message
|
||||
* @param cause
|
||||
* the cause
|
||||
*/
|
||||
protected ParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
|
||||
public interface ParsedField extends Field {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this field is valid, i.e. no errors were
|
||||
* encountered while parsing the field value.
|
||||
*
|
||||
* @return <code>true</code> if this field is valid, <code>false</code>
|
||||
* otherwise.
|
||||
* @see #getParseException()
|
||||
*/
|
||||
boolean isValidField();
|
||||
|
||||
/**
|
||||
* Returns the exception that was thrown by the field parser while parsing
|
||||
* the field value. The result is <code>null</code> if the field is valid
|
||||
* and no errors were encountered.
|
||||
*
|
||||
* @return the exception that was thrown by the field parser or
|
||||
* <code>null</code> if the field is valid.
|
||||
*/
|
||||
ParseException getParseException();
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.dom.field;
|
||||
|
||||
public interface UnstructuredField extends ParsedField {
|
||||
|
||||
String getValue();
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.ParseException;
|
||||
import org.apache.james.mime4j.dom.field.ParsedField;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* The base class of all field classes.
|
||||
*/
|
||||
public abstract class AbstractField implements ParsedField {
|
||||
|
||||
private final String name;
|
||||
private final String body;
|
||||
private final ByteSequence raw;
|
||||
protected DecodeMonitor monitor;
|
||||
|
||||
protected AbstractField(
|
||||
final String name,
|
||||
final String body,
|
||||
final ByteSequence raw,
|
||||
final DecodeMonitor monitor) {
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
this.raw = raw;
|
||||
this.monitor = monitor != null ? monitor : DecodeMonitor.SILENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the field (<code>Subject</code>,
|
||||
* <code>From</code>, etc).
|
||||
*
|
||||
* @return the field name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.Field#writeTo(java.io.OutputStream)
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
out.write(raw.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field
|
||||
* body string.
|
||||
*
|
||||
* @return the unfolded unparsed field body string.
|
||||
*/
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ParsedField#isValidField()
|
||||
*/
|
||||
public boolean isValidField() {
|
||||
return getParseException() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ParsedField#getParseException()
|
||||
*/
|
||||
public ParseException getParseException() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + ": " + body;
|
||||
}
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.address.AddressList;
|
||||
import org.apache.james.mime4j.field.address.parser.AddressBuilder;
|
||||
import org.apache.james.mime4j.field.address.parser.ParseException;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Address list field such as <code>To</code> or <code>Reply-To</code>.
|
||||
*/
|
||||
public class AddressListFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.AddressListField {
|
||||
|
||||
private boolean parsed = false;
|
||||
|
||||
private AddressList addressList;
|
||||
private ParseException parseException;
|
||||
|
||||
AddressListFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.AddressListField#getAddressList()
|
||||
*/
|
||||
public AddressList getAddressList() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return addressList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.AddressListField#getParseException()
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
try {
|
||||
addressList = AddressBuilder.parseAddressList(body, monitor);
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<AddressListFieldImpl> PARSER = new FieldParser<AddressListFieldImpl>() {
|
||||
public AddressListFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new AddressListFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,253 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.field.contentdisposition.parser.ContentDispositionParser;
|
||||
import org.apache.james.mime4j.field.contentdisposition.parser.ParseException;
|
||||
import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError;
|
||||
import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Represents a <code>Content-Disposition</code> field.
|
||||
*/
|
||||
public class ContentDispositionFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.ContentDispositionField {
|
||||
|
||||
private boolean parsed = false;
|
||||
|
||||
private String dispositionType = "";
|
||||
private Map<String, String> parameters = new HashMap<String, String>();
|
||||
private ParseException parseException;
|
||||
|
||||
private boolean creationDateParsed;
|
||||
private Date creationDate;
|
||||
|
||||
private boolean modificationDateParsed;
|
||||
private Date modificationDate;
|
||||
|
||||
private boolean readDateParsed;
|
||||
private Date readDate;
|
||||
|
||||
ContentDispositionFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exception that was raised during parsing of the field value, if
|
||||
* any; otherwise, null.
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getDispositionType()
|
||||
*/
|
||||
public String getDispositionType() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return dispositionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getParameter(java.lang.String)
|
||||
*/
|
||||
public String getParameter(String name) {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parameters.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getParameters()
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return Collections.unmodifiableMap(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#isDispositionType(java.lang.String)
|
||||
*/
|
||||
public boolean isDispositionType(String dispositionType) {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return this.dispositionType.equalsIgnoreCase(dispositionType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#isInline()
|
||||
*/
|
||||
public boolean isInline() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return dispositionType.equals(DISPOSITION_TYPE_INLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#isAttachment()
|
||||
*/
|
||||
public boolean isAttachment() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return dispositionType.equals(DISPOSITION_TYPE_ATTACHMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getFilename()
|
||||
*/
|
||||
public String getFilename() {
|
||||
return getParameter(PARAM_FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getCreationDate()
|
||||
*/
|
||||
public Date getCreationDate() {
|
||||
if (!creationDateParsed) {
|
||||
creationDate = parseDate(PARAM_CREATION_DATE);
|
||||
creationDateParsed = true;
|
||||
}
|
||||
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getModificationDate()
|
||||
*/
|
||||
public Date getModificationDate() {
|
||||
if (!modificationDateParsed) {
|
||||
modificationDate = parseDate(PARAM_MODIFICATION_DATE);
|
||||
modificationDateParsed = true;
|
||||
}
|
||||
|
||||
return modificationDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getReadDate()
|
||||
*/
|
||||
public Date getReadDate() {
|
||||
if (!readDateParsed) {
|
||||
readDate = parseDate(PARAM_READ_DATE);
|
||||
readDateParsed = true;
|
||||
}
|
||||
|
||||
return readDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentDispositionField#getSize()
|
||||
*/
|
||||
public long getSize() {
|
||||
String value = getParameter(PARAM_SIZE);
|
||||
if (value == null)
|
||||
return -1;
|
||||
|
||||
try {
|
||||
long size = Long.parseLong(value);
|
||||
return size < 0 ? -1 : size;
|
||||
} catch (NumberFormatException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private Date parseDate(String paramName) {
|
||||
String value = getParameter(paramName);
|
||||
if (value == null) {
|
||||
monitor.warn("Parsing " + paramName + " null", "returning null");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new DateTimeParser(new StringReader(value)).parseAll()
|
||||
.getDate();
|
||||
} catch (org.apache.james.mime4j.field.datetime.parser.ParseException e) {
|
||||
monitor.warn("Parsing " + paramName + " '" + value + "': "
|
||||
+ e.getMessage(), "returning null");
|
||||
return null;
|
||||
} catch (org.apache.james.mime4j.field.datetime.parser.TokenMgrError e) {
|
||||
monitor.warn("Parsing " + paramName + " '" + value + "': "
|
||||
+ e.getMessage(), "returning null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
ContentDispositionParser parser = new ContentDispositionParser(
|
||||
new StringReader(body));
|
||||
try {
|
||||
parser.parseAll();
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
} catch (TokenMgrError e) {
|
||||
parseException = new ParseException(e.getMessage());
|
||||
}
|
||||
|
||||
final String dispositionType = parser.getDispositionType();
|
||||
|
||||
if (dispositionType != null) {
|
||||
this.dispositionType = dispositionType.toLowerCase(Locale.US);
|
||||
|
||||
List<String> paramNames = parser.getParamNames();
|
||||
List<String> paramValues = parser.getParamValues();
|
||||
|
||||
if (paramNames != null && paramValues != null) {
|
||||
final int len = Math.min(paramNames.size(), paramValues.size());
|
||||
for (int i = 0; i < len; i++) {
|
||||
String paramName = paramNames.get(i).toLowerCase(Locale.US);
|
||||
String paramValue = paramValues.get(i);
|
||||
parameters.put(paramName, paramValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<ContentDispositionFieldImpl> PARSER = new FieldParser<ContentDispositionFieldImpl>() {
|
||||
public ContentDispositionFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new ContentDispositionFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
|
||||
/**
|
||||
* Represents a <code>Content-Transfer-Encoding</code> field.
|
||||
*/
|
||||
public class ContentTransferEncodingFieldImpl extends AbstractField implements ContentTransferEncodingField {
|
||||
private String encoding;
|
||||
|
||||
ContentTransferEncodingFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
encoding = body.trim().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTransferEncodingField#getEncoding()
|
||||
*/
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the encoding of the given field if. Returns the default
|
||||
* <code>7bit</code> if not set or if <code>f</code> is
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @return the encoding.
|
||||
*/
|
||||
public static String getEncoding(ContentTransferEncodingField f) {
|
||||
if (f != null && f.getEncoding().length() != 0) {
|
||||
return f.getEncoding();
|
||||
}
|
||||
return MimeUtil.ENC_7BIT;
|
||||
}
|
||||
|
||||
static final FieldParser<ContentTransferEncodingFieldImpl> PARSER = new FieldParser<ContentTransferEncodingFieldImpl>() {
|
||||
public ContentTransferEncodingFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new ContentTransferEncodingFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.ContentTypeField;
|
||||
import org.apache.james.mime4j.field.contenttype.parser.ContentTypeParser;
|
||||
import org.apache.james.mime4j.field.contenttype.parser.ParseException;
|
||||
import org.apache.james.mime4j.field.contenttype.parser.TokenMgrError;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Represents a <code>Content-Type</code> field.
|
||||
*/
|
||||
public class ContentTypeFieldImpl extends AbstractField implements ContentTypeField {
|
||||
private boolean parsed = false;
|
||||
|
||||
private String mimeType = "";
|
||||
private Map<String, String> parameters = new HashMap<String, String>();
|
||||
private ParseException parseException;
|
||||
|
||||
ContentTypeFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getParseException()
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getMimeType()
|
||||
*/
|
||||
public String getMimeType() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getParameter(java.lang.String)
|
||||
*/
|
||||
public String getParameter(String name) {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parameters.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getParameters()
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return Collections.unmodifiableMap(parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#isMimeType(java.lang.String)
|
||||
*/
|
||||
public boolean isMimeType(String mimeType) {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return this.mimeType.equalsIgnoreCase(mimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#isMultipart()
|
||||
*/
|
||||
public boolean isMultipart() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return mimeType.startsWith(TYPE_MULTIPART_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getBoundary()
|
||||
*/
|
||||
public String getBoundary() {
|
||||
return getParameter(PARAM_BOUNDARY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.ContentTypeField#getCharset()
|
||||
*/
|
||||
public String getCharset() {
|
||||
return getParameter(PARAM_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MIME type defined in the child's Content-Type field or derives a
|
||||
* MIME type from the parent if child is <code>null</code> or hasn't got a
|
||||
* MIME type value set. If child's MIME type is multipart but no boundary
|
||||
* has been set the MIME type of child will be derived from the parent.
|
||||
*
|
||||
* @param child
|
||||
* the child.
|
||||
* @param parent
|
||||
* the parent.
|
||||
* @return the MIME type.
|
||||
*/
|
||||
public static String getMimeType(ContentTypeField child,
|
||||
ContentTypeField parent) {
|
||||
if (child == null || child.getMimeType().length() == 0
|
||||
|| child.isMultipart() && child.getBoundary() == null) {
|
||||
|
||||
if (parent != null && parent.isMimeType(TYPE_MULTIPART_DIGEST)) {
|
||||
return TYPE_MESSAGE_RFC822;
|
||||
} else {
|
||||
return TYPE_TEXT_PLAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return child.getMimeType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the <code>charset</code> parameter if set for the
|
||||
* given field. Returns the default <code>us-ascii</code> if not set or if
|
||||
* <code>f</code> is <code>null</code>.
|
||||
*
|
||||
* @return the <code>charset</code> parameter value.
|
||||
*/
|
||||
public static String getCharset(ContentTypeField f) {
|
||||
if (f != null) {
|
||||
String charset = f.getCharset();
|
||||
if (charset != null && charset.length() > 0) {
|
||||
return charset;
|
||||
}
|
||||
}
|
||||
return "us-ascii";
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
ContentTypeParser parser = new ContentTypeParser(new StringReader(body));
|
||||
try {
|
||||
parser.parseAll();
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
} catch (TokenMgrError e) {
|
||||
parseException = new ParseException(e.getMessage());
|
||||
}
|
||||
|
||||
final String type = parser.getType();
|
||||
final String subType = parser.getSubType();
|
||||
|
||||
if (type != null && subType != null) {
|
||||
mimeType = (type + "/" + subType).toLowerCase();
|
||||
|
||||
List<String> paramNames = parser.getParamNames();
|
||||
List<String> paramValues = parser.getParamValues();
|
||||
|
||||
if (paramNames != null && paramValues != null) {
|
||||
final int len = Math.min(paramNames.size(), paramValues.size());
|
||||
for (int i = 0; i < len; i++) {
|
||||
String paramName = paramNames.get(i).toLowerCase();
|
||||
String paramValue = paramValues.get(i);
|
||||
parameters.put(paramName, paramValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<ContentTypeFieldImpl> PARSER = new FieldParser<ContentTypeFieldImpl>() {
|
||||
public ContentTypeFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new ContentTypeFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
|
||||
import org.apache.james.mime4j.field.datetime.parser.ParseException;
|
||||
import org.apache.james.mime4j.field.datetime.parser.TokenMgrError;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Date-time field such as <code>Date</code> or <code>Resent-Date</code>.
|
||||
*/
|
||||
public class DateTimeFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.DateTimeField {
|
||||
private boolean parsed = false;
|
||||
|
||||
private Date date;
|
||||
private ParseException parseException;
|
||||
|
||||
DateTimeFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.DateTimeField#getDate()
|
||||
*/
|
||||
public Date getDate() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.DateTimeField#getParseException()
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
try {
|
||||
date = new DateTimeParser(new StringReader(body)).parseAll()
|
||||
.getDate();
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
} catch (TokenMgrError e) {
|
||||
parseException = new ParseException(e.getMessage());
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<DateTimeFieldImpl> PARSER = new FieldParser<DateTimeFieldImpl>() {
|
||||
public DateTimeFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new DateTimeFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.MimeException;
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.FieldName;
|
||||
import org.apache.james.mime4j.dom.field.ParsedField;
|
||||
import org.apache.james.mime4j.field.AddressListFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentDispositionFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentTransferEncodingFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentTypeFieldImpl;
|
||||
import org.apache.james.mime4j.field.DateTimeFieldImpl;
|
||||
import org.apache.james.mime4j.field.MailboxFieldImpl;
|
||||
import org.apache.james.mime4j.field.MailboxListFieldImpl;
|
||||
import org.apache.james.mime4j.field.UnstructuredFieldImpl;
|
||||
import org.apache.james.mime4j.stream.RawField;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
import org.apache.james.mime4j.util.ContentUtil;
|
||||
|
||||
public class DefaultFieldParser extends DelegatingFieldParser {
|
||||
|
||||
private static final DefaultFieldParser PARSER = new DefaultFieldParser();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the default parser used to parse fields.
|
||||
*
|
||||
* @return the default field parser
|
||||
*/
|
||||
public static DefaultFieldParser getParser() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the given byte sequence and returns an instance of the
|
||||
* <code>Field</code> class. The type of the class returned depends on the
|
||||
* field name; see {@link #parse(String)} for a table of field names and
|
||||
* their corresponding classes.
|
||||
*
|
||||
* @param raw the bytes to parse.
|
||||
* @param monitor a DecodeMonitor object used while parsing/decoding.
|
||||
* @return a <code>ParsedField</code> instance.
|
||||
* @throws MimeException if the raw string cannot be split into field name and body.
|
||||
*/
|
||||
public static ParsedField parse(
|
||||
final ByteSequence raw,
|
||||
final DecodeMonitor monitor) throws MimeException {
|
||||
RawField rawField = new RawField(raw);
|
||||
return PARSER.parse(rawField.getName(), rawField.getBody(), raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given string and returns an instance of the
|
||||
* <code>Field</code> class. The type of the class returned depends on
|
||||
* the field name:
|
||||
* <p>
|
||||
* <table>
|
||||
* <tr><th>Class returned</th><th>Field names</th></tr>
|
||||
* <tr><td>{@link ContentTypeFieldImpl}</td><td>Content-Type</td></tr>
|
||||
* <tr><td>{@link ContentTransferEncodingFieldImpl}</td><td>Content-Transfer-Encoding</td></tr>
|
||||
* <tr><td>{@link ContentDispositionFieldImpl}</td><td>Content-Disposition</td></tr>
|
||||
* <tr><td>{@link DateTimeFieldImpl}</td><td>Date, Resent-Date</td></tr>
|
||||
* <tr><td>{@link MailboxFieldImpl}</td><td>Sender, Resent-Sender</td></tr>
|
||||
* <tr><td>{@link MailboxListFieldImpl}</td><td>From, Resent-From</td></tr>
|
||||
* <tr><td>{@link AddressListFieldImpl}</td><td>To, Cc, Bcc, Reply-To, Resent-To, Resent-Cc, Resent-Bcc</td></tr>
|
||||
* <tr><td>{@link UnstructuredFieldImpl}</td><td>Subject and others</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* @param rawStr the string to parse.
|
||||
* @return a <code>ParsedField</code> instance.
|
||||
* @throws MimeException if the raw string cannot be split into field name and body.
|
||||
*/
|
||||
public static ParsedField parse(
|
||||
final String rawStr,
|
||||
final DecodeMonitor monitor) throws MimeException {
|
||||
ByteSequence raw = ContentUtil.encode(rawStr);
|
||||
return parse(raw, monitor);
|
||||
}
|
||||
|
||||
public static ParsedField parse(final String rawStr) throws MimeException {
|
||||
ByteSequence raw = ContentUtil.encode(rawStr);
|
||||
return parse(raw, DecodeMonitor.SILENT);
|
||||
}
|
||||
|
||||
public DefaultFieldParser() {
|
||||
setFieldParser(FieldName.CONTENT_TRANSFER_ENCODING,
|
||||
ContentTransferEncodingFieldImpl.PARSER);
|
||||
setFieldParser(FieldName.CONTENT_TYPE, ContentTypeFieldImpl.PARSER);
|
||||
setFieldParser(FieldName.CONTENT_DISPOSITION,
|
||||
ContentDispositionFieldImpl.PARSER);
|
||||
|
||||
final FieldParser<DateTimeFieldImpl> dateTimeParser = DateTimeFieldImpl.PARSER;
|
||||
setFieldParser(FieldName.DATE, dateTimeParser);
|
||||
setFieldParser(FieldName.RESENT_DATE, dateTimeParser);
|
||||
|
||||
final FieldParser<MailboxListFieldImpl> mailboxListParser = MailboxListFieldImpl.PARSER;
|
||||
setFieldParser(FieldName.FROM, mailboxListParser);
|
||||
setFieldParser(FieldName.RESENT_FROM, mailboxListParser);
|
||||
|
||||
final FieldParser<MailboxFieldImpl> mailboxParser = MailboxFieldImpl.PARSER;
|
||||
setFieldParser(FieldName.SENDER, mailboxParser);
|
||||
setFieldParser(FieldName.RESENT_SENDER, mailboxParser);
|
||||
|
||||
final FieldParser<AddressListFieldImpl> addressListParser = AddressListFieldImpl.PARSER;
|
||||
setFieldParser(FieldName.TO, addressListParser);
|
||||
setFieldParser(FieldName.RESENT_TO, addressListParser);
|
||||
setFieldParser(FieldName.CC, addressListParser);
|
||||
setFieldParser(FieldName.RESENT_CC, addressListParser);
|
||||
setFieldParser(FieldName.BCC, addressListParser);
|
||||
setFieldParser(FieldName.RESENT_BCC, addressListParser);
|
||||
setFieldParser(FieldName.REPLY_TO, addressListParser);
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.ParsedField;
|
||||
import org.apache.james.mime4j.field.UnstructuredFieldImpl;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
public class DelegatingFieldParser implements FieldParser<ParsedField> {
|
||||
private static final FieldParser<UnstructuredFieldImpl> DEFAULT_PARSER = UnstructuredFieldImpl.PARSER;
|
||||
|
||||
private Map<String, FieldParser<? extends ParsedField>> parsers = new HashMap<String, FieldParser<? extends ParsedField>>();
|
||||
|
||||
/**
|
||||
* Sets the parser used for the field named <code>name</code>.
|
||||
* @param name the name of the field
|
||||
* @param parser the parser for fields named <code>name</code>
|
||||
*/
|
||||
public void setFieldParser(final String name, final FieldParser<? extends ParsedField> parser) {
|
||||
parsers.put(name.toLowerCase(), parser);
|
||||
}
|
||||
|
||||
public FieldParser<? extends ParsedField> getParser(final String name) {
|
||||
final FieldParser<? extends ParsedField> field = parsers.get(name.toLowerCase());
|
||||
if (field == null) {
|
||||
return DEFAULT_PARSER;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
public ParsedField parse(final String name, final String body, final ByteSequence raw, DecodeMonitor monitor) {
|
||||
final FieldParser<? extends ParsedField> parser = getParser(name);
|
||||
return parser.parse(name, body, raw, monitor);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.field.ParsedField;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
public interface FieldParser<T extends ParsedField> {
|
||||
|
||||
T parse(final String name, final String body, final ByteSequence raw, DecodeMonitor monitor);
|
||||
|
||||
}
|
@ -1,643 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||
import org.apache.james.mime4j.dom.address.Address;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
import org.apache.james.mime4j.dom.field.AddressListField;
|
||||
import org.apache.james.mime4j.dom.field.ContentDispositionField;
|
||||
import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
|
||||
import org.apache.james.mime4j.dom.field.ContentTypeField;
|
||||
import org.apache.james.mime4j.dom.field.DateTimeField;
|
||||
import org.apache.james.mime4j.dom.field.Field;
|
||||
import org.apache.james.mime4j.dom.field.FieldName;
|
||||
import org.apache.james.mime4j.dom.field.MailboxField;
|
||||
import org.apache.james.mime4j.dom.field.MailboxListField;
|
||||
import org.apache.james.mime4j.dom.field.ParsedField;
|
||||
import org.apache.james.mime4j.dom.field.UnstructuredField;
|
||||
import org.apache.james.mime4j.field.AddressListFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentDispositionFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentTransferEncodingFieldImpl;
|
||||
import org.apache.james.mime4j.field.ContentTypeFieldImpl;
|
||||
import org.apache.james.mime4j.field.DateTimeFieldImpl;
|
||||
import org.apache.james.mime4j.field.MailboxFieldImpl;
|
||||
import org.apache.james.mime4j.field.MailboxListFieldImpl;
|
||||
import org.apache.james.mime4j.field.UnstructuredFieldImpl;
|
||||
import org.apache.james.mime4j.field.address.formatter.AddressFormatter;
|
||||
import org.apache.james.mime4j.stream.RawField;
|
||||
import org.apache.james.mime4j.util.MimeUtil;
|
||||
|
||||
/**
|
||||
* Factory for concrete {@link Field} instances.
|
||||
*/
|
||||
public class Fields {
|
||||
|
||||
private static final Pattern FIELD_NAME_PATTERN = Pattern
|
||||
.compile("[\\x21-\\x39\\x3b-\\x7e]+");
|
||||
|
||||
private Fields() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Type</i> field from the specified raw field value.
|
||||
* The specified string gets folded into a multiple-line representation if
|
||||
* necessary but is otherwise taken as is.
|
||||
*
|
||||
* @param contentType
|
||||
* raw content type containing a MIME type and optional
|
||||
* parameters.
|
||||
* @return the newly created <i>Content-Type</i> field.
|
||||
*/
|
||||
public static ContentTypeField contentType(String contentType) {
|
||||
return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE,
|
||||
contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Type</i> field from the specified MIME type and
|
||||
* parameters.
|
||||
*
|
||||
* @param mimeType
|
||||
* a MIME type (such as <code>"text/plain"</code> or
|
||||
* <code>"application/octet-stream"</code>).
|
||||
* @param parameters
|
||||
* map containing content-type parameters such as
|
||||
* <code>"boundary"</code>.
|
||||
* @return the newly created <i>Content-Type</i> field.
|
||||
*/
|
||||
public static ContentTypeField contentType(String mimeType,
|
||||
Map<String, String> parameters) {
|
||||
if (!isValidMimeType(mimeType))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
if (parameters == null || parameters.isEmpty()) {
|
||||
return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE,
|
||||
mimeType);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder(mimeType);
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
sb.append("; ");
|
||||
sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(),
|
||||
entry.getValue()));
|
||||
}
|
||||
String contentType = sb.toString();
|
||||
return contentType(contentType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Transfer-Encoding</i> field from the specified raw
|
||||
* field value.
|
||||
*
|
||||
* @param contentTransferEncoding
|
||||
* an encoding mechanism such as <code>"7-bit"</code>
|
||||
* or <code>"quoted-printable"</code>.
|
||||
* @return the newly created <i>Content-Transfer-Encoding</i> field.
|
||||
*/
|
||||
public static ContentTransferEncodingField contentTransferEncoding(
|
||||
String contentTransferEncoding) {
|
||||
return parse(ContentTransferEncodingFieldImpl.PARSER,
|
||||
FieldName.CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Disposition</i> field from the specified raw field
|
||||
* value. The specified string gets folded into a multiple-line
|
||||
* representation if necessary but is otherwise taken as is.
|
||||
*
|
||||
* @param contentDisposition
|
||||
* raw content disposition containing a disposition type and
|
||||
* optional parameters.
|
||||
* @return the newly created <i>Content-Disposition</i> field.
|
||||
*/
|
||||
public static ContentDispositionField contentDisposition(
|
||||
String contentDisposition) {
|
||||
return parse(ContentDispositionFieldImpl.PARSER,
|
||||
FieldName.CONTENT_DISPOSITION, contentDisposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Disposition</i> field from the specified
|
||||
* disposition type and parameters.
|
||||
*
|
||||
* @param dispositionType
|
||||
* a disposition type (usually <code>"inline"</code>
|
||||
* or <code>"attachment"</code>).
|
||||
* @param parameters
|
||||
* map containing disposition parameters such as
|
||||
* <code>"filename"</code>.
|
||||
* @return the newly created <i>Content-Disposition</i> field.
|
||||
*/
|
||||
public static ContentDispositionField contentDisposition(
|
||||
String dispositionType, Map<String, String> parameters) {
|
||||
if (!isValidDispositionType(dispositionType))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
if (parameters == null || parameters.isEmpty()) {
|
||||
return parse(ContentDispositionFieldImpl.PARSER,
|
||||
FieldName.CONTENT_DISPOSITION, dispositionType);
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder(dispositionType);
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
sb.append("; ");
|
||||
sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(),
|
||||
entry.getValue()));
|
||||
}
|
||||
String contentDisposition = sb.toString();
|
||||
return contentDisposition(contentDisposition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Disposition</i> field from the specified
|
||||
* disposition type and filename.
|
||||
*
|
||||
* @param dispositionType
|
||||
* a disposition type (usually <code>"inline"</code>
|
||||
* or <code>"attachment"</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @return the newly created <i>Content-Disposition</i> field.
|
||||
*/
|
||||
public static ContentDispositionField contentDisposition(
|
||||
String dispositionType, String filename) {
|
||||
return contentDisposition(dispositionType, filename, -1, null, null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Disposition</i> field from the specified values.
|
||||
*
|
||||
* @param dispositionType
|
||||
* a disposition type (usually <code>"inline"</code>
|
||||
* or <code>"attachment"</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param size
|
||||
* size parameter value or <code>-1</code> if the parameter
|
||||
* should not be included.
|
||||
* @return the newly created <i>Content-Disposition</i> field.
|
||||
*/
|
||||
public static ContentDispositionField contentDisposition(
|
||||
String dispositionType, String filename, long size) {
|
||||
return contentDisposition(dispositionType, filename, size, null, null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Content-Disposition</i> field from the specified values.
|
||||
*
|
||||
* @param dispositionType
|
||||
* a disposition type (usually <code>"inline"</code>
|
||||
* or <code>"attachment"</code>).
|
||||
* @param filename
|
||||
* filename parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param size
|
||||
* size parameter value or <code>-1</code> if the parameter
|
||||
* should not be included.
|
||||
* @param creationDate
|
||||
* creation-date parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @param modificationDate
|
||||
* modification-date parameter value or <code>null</code> if
|
||||
* the parameter should not be included.
|
||||
* @param readDate
|
||||
* read-date parameter value or <code>null</code> if the
|
||||
* parameter should not be included.
|
||||
* @return the newly created <i>Content-Disposition</i> field.
|
||||
*/
|
||||
public static ContentDispositionField contentDisposition(
|
||||
String dispositionType, String filename, long size,
|
||||
Date creationDate, Date modificationDate, Date readDate) {
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
if (filename != null) {
|
||||
parameters.put(ContentDispositionFieldImpl.PARAM_FILENAME, filename);
|
||||
}
|
||||
if (size >= 0) {
|
||||
parameters.put(ContentDispositionFieldImpl.PARAM_SIZE, Long
|
||||
.toString(size));
|
||||
}
|
||||
if (creationDate != null) {
|
||||
parameters.put(ContentDispositionFieldImpl.PARAM_CREATION_DATE,
|
||||
MimeUtil.formatDate(creationDate, null));
|
||||
}
|
||||
if (modificationDate != null) {
|
||||
parameters.put(ContentDispositionFieldImpl.PARAM_MODIFICATION_DATE,
|
||||
MimeUtil.formatDate(modificationDate, null));
|
||||
}
|
||||
if (readDate != null) {
|
||||
parameters.put(ContentDispositionFieldImpl.PARAM_READ_DATE, MimeUtil
|
||||
.formatDate(readDate, null));
|
||||
}
|
||||
return contentDisposition(dispositionType, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Date</i> field from the specified <code>Date</code>
|
||||
* value. The default time zone of the host is used to format the date.
|
||||
*
|
||||
* @param date
|
||||
* date value for the header field.
|
||||
* @return the newly created <i>Date</i> field.
|
||||
*/
|
||||
public static DateTimeField date(Date date) {
|
||||
return date0(FieldName.DATE, date, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a date field from the specified field name and <code>Date</code>
|
||||
* value. The default time zone of the host is used to format the date.
|
||||
*
|
||||
* @param fieldName
|
||||
* a field name such as <code>Date</code> or
|
||||
* <code>Resent-Date</code>.
|
||||
* @param date
|
||||
* date value for the header field.
|
||||
* @return the newly created date field.
|
||||
*/
|
||||
public static DateTimeField date(String fieldName, Date date) {
|
||||
checkValidFieldName(fieldName);
|
||||
return date0(fieldName, date, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a date field from the specified field name, <code>Date</code>
|
||||
* and <code>TimeZone</code> values.
|
||||
*
|
||||
* @param fieldName
|
||||
* a field name such as <code>Date</code> or
|
||||
* <code>Resent-Date</code>.
|
||||
* @param date
|
||||
* date value for the header field.
|
||||
* @param zone
|
||||
* the time zone to be used for formatting the date.
|
||||
* @return the newly created date field.
|
||||
*/
|
||||
public static DateTimeField date(String fieldName, Date date, TimeZone zone) {
|
||||
checkValidFieldName(fieldName);
|
||||
return date0(fieldName, date, zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Message-ID</i> field for the specified host name.
|
||||
*
|
||||
* @param hostname
|
||||
* host name to be included in the message ID or
|
||||
* <code>null</code> if no host name should be included.
|
||||
* @return the newly created <i>Message-ID</i> field.
|
||||
*/
|
||||
public static UnstructuredField messageId(String hostname) {
|
||||
String fieldValue = MimeUtil.createUniqueMessageId(hostname);
|
||||
return parse(UnstructuredFieldImpl.PARSER, FieldName.MESSAGE_ID, fieldValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Subject</i> field from the specified string value. The
|
||||
* specified string may contain non-ASCII characters.
|
||||
*
|
||||
* @param subject
|
||||
* the subject string.
|
||||
* @return the newly created <i>Subject</i> field.
|
||||
*/
|
||||
public static UnstructuredField subject(String subject) {
|
||||
int usedCharacters = FieldName.SUBJECT.length() + 2;
|
||||
String fieldValue = EncoderUtil.encodeIfNecessary(subject,
|
||||
EncoderUtil.Usage.TEXT_TOKEN, usedCharacters);
|
||||
|
||||
return parse(UnstructuredFieldImpl.PARSER, FieldName.SUBJECT, fieldValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Sender</i> field for the specified mailbox address.
|
||||
*
|
||||
* @param mailbox
|
||||
* address to be included in the field.
|
||||
* @return the newly created <i>Sender</i> field.
|
||||
*/
|
||||
public static MailboxField sender(Mailbox mailbox) {
|
||||
return mailbox0(FieldName.SENDER, mailbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>From</i> field for the specified mailbox address.
|
||||
*
|
||||
* @param mailbox
|
||||
* address to be included in the field.
|
||||
* @return the newly created <i>From</i> field.
|
||||
*/
|
||||
public static MailboxListField from(Mailbox mailbox) {
|
||||
return mailboxList0(FieldName.FROM, Collections.singleton(mailbox));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>From</i> field for the specified mailbox addresses.
|
||||
*
|
||||
* @param mailboxes
|
||||
* addresses to be included in the field.
|
||||
* @return the newly created <i>From</i> field.
|
||||
*/
|
||||
public static MailboxListField from(Mailbox... mailboxes) {
|
||||
return mailboxList0(FieldName.FROM, Arrays.asList(mailboxes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>From</i> field for the specified mailbox addresses.
|
||||
*
|
||||
* @param mailboxes
|
||||
* addresses to be included in the field.
|
||||
* @return the newly created <i>From</i> field.
|
||||
*/
|
||||
public static MailboxListField from(Iterable<Mailbox> mailboxes) {
|
||||
return mailboxList0(FieldName.FROM, mailboxes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>To</i> field for the specified mailbox or group address.
|
||||
*
|
||||
* @param address
|
||||
* mailbox or group address to be included in the field.
|
||||
* @return the newly created <i>To</i> field.
|
||||
*/
|
||||
public static AddressListField to(Address address) {
|
||||
return addressList0(FieldName.TO, Collections.singleton(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>To</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>To</i> field.
|
||||
*/
|
||||
public static AddressListField to(Address... addresses) {
|
||||
return addressList0(FieldName.TO, Arrays.asList(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>To</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>To</i> field.
|
||||
*/
|
||||
public static AddressListField to(Iterable<Address> addresses) {
|
||||
return addressList0(FieldName.TO, addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Cc</i> field for the specified mailbox or group address.
|
||||
*
|
||||
* @param address
|
||||
* mailbox or group address to be included in the field.
|
||||
* @return the newly created <i>Cc</i> field.
|
||||
*/
|
||||
public static AddressListField cc(Address address) {
|
||||
return addressList0(FieldName.CC, Collections.singleton(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Cc</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Cc</i> field.
|
||||
*/
|
||||
public static AddressListField cc(Address... addresses) {
|
||||
return addressList0(FieldName.CC, Arrays.asList(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Cc</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Cc</i> field.
|
||||
*/
|
||||
public static AddressListField cc(Iterable<Address> addresses) {
|
||||
return addressList0(FieldName.CC, addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Bcc</i> field for the specified mailbox or group address.
|
||||
*
|
||||
* @param address
|
||||
* mailbox or group address to be included in the field.
|
||||
* @return the newly created <i>Bcc</i> field.
|
||||
*/
|
||||
public static AddressListField bcc(Address address) {
|
||||
return addressList0(FieldName.BCC, Collections.singleton(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Bcc</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Bcc</i> field.
|
||||
*/
|
||||
public static AddressListField bcc(Address... addresses) {
|
||||
return addressList0(FieldName.BCC, Arrays.asList(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Bcc</i> field for the specified mailbox or group addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Bcc</i> field.
|
||||
*/
|
||||
public static AddressListField bcc(Iterable<Address> addresses) {
|
||||
return addressList0(FieldName.BCC, addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Reply-To</i> field for the specified mailbox or group
|
||||
* address.
|
||||
*
|
||||
* @param address
|
||||
* mailbox or group address to be included in the field.
|
||||
* @return the newly created <i>Reply-To</i> field.
|
||||
*/
|
||||
public static AddressListField replyTo(Address address) {
|
||||
return addressList0(FieldName.REPLY_TO, Collections.singleton(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Reply-To</i> field for the specified mailbox or group
|
||||
* addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Reply-To</i> field.
|
||||
*/
|
||||
public static AddressListField replyTo(Address... addresses) {
|
||||
return addressList0(FieldName.REPLY_TO, Arrays.asList(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <i>Reply-To</i> field for the specified mailbox or group
|
||||
* addresses.
|
||||
*
|
||||
* @param addresses
|
||||
* mailbox or group addresses to be included in the field.
|
||||
* @return the newly created <i>Reply-To</i> field.
|
||||
*/
|
||||
public static AddressListField replyTo(Iterable<Address> addresses) {
|
||||
return addressList0(FieldName.REPLY_TO, addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mailbox field from the specified field name and mailbox
|
||||
* address. Valid field names are <code>Sender</code> and
|
||||
* <code>Resent-Sender</code>.
|
||||
*
|
||||
* @param fieldName
|
||||
* the name of the mailbox field (<code>Sender</code> or
|
||||
* <code>Resent-Sender</code>).
|
||||
* @param mailbox
|
||||
* mailbox address for the field value.
|
||||
* @return the newly created mailbox field.
|
||||
*/
|
||||
public static MailboxField mailbox(String fieldName, Mailbox mailbox) {
|
||||
checkValidFieldName(fieldName);
|
||||
return mailbox0(fieldName, mailbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mailbox-list field from the specified field name and mailbox
|
||||
* addresses. Valid field names are <code>From</code> and
|
||||
* <code>Resent-From</code>.
|
||||
*
|
||||
* @param fieldName
|
||||
* the name of the mailbox field (<code>From</code> or
|
||||
* <code>Resent-From</code>).
|
||||
* @param mailboxes
|
||||
* mailbox addresses for the field value.
|
||||
* @return the newly created mailbox-list field.
|
||||
*/
|
||||
public static MailboxListField mailboxList(String fieldName,
|
||||
Iterable<Mailbox> mailboxes) {
|
||||
checkValidFieldName(fieldName);
|
||||
return mailboxList0(fieldName, mailboxes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an address-list field from the specified field name and mailbox
|
||||
* or group addresses. Valid field names are <code>To</code>,
|
||||
* <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>,
|
||||
* <code>Resent-To</code>, <code>Resent-Cc</code> and
|
||||
* <code>Resent-Bcc</code>.
|
||||
*
|
||||
* @param fieldName
|
||||
* the name of the mailbox field (<code>To</code>,
|
||||
* <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>,
|
||||
* <code>Resent-To</code>, <code>Resent-Cc</code> or
|
||||
* <code>Resent-Bcc</code>).
|
||||
* @param addresses
|
||||
* mailbox or group addresses for the field value.
|
||||
* @return the newly created address-list field.
|
||||
*/
|
||||
public static AddressListField addressList(String fieldName,
|
||||
Iterable<Address> addresses) {
|
||||
checkValidFieldName(fieldName);
|
||||
return addressList0(fieldName, addresses);
|
||||
}
|
||||
|
||||
private static DateTimeField date0(String fieldName, Date date,
|
||||
TimeZone zone) {
|
||||
final String formattedDate = MimeUtil.formatDate(date, zone);
|
||||
return parse(DateTimeFieldImpl.PARSER, fieldName, formattedDate);
|
||||
}
|
||||
|
||||
private static MailboxField mailbox0(String fieldName, Mailbox mailbox) {
|
||||
String fieldValue = encodeAddresses(Collections.singleton(mailbox));
|
||||
return parse(MailboxFieldImpl.PARSER, fieldName, fieldValue);
|
||||
}
|
||||
|
||||
private static MailboxListField mailboxList0(String fieldName,
|
||||
Iterable<Mailbox> mailboxes) {
|
||||
String fieldValue = encodeAddresses(mailboxes);
|
||||
return parse(MailboxListFieldImpl.PARSER, fieldName, fieldValue);
|
||||
}
|
||||
|
||||
private static AddressListField addressList0(String fieldName,
|
||||
Iterable<Address> addresses) {
|
||||
String fieldValue = encodeAddresses(addresses);
|
||||
return parse(AddressListFieldImpl.PARSER, fieldName, fieldValue);
|
||||
}
|
||||
|
||||
private static void checkValidFieldName(String fieldName) {
|
||||
if (!FIELD_NAME_PATTERN.matcher(fieldName).matches())
|
||||
throw new IllegalArgumentException("Invalid field name");
|
||||
}
|
||||
|
||||
private static boolean isValidMimeType(String mimeType) {
|
||||
if (mimeType == null)
|
||||
return false;
|
||||
|
||||
int idx = mimeType.indexOf('/');
|
||||
if (idx == -1)
|
||||
return false;
|
||||
|
||||
String type = mimeType.substring(0, idx);
|
||||
String subType = mimeType.substring(idx + 1);
|
||||
return EncoderUtil.isToken(type) && EncoderUtil.isToken(subType);
|
||||
}
|
||||
|
||||
private static boolean isValidDispositionType(String dispositionType) {
|
||||
if (dispositionType == null)
|
||||
return false;
|
||||
|
||||
return EncoderUtil.isToken(dispositionType);
|
||||
}
|
||||
|
||||
private static <F extends ParsedField> F parse(FieldParser<F> parser,
|
||||
String fieldName, String fieldBody) {
|
||||
RawField rawField = new RawField(fieldName, fieldBody);
|
||||
return parser.parse(rawField.getName(), rawField.getBody(), rawField.getRaw(),
|
||||
DecodeMonitor.SILENT);
|
||||
}
|
||||
|
||||
private static String encodeAddresses(Iterable<? extends Address> addresses) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Address address : addresses) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
AddressFormatter.encode(sb, address);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
import org.apache.james.mime4j.dom.address.MailboxList;
|
||||
import org.apache.james.mime4j.field.address.parser.AddressBuilder;
|
||||
import org.apache.james.mime4j.field.address.parser.ParseException;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Mailbox field such as <code>Sender</code> or <code>Resent-Sender</code>.
|
||||
*/
|
||||
public class MailboxFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.MailboxField {
|
||||
private boolean parsed = false;
|
||||
|
||||
private Mailbox mailbox;
|
||||
private ParseException parseException;
|
||||
|
||||
MailboxFieldImpl(final String name, final String body, final ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.MailboxField#getMailbox()
|
||||
*/
|
||||
public Mailbox getMailbox() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return mailbox;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.MailboxField#getParseException()
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
try {
|
||||
MailboxList mailboxList = AddressBuilder.parseAddressList(body, monitor).flatten();
|
||||
if (mailboxList.size() > 0) {
|
||||
mailbox = mailboxList.get(0);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<MailboxFieldImpl> PARSER = new FieldParser<MailboxFieldImpl>() {
|
||||
public MailboxFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new MailboxFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.address.MailboxList;
|
||||
import org.apache.james.mime4j.field.address.parser.AddressBuilder;
|
||||
import org.apache.james.mime4j.field.address.parser.ParseException;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Mailbox-list field such as <code>From</code> or <code>Resent-From</code>.
|
||||
*/
|
||||
public class MailboxListFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.MailboxListField {
|
||||
private boolean parsed = false;
|
||||
|
||||
private MailboxList mailboxList;
|
||||
private ParseException parseException;
|
||||
|
||||
MailboxListFieldImpl(final String name, final String body, final ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.MailboxListField#getMailboxList()
|
||||
*/
|
||||
public MailboxList getMailboxList() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return mailboxList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.MailboxListField#getParseException()
|
||||
*/
|
||||
@Override
|
||||
public ParseException getParseException() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return parseException;
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
try {
|
||||
mailboxList = AddressBuilder.parseAddressList(body, monitor).flatten();
|
||||
} catch (ParseException e) {
|
||||
parseException = e;
|
||||
}
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<MailboxListFieldImpl> PARSER = new FieldParser<MailboxListFieldImpl>() {
|
||||
public MailboxListFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new MailboxListFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.codec.DecoderUtil;
|
||||
import org.apache.james.mime4j.util.ByteSequence;
|
||||
|
||||
/**
|
||||
* Simple unstructured field such as <code>Subject</code>.
|
||||
*/
|
||||
public class UnstructuredFieldImpl extends AbstractField implements org.apache.james.mime4j.dom.field.UnstructuredField {
|
||||
private boolean parsed = false;
|
||||
|
||||
private String value;
|
||||
|
||||
UnstructuredFieldImpl(String name, String body, ByteSequence raw, DecodeMonitor monitor) {
|
||||
super(name, body, raw, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.james.mime4j.dom.field.UnstructuredField#getValue()
|
||||
*/
|
||||
public String getValue() {
|
||||
if (!parsed)
|
||||
parse();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
String body = getBody();
|
||||
|
||||
value = DecoderUtil.decodeEncodedWords(body, monitor);
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
static final FieldParser<UnstructuredFieldImpl> PARSER = new FieldParser<UnstructuredFieldImpl>() {
|
||||
public UnstructuredFieldImpl parse(final String name, final String body,
|
||||
final ByteSequence raw, DecodeMonitor monitor) {
|
||||
return new UnstructuredFieldImpl(name, body, raw, monitor);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,209 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field.address.formatter;
|
||||
|
||||
import org.apache.james.mime4j.codec.EncoderUtil;
|
||||
import org.apache.james.mime4j.dom.address.Address;
|
||||
import org.apache.james.mime4j.dom.address.Group;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
|
||||
public class AddressFormatter {
|
||||
|
||||
/**
|
||||
* Formats the address as a human readable string, not including the route.
|
||||
* The resulting string is intended for display purposes only and cannot be
|
||||
* used for transport purposes.
|
||||
*
|
||||
* For example, if the unparsed address was
|
||||
*
|
||||
* <"Joe Cheng"@joecheng.com>
|
||||
*
|
||||
* this method would return
|
||||
*
|
||||
* <Joe Cheng@joecheng.com>
|
||||
*
|
||||
* which is not valid for transport; the local part would need to be
|
||||
* re-quoted.
|
||||
*
|
||||
* @param includeRoute
|
||||
* <code>true</code> if the route should be included if it
|
||||
* exists, <code>false</code> otherwise.
|
||||
* @return a string representation of this address intended to be displayed.
|
||||
*/
|
||||
public static void format(final StringBuilder sb, final Address address, boolean includeRoute) {
|
||||
if (address == null) {
|
||||
return;
|
||||
}
|
||||
if (address instanceof Mailbox) {
|
||||
format(sb, (Mailbox) address, includeRoute);
|
||||
} else if (address instanceof Group) {
|
||||
format(sb, (Group) address, includeRoute);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsuppported Address class: " + address.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this address that can be used for
|
||||
* transport purposes. The route is never included in this representation
|
||||
* because routes are obsolete and RFC 5322 states that obsolete syntactic
|
||||
* forms MUST NOT be generated.
|
||||
*
|
||||
* @return a string representation of this address intended for transport
|
||||
* purposes.
|
||||
*/
|
||||
public static void encode(final StringBuilder sb, final Address address) {
|
||||
if (address == null) {
|
||||
return;
|
||||
}
|
||||
if (address instanceof Mailbox) {
|
||||
encode(sb, (Mailbox) address);
|
||||
} else if (address instanceof Group) {
|
||||
encode(sb, (Group) address);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsuppported Address class: " + address.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public static void format(final StringBuilder sb, final Mailbox mailbox, boolean includeRoute) {
|
||||
if (sb == null) {
|
||||
throw new IllegalArgumentException("StringBuilder may not be null");
|
||||
}
|
||||
if (mailbox == null) {
|
||||
throw new IllegalArgumentException("Mailbox may not be null");
|
||||
}
|
||||
includeRoute &= mailbox.getRoute() != null;
|
||||
boolean includeAngleBrackets = mailbox.getName() != null || includeRoute;
|
||||
if (mailbox.getName() != null) {
|
||||
sb.append(mailbox.getName());
|
||||
sb.append(' ');
|
||||
}
|
||||
if (includeAngleBrackets) {
|
||||
sb.append('<');
|
||||
}
|
||||
if (includeRoute) {
|
||||
sb.append(mailbox.getRoute().toRouteString());
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append(mailbox.getLocalPart());
|
||||
if (mailbox.getDomain() != null) {
|
||||
sb.append('@');
|
||||
sb.append(mailbox.getDomain());
|
||||
}
|
||||
if (includeAngleBrackets) {
|
||||
sb.append('>');
|
||||
}
|
||||
}
|
||||
|
||||
public static String format(final Mailbox mailbox, boolean includeRoute) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
format(sb, mailbox, includeRoute);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void encode(final StringBuilder sb, final Mailbox mailbox) {
|
||||
if (sb == null) {
|
||||
throw new IllegalArgumentException("StringBuilder may not be null");
|
||||
}
|
||||
if (mailbox == null) {
|
||||
throw new IllegalArgumentException("Mailbox may not be null");
|
||||
}
|
||||
if (mailbox.getName() != null) {
|
||||
sb.append(EncoderUtil.encodeAddressDisplayName(mailbox.getName()));
|
||||
sb.append(" <");
|
||||
}
|
||||
sb.append(EncoderUtil.encodeAddressLocalPart(mailbox.getLocalPart()));
|
||||
// domain = dot-atom / domain-literal
|
||||
// domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
|
||||
// dtext = %d33-90 / %d94-126
|
||||
if (mailbox.getDomain() != null) {
|
||||
sb.append('@');
|
||||
sb.append(mailbox.getDomain());
|
||||
}
|
||||
if (mailbox.getName() != null) {
|
||||
sb.append('>');
|
||||
}
|
||||
}
|
||||
|
||||
public static String encode(final Mailbox mailbox) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
encode(sb, mailbox);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void format(final StringBuilder sb, final Group group, boolean includeRoute) {
|
||||
if (sb == null) {
|
||||
throw new IllegalArgumentException("StringBuilder may not be null");
|
||||
}
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Group may not be null");
|
||||
}
|
||||
sb.append(group.getName());
|
||||
sb.append(':');
|
||||
|
||||
boolean first = true;
|
||||
for (Mailbox mailbox : group.getMailboxes()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(' ');
|
||||
format(sb, mailbox, includeRoute);
|
||||
}
|
||||
sb.append(";");
|
||||
}
|
||||
|
||||
public static String format(final Group group, boolean includeRoute) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
format(sb, group, includeRoute);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void encode(final StringBuilder sb, final Group group) {
|
||||
if (sb == null) {
|
||||
throw new IllegalArgumentException("StringBuilder may not be null");
|
||||
}
|
||||
if (group == null) {
|
||||
throw new IllegalArgumentException("Group may not be null");
|
||||
}
|
||||
sb.append(EncoderUtil.encodeAddressDisplayName(group.getName()));
|
||||
sb.append(':');
|
||||
boolean first = true;
|
||||
for (Mailbox mailbox : group.getMailboxes()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(',');
|
||||
}
|
||||
|
||||
sb.append(' ');
|
||||
encode(sb, mailbox);
|
||||
}
|
||||
sb.append(';');
|
||||
}
|
||||
|
||||
public static String encode(final Group group) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
encode(sb, group);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTaddr_spec.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTaddr_spec extends SimpleNode {
|
||||
public ASTaddr_spec(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTaddr_spec(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=750ab0a2f6a942d3f4a7a7e076d12a4d (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTaddress.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTaddress extends SimpleNode {
|
||||
public ASTaddress(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTaddress(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=73be0a52ecfe4cf5d5a926be94fbb411 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTaddress_list.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTaddress_list extends SimpleNode {
|
||||
public ASTaddress_list(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTaddress_list(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=6615a805f4abebfcf7252d9aad462299 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTangle_addr.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTangle_addr extends SimpleNode {
|
||||
public ASTangle_addr(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTangle_addr(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=2201bedb23ef9d1b75dd88b2a5571384 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTdomain.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTdomain extends SimpleNode {
|
||||
public ASTdomain(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTdomain(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=0105eb2d00d34d34b0665fd5ced14d52 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTgroup_body.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTgroup_body extends SimpleNode {
|
||||
public ASTgroup_body(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTgroup_body(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=29b09d0a20de5b5f3d7e08c7e325d23f (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTlocal_part.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTlocal_part extends SimpleNode {
|
||||
public ASTlocal_part(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTlocal_part(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=42e77dd54203428772aecd61a95fc01c (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTmailbox.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTmailbox extends SimpleNode {
|
||||
public ASTmailbox(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTmailbox(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=246fe7d146969407e2c7977748e2fc99 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTname_addr.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTname_addr extends SimpleNode {
|
||||
public ASTname_addr(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTname_addr(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=37e69dc07dfc157b3fb2449483ff82b6 (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTphrase.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTphrase extends SimpleNode {
|
||||
public ASTphrase(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTphrase(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=f1c7166e3c5b192d1f6db62b8239b0be (do not edit this line) */
|
@ -1,21 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTroute.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class ASTroute extends SimpleNode {
|
||||
public ASTroute(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTroute(AddressListParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=bcec06c89402cfcb3700aefe8d5f14f9 (do not edit this line) */
|
@ -1,115 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.dom.address.Address;
|
||||
import org.apache.james.mime4j.dom.address.AddressList;
|
||||
import org.apache.james.mime4j.dom.address.Group;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
|
||||
public class AddressBuilder {
|
||||
|
||||
/**
|
||||
* Parses the specified raw string into an address.
|
||||
*
|
||||
* @param rawAddressString
|
||||
* string to parse.
|
||||
* @param monitor the DecodeMonitor to be used while parsing/decoding
|
||||
* @return an <code>Address</code> object for the specified string.
|
||||
* @throws ParseException if the raw string does not represent a single address.
|
||||
*/
|
||||
public static Address parseAddress(String rawAddressString, DecodeMonitor monitor) throws ParseException {
|
||||
AddressListParser parser = new AddressListParser(new StringReader(
|
||||
rawAddressString));
|
||||
return Builder.getInstance().buildAddress(parser.parseAddress(), monitor);
|
||||
}
|
||||
|
||||
public static Address parseAddress(String rawAddressString) throws ParseException {
|
||||
return parseAddress(rawAddressString, DecodeMonitor.STRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the address list string, such as the value of a From, To, Cc, Bcc,
|
||||
* Sender, or Reply-To header.
|
||||
*
|
||||
* The string MUST be unfolded already.
|
||||
* @param monitor the DecodeMonitor to be used while parsing/decoding
|
||||
*/
|
||||
public static AddressList parseAddressList(String rawAddressList, DecodeMonitor monitor)
|
||||
throws ParseException {
|
||||
AddressListParser parser = new AddressListParser(new StringReader(
|
||||
rawAddressList));
|
||||
try {
|
||||
return Builder.getInstance().buildAddressList(parser.parseAddressList(), monitor);
|
||||
} catch (RuntimeException e) {
|
||||
throw new ParseException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static AddressList parseAddressList(String rawAddressList) throws ParseException {
|
||||
return parseAddressList(rawAddressList, DecodeMonitor.STRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the specified raw string into a mailbox address.
|
||||
*
|
||||
* @param rawMailboxString
|
||||
* string to parse.
|
||||
* @param monitor the DecodeMonitor to be used while parsing/decoding.
|
||||
* @return a <code>Mailbox</code> object for the specified string.
|
||||
* @throws ParseException
|
||||
* if the raw string does not represent a single mailbox
|
||||
* address.
|
||||
*/
|
||||
public static Mailbox parseMailbox(String rawMailboxString, DecodeMonitor monitor) throws ParseException {
|
||||
AddressListParser parser = new AddressListParser(new StringReader(
|
||||
rawMailboxString));
|
||||
return Builder.getInstance().buildMailbox(parser.parseMailbox(), monitor);
|
||||
}
|
||||
|
||||
public static Mailbox parseMailbox(String rawMailboxString) throws ParseException {
|
||||
return parseMailbox(rawMailboxString, DecodeMonitor.STRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the specified raw string into a group address.
|
||||
*
|
||||
* @param rawGroupString
|
||||
* string to parse.
|
||||
* @return a <code>Group</code> object for the specified string.
|
||||
* @throws ParseException
|
||||
* if the raw string does not represent a single group address.
|
||||
*/
|
||||
public static Group parseGroup(String rawGroupString, DecodeMonitor monitor) throws ParseException {
|
||||
Address address = parseAddress(rawGroupString, monitor);
|
||||
if (!(address instanceof Group))
|
||||
throw new ParseException("Not a group address");
|
||||
|
||||
return (Group) address;
|
||||
}
|
||||
|
||||
public static Group parseGroup(String rawGroupString) throws ParseException {
|
||||
return parseGroup(rawGroupString, DecodeMonitor.STRICT);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserConstants.java */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
|
||||
/**
|
||||
* Token literal values and constants.
|
||||
* Generated by org.javacc.parser.OtherFilesGen#start()
|
||||
*/
|
||||
public interface AddressListParserConstants {
|
||||
|
||||
/** End of File. */
|
||||
int EOF = 0;
|
||||
/** RegularExpression Id. */
|
||||
int WS = 10;
|
||||
/** RegularExpression Id. */
|
||||
int ALPHA = 11;
|
||||
/** RegularExpression Id. */
|
||||
int DIGIT = 12;
|
||||
/** RegularExpression Id. */
|
||||
int ATEXT = 13;
|
||||
/** RegularExpression Id. */
|
||||
int DOTATOM = 14;
|
||||
/** RegularExpression Id. */
|
||||
int DOMAINLITERAL = 18;
|
||||
/** RegularExpression Id. */
|
||||
int COMMENT = 20;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDSTRING = 31;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDPAIR = 32;
|
||||
/** RegularExpression Id. */
|
||||
int ANY = 33;
|
||||
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 0;
|
||||
/** Lexical state. */
|
||||
int INDOMAINLITERAL = 1;
|
||||
/** Lexical state. */
|
||||
int INCOMMENT = 2;
|
||||
/** Lexical state. */
|
||||
int NESTED_COMMENT = 3;
|
||||
/** Lexical state. */
|
||||
int INQUOTEDSTRING = 4;
|
||||
|
||||
/** Literal token values. */
|
||||
String[] tokenImage = {
|
||||
"<EOF>",
|
||||
"\"\\r\"",
|
||||
"\"\\n\"",
|
||||
"\",\"",
|
||||
"\":\"",
|
||||
"\";\"",
|
||||
"\"<\"",
|
||||
"\">\"",
|
||||
"\"@\"",
|
||||
"\".\"",
|
||||
"<WS>",
|
||||
"<ALPHA>",
|
||||
"<DIGIT>",
|
||||
"<ATEXT>",
|
||||
"<DOTATOM>",
|
||||
"\"[\"",
|
||||
"<token of kind 16>",
|
||||
"<token of kind 17>",
|
||||
"\"]\"",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 21>",
|
||||
"\"(\"",
|
||||
"<token of kind 23>",
|
||||
"<token of kind 24>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 27>",
|
||||
"\"\\\"\"",
|
||||
"<token of kind 29>",
|
||||
"<token of kind 30>",
|
||||
"\"\\\"\"",
|
||||
"<QUOTEDPAIR>",
|
||||
"<ANY>",
|
||||
};
|
||||
|
||||
}
|
@ -1,969 +0,0 @@
|
||||
/* Generated By:JJTree&JavaCC: Do not edit this line. AddressListParserTokenManager.java */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
/** Token Manager. */
|
||||
public class AddressListParserTokenManager implements AddressListParserConstants
|
||||
{
|
||||
// Keeps track of how many levels of comment nesting
|
||||
// we've encountered. This is only used when the 2nd
|
||||
// level is reached, for example ((this)), not (this).
|
||||
// This is because the outermost level must be treated
|
||||
// specially anyway, because the outermost ")" has a
|
||||
// different token type than inner ")" instances.
|
||||
static int commentNest;
|
||||
|
||||
/** Debug output. */
|
||||
public java.io.PrintStream debugStream = System.out;
|
||||
/** Set debug output. */
|
||||
public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
|
||||
private final int jjStopStringLiteralDfa_0(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_0(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjStopAtPos(int pos, int kind)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
return pos + 1;
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_0()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 10:
|
||||
return jjStopAtPos(0, 2);
|
||||
case 13:
|
||||
return jjStopAtPos(0, 1);
|
||||
case 34:
|
||||
return jjStopAtPos(0, 28);
|
||||
case 40:
|
||||
return jjStopAtPos(0, 19);
|
||||
case 44:
|
||||
return jjStopAtPos(0, 3);
|
||||
case 46:
|
||||
return jjStopAtPos(0, 9);
|
||||
case 58:
|
||||
return jjStopAtPos(0, 4);
|
||||
case 59:
|
||||
return jjStopAtPos(0, 5);
|
||||
case 60:
|
||||
return jjStopAtPos(0, 6);
|
||||
case 62:
|
||||
return jjStopAtPos(0, 7);
|
||||
case 64:
|
||||
return jjStopAtPos(0, 8);
|
||||
case 91:
|
||||
return jjStopAtPos(0, 15);
|
||||
default :
|
||||
return jjMoveNfa_0(1, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_0(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 1:
|
||||
if ((0xa3ffacfa00000000L & l) != 0L)
|
||||
{
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if ((0x100000200L & l) != 0L)
|
||||
{
|
||||
if (kind > 10)
|
||||
kind = 10;
|
||||
jjCheckNAdd(0);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if ((0x100000200L & l) == 0L)
|
||||
break;
|
||||
kind = 10;
|
||||
jjCheckNAdd(0);
|
||||
break;
|
||||
case 2:
|
||||
if ((0xa3ffecfa00000000L & l) == 0L)
|
||||
break;
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
if ((0x7fffffffc7fffffeL & l) == 0L)
|
||||
break;
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_2(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_2(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_2()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 22);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 20);
|
||||
default :
|
||||
return jjMoveNfa_2(0, 0);
|
||||
}
|
||||
}
|
||||
static final long[] jjbitVec0 = {
|
||||
0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
|
||||
};
|
||||
private int jjMoveNfa_2(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 23)
|
||||
kind = 23;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 21)
|
||||
kind = 21;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 23)
|
||||
kind = 23;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 21)
|
||||
kind = 21;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 23)
|
||||
kind = 23;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 23)
|
||||
kind = 23;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 21)
|
||||
kind = 21;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_4(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_4(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_4(jjStopStringLiteralDfa_4(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_4()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 34:
|
||||
return jjStopAtPos(0, 31);
|
||||
default :
|
||||
return jjMoveNfa_4(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_4(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((0xfffffffbffffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 30)
|
||||
kind = 30;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 29)
|
||||
kind = 29;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0xffffffffefffffffL & l) != 0L)
|
||||
{
|
||||
if (kind > 30)
|
||||
kind = 30;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 29)
|
||||
kind = 29;
|
||||
break;
|
||||
case 2:
|
||||
if ((0xffffffffefffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 30)
|
||||
kind = 30;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((jjbitVec0[i2] & l2) == 0L)
|
||||
break;
|
||||
if (kind > 30)
|
||||
kind = 30;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 29)
|
||||
kind = 29;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_3(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_3(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_3()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 25);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 26);
|
||||
default :
|
||||
return jjMoveNfa_3(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_3(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 27)
|
||||
kind = 27;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 24)
|
||||
kind = 24;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 27)
|
||||
kind = 27;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 24)
|
||||
kind = 24;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 27)
|
||||
kind = 27;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 27)
|
||||
kind = 27;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 24)
|
||||
kind = 24;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_1(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_1(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_1()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 93:
|
||||
return jjStopAtPos(0, 18);
|
||||
default :
|
||||
return jjMoveNfa_1(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_1(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0xffffffffc7ffffffL & l) != 0L)
|
||||
{
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
}
|
||||
else if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
case 2:
|
||||
if ((0xffffffffc7ffffffL & l) != 0L && kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
static final int[] jjnextStates = {
|
||||
};
|
||||
|
||||
/** Token literal values. */
|
||||
public static final String[] jjstrLiteralImages = {
|
||||
"", "\15", "\12", "\54", "\72", "\73", "\74", "\76", "\100", "\56", null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, };
|
||||
|
||||
/** Lexer state names. */
|
||||
public static final String[] lexStateNames = {
|
||||
"DEFAULT",
|
||||
"INDOMAINLITERAL",
|
||||
"INCOMMENT",
|
||||
"NESTED_COMMENT",
|
||||
"INQUOTEDSTRING",
|
||||
};
|
||||
|
||||
/** Lex State array. */
|
||||
public static final int[] jjnewLexState = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, 2, 0, -1, 3, -1, -1,
|
||||
-1, -1, -1, 4, -1, -1, 0, -1, -1,
|
||||
};
|
||||
static final long[] jjtoToken = {
|
||||
0x800443ffL,
|
||||
};
|
||||
static final long[] jjtoSkip = {
|
||||
0x100400L,
|
||||
};
|
||||
static final long[] jjtoSpecial = {
|
||||
0x400L,
|
||||
};
|
||||
static final long[] jjtoMore = {
|
||||
0x7feb8000L,
|
||||
};
|
||||
protected SimpleCharStream input_stream;
|
||||
private final int[] jjrounds = new int[3];
|
||||
private final int[] jjstateSet = new int[6];
|
||||
private final StringBuilder jjimage = new StringBuilder();
|
||||
private StringBuilder image = jjimage;
|
||||
private int jjimageLen;
|
||||
private int lengthOfMatch;
|
||||
protected char curChar;
|
||||
/** Constructor. */
|
||||
public AddressListParserTokenManager(SimpleCharStream stream){
|
||||
if (SimpleCharStream.staticFlag)
|
||||
throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
|
||||
input_stream = stream;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public AddressListParserTokenManager(SimpleCharStream stream, int lexState){
|
||||
this(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream)
|
||||
{
|
||||
jjmatchedPos = jjnewStateCnt = 0;
|
||||
curLexState = defaultLexState;
|
||||
input_stream = stream;
|
||||
ReInitRounds();
|
||||
}
|
||||
private void ReInitRounds()
|
||||
{
|
||||
int i;
|
||||
jjround = 0x80000001;
|
||||
for (i = 3; i-- > 0;)
|
||||
jjrounds[i] = 0x80000000;
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream, int lexState)
|
||||
{
|
||||
ReInit(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Switch to specified lex state. */
|
||||
public void SwitchTo(int lexState)
|
||||
{
|
||||
if (lexState >= 5 || lexState < 0)
|
||||
throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
|
||||
else
|
||||
curLexState = lexState;
|
||||
}
|
||||
|
||||
protected Token jjFillToken()
|
||||
{
|
||||
final Token t;
|
||||
final String curTokenImage;
|
||||
final int beginLine;
|
||||
final int endLine;
|
||||
final int beginColumn;
|
||||
final int endColumn;
|
||||
String im = jjstrLiteralImages[jjmatchedKind];
|
||||
curTokenImage = (im == null) ? input_stream.GetImage() : im;
|
||||
beginLine = input_stream.getBeginLine();
|
||||
beginColumn = input_stream.getBeginColumn();
|
||||
endLine = input_stream.getEndLine();
|
||||
endColumn = input_stream.getEndColumn();
|
||||
t = Token.newToken(jjmatchedKind, curTokenImage);
|
||||
|
||||
t.beginLine = beginLine;
|
||||
t.endLine = endLine;
|
||||
t.beginColumn = beginColumn;
|
||||
t.endColumn = endColumn;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int curLexState = 0;
|
||||
int defaultLexState = 0;
|
||||
int jjnewStateCnt;
|
||||
int jjround;
|
||||
int jjmatchedPos;
|
||||
int jjmatchedKind;
|
||||
|
||||
/** Get the next Token. */
|
||||
public Token getNextToken()
|
||||
{
|
||||
Token specialToken = null;
|
||||
Token matchedToken;
|
||||
int curPos = 0;
|
||||
|
||||
EOFLoop :
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
curChar = input_stream.BeginToken();
|
||||
}
|
||||
catch(java.io.IOException e)
|
||||
{
|
||||
jjmatchedKind = 0;
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
return matchedToken;
|
||||
}
|
||||
image = jjimage;
|
||||
image.setLength(0);
|
||||
jjimageLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(curLexState)
|
||||
{
|
||||
case 0:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_0();
|
||||
break;
|
||||
case 1:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_1();
|
||||
break;
|
||||
case 2:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_2();
|
||||
break;
|
||||
case 3:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_3();
|
||||
break;
|
||||
case 4:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_4();
|
||||
break;
|
||||
}
|
||||
if (jjmatchedKind != 0x7fffffff)
|
||||
{
|
||||
if (jjmatchedPos + 1 < curPos)
|
||||
input_stream.backup(curPos - jjmatchedPos - 1);
|
||||
if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
TokenLexicalActions(matchedToken);
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
return matchedToken;
|
||||
}
|
||||
else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
if (specialToken == null)
|
||||
specialToken = matchedToken;
|
||||
else
|
||||
{
|
||||
matchedToken.specialToken = specialToken;
|
||||
specialToken = (specialToken.next = matchedToken);
|
||||
}
|
||||
}
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
continue EOFLoop;
|
||||
}
|
||||
MoreLexicalActions();
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
curPos = 0;
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
try {
|
||||
curChar = input_stream.readChar();
|
||||
continue;
|
||||
}
|
||||
catch (java.io.IOException e1) { }
|
||||
}
|
||||
int error_line = input_stream.getEndLine();
|
||||
int error_column = input_stream.getEndColumn();
|
||||
String error_after = null;
|
||||
boolean EOFSeen = false;
|
||||
try { input_stream.readChar(); input_stream.backup(1); }
|
||||
catch (java.io.IOException e1) {
|
||||
EOFSeen = true;
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
if (curChar == '\n' || curChar == '\r') {
|
||||
error_line++;
|
||||
error_column = 0;
|
||||
}
|
||||
else
|
||||
error_column++;
|
||||
}
|
||||
if (!EOFSeen) {
|
||||
input_stream.backup(1);
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
}
|
||||
throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoreLexicalActions()
|
||||
{
|
||||
jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 16 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 21 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 22 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
commentNest = 1;
|
||||
break;
|
||||
case 24 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 25 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
++commentNest;
|
||||
break;
|
||||
case 26 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
--commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
|
||||
break;
|
||||
case 28 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 1);
|
||||
break;
|
||||
case 29 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
void TokenLexicalActions(Token matchedToken)
|
||||
{
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 18 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
|
||||
matchedToken.image = image.toString();
|
||||
break;
|
||||
case 31 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
|
||||
matchedToken.image = image.substring(0, image.length() - 1);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void jjCheckNAdd(int state)
|
||||
{
|
||||
if (jjrounds[state] != jjround)
|
||||
{
|
||||
jjstateSet[jjnewStateCnt++] = state;
|
||||
jjrounds[state] = jjround;
|
||||
}
|
||||
}
|
||||
private void jjAddStates(int start, int end)
|
||||
{
|
||||
do {
|
||||
jjstateSet[jjnewStateCnt++] = jjnextStates[start];
|
||||
} while (start++ != end);
|
||||
}
|
||||
private void jjCheckNAddTwoStates(int state1, int state2)
|
||||
{
|
||||
jjCheckNAdd(state1);
|
||||
jjCheckNAdd(state2);
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. AddressListParserTreeConstants.java Version 5.0 */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public interface AddressListParserTreeConstants
|
||||
{
|
||||
public int JJTVOID = 0;
|
||||
public int JJTADDRESS_LIST = 1;
|
||||
public int JJTADDRESS = 2;
|
||||
public int JJTMAILBOX = 3;
|
||||
public int JJTNAME_ADDR = 4;
|
||||
public int JJTGROUP_BODY = 5;
|
||||
public int JJTANGLE_ADDR = 6;
|
||||
public int JJTROUTE = 7;
|
||||
public int JJTPHRASE = 8;
|
||||
public int JJTADDR_SPEC = 9;
|
||||
public int JJTLOCAL_PART = 10;
|
||||
public int JJTDOMAIN = 11;
|
||||
|
||||
|
||||
public String[] jjtNodeName = {
|
||||
"void",
|
||||
"address_list",
|
||||
"address",
|
||||
"mailbox",
|
||||
"name_addr",
|
||||
"group_body",
|
||||
"angle_addr",
|
||||
"route",
|
||||
"phrase",
|
||||
"addr_spec",
|
||||
"local_part",
|
||||
"domain",
|
||||
};
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=e7d2b24000a70a573955cf10036f0056 (do not edit this line) */
|
@ -1,19 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. AddressListParserVisitor.java Version 5.0 */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public interface AddressListParserVisitor
|
||||
{
|
||||
public Object visit(SimpleNode node, Object data);
|
||||
public Object visit(ASTaddress_list node, Object data);
|
||||
public Object visit(ASTaddress node, Object data);
|
||||
public Object visit(ASTmailbox node, Object data);
|
||||
public Object visit(ASTname_addr node, Object data);
|
||||
public Object visit(ASTgroup_body node, Object data);
|
||||
public Object visit(ASTangle_addr node, Object data);
|
||||
public Object visit(ASTroute node, Object data);
|
||||
public Object visit(ASTphrase node, Object data);
|
||||
public Object visit(ASTaddr_spec node, Object data);
|
||||
public Object visit(ASTlocal_part node, Object data);
|
||||
public Object visit(ASTdomain node, Object data);
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=f57edd9a1eb17afa5907a87b3c51e284 (do not edit this line) */
|
@ -1,28 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
|
||||
public abstract class BaseNode implements Node {
|
||||
|
||||
public Token firstToken;
|
||||
public Token lastToken;
|
||||
|
||||
}
|
@ -1,229 +0,0 @@
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.james.mime4j.codec.DecodeMonitor;
|
||||
import org.apache.james.mime4j.codec.DecoderUtil;
|
||||
import org.apache.james.mime4j.dom.address.Address;
|
||||
import org.apache.james.mime4j.dom.address.AddressList;
|
||||
import org.apache.james.mime4j.dom.address.DomainList;
|
||||
import org.apache.james.mime4j.dom.address.Group;
|
||||
import org.apache.james.mime4j.dom.address.Mailbox;
|
||||
import org.apache.james.mime4j.dom.address.MailboxList;
|
||||
|
||||
/**
|
||||
* Transforms the JJTree-generated abstract syntax tree into a graph of
|
||||
* org.apache.james.mime4j.dom.address objects.
|
||||
*/
|
||||
class Builder {
|
||||
|
||||
private static Builder singleton = new Builder();
|
||||
|
||||
public static Builder getInstance() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
public AddressList buildAddressList(ASTaddress_list node, DecodeMonitor monitor) throws ParseException {
|
||||
List<Address> list = new ArrayList<Address>();
|
||||
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
|
||||
ASTaddress childNode = (ASTaddress) node.jjtGetChild(i);
|
||||
Address address = buildAddress(childNode, monitor);
|
||||
list.add(address);
|
||||
}
|
||||
return new AddressList(list, true);
|
||||
}
|
||||
|
||||
public Address buildAddress(ASTaddress node, DecodeMonitor monitor) throws ParseException {
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
Node n = it.next();
|
||||
if (n instanceof ASTaddr_spec) {
|
||||
return buildAddrSpec((ASTaddr_spec) n);
|
||||
} else if (n instanceof ASTangle_addr) {
|
||||
return buildAngleAddr((ASTangle_addr) n);
|
||||
} else if (n instanceof ASTphrase) {
|
||||
String name = buildString((ASTphrase) n, false);
|
||||
Node n2 = it.next();
|
||||
if (n2 instanceof ASTgroup_body) {
|
||||
return new Group(name, buildGroupBody((ASTgroup_body) n2, monitor));
|
||||
} else if (n2 instanceof ASTangle_addr) {
|
||||
try {
|
||||
name = DecoderUtil.decodeEncodedWords(name, monitor);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ParseException(e.getMessage());
|
||||
}
|
||||
Mailbox mb = buildAngleAddr((ASTangle_addr) n2);
|
||||
return new Mailbox(name, mb.getRoute(), mb.getLocalPart(),
|
||||
mb.getDomain());
|
||||
} else {
|
||||
throw new ParseException();
|
||||
}
|
||||
} else {
|
||||
throw new ParseException();
|
||||
}
|
||||
}
|
||||
|
||||
private MailboxList buildGroupBody(ASTgroup_body node, DecodeMonitor monitor) throws ParseException {
|
||||
List<Mailbox> results = new ArrayList<Mailbox>();
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
while (it.hasNext()) {
|
||||
Node n = it.next();
|
||||
if (n instanceof ASTmailbox)
|
||||
results.add(buildMailbox((ASTmailbox) n, monitor));
|
||||
else
|
||||
throw new ParseException();
|
||||
}
|
||||
return new MailboxList(results, true);
|
||||
}
|
||||
|
||||
public Mailbox buildMailbox(ASTmailbox node, DecodeMonitor monitor) throws ParseException {
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
Node n = it.next();
|
||||
if (n instanceof ASTaddr_spec) {
|
||||
return buildAddrSpec((ASTaddr_spec) n);
|
||||
} else if (n instanceof ASTangle_addr) {
|
||||
return buildAngleAddr((ASTangle_addr) n);
|
||||
} else if (n instanceof ASTname_addr) {
|
||||
return buildNameAddr((ASTname_addr) n, monitor);
|
||||
} else {
|
||||
throw new ParseException();
|
||||
}
|
||||
}
|
||||
|
||||
private Mailbox buildNameAddr(ASTname_addr node, DecodeMonitor monitor) throws ParseException {
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
Node n = it.next();
|
||||
String name;
|
||||
if (n instanceof ASTphrase) {
|
||||
name = buildString((ASTphrase) n, false);
|
||||
} else {
|
||||
throw new ParseException();
|
||||
}
|
||||
|
||||
n = it.next();
|
||||
if (n instanceof ASTangle_addr) {
|
||||
try {
|
||||
name = DecoderUtil.decodeEncodedWords(name, monitor);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ParseException(e.getMessage());
|
||||
}
|
||||
Mailbox mb = buildAngleAddr((ASTangle_addr) n);
|
||||
return new Mailbox(name, mb.getRoute(), mb.getLocalPart(),
|
||||
mb.getDomain());
|
||||
} else {
|
||||
throw new ParseException();
|
||||
}
|
||||
}
|
||||
|
||||
private Mailbox buildAngleAddr(ASTangle_addr node) throws ParseException {
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
DomainList route = null;
|
||||
Node n = it.next();
|
||||
if (n instanceof ASTroute) {
|
||||
route = buildRoute((ASTroute) n);
|
||||
n = it.next();
|
||||
} else if (n instanceof ASTaddr_spec) {
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
throw new ParseException();
|
||||
|
||||
if (n instanceof ASTaddr_spec)
|
||||
return buildAddrSpec(route, (ASTaddr_spec) n);
|
||||
else
|
||||
throw new ParseException();
|
||||
}
|
||||
|
||||
private DomainList buildRoute(ASTroute node) throws ParseException {
|
||||
List<String> results = new ArrayList<String>(node.jjtGetNumChildren());
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
while (it.hasNext()) {
|
||||
Node n = it.next();
|
||||
if (n instanceof ASTdomain)
|
||||
results.add(buildString((ASTdomain) n, true));
|
||||
else
|
||||
throw new ParseException();
|
||||
}
|
||||
return new DomainList(results, true);
|
||||
}
|
||||
|
||||
private Mailbox buildAddrSpec(ASTaddr_spec node) {
|
||||
return buildAddrSpec(null, node);
|
||||
}
|
||||
|
||||
private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) {
|
||||
ChildNodeIterator it = new ChildNodeIterator(node);
|
||||
String localPart = buildString((ASTlocal_part) it.next(), true);
|
||||
String domain = buildString((ASTdomain) it.next(), true);
|
||||
return new Mailbox(route, localPart, domain);
|
||||
}
|
||||
|
||||
private String buildString(SimpleNode node, boolean stripSpaces) {
|
||||
Token head = node.firstToken;
|
||||
Token tail = node.lastToken;
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
while (head != tail) {
|
||||
out.append(head.image);
|
||||
head = head.next;
|
||||
if (!stripSpaces)
|
||||
addSpecials(out, head.specialToken);
|
||||
}
|
||||
out.append(tail.image);
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private void addSpecials(StringBuilder out, Token specialToken) {
|
||||
if (specialToken != null) {
|
||||
addSpecials(out, specialToken.specialToken);
|
||||
out.append(specialToken.image);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChildNodeIterator implements Iterator<Node> {
|
||||
|
||||
private SimpleNode simpleNode;
|
||||
private int index;
|
||||
private int len;
|
||||
|
||||
public ChildNodeIterator(SimpleNode simpleNode) {
|
||||
this.simpleNode = simpleNode;
|
||||
this.len = simpleNode.jjtGetNumChildren();
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < len;
|
||||
}
|
||||
|
||||
public Node next() {
|
||||
return simpleNode.jjtGetChild(index++);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. JJTAddressListParserState.java Version 5.0 */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public class JJTAddressListParserState {
|
||||
private java.util.List<Node> nodes;
|
||||
private java.util.List<Integer> marks;
|
||||
|
||||
private int sp; // number of nodes on stack
|
||||
private int mk; // current mark
|
||||
private boolean node_created;
|
||||
|
||||
public JJTAddressListParserState() {
|
||||
nodes = new java.util.ArrayList<Node>();
|
||||
marks = new java.util.ArrayList<Integer>();
|
||||
sp = 0;
|
||||
mk = 0;
|
||||
}
|
||||
|
||||
/* Determines whether the current node was actually closed and
|
||||
pushed. This should only be called in the final user action of a
|
||||
node scope. */
|
||||
public boolean nodeCreated() {
|
||||
return node_created;
|
||||
}
|
||||
|
||||
/* Call this to reinitialize the node stack. It is called
|
||||
automatically by the parser's ReInit() method. */
|
||||
public void reset() {
|
||||
nodes.clear();
|
||||
marks.clear();
|
||||
sp = 0;
|
||||
mk = 0;
|
||||
}
|
||||
|
||||
/* Returns the root node of the AST. It only makes sense to call
|
||||
this after a successful parse. */
|
||||
public Node rootNode() {
|
||||
return nodes.get(0);
|
||||
}
|
||||
|
||||
/* Pushes a node on to the stack. */
|
||||
public void pushNode(Node n) {
|
||||
nodes.add(n);
|
||||
++sp;
|
||||
}
|
||||
|
||||
/* Returns the node on the top of the stack, and remove it from the
|
||||
stack. */
|
||||
public Node popNode() {
|
||||
if (--sp < mk) {
|
||||
mk = marks.remove(marks.size()-1);
|
||||
}
|
||||
return nodes.remove(nodes.size()-1);
|
||||
}
|
||||
|
||||
/* Returns the node currently on the top of the stack. */
|
||||
public Node peekNode() {
|
||||
return nodes.get(nodes.size()-1);
|
||||
}
|
||||
|
||||
/* Returns the number of children on the stack in the current node
|
||||
scope. */
|
||||
public int nodeArity() {
|
||||
return sp - mk;
|
||||
}
|
||||
|
||||
|
||||
public void clearNodeScope(Node n) {
|
||||
while (sp > mk) {
|
||||
popNode();
|
||||
}
|
||||
mk = marks.remove(marks.size()-1);
|
||||
}
|
||||
|
||||
|
||||
public void openNodeScope(Node n) {
|
||||
marks.add(mk);
|
||||
mk = sp;
|
||||
n.jjtOpen();
|
||||
}
|
||||
|
||||
|
||||
/* A definite node is constructed from a specified number of
|
||||
children. That number of nodes are popped from the stack and
|
||||
made the children of the definite node. Then the definite node
|
||||
is pushed on to the stack. */
|
||||
public void closeNodeScope(Node n, int num) {
|
||||
mk = marks.remove(marks.size()-1);
|
||||
while (num-- > 0) {
|
||||
Node c = popNode();
|
||||
c.jjtSetParent(n);
|
||||
n.jjtAddChild(c, num);
|
||||
}
|
||||
n.jjtClose();
|
||||
pushNode(n);
|
||||
node_created = true;
|
||||
}
|
||||
|
||||
|
||||
/* A conditional node is constructed if its condition is true. All
|
||||
the nodes that have been pushed since the node was opened are
|
||||
made children of the conditional node, which is then pushed
|
||||
on to the stack. If the condition is false the node is not
|
||||
constructed and they are left on the stack. */
|
||||
public void closeNodeScope(Node n, boolean condition) {
|
||||
if (condition) {
|
||||
int a = nodeArity();
|
||||
mk = marks.remove(marks.size()-1);
|
||||
while (a-- > 0) {
|
||||
Node c = popNode();
|
||||
c.jjtSetParent(n);
|
||||
n.jjtAddChild(c, a);
|
||||
}
|
||||
n.jjtClose();
|
||||
pushNode(n);
|
||||
node_created = true;
|
||||
} else {
|
||||
mk = marks.remove(marks.size()-1);
|
||||
node_created = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=e61a7a50ac6b2ea6fa91b5482005b3ce (do not edit this line) */
|
@ -1,39 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. Node.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
/* All AST nodes must implement this interface. It provides basic
|
||||
machinery for constructing the parent and child relationships
|
||||
between nodes. */
|
||||
|
||||
public
|
||||
interface Node {
|
||||
|
||||
/** This method is called after the node has been made the current
|
||||
node. It indicates that child nodes can now be added to it. */
|
||||
public void jjtOpen();
|
||||
|
||||
/** This method is called after all the child nodes have been
|
||||
added. */
|
||||
public void jjtClose();
|
||||
|
||||
/** This pair of methods are used to inform the node of its
|
||||
parent. */
|
||||
public void jjtSetParent(Node n);
|
||||
public Node jjtGetParent();
|
||||
|
||||
/** This method tells the node to add its argument to the node's
|
||||
list of children. */
|
||||
public void jjtAddChild(Node n, int i);
|
||||
|
||||
/** This method returns a child node. The children are numbered
|
||||
from zero, left to right. */
|
||||
public Node jjtGetChild(int i);
|
||||
|
||||
/** Return the number of children the node has. */
|
||||
public int jjtGetNumChildren();
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data);
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=b3b1bedb94f5dcae7af8d6e02371fe1e (do not edit this line) */
|
@ -1,220 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
/**
|
||||
* This exception is thrown when parse errors are encountered.
|
||||
* You can explicitly create objects of this exception type by
|
||||
* calling the method generateParseException in the generated
|
||||
* parser.
|
||||
*
|
||||
* Changes for Mime4J:
|
||||
* extends org.apache.james.mime4j.field.ParseException
|
||||
* added serialVersionUID
|
||||
* added constructor ParseException(Throwable)
|
||||
* default detail message is "Cannot parse field"
|
||||
*/
|
||||
public class ParseException extends org.apache.james.mime4j.dom.field.ParseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* This constructor is used by the method "generateParseException"
|
||||
* in the generated parser. Calling this constructor generates
|
||||
* a new object of this type with the fields "currentToken",
|
||||
* "expectedTokenSequences", and "tokenImage" set. The boolean
|
||||
* flag "specialConstructor" is also set to true to indicate that
|
||||
* this constructor was used to create this object.
|
||||
* This constructor calls its super class with the empty string
|
||||
* to force the "toString" method of parent class "Throwable" to
|
||||
* print the error message in the form:
|
||||
* ParseException: <result of getMessage>
|
||||
*/
|
||||
public ParseException(Token currentTokenVal,
|
||||
int[][] expectedTokenSequencesVal,
|
||||
String[] tokenImageVal
|
||||
)
|
||||
{
|
||||
super("");
|
||||
specialConstructor = true;
|
||||
currentToken = currentTokenVal;
|
||||
expectedTokenSequences = expectedTokenSequencesVal;
|
||||
tokenImage = tokenImageVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following constructors are for use by you for whatever
|
||||
* purpose you can think of. Constructing the exception in this
|
||||
* manner makes the exception behave in the normal way - i.e., as
|
||||
* documented in the class "Throwable". The fields "errorToken",
|
||||
* "expectedTokenSequences", and "tokenImage" do not contain
|
||||
* relevant information. The JavaCC generated code does not use
|
||||
* these constructors.
|
||||
*/
|
||||
|
||||
public ParseException() {
|
||||
super("Cannot parse field");
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This variable determines which constructor was used to create
|
||||
* this object and thereby affects the semantics of the
|
||||
* "getMessage" method (see below).
|
||||
*/
|
||||
protected boolean specialConstructor;
|
||||
|
||||
/**
|
||||
* This is the last token that has been consumed successfully. If
|
||||
* this object has been created due to a parse error, the token
|
||||
* followng this token will (therefore) be the first error token.
|
||||
*/
|
||||
public Token currentToken;
|
||||
|
||||
/**
|
||||
* Each entry in this array is an array of integers. Each array
|
||||
* of integers represents a sequence of tokens (by their ordinal
|
||||
* values) that is expected at this point of the parse.
|
||||
*/
|
||||
public int[][] expectedTokenSequences;
|
||||
|
||||
/**
|
||||
* This is a reference to the "tokenImage" array of the generated
|
||||
* parser within which the parse error occurred. This array is
|
||||
* defined in the generated ...Constants interface.
|
||||
*/
|
||||
public String[] tokenImage;
|
||||
|
||||
/**
|
||||
* This method has the standard behavior when this object has been
|
||||
* created using the standard constructors. Otherwise, it uses
|
||||
* "currentToken" and "expectedTokenSequences" to generate a parse
|
||||
* error message and returns it. If this object has been created
|
||||
* due to a parse error, and you do not catch it (it gets thrown
|
||||
* from the parser), then this method is called during the printing
|
||||
* of the final stack trace, and hence the correct error message
|
||||
* gets displayed.
|
||||
*/
|
||||
public String getMessage() {
|
||||
if (!specialConstructor) {
|
||||
return super.getMessage();
|
||||
}
|
||||
StringBuffer expected = new StringBuffer();
|
||||
int maxSize = 0;
|
||||
for (int i = 0; i < expectedTokenSequences.length; i++) {
|
||||
if (maxSize < expectedTokenSequences[i].length) {
|
||||
maxSize = expectedTokenSequences[i].length;
|
||||
}
|
||||
for (int j = 0; j < expectedTokenSequences[i].length; j++) {
|
||||
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
|
||||
}
|
||||
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
|
||||
expected.append("...");
|
||||
}
|
||||
expected.append(eol).append(" ");
|
||||
}
|
||||
String retval = "Encountered \"";
|
||||
Token tok = currentToken.next;
|
||||
for (int i = 0; i < maxSize; i++) {
|
||||
if (i != 0) retval += " ";
|
||||
if (tok.kind == 0) {
|
||||
retval += tokenImage[0];
|
||||
break;
|
||||
}
|
||||
retval += add_escapes(tok.image);
|
||||
tok = tok.next;
|
||||
}
|
||||
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
|
||||
retval += "." + eol;
|
||||
if (expectedTokenSequences.length == 1) {
|
||||
retval += "Was expecting:" + eol + " ";
|
||||
} else {
|
||||
retval += "Was expecting one of:" + eol + " ";
|
||||
}
|
||||
retval += expected.toString();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The end of line string for this machine.
|
||||
*/
|
||||
protected String eol = System.getProperty("line.separator", "\n");
|
||||
|
||||
/**
|
||||
* Used to convert raw characters to their escaped version
|
||||
* when these raw version cannot be used as part of an ASCII
|
||||
* string literal.
|
||||
*/
|
||||
protected String add_escapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,489 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
|
||||
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
/**
|
||||
* An implementation of interface CharStream, where the stream is assumed to
|
||||
* contain only ASCII characters (without unicode processing).
|
||||
*/
|
||||
|
||||
public class SimpleCharStream
|
||||
{
|
||||
/** Whether parser is static. */
|
||||
public static final boolean staticFlag = false;
|
||||
int bufsize;
|
||||
int available;
|
||||
int tokenBegin;
|
||||
/** Position in buffer. */
|
||||
public int bufpos = -1;
|
||||
protected int bufline[];
|
||||
protected int bufcolumn[];
|
||||
|
||||
protected int column = 0;
|
||||
protected int line = 1;
|
||||
|
||||
protected boolean prevCharIsCR = false;
|
||||
protected boolean prevCharIsLF = false;
|
||||
|
||||
protected java.io.Reader inputStream;
|
||||
|
||||
protected char[] buffer;
|
||||
protected int maxNextCharInd = 0;
|
||||
protected int inBuf = 0;
|
||||
protected int tabSize = 8;
|
||||
|
||||
protected void setTabSize(int i) { tabSize = i; }
|
||||
protected int getTabSize(int i) { return tabSize; }
|
||||
|
||||
|
||||
protected void ExpandBuff(boolean wrapAround)
|
||||
{
|
||||
char[] newbuffer = new char[bufsize + 2048];
|
||||
int newbufline[] = new int[bufsize + 2048];
|
||||
int newbufcolumn[] = new int[bufsize + 2048];
|
||||
|
||||
try
|
||||
{
|
||||
if (wrapAround)
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos -= tokenBegin);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new Error(t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
bufsize += 2048;
|
||||
available = bufsize;
|
||||
tokenBegin = 0;
|
||||
}
|
||||
|
||||
protected void FillBuff() throws java.io.IOException
|
||||
{
|
||||
if (maxNextCharInd == available)
|
||||
{
|
||||
if (available == bufsize)
|
||||
{
|
||||
if (tokenBegin > 2048)
|
||||
{
|
||||
bufpos = maxNextCharInd = 0;
|
||||
available = tokenBegin;
|
||||
}
|
||||
else if (tokenBegin < 0)
|
||||
bufpos = maxNextCharInd = 0;
|
||||
else
|
||||
ExpandBuff(false);
|
||||
}
|
||||
else if (available > tokenBegin)
|
||||
available = bufsize;
|
||||
else if ((tokenBegin - available) < 2048)
|
||||
ExpandBuff(true);
|
||||
else
|
||||
available = tokenBegin;
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
|
||||
{
|
||||
inputStream.close();
|
||||
throw new java.io.IOException();
|
||||
}
|
||||
else
|
||||
maxNextCharInd += i;
|
||||
return;
|
||||
}
|
||||
catch(java.io.IOException e) {
|
||||
--bufpos;
|
||||
backup(0);
|
||||
if (tokenBegin == -1)
|
||||
tokenBegin = bufpos;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/** Start. */
|
||||
public char BeginToken() throws java.io.IOException
|
||||
{
|
||||
tokenBegin = -1;
|
||||
char c = readChar();
|
||||
tokenBegin = bufpos;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
protected void UpdateLineColumn(char c)
|
||||
{
|
||||
column++;
|
||||
|
||||
if (prevCharIsLF)
|
||||
{
|
||||
prevCharIsLF = false;
|
||||
line += (column = 1);
|
||||
}
|
||||
else if (prevCharIsCR)
|
||||
{
|
||||
prevCharIsCR = false;
|
||||
if (c == '\n')
|
||||
{
|
||||
prevCharIsLF = true;
|
||||
}
|
||||
else
|
||||
line += (column = 1);
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r' :
|
||||
prevCharIsCR = true;
|
||||
break;
|
||||
case '\n' :
|
||||
prevCharIsLF = true;
|
||||
break;
|
||||
case '\t' :
|
||||
column--;
|
||||
column += (tabSize - (column % tabSize));
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
bufline[bufpos] = line;
|
||||
bufcolumn[bufpos] = column;
|
||||
}
|
||||
|
||||
/** Read a character. */
|
||||
public char readChar() throws java.io.IOException
|
||||
{
|
||||
if (inBuf > 0)
|
||||
{
|
||||
--inBuf;
|
||||
|
||||
if (++bufpos == bufsize)
|
||||
bufpos = 0;
|
||||
|
||||
return buffer[bufpos];
|
||||
}
|
||||
|
||||
if (++bufpos >= maxNextCharInd)
|
||||
FillBuff();
|
||||
|
||||
char c = buffer[bufpos];
|
||||
|
||||
UpdateLineColumn(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndColumn
|
||||
*/
|
||||
|
||||
public int getColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndLine
|
||||
*/
|
||||
|
||||
public int getLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end column number. */
|
||||
public int getEndColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end line number. */
|
||||
public int getEndLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token beginning column number. */
|
||||
public int getBeginColumn() {
|
||||
return bufcolumn[tokenBegin];
|
||||
}
|
||||
|
||||
/** Get token beginning line number. */
|
||||
public int getBeginLine() {
|
||||
return bufline[tokenBegin];
|
||||
}
|
||||
|
||||
/** Backup a number of characters. */
|
||||
public void backup(int amount) {
|
||||
|
||||
inBuf += amount;
|
||||
if ((bufpos -= amount) < 0)
|
||||
bufpos += bufsize;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
if (buffer == null || buffersize != buffer.length)
|
||||
{
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
prevCharIsLF = prevCharIsCR = false;
|
||||
tokenBegin = inBuf = maxNextCharInd = 0;
|
||||
bufpos = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Get token literal value. */
|
||||
public String GetImage()
|
||||
{
|
||||
if (bufpos >= tokenBegin)
|
||||
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
|
||||
else
|
||||
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
|
||||
new String(buffer, 0, bufpos + 1);
|
||||
}
|
||||
|
||||
/** Get the suffix. */
|
||||
public char[] GetSuffix(int len)
|
||||
{
|
||||
char[] ret = new char[len];
|
||||
|
||||
if ((bufpos + 1) >= len)
|
||||
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
|
||||
len - bufpos - 1);
|
||||
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Reset buffer when finished. */
|
||||
public void Done()
|
||||
{
|
||||
buffer = null;
|
||||
bufline = null;
|
||||
bufcolumn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to adjust line and column numbers for the start of a token.
|
||||
*/
|
||||
public void adjustBeginLineColumn(int newLine, int newCol)
|
||||
{
|
||||
int start = tokenBegin;
|
||||
int len;
|
||||
|
||||
if (bufpos >= tokenBegin)
|
||||
{
|
||||
len = bufpos - tokenBegin + inBuf + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
|
||||
}
|
||||
|
||||
int i = 0, j = 0, k = 0;
|
||||
int nextColDiff = 0, columnDiff = 0;
|
||||
|
||||
while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
|
||||
{
|
||||
bufline[j] = newLine;
|
||||
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
columnDiff = nextColDiff;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < len)
|
||||
{
|
||||
bufline[j] = newLine++;
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
|
||||
while (i++ < len)
|
||||
{
|
||||
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
|
||||
bufline[j] = newLine++;
|
||||
else
|
||||
bufline[j] = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
line = bufline[j];
|
||||
column = bufcolumn[j];
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=aa11a0881c952a5f8ec0ffbd5648e1c4 (do not edit this line) */
|
@ -1,96 +0,0 @@
|
||||
/* Generated By:JJTree: Do not edit this line. SimpleNode.java Version 4.3 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=false,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=org.apache.james.mime4j.field.address.parser.BaseNode,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
package org.apache.james.mime4j.field.address.parser;
|
||||
|
||||
public
|
||||
class SimpleNode extends org.apache.james.mime4j.field.address.parser.BaseNode implements Node {
|
||||
|
||||
protected Node parent;
|
||||
protected Node[] children;
|
||||
protected int id;
|
||||
protected Object value;
|
||||
protected AddressListParser parser;
|
||||
|
||||
public SimpleNode(int i) {
|
||||
id = i;
|
||||
}
|
||||
|
||||
public SimpleNode(AddressListParser p, int i) {
|
||||
this(i);
|
||||
parser = p;
|
||||
}
|
||||
|
||||
public void jjtOpen() {
|
||||
}
|
||||
|
||||
public void jjtClose() {
|
||||
}
|
||||
|
||||
public void jjtSetParent(Node n) { parent = n; }
|
||||
public Node jjtGetParent() { return parent; }
|
||||
|
||||
public void jjtAddChild(Node n, int i) {
|
||||
if (children == null) {
|
||||
children = new Node[i + 1];
|
||||
} else if (i >= children.length) {
|
||||
Node c[] = new Node[i + 1];
|
||||
System.arraycopy(children, 0, c, 0, children.length);
|
||||
children = c;
|
||||
}
|
||||
children[i] = n;
|
||||
}
|
||||
|
||||
public Node jjtGetChild(int i) {
|
||||
return children[i];
|
||||
}
|
||||
|
||||
public int jjtGetNumChildren() {
|
||||
return (children == null) ? 0 : children.length;
|
||||
}
|
||||
|
||||
public void jjtSetValue(Object value) { this.value = value; }
|
||||
public Object jjtGetValue() { return value; }
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(AddressListParserVisitor visitor, Object data)
|
||||
{
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object childrenAccept(AddressListParserVisitor visitor, Object data)
|
||||
{
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.length; ++i) {
|
||||
children[i].jjtAccept(visitor, data);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* You can override these two methods in subclasses of SimpleNode to
|
||||
customize the way the node appears when the tree is dumped. If
|
||||
your output uses more than one line you should override
|
||||
toString(String), otherwise overriding toString() is probably all
|
||||
you need to do. */
|
||||
|
||||
public String toString() { return AddressListParserTreeConstants.jjtNodeName[id]; }
|
||||
public String toString(String prefix) { return prefix + toString(); }
|
||||
|
||||
/* Override this method if you want to customize how the node dumps
|
||||
out its children. */
|
||||
|
||||
public void dump(String prefix) {
|
||||
System.out.println(toString(prefix));
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.length; ++i) {
|
||||
SimpleNode n = (SimpleNode)children[i];
|
||||
if (n != null) {
|
||||
n.dump(prefix + " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* JavaCC - OriginalChecksum=055879471a7647d34de4235b3186aa17 (do not edit this line) */
|
@ -1,149 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
|
||||
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
/**
|
||||
* Describes the input token stream.
|
||||
*/
|
||||
|
||||
public class Token implements java.io.Serializable {
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* An integer that describes the kind of this token. This numbering
|
||||
* system is determined by JavaCCParser, and a table of these numbers is
|
||||
* stored in the file ...Constants.java.
|
||||
*/
|
||||
public int kind;
|
||||
|
||||
/** The line number of the first character of this Token. */
|
||||
public int beginLine;
|
||||
/** The column number of the first character of this Token. */
|
||||
public int beginColumn;
|
||||
/** The line number of the last character of this Token. */
|
||||
public int endLine;
|
||||
/** The column number of the last character of this Token. */
|
||||
public int endColumn;
|
||||
|
||||
/**
|
||||
* The string image of the token.
|
||||
*/
|
||||
public String image;
|
||||
|
||||
/**
|
||||
* A reference to the next regular (non-special) token from the input
|
||||
* stream. If this is the last token from the input stream, or if the
|
||||
* token manager has not read tokens beyond this one, this field is
|
||||
* set to null. This is true only if this token is also a regular
|
||||
* token. Otherwise, see below for a description of the contents of
|
||||
* this field.
|
||||
*/
|
||||
public Token next;
|
||||
|
||||
/**
|
||||
* This field is used to access special tokens that occur prior to this
|
||||
* token, but after the immediately preceding regular (non-special) token.
|
||||
* If there are no such special tokens, this field is set to null.
|
||||
* When there are more than one such special token, this field refers
|
||||
* to the last of these special tokens, which in turn refers to the next
|
||||
* previous special token through its specialToken field, and so on
|
||||
* until the first special token (whose specialToken field is null).
|
||||
* The next fields of special tokens refer to other special tokens that
|
||||
* immediately follow it (without an intervening regular token). If there
|
||||
* is no such token, this field is null.
|
||||
*/
|
||||
public Token specialToken;
|
||||
|
||||
/**
|
||||
* An optional attribute value of the Token.
|
||||
* Tokens which are not used as syntactic sugar will often contain
|
||||
* meaningful values that will be used later on by the compiler or
|
||||
* interpreter. This attribute value is often different from the image.
|
||||
* Any subclass of Token that actually wants to return a non-null value can
|
||||
* override this method as appropriate.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-argument constructor
|
||||
*/
|
||||
public Token() {}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image.
|
||||
*/
|
||||
public Token(int kind)
|
||||
{
|
||||
this(kind, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image and Kind.
|
||||
*/
|
||||
public Token(int kind, String image)
|
||||
{
|
||||
this.kind = kind;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Token object, by default. However, if you want, you
|
||||
* can create and return subclass objects based on the value of ofKind.
|
||||
* Simply add the cases to the switch for all those special cases.
|
||||
* For example, if you have a subclass of Token called IDToken that
|
||||
* you want to create if ofKind is ID, simply add something like :
|
||||
*
|
||||
* case MyParserConstants.ID : return new IDToken(ofKind, image);
|
||||
*
|
||||
* to the following switch statement. Then you can cast matchedToken
|
||||
* variable to the appropriate type and use sit in your lexical actions.
|
||||
*/
|
||||
public static Token newToken(int ofKind, String image)
|
||||
{
|
||||
switch(ofKind)
|
||||
{
|
||||
default : return new Token(ofKind, image);
|
||||
}
|
||||
}
|
||||
|
||||
public static Token newToken(int ofKind)
|
||||
{
|
||||
return newToken(ofKind, null);
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=a51dc23d1faa88394342107e41df07b3 (do not edit this line) */
|
@ -1,165 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
|
||||
/* JavaCCOptions: */
|
||||
/****************************************************************
|
||||
* 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.field.address.parser;
|
||||
|
||||
/** Token Manager Error. */
|
||||
public class TokenMgrError extends Error
|
||||
{
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/*
|
||||
* Ordinals for various reasons why an Error of this type can be thrown.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lexical error occurred.
|
||||
*/
|
||||
static final int LEXICAL_ERROR = 0;
|
||||
|
||||
/**
|
||||
* An attempt was made to create a second instance of a static token manager.
|
||||
*/
|
||||
static final int STATIC_LEXER_ERROR = 1;
|
||||
|
||||
/**
|
||||
* Tried to change to an invalid lexical state.
|
||||
*/
|
||||
static final int INVALID_LEXICAL_STATE = 2;
|
||||
|
||||
/**
|
||||
* Detected (and bailed out of) an infinite loop in the token manager.
|
||||
*/
|
||||
static final int LOOP_DETECTED = 3;
|
||||
|
||||
/**
|
||||
* Indicates the reason why the exception is thrown. It will have
|
||||
* one of the above 4 values.
|
||||
*/
|
||||
int errorCode;
|
||||
|
||||
/**
|
||||
* Replaces unprintable characters by their escaped (or unicode escaped)
|
||||
* equivalents in the given string
|
||||
*/
|
||||
protected static final String addEscapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a detailed message for the Error when it is thrown by the
|
||||
* token manager to indicate a lexical error.
|
||||
* Parameters :
|
||||
* EOFSeen : indicates if EOF caused the lexical error
|
||||
* curLexState : lexical state in which this error occurred
|
||||
* errorLine : line number when the error occurred
|
||||
* errorColumn : column number when the error occurred
|
||||
* errorAfter : prefix that was seen before this error occurred
|
||||
* curchar : the offending character
|
||||
* Note: You can customize the lexical error message by modifying this method.
|
||||
*/
|
||||
protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
|
||||
return("Lexical error at line " +
|
||||
errorLine + ", column " +
|
||||
errorColumn + ". Encountered: " +
|
||||
(EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
|
||||
"after : \"" + addEscapes(errorAfter) + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* You can also modify the body of this method to customize your error messages.
|
||||
* For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
|
||||
* of end-users concern, so you can return something like :
|
||||
*
|
||||
* "Internal Error : Please file a bug report .... "
|
||||
*
|
||||
* from this method for such cases in the release version of your parser.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructors of various flavors follow.
|
||||
*/
|
||||
|
||||
/** No arg constructor. */
|
||||
public TokenMgrError() {
|
||||
}
|
||||
|
||||
/** Constructor with message and reason. */
|
||||
public TokenMgrError(String message, int reason) {
|
||||
super(message);
|
||||
errorCode = reason;
|
||||
}
|
||||
|
||||
/** Full Constructor. */
|
||||
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
|
||||
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=c00a20fac1340b0977b68c98d352e42d (do not edit this line) */
|
@ -1,292 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentDispositionParser.java */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ContentDispositionParser implements ContentDispositionParserConstants {
|
||||
|
||||
private String dispositionType;
|
||||
private List<String> paramNames = new ArrayList<String>();
|
||||
private List<String> paramValues = new ArrayList<String>();
|
||||
|
||||
public String getDispositionType() {
|
||||
return dispositionType;
|
||||
}
|
||||
|
||||
public List<String> getParamNames() {
|
||||
return paramNames;
|
||||
}
|
||||
|
||||
public List<String> getParamValues() {
|
||||
return paramValues;
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws ParseException {
|
||||
while (true) {
|
||||
try {
|
||||
ContentDispositionParser parser = new ContentDispositionParser(
|
||||
System.in);
|
||||
parser.parseLine();
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final public void parseLine() throws ParseException {
|
||||
parse();
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 1:
|
||||
jj_consume_token(1);
|
||||
break;
|
||||
default:
|
||||
jj_la1[0] = jj_gen;
|
||||
;
|
||||
}
|
||||
jj_consume_token(2);
|
||||
}
|
||||
|
||||
final public void parseAll() throws ParseException {
|
||||
parse();
|
||||
jj_consume_token(0);
|
||||
}
|
||||
|
||||
final public void parse() throws ParseException {
|
||||
Token dispositionType;
|
||||
dispositionType = jj_consume_token(ATOKEN);
|
||||
this.dispositionType = dispositionType.image;
|
||||
label_1:
|
||||
while (true) {
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 3:
|
||||
;
|
||||
break;
|
||||
default:
|
||||
jj_la1[1] = jj_gen;
|
||||
break label_1;
|
||||
}
|
||||
jj_consume_token(3);
|
||||
parameter();
|
||||
}
|
||||
}
|
||||
|
||||
final public void parameter() throws ParseException {
|
||||
Token attrib;
|
||||
String val;
|
||||
attrib = jj_consume_token(ATOKEN);
|
||||
jj_consume_token(4);
|
||||
val = value();
|
||||
paramNames.add(attrib.image);
|
||||
paramValues.add(val);
|
||||
}
|
||||
|
||||
final public String value() throws ParseException {
|
||||
Token t;
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case ATOKEN:
|
||||
t = jj_consume_token(ATOKEN);
|
||||
break;
|
||||
case DIGITS:
|
||||
t = jj_consume_token(DIGITS);
|
||||
break;
|
||||
case QUOTEDSTRING:
|
||||
t = jj_consume_token(QUOTEDSTRING);
|
||||
break;
|
||||
default:
|
||||
jj_la1[2] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
{if (true) return t.image;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
/** Generated Token Manager. */
|
||||
public ContentDispositionParserTokenManager token_source;
|
||||
SimpleCharStream jj_input_stream;
|
||||
/** Current token. */
|
||||
public Token token;
|
||||
/** Next token. */
|
||||
public Token jj_nt;
|
||||
private int jj_ntk;
|
||||
private int jj_gen;
|
||||
final private int[] jj_la1 = new int[3];
|
||||
static private int[] jj_la1_0;
|
||||
static {
|
||||
jj_la1_init_0();
|
||||
}
|
||||
private static void jj_la1_init_0() {
|
||||
jj_la1_0 = new int[] {0x2,0x8,0x1c0000,};
|
||||
}
|
||||
|
||||
/** Constructor with InputStream. */
|
||||
public ContentDispositionParser(java.io.InputStream stream) {
|
||||
this(stream, null);
|
||||
}
|
||||
/** Constructor with InputStream and supplied encoding */
|
||||
public ContentDispositionParser(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source = new ContentDispositionParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream) {
|
||||
ReInit(stream, null);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public ContentDispositionParser(java.io.Reader stream) {
|
||||
jj_input_stream = new SimpleCharStream(stream, 1, 1);
|
||||
token_source = new ContentDispositionParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader stream) {
|
||||
jj_input_stream.ReInit(stream, 1, 1);
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor with generated Token Manager. */
|
||||
public ContentDispositionParser(ContentDispositionParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(ContentDispositionParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
private Token jj_consume_token(int kind) throws ParseException {
|
||||
Token oldToken;
|
||||
if ((oldToken = token).next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
if (token.kind == kind) {
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
token = oldToken;
|
||||
jj_kind = kind;
|
||||
throw generateParseException();
|
||||
}
|
||||
|
||||
|
||||
/** Get the next Token. */
|
||||
final public Token getNextToken() {
|
||||
if (token.next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
|
||||
/** Get the specific Token. */
|
||||
final public Token getToken(int index) {
|
||||
Token t = token;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (t.next != null) t = t.next;
|
||||
else t = t.next = token_source.getNextToken();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
private int jj_ntk() {
|
||||
if ((jj_nt=token.next) == null)
|
||||
return (jj_ntk = (token.next=token_source.getNextToken()).kind);
|
||||
else
|
||||
return (jj_ntk = jj_nt.kind);
|
||||
}
|
||||
|
||||
private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
|
||||
private int[] jj_expentry;
|
||||
private int jj_kind = -1;
|
||||
|
||||
/** Generate ParseException. */
|
||||
public ParseException generateParseException() {
|
||||
jj_expentries.clear();
|
||||
boolean[] la1tokens = new boolean[23];
|
||||
if (jj_kind >= 0) {
|
||||
la1tokens[jj_kind] = true;
|
||||
jj_kind = -1;
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (jj_la1[i] == jj_gen) {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
if ((jj_la1_0[i] & (1<<j)) != 0) {
|
||||
la1tokens[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 23; i++) {
|
||||
if (la1tokens[i]) {
|
||||
jj_expentry = new int[1];
|
||||
jj_expentry[0] = i;
|
||||
jj_expentries.add(jj_expentry);
|
||||
}
|
||||
}
|
||||
int[][] exptokseq = new int[jj_expentries.size()][];
|
||||
for (int i = 0; i < jj_expentries.size(); i++) {
|
||||
exptokseq[i] = jj_expentries.get(i);
|
||||
}
|
||||
return new ParseException(token, exptokseq, tokenImage);
|
||||
}
|
||||
|
||||
/** Enable tracing. */
|
||||
final public void enable_tracing() {
|
||||
}
|
||||
|
||||
/** Disable tracing. */
|
||||
final public void disable_tracing() {
|
||||
}
|
||||
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentDispositionParserConstants.java */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
|
||||
/**
|
||||
* Token literal values and constants.
|
||||
* Generated by org.javacc.parser.OtherFilesGen#start()
|
||||
*/
|
||||
public interface ContentDispositionParserConstants {
|
||||
|
||||
/** End of File. */
|
||||
int EOF = 0;
|
||||
/** RegularExpression Id. */
|
||||
int WS = 5;
|
||||
/** RegularExpression Id. */
|
||||
int COMMENT = 7;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDSTRING = 18;
|
||||
/** RegularExpression Id. */
|
||||
int DIGITS = 19;
|
||||
/** RegularExpression Id. */
|
||||
int ATOKEN = 20;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDPAIR = 21;
|
||||
/** RegularExpression Id. */
|
||||
int ANY = 22;
|
||||
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 0;
|
||||
/** Lexical state. */
|
||||
int INCOMMENT = 1;
|
||||
/** Lexical state. */
|
||||
int NESTED_COMMENT = 2;
|
||||
/** Lexical state. */
|
||||
int INQUOTEDSTRING = 3;
|
||||
|
||||
/** Literal token values. */
|
||||
String[] tokenImage = {
|
||||
"<EOF>",
|
||||
"\"\\r\"",
|
||||
"\"\\n\"",
|
||||
"\";\"",
|
||||
"\"=\"",
|
||||
"<WS>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 8>",
|
||||
"\"(\"",
|
||||
"<token of kind 10>",
|
||||
"<token of kind 11>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 14>",
|
||||
"\"\\\"\"",
|
||||
"<token of kind 16>",
|
||||
"<token of kind 17>",
|
||||
"\"\\\"\"",
|
||||
"<DIGITS>",
|
||||
"<ATOKEN>",
|
||||
"<QUOTEDPAIR>",
|
||||
"<ANY>",
|
||||
};
|
||||
|
||||
}
|
@ -1,857 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentDispositionParserTokenManager.java */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Token Manager. */
|
||||
public class ContentDispositionParserTokenManager implements ContentDispositionParserConstants
|
||||
{
|
||||
// Keeps track of how many levels of comment nesting
|
||||
// we've encountered. This is only used when the 2nd
|
||||
// level is reached, for example ((this)), not (this).
|
||||
// This is because the outermost level must be treated
|
||||
// specially anyway, because the outermost ")" has a
|
||||
// different token type than inner ")" instances.
|
||||
static int commentNest;
|
||||
|
||||
/** Debug output. */
|
||||
public java.io.PrintStream debugStream = System.out;
|
||||
/** Set debug output. */
|
||||
public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
|
||||
private final int jjStopStringLiteralDfa_0(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_0(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjStopAtPos(int pos, int kind)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
return pos + 1;
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_0()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 10:
|
||||
return jjStartNfaWithStates_0(0, 2, 2);
|
||||
case 13:
|
||||
return jjStartNfaWithStates_0(0, 1, 2);
|
||||
case 34:
|
||||
return jjStopAtPos(0, 15);
|
||||
case 40:
|
||||
return jjStopAtPos(0, 6);
|
||||
case 59:
|
||||
return jjStopAtPos(0, 3);
|
||||
case 61:
|
||||
return jjStopAtPos(0, 4);
|
||||
default :
|
||||
return jjMoveNfa_0(3, 0);
|
||||
}
|
||||
}
|
||||
private int jjStartNfaWithStates_0(int pos, int kind, int state)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return pos + 1; }
|
||||
return jjMoveNfa_0(state, pos + 1);
|
||||
}
|
||||
static final long[] jjbitVec0 = {
|
||||
0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
|
||||
};
|
||||
private int jjMoveNfa_0(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
if ((0x3ff6cfafffffdffL & l) != 0L)
|
||||
{
|
||||
if (kind > 20)
|
||||
kind = 20;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if ((0x100000200L & l) != 0L)
|
||||
{
|
||||
if (kind > 5)
|
||||
kind = 5;
|
||||
jjCheckNAdd(0);
|
||||
}
|
||||
if ((0x3ff000000000000L & l) != 0L)
|
||||
{
|
||||
if (kind > 19)
|
||||
kind = 19;
|
||||
jjCheckNAdd(1);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if ((0x100000200L & l) == 0L)
|
||||
break;
|
||||
kind = 5;
|
||||
jjCheckNAdd(0);
|
||||
break;
|
||||
case 1:
|
||||
if ((0x3ff000000000000L & l) == 0L)
|
||||
break;
|
||||
if (kind > 19)
|
||||
kind = 19;
|
||||
jjCheckNAdd(1);
|
||||
break;
|
||||
case 2:
|
||||
if ((0x3ff6cfafffffdffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 20)
|
||||
kind = 20;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
case 2:
|
||||
if ((0xffffffffc7fffffeL & l) == 0L)
|
||||
break;
|
||||
kind = 20;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
case 2:
|
||||
if ((jjbitVec0[i2] & l2) == 0L)
|
||||
break;
|
||||
if (kind > 20)
|
||||
kind = 20;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_1(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_1(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_1()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 9);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 7);
|
||||
default :
|
||||
return jjMoveNfa_1(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_1(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 10)
|
||||
kind = 10;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 8)
|
||||
kind = 8;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 10)
|
||||
kind = 10;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 8)
|
||||
kind = 8;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 10)
|
||||
kind = 10;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 10)
|
||||
kind = 10;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 8)
|
||||
kind = 8;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_3(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_3(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_3()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 34:
|
||||
return jjStopAtPos(0, 18);
|
||||
default :
|
||||
return jjMoveNfa_3(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_3(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((0xfffffffbffffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0xffffffffefffffffL & l) != 0L)
|
||||
{
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
case 2:
|
||||
if ((0xffffffffefffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((jjbitVec0[i2] & l2) == 0L)
|
||||
break;
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 16)
|
||||
kind = 16;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_2(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_2(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_2()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 12);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 13);
|
||||
default :
|
||||
return jjMoveNfa_2(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_2(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 14)
|
||||
kind = 14;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 14)
|
||||
kind = 14;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
static final int[] jjnextStates = {
|
||||
};
|
||||
|
||||
/** Token literal values. */
|
||||
public static final String[] jjstrLiteralImages = {
|
||||
"", "\15", "\12", "\73", "\75", null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, };
|
||||
|
||||
/** Lexer state names. */
|
||||
public static final String[] lexStateNames = {
|
||||
"DEFAULT",
|
||||
"INCOMMENT",
|
||||
"NESTED_COMMENT",
|
||||
"INQUOTEDSTRING",
|
||||
};
|
||||
|
||||
/** Lex State array. */
|
||||
public static final int[] jjnewLexState = {
|
||||
-1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, -1, -1, -1,
|
||||
};
|
||||
static final long[] jjtoToken = {
|
||||
0x1c001fL,
|
||||
};
|
||||
static final long[] jjtoSkip = {
|
||||
0xa0L,
|
||||
};
|
||||
static final long[] jjtoSpecial = {
|
||||
0x20L,
|
||||
};
|
||||
static final long[] jjtoMore = {
|
||||
0x3ff40L,
|
||||
};
|
||||
protected SimpleCharStream input_stream;
|
||||
private final int[] jjrounds = new int[3];
|
||||
private final int[] jjstateSet = new int[6];
|
||||
private final StringBuilder jjimage = new StringBuilder();
|
||||
private StringBuilder image = jjimage;
|
||||
private int jjimageLen;
|
||||
private int lengthOfMatch;
|
||||
protected char curChar;
|
||||
/** Constructor. */
|
||||
public ContentDispositionParserTokenManager(SimpleCharStream stream){
|
||||
if (SimpleCharStream.staticFlag)
|
||||
throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
|
||||
input_stream = stream;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public ContentDispositionParserTokenManager(SimpleCharStream stream, int lexState){
|
||||
this(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream)
|
||||
{
|
||||
jjmatchedPos = jjnewStateCnt = 0;
|
||||
curLexState = defaultLexState;
|
||||
input_stream = stream;
|
||||
ReInitRounds();
|
||||
}
|
||||
private void ReInitRounds()
|
||||
{
|
||||
int i;
|
||||
jjround = 0x80000001;
|
||||
for (i = 3; i-- > 0;)
|
||||
jjrounds[i] = 0x80000000;
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream, int lexState)
|
||||
{
|
||||
ReInit(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Switch to specified lex state. */
|
||||
public void SwitchTo(int lexState)
|
||||
{
|
||||
if (lexState >= 4 || lexState < 0)
|
||||
throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
|
||||
else
|
||||
curLexState = lexState;
|
||||
}
|
||||
|
||||
protected Token jjFillToken()
|
||||
{
|
||||
final Token t;
|
||||
final String curTokenImage;
|
||||
final int beginLine;
|
||||
final int endLine;
|
||||
final int beginColumn;
|
||||
final int endColumn;
|
||||
String im = jjstrLiteralImages[jjmatchedKind];
|
||||
curTokenImage = (im == null) ? input_stream.GetImage() : im;
|
||||
beginLine = input_stream.getBeginLine();
|
||||
beginColumn = input_stream.getBeginColumn();
|
||||
endLine = input_stream.getEndLine();
|
||||
endColumn = input_stream.getEndColumn();
|
||||
t = Token.newToken(jjmatchedKind, curTokenImage);
|
||||
|
||||
t.beginLine = beginLine;
|
||||
t.endLine = endLine;
|
||||
t.beginColumn = beginColumn;
|
||||
t.endColumn = endColumn;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int curLexState = 0;
|
||||
int defaultLexState = 0;
|
||||
int jjnewStateCnt;
|
||||
int jjround;
|
||||
int jjmatchedPos;
|
||||
int jjmatchedKind;
|
||||
|
||||
/** Get the next Token. */
|
||||
public Token getNextToken()
|
||||
{
|
||||
Token specialToken = null;
|
||||
Token matchedToken;
|
||||
int curPos = 0;
|
||||
|
||||
EOFLoop :
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
curChar = input_stream.BeginToken();
|
||||
}
|
||||
catch(java.io.IOException e)
|
||||
{
|
||||
jjmatchedKind = 0;
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
return matchedToken;
|
||||
}
|
||||
image = jjimage;
|
||||
image.setLength(0);
|
||||
jjimageLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(curLexState)
|
||||
{
|
||||
case 0:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_0();
|
||||
break;
|
||||
case 1:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_1();
|
||||
break;
|
||||
case 2:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_2();
|
||||
break;
|
||||
case 3:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_3();
|
||||
break;
|
||||
}
|
||||
if (jjmatchedKind != 0x7fffffff)
|
||||
{
|
||||
if (jjmatchedPos + 1 < curPos)
|
||||
input_stream.backup(curPos - jjmatchedPos - 1);
|
||||
if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
TokenLexicalActions(matchedToken);
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
return matchedToken;
|
||||
}
|
||||
else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
if (specialToken == null)
|
||||
specialToken = matchedToken;
|
||||
else
|
||||
{
|
||||
matchedToken.specialToken = specialToken;
|
||||
specialToken = (specialToken.next = matchedToken);
|
||||
}
|
||||
}
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
continue EOFLoop;
|
||||
}
|
||||
MoreLexicalActions();
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
curPos = 0;
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
try {
|
||||
curChar = input_stream.readChar();
|
||||
continue;
|
||||
}
|
||||
catch (java.io.IOException e1) { }
|
||||
}
|
||||
int error_line = input_stream.getEndLine();
|
||||
int error_column = input_stream.getEndColumn();
|
||||
String error_after = null;
|
||||
boolean EOFSeen = false;
|
||||
try { input_stream.readChar(); input_stream.backup(1); }
|
||||
catch (java.io.IOException e1) {
|
||||
EOFSeen = true;
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
if (curChar == '\n' || curChar == '\r') {
|
||||
error_line++;
|
||||
error_column = 0;
|
||||
}
|
||||
else
|
||||
error_column++;
|
||||
}
|
||||
if (!EOFSeen) {
|
||||
input_stream.backup(1);
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
}
|
||||
throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoreLexicalActions()
|
||||
{
|
||||
jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 8 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 9 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
commentNest = 1;
|
||||
break;
|
||||
case 11 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 12 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
++commentNest;
|
||||
break;
|
||||
case 13 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
--commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
|
||||
break;
|
||||
case 15 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 1);
|
||||
break;
|
||||
case 16 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
void TokenLexicalActions(Token matchedToken)
|
||||
{
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 18 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
|
||||
matchedToken.image = image.substring(0, image.length() - 1);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void jjCheckNAdd(int state)
|
||||
{
|
||||
if (jjrounds[state] != jjround)
|
||||
{
|
||||
jjstateSet[jjnewStateCnt++] = state;
|
||||
jjrounds[state] = jjround;
|
||||
}
|
||||
}
|
||||
private void jjAddStates(int start, int end)
|
||||
{
|
||||
do {
|
||||
jjstateSet[jjnewStateCnt++] = jjnextStates[start];
|
||||
} while (start++ != end);
|
||||
}
|
||||
private void jjCheckNAddTwoStates(int state1, int state2)
|
||||
{
|
||||
jjCheckNAdd(state1);
|
||||
jjCheckNAdd(state2);
|
||||
}
|
||||
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
/**
|
||||
* This exception is thrown when parse errors are encountered.
|
||||
* You can explicitly create objects of this exception type by
|
||||
* calling the method generateParseException in the generated
|
||||
* parser.
|
||||
*
|
||||
* Changes for Mime4J:
|
||||
* extends org.apache.james.mime4j.field.ParseException
|
||||
* added serialVersionUID
|
||||
* added constructor ParseException(Throwable)
|
||||
* default detail message is "Cannot parse field"
|
||||
*/
|
||||
public class ParseException extends org.apache.james.mime4j.dom.field.ParseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* This constructor is used by the method "generateParseException"
|
||||
* in the generated parser. Calling this constructor generates
|
||||
* a new object of this type with the fields "currentToken",
|
||||
* "expectedTokenSequences", and "tokenImage" set. The boolean
|
||||
* flag "specialConstructor" is also set to true to indicate that
|
||||
* this constructor was used to create this object.
|
||||
* This constructor calls its super class with the empty string
|
||||
* to force the "toString" method of parent class "Throwable" to
|
||||
* print the error message in the form:
|
||||
* ParseException: <result of getMessage>
|
||||
*/
|
||||
public ParseException(Token currentTokenVal,
|
||||
int[][] expectedTokenSequencesVal,
|
||||
String[] tokenImageVal
|
||||
)
|
||||
{
|
||||
super("");
|
||||
specialConstructor = true;
|
||||
currentToken = currentTokenVal;
|
||||
expectedTokenSequences = expectedTokenSequencesVal;
|
||||
tokenImage = tokenImageVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following constructors are for use by you for whatever
|
||||
* purpose you can think of. Constructing the exception in this
|
||||
* manner makes the exception behave in the normal way - i.e., as
|
||||
* documented in the class "Throwable". The fields "errorToken",
|
||||
* "expectedTokenSequences", and "tokenImage" do not contain
|
||||
* relevant information. The JavaCC generated code does not use
|
||||
* these constructors.
|
||||
*/
|
||||
|
||||
public ParseException() {
|
||||
super("Cannot parse field");
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This variable determines which constructor was used to create
|
||||
* this object and thereby affects the semantics of the
|
||||
* "getMessage" method (see below).
|
||||
*/
|
||||
protected boolean specialConstructor;
|
||||
|
||||
/**
|
||||
* This is the last token that has been consumed successfully. If
|
||||
* this object has been created due to a parse error, the token
|
||||
* followng this token will (therefore) be the first error token.
|
||||
*/
|
||||
public Token currentToken;
|
||||
|
||||
/**
|
||||
* Each entry in this array is an array of integers. Each array
|
||||
* of integers represents a sequence of tokens (by their ordinal
|
||||
* values) that is expected at this point of the parse.
|
||||
*/
|
||||
public int[][] expectedTokenSequences;
|
||||
|
||||
/**
|
||||
* This is a reference to the "tokenImage" array of the generated
|
||||
* parser within which the parse error occurred. This array is
|
||||
* defined in the generated ...Constants interface.
|
||||
*/
|
||||
public String[] tokenImage;
|
||||
|
||||
/**
|
||||
* This method has the standard behavior when this object has been
|
||||
* created using the standard constructors. Otherwise, it uses
|
||||
* "currentToken" and "expectedTokenSequences" to generate a parse
|
||||
* error message and returns it. If this object has been created
|
||||
* due to a parse error, and you do not catch it (it gets thrown
|
||||
* from the parser), then this method is called during the printing
|
||||
* of the final stack trace, and hence the correct error message
|
||||
* gets displayed.
|
||||
*/
|
||||
public String getMessage() {
|
||||
if (!specialConstructor) {
|
||||
return super.getMessage();
|
||||
}
|
||||
StringBuffer expected = new StringBuffer();
|
||||
int maxSize = 0;
|
||||
for (int i = 0; i < expectedTokenSequences.length; i++) {
|
||||
if (maxSize < expectedTokenSequences[i].length) {
|
||||
maxSize = expectedTokenSequences[i].length;
|
||||
}
|
||||
for (int j = 0; j < expectedTokenSequences[i].length; j++) {
|
||||
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
|
||||
}
|
||||
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
|
||||
expected.append("...");
|
||||
}
|
||||
expected.append(eol).append(" ");
|
||||
}
|
||||
String retval = "Encountered \"";
|
||||
Token tok = currentToken.next;
|
||||
for (int i = 0; i < maxSize; i++) {
|
||||
if (i != 0) retval += " ";
|
||||
if (tok.kind == 0) {
|
||||
retval += tokenImage[0];
|
||||
break;
|
||||
}
|
||||
retval += add_escapes(tok.image);
|
||||
tok = tok.next;
|
||||
}
|
||||
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
|
||||
retval += "." + eol;
|
||||
if (expectedTokenSequences.length == 1) {
|
||||
retval += "Was expecting:" + eol + " ";
|
||||
} else {
|
||||
retval += "Was expecting one of:" + eol + " ";
|
||||
}
|
||||
retval += expected.toString();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The end of line string for this machine.
|
||||
*/
|
||||
protected String eol = System.getProperty("line.separator", "\n");
|
||||
|
||||
/**
|
||||
* Used to convert raw characters to their escaped version
|
||||
* when these raw version cannot be used as part of an ASCII
|
||||
* string literal.
|
||||
*/
|
||||
protected String add_escapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,489 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
|
||||
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
/**
|
||||
* An implementation of interface CharStream, where the stream is assumed to
|
||||
* contain only ASCII characters (without unicode processing).
|
||||
*/
|
||||
|
||||
public class SimpleCharStream
|
||||
{
|
||||
/** Whether parser is static. */
|
||||
public static final boolean staticFlag = false;
|
||||
int bufsize;
|
||||
int available;
|
||||
int tokenBegin;
|
||||
/** Position in buffer. */
|
||||
public int bufpos = -1;
|
||||
protected int bufline[];
|
||||
protected int bufcolumn[];
|
||||
|
||||
protected int column = 0;
|
||||
protected int line = 1;
|
||||
|
||||
protected boolean prevCharIsCR = false;
|
||||
protected boolean prevCharIsLF = false;
|
||||
|
||||
protected java.io.Reader inputStream;
|
||||
|
||||
protected char[] buffer;
|
||||
protected int maxNextCharInd = 0;
|
||||
protected int inBuf = 0;
|
||||
protected int tabSize = 8;
|
||||
|
||||
protected void setTabSize(int i) { tabSize = i; }
|
||||
protected int getTabSize(int i) { return tabSize; }
|
||||
|
||||
|
||||
protected void ExpandBuff(boolean wrapAround)
|
||||
{
|
||||
char[] newbuffer = new char[bufsize + 2048];
|
||||
int newbufline[] = new int[bufsize + 2048];
|
||||
int newbufcolumn[] = new int[bufsize + 2048];
|
||||
|
||||
try
|
||||
{
|
||||
if (wrapAround)
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos -= tokenBegin);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new Error(t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
bufsize += 2048;
|
||||
available = bufsize;
|
||||
tokenBegin = 0;
|
||||
}
|
||||
|
||||
protected void FillBuff() throws java.io.IOException
|
||||
{
|
||||
if (maxNextCharInd == available)
|
||||
{
|
||||
if (available == bufsize)
|
||||
{
|
||||
if (tokenBegin > 2048)
|
||||
{
|
||||
bufpos = maxNextCharInd = 0;
|
||||
available = tokenBegin;
|
||||
}
|
||||
else if (tokenBegin < 0)
|
||||
bufpos = maxNextCharInd = 0;
|
||||
else
|
||||
ExpandBuff(false);
|
||||
}
|
||||
else if (available > tokenBegin)
|
||||
available = bufsize;
|
||||
else if ((tokenBegin - available) < 2048)
|
||||
ExpandBuff(true);
|
||||
else
|
||||
available = tokenBegin;
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
|
||||
{
|
||||
inputStream.close();
|
||||
throw new java.io.IOException();
|
||||
}
|
||||
else
|
||||
maxNextCharInd += i;
|
||||
return;
|
||||
}
|
||||
catch(java.io.IOException e) {
|
||||
--bufpos;
|
||||
backup(0);
|
||||
if (tokenBegin == -1)
|
||||
tokenBegin = bufpos;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/** Start. */
|
||||
public char BeginToken() throws java.io.IOException
|
||||
{
|
||||
tokenBegin = -1;
|
||||
char c = readChar();
|
||||
tokenBegin = bufpos;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
protected void UpdateLineColumn(char c)
|
||||
{
|
||||
column++;
|
||||
|
||||
if (prevCharIsLF)
|
||||
{
|
||||
prevCharIsLF = false;
|
||||
line += (column = 1);
|
||||
}
|
||||
else if (prevCharIsCR)
|
||||
{
|
||||
prevCharIsCR = false;
|
||||
if (c == '\n')
|
||||
{
|
||||
prevCharIsLF = true;
|
||||
}
|
||||
else
|
||||
line += (column = 1);
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r' :
|
||||
prevCharIsCR = true;
|
||||
break;
|
||||
case '\n' :
|
||||
prevCharIsLF = true;
|
||||
break;
|
||||
case '\t' :
|
||||
column--;
|
||||
column += (tabSize - (column % tabSize));
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
bufline[bufpos] = line;
|
||||
bufcolumn[bufpos] = column;
|
||||
}
|
||||
|
||||
/** Read a character. */
|
||||
public char readChar() throws java.io.IOException
|
||||
{
|
||||
if (inBuf > 0)
|
||||
{
|
||||
--inBuf;
|
||||
|
||||
if (++bufpos == bufsize)
|
||||
bufpos = 0;
|
||||
|
||||
return buffer[bufpos];
|
||||
}
|
||||
|
||||
if (++bufpos >= maxNextCharInd)
|
||||
FillBuff();
|
||||
|
||||
char c = buffer[bufpos];
|
||||
|
||||
UpdateLineColumn(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndColumn
|
||||
*/
|
||||
|
||||
public int getColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndLine
|
||||
*/
|
||||
|
||||
public int getLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end column number. */
|
||||
public int getEndColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end line number. */
|
||||
public int getEndLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token beginning column number. */
|
||||
public int getBeginColumn() {
|
||||
return bufcolumn[tokenBegin];
|
||||
}
|
||||
|
||||
/** Get token beginning line number. */
|
||||
public int getBeginLine() {
|
||||
return bufline[tokenBegin];
|
||||
}
|
||||
|
||||
/** Backup a number of characters. */
|
||||
public void backup(int amount) {
|
||||
|
||||
inBuf += amount;
|
||||
if ((bufpos -= amount) < 0)
|
||||
bufpos += bufsize;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
if (buffer == null || buffersize != buffer.length)
|
||||
{
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
prevCharIsLF = prevCharIsCR = false;
|
||||
tokenBegin = inBuf = maxNextCharInd = 0;
|
||||
bufpos = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Get token literal value. */
|
||||
public String GetImage()
|
||||
{
|
||||
if (bufpos >= tokenBegin)
|
||||
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
|
||||
else
|
||||
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
|
||||
new String(buffer, 0, bufpos + 1);
|
||||
}
|
||||
|
||||
/** Get the suffix. */
|
||||
public char[] GetSuffix(int len)
|
||||
{
|
||||
char[] ret = new char[len];
|
||||
|
||||
if ((bufpos + 1) >= len)
|
||||
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
|
||||
len - bufpos - 1);
|
||||
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Reset buffer when finished. */
|
||||
public void Done()
|
||||
{
|
||||
buffer = null;
|
||||
bufline = null;
|
||||
bufcolumn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to adjust line and column numbers for the start of a token.
|
||||
*/
|
||||
public void adjustBeginLineColumn(int newLine, int newCol)
|
||||
{
|
||||
int start = tokenBegin;
|
||||
int len;
|
||||
|
||||
if (bufpos >= tokenBegin)
|
||||
{
|
||||
len = bufpos - tokenBegin + inBuf + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
|
||||
}
|
||||
|
||||
int i = 0, j = 0, k = 0;
|
||||
int nextColDiff = 0, columnDiff = 0;
|
||||
|
||||
while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
|
||||
{
|
||||
bufline[j] = newLine;
|
||||
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
columnDiff = nextColDiff;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < len)
|
||||
{
|
||||
bufline[j] = newLine++;
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
|
||||
while (i++ < len)
|
||||
{
|
||||
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
|
||||
bufline[j] = newLine++;
|
||||
else
|
||||
bufline[j] = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
line = bufline[j];
|
||||
column = bufcolumn[j];
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=3a0a96dd40a434f5b242b9ed9202faa4 (do not edit this line) */
|
@ -1,149 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
|
||||
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
/**
|
||||
* Describes the input token stream.
|
||||
*/
|
||||
|
||||
public class Token implements java.io.Serializable {
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* An integer that describes the kind of this token. This numbering
|
||||
* system is determined by JavaCCParser, and a table of these numbers is
|
||||
* stored in the file ...Constants.java.
|
||||
*/
|
||||
public int kind;
|
||||
|
||||
/** The line number of the first character of this Token. */
|
||||
public int beginLine;
|
||||
/** The column number of the first character of this Token. */
|
||||
public int beginColumn;
|
||||
/** The line number of the last character of this Token. */
|
||||
public int endLine;
|
||||
/** The column number of the last character of this Token. */
|
||||
public int endColumn;
|
||||
|
||||
/**
|
||||
* The string image of the token.
|
||||
*/
|
||||
public String image;
|
||||
|
||||
/**
|
||||
* A reference to the next regular (non-special) token from the input
|
||||
* stream. If this is the last token from the input stream, or if the
|
||||
* token manager has not read tokens beyond this one, this field is
|
||||
* set to null. This is true only if this token is also a regular
|
||||
* token. Otherwise, see below for a description of the contents of
|
||||
* this field.
|
||||
*/
|
||||
public Token next;
|
||||
|
||||
/**
|
||||
* This field is used to access special tokens that occur prior to this
|
||||
* token, but after the immediately preceding regular (non-special) token.
|
||||
* If there are no such special tokens, this field is set to null.
|
||||
* When there are more than one such special token, this field refers
|
||||
* to the last of these special tokens, which in turn refers to the next
|
||||
* previous special token through its specialToken field, and so on
|
||||
* until the first special token (whose specialToken field is null).
|
||||
* The next fields of special tokens refer to other special tokens that
|
||||
* immediately follow it (without an intervening regular token). If there
|
||||
* is no such token, this field is null.
|
||||
*/
|
||||
public Token specialToken;
|
||||
|
||||
/**
|
||||
* An optional attribute value of the Token.
|
||||
* Tokens which are not used as syntactic sugar will often contain
|
||||
* meaningful values that will be used later on by the compiler or
|
||||
* interpreter. This attribute value is often different from the image.
|
||||
* Any subclass of Token that actually wants to return a non-null value can
|
||||
* override this method as appropriate.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-argument constructor
|
||||
*/
|
||||
public Token() {}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image.
|
||||
*/
|
||||
public Token(int kind)
|
||||
{
|
||||
this(kind, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image and Kind.
|
||||
*/
|
||||
public Token(int kind, String image)
|
||||
{
|
||||
this.kind = kind;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Token object, by default. However, if you want, you
|
||||
* can create and return subclass objects based on the value of ofKind.
|
||||
* Simply add the cases to the switch for all those special cases.
|
||||
* For example, if you have a subclass of Token called IDToken that
|
||||
* you want to create if ofKind is ID, simply add something like :
|
||||
*
|
||||
* case MyParserConstants.ID : return new IDToken(ofKind, image);
|
||||
*
|
||||
* to the following switch statement. Then you can cast matchedToken
|
||||
* variable to the appropriate type and use sit in your lexical actions.
|
||||
*/
|
||||
public static Token newToken(int ofKind, String image)
|
||||
{
|
||||
switch(ofKind)
|
||||
{
|
||||
default : return new Token(ofKind, image);
|
||||
}
|
||||
}
|
||||
|
||||
public static Token newToken(int ofKind)
|
||||
{
|
||||
return newToken(ofKind, null);
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=b1ee9aaf7cbe47fcd350a0df848362b5 (do not edit this line) */
|
@ -1,165 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
|
||||
/* JavaCCOptions: */
|
||||
/****************************************************************
|
||||
* 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.field.contentdisposition.parser;
|
||||
|
||||
/** Token Manager Error. */
|
||||
public class TokenMgrError extends Error
|
||||
{
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/*
|
||||
* Ordinals for various reasons why an Error of this type can be thrown.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lexical error occurred.
|
||||
*/
|
||||
static final int LEXICAL_ERROR = 0;
|
||||
|
||||
/**
|
||||
* An attempt was made to create a second instance of a static token manager.
|
||||
*/
|
||||
static final int STATIC_LEXER_ERROR = 1;
|
||||
|
||||
/**
|
||||
* Tried to change to an invalid lexical state.
|
||||
*/
|
||||
static final int INVALID_LEXICAL_STATE = 2;
|
||||
|
||||
/**
|
||||
* Detected (and bailed out of) an infinite loop in the token manager.
|
||||
*/
|
||||
static final int LOOP_DETECTED = 3;
|
||||
|
||||
/**
|
||||
* Indicates the reason why the exception is thrown. It will have
|
||||
* one of the above 4 values.
|
||||
*/
|
||||
int errorCode;
|
||||
|
||||
/**
|
||||
* Replaces unprintable characters by their escaped (or unicode escaped)
|
||||
* equivalents in the given string
|
||||
*/
|
||||
protected static final String addEscapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a detailed message for the Error when it is thrown by the
|
||||
* token manager to indicate a lexical error.
|
||||
* Parameters :
|
||||
* EOFSeen : indicates if EOF caused the lexical error
|
||||
* curLexState : lexical state in which this error occurred
|
||||
* errorLine : line number when the error occurred
|
||||
* errorColumn : column number when the error occurred
|
||||
* errorAfter : prefix that was seen before this error occurred
|
||||
* curchar : the offending character
|
||||
* Note: You can customize the lexical error message by modifying this method.
|
||||
*/
|
||||
protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
|
||||
return("Lexical error at line " +
|
||||
errorLine + ", column " +
|
||||
errorColumn + ". Encountered: " +
|
||||
(EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
|
||||
"after : \"" + addEscapes(errorAfter) + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* You can also modify the body of this method to customize your error messages.
|
||||
* For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
|
||||
* of end-users concern, so you can return something like :
|
||||
*
|
||||
* "Internal Error : Please file a bug report .... "
|
||||
*
|
||||
* from this method for such cases in the release version of your parser.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructors of various flavors follow.
|
||||
*/
|
||||
|
||||
/** No arg constructor. */
|
||||
public TokenMgrError() {
|
||||
}
|
||||
|
||||
/** Constructor with message and reason. */
|
||||
public TokenMgrError(String message, int reason) {
|
||||
super(message);
|
||||
errorCode = reason;
|
||||
}
|
||||
|
||||
/** Full Constructor. */
|
||||
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
|
||||
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=9fa2b884a567f978be9291126c2a21c0 (do not edit this line) */
|
@ -1,289 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentTypeParser.java */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ContentTypeParser implements ContentTypeParserConstants {
|
||||
|
||||
private String type;
|
||||
private String subtype;
|
||||
private List<String> paramNames = new ArrayList<String>();
|
||||
private List<String> paramValues = new ArrayList<String>();
|
||||
|
||||
public String getType() { return type; }
|
||||
public String getSubType() { return subtype; }
|
||||
public List<String> getParamNames() { return paramNames; }
|
||||
public List<String> getParamValues() { return paramValues; }
|
||||
|
||||
public static void main(String args[]) throws ParseException {
|
||||
while (true) {
|
||||
try {
|
||||
ContentTypeParser parser = new ContentTypeParser(System.in);
|
||||
parser.parseLine();
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final public void parseLine() throws ParseException {
|
||||
parse();
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 1:
|
||||
jj_consume_token(1);
|
||||
break;
|
||||
default:
|
||||
jj_la1[0] = jj_gen;
|
||||
;
|
||||
}
|
||||
jj_consume_token(2);
|
||||
}
|
||||
|
||||
final public void parseAll() throws ParseException {
|
||||
parse();
|
||||
jj_consume_token(0);
|
||||
}
|
||||
|
||||
final public void parse() throws ParseException {
|
||||
Token type;
|
||||
Token subtype;
|
||||
type = jj_consume_token(ATOKEN);
|
||||
jj_consume_token(3);
|
||||
subtype = jj_consume_token(ATOKEN);
|
||||
this.type = type.image;
|
||||
this.subtype = subtype.image;
|
||||
label_1:
|
||||
while (true) {
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 4:
|
||||
;
|
||||
break;
|
||||
default:
|
||||
jj_la1[1] = jj_gen;
|
||||
break label_1;
|
||||
}
|
||||
jj_consume_token(4);
|
||||
parameter();
|
||||
}
|
||||
}
|
||||
|
||||
final public void parameter() throws ParseException {
|
||||
Token attrib;
|
||||
String val;
|
||||
attrib = jj_consume_token(ATOKEN);
|
||||
jj_consume_token(5);
|
||||
val = value();
|
||||
paramNames.add(attrib.image);
|
||||
paramValues.add(val);
|
||||
}
|
||||
|
||||
final public String value() throws ParseException {
|
||||
Token t;
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case ATOKEN:
|
||||
t = jj_consume_token(ATOKEN);
|
||||
break;
|
||||
case DIGITS:
|
||||
t = jj_consume_token(DIGITS);
|
||||
break;
|
||||
case QUOTEDSTRING:
|
||||
t = jj_consume_token(QUOTEDSTRING);
|
||||
break;
|
||||
default:
|
||||
jj_la1[2] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
{if (true) return t.image;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
/** Generated Token Manager. */
|
||||
public ContentTypeParserTokenManager token_source;
|
||||
SimpleCharStream jj_input_stream;
|
||||
/** Current token. */
|
||||
public Token token;
|
||||
/** Next token. */
|
||||
public Token jj_nt;
|
||||
private int jj_ntk;
|
||||
private int jj_gen;
|
||||
final private int[] jj_la1 = new int[3];
|
||||
static private int[] jj_la1_0;
|
||||
static {
|
||||
jj_la1_init_0();
|
||||
}
|
||||
private static void jj_la1_init_0() {
|
||||
jj_la1_0 = new int[] {0x2,0x10,0x380000,};
|
||||
}
|
||||
|
||||
/** Constructor with InputStream. */
|
||||
public ContentTypeParser(java.io.InputStream stream) {
|
||||
this(stream, null);
|
||||
}
|
||||
/** Constructor with InputStream and supplied encoding */
|
||||
public ContentTypeParser(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source = new ContentTypeParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream) {
|
||||
ReInit(stream, null);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public ContentTypeParser(java.io.Reader stream) {
|
||||
jj_input_stream = new SimpleCharStream(stream, 1, 1);
|
||||
token_source = new ContentTypeParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader stream) {
|
||||
jj_input_stream.ReInit(stream, 1, 1);
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor with generated Token Manager. */
|
||||
public ContentTypeParser(ContentTypeParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(ContentTypeParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 3; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
private Token jj_consume_token(int kind) throws ParseException {
|
||||
Token oldToken;
|
||||
if ((oldToken = token).next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
if (token.kind == kind) {
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
token = oldToken;
|
||||
jj_kind = kind;
|
||||
throw generateParseException();
|
||||
}
|
||||
|
||||
|
||||
/** Get the next Token. */
|
||||
final public Token getNextToken() {
|
||||
if (token.next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
|
||||
/** Get the specific Token. */
|
||||
final public Token getToken(int index) {
|
||||
Token t = token;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (t.next != null) t = t.next;
|
||||
else t = t.next = token_source.getNextToken();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
private int jj_ntk() {
|
||||
if ((jj_nt=token.next) == null)
|
||||
return (jj_ntk = (token.next=token_source.getNextToken()).kind);
|
||||
else
|
||||
return (jj_ntk = jj_nt.kind);
|
||||
}
|
||||
|
||||
private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
|
||||
private int[] jj_expentry;
|
||||
private int jj_kind = -1;
|
||||
|
||||
/** Generate ParseException. */
|
||||
public ParseException generateParseException() {
|
||||
jj_expentries.clear();
|
||||
boolean[] la1tokens = new boolean[24];
|
||||
if (jj_kind >= 0) {
|
||||
la1tokens[jj_kind] = true;
|
||||
jj_kind = -1;
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (jj_la1[i] == jj_gen) {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
if ((jj_la1_0[i] & (1<<j)) != 0) {
|
||||
la1tokens[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (la1tokens[i]) {
|
||||
jj_expentry = new int[1];
|
||||
jj_expentry[0] = i;
|
||||
jj_expentries.add(jj_expentry);
|
||||
}
|
||||
}
|
||||
int[][] exptokseq = new int[jj_expentries.size()][];
|
||||
for (int i = 0; i < jj_expentries.size(); i++) {
|
||||
exptokseq[i] = jj_expentries.get(i);
|
||||
}
|
||||
return new ParseException(token, exptokseq, tokenImage);
|
||||
}
|
||||
|
||||
/** Enable tracing. */
|
||||
final public void enable_tracing() {
|
||||
}
|
||||
|
||||
/** Disable tracing. */
|
||||
final public void disable_tracing() {
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentTypeParserConstants.java */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
|
||||
/**
|
||||
* Token literal values and constants.
|
||||
* Generated by org.javacc.parser.OtherFilesGen#start()
|
||||
*/
|
||||
public interface ContentTypeParserConstants {
|
||||
|
||||
/** End of File. */
|
||||
int EOF = 0;
|
||||
/** RegularExpression Id. */
|
||||
int WS = 6;
|
||||
/** RegularExpression Id. */
|
||||
int COMMENT = 8;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDSTRING = 19;
|
||||
/** RegularExpression Id. */
|
||||
int DIGITS = 20;
|
||||
/** RegularExpression Id. */
|
||||
int ATOKEN = 21;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDPAIR = 22;
|
||||
/** RegularExpression Id. */
|
||||
int ANY = 23;
|
||||
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 0;
|
||||
/** Lexical state. */
|
||||
int INCOMMENT = 1;
|
||||
/** Lexical state. */
|
||||
int NESTED_COMMENT = 2;
|
||||
/** Lexical state. */
|
||||
int INQUOTEDSTRING = 3;
|
||||
|
||||
/** Literal token values. */
|
||||
String[] tokenImage = {
|
||||
"<EOF>",
|
||||
"\"\\r\"",
|
||||
"\"\\n\"",
|
||||
"\"/\"",
|
||||
"\";\"",
|
||||
"\"=\"",
|
||||
"<WS>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 9>",
|
||||
"\"(\"",
|
||||
"<token of kind 11>",
|
||||
"<token of kind 12>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 15>",
|
||||
"\"\\\"\"",
|
||||
"<token of kind 17>",
|
||||
"<token of kind 18>",
|
||||
"\"\\\"\"",
|
||||
"<DIGITS>",
|
||||
"<ATOKEN>",
|
||||
"<QUOTEDPAIR>",
|
||||
"<ANY>",
|
||||
};
|
||||
|
||||
}
|
@ -1,859 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ContentTypeParserTokenManager.java */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** Token Manager. */
|
||||
public class ContentTypeParserTokenManager implements ContentTypeParserConstants
|
||||
{
|
||||
// Keeps track of how many levels of comment nesting
|
||||
// we've encountered. This is only used when the 2nd
|
||||
// level is reached, for example ((this)), not (this).
|
||||
// This is because the outermost level must be treated
|
||||
// specially anyway, because the outermost ")" has a
|
||||
// different token type than inner ")" instances.
|
||||
static int commentNest;
|
||||
|
||||
/** Debug output. */
|
||||
public java.io.PrintStream debugStream = System.out;
|
||||
/** Set debug output. */
|
||||
public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
|
||||
private final int jjStopStringLiteralDfa_0(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_0(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjStopAtPos(int pos, int kind)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
return pos + 1;
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_0()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 10:
|
||||
return jjStartNfaWithStates_0(0, 2, 2);
|
||||
case 13:
|
||||
return jjStartNfaWithStates_0(0, 1, 2);
|
||||
case 34:
|
||||
return jjStopAtPos(0, 16);
|
||||
case 40:
|
||||
return jjStopAtPos(0, 7);
|
||||
case 47:
|
||||
return jjStopAtPos(0, 3);
|
||||
case 59:
|
||||
return jjStopAtPos(0, 4);
|
||||
case 61:
|
||||
return jjStopAtPos(0, 5);
|
||||
default :
|
||||
return jjMoveNfa_0(3, 0);
|
||||
}
|
||||
}
|
||||
private int jjStartNfaWithStates_0(int pos, int kind, int state)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return pos + 1; }
|
||||
return jjMoveNfa_0(state, pos + 1);
|
||||
}
|
||||
static final long[] jjbitVec0 = {
|
||||
0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
|
||||
};
|
||||
private int jjMoveNfa_0(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
if ((0x3ff6cfafffffdffL & l) != 0L)
|
||||
{
|
||||
if (kind > 21)
|
||||
kind = 21;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if ((0x100000200L & l) != 0L)
|
||||
{
|
||||
if (kind > 6)
|
||||
kind = 6;
|
||||
jjCheckNAdd(0);
|
||||
}
|
||||
if ((0x3ff000000000000L & l) != 0L)
|
||||
{
|
||||
if (kind > 20)
|
||||
kind = 20;
|
||||
jjCheckNAdd(1);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if ((0x100000200L & l) == 0L)
|
||||
break;
|
||||
kind = 6;
|
||||
jjCheckNAdd(0);
|
||||
break;
|
||||
case 1:
|
||||
if ((0x3ff000000000000L & l) == 0L)
|
||||
break;
|
||||
if (kind > 20)
|
||||
kind = 20;
|
||||
jjCheckNAdd(1);
|
||||
break;
|
||||
case 2:
|
||||
if ((0x3ff6cfafffffdffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 21)
|
||||
kind = 21;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
case 2:
|
||||
if ((0xffffffffc7fffffeL & l) == 0L)
|
||||
break;
|
||||
kind = 21;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 3:
|
||||
case 2:
|
||||
if ((jjbitVec0[i2] & l2) == 0L)
|
||||
break;
|
||||
if (kind > 21)
|
||||
kind = 21;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_1(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_1(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_1()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 10);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 8);
|
||||
default :
|
||||
return jjMoveNfa_1(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_1(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 9)
|
||||
kind = 9;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 11)
|
||||
kind = 11;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 9)
|
||||
kind = 9;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 11)
|
||||
kind = 11;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 9)
|
||||
kind = 9;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_3(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_3(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_3()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 34:
|
||||
return jjStopAtPos(0, 19);
|
||||
default :
|
||||
return jjMoveNfa_3(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_3(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((0xfffffffbffffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 18)
|
||||
kind = 18;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0xffffffffefffffffL & l) != 0L)
|
||||
{
|
||||
if (kind > 18)
|
||||
kind = 18;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
case 2:
|
||||
if ((0xffffffffefffffffL & l) == 0L)
|
||||
break;
|
||||
if (kind > 18)
|
||||
kind = 18;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
if ((jjbitVec0[i2] & l2) == 0L)
|
||||
break;
|
||||
if (kind > 18)
|
||||
kind = 18;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 17)
|
||||
kind = 17;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_2(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_2(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_2()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 13);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 14);
|
||||
default :
|
||||
return jjMoveNfa_2(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_2(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 15)
|
||||
kind = 15;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 12)
|
||||
kind = 12;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 15)
|
||||
kind = 15;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 12)
|
||||
kind = 12;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 15)
|
||||
kind = 15;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 15)
|
||||
kind = 15;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 12)
|
||||
kind = 12;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
static final int[] jjnextStates = {
|
||||
};
|
||||
|
||||
/** Token literal values. */
|
||||
public static final String[] jjstrLiteralImages = {
|
||||
"", "\15", "\12", "\57", "\73", "\75", null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, };
|
||||
|
||||
/** Lexer state names. */
|
||||
public static final String[] lexStateNames = {
|
||||
"DEFAULT",
|
||||
"INCOMMENT",
|
||||
"NESTED_COMMENT",
|
||||
"INQUOTEDSTRING",
|
||||
};
|
||||
|
||||
/** Lex State array. */
|
||||
public static final int[] jjnewLexState = {
|
||||
-1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, -1, -1, -1,
|
||||
};
|
||||
static final long[] jjtoToken = {
|
||||
0x38003fL,
|
||||
};
|
||||
static final long[] jjtoSkip = {
|
||||
0x140L,
|
||||
};
|
||||
static final long[] jjtoSpecial = {
|
||||
0x40L,
|
||||
};
|
||||
static final long[] jjtoMore = {
|
||||
0x7fe80L,
|
||||
};
|
||||
protected SimpleCharStream input_stream;
|
||||
private final int[] jjrounds = new int[3];
|
||||
private final int[] jjstateSet = new int[6];
|
||||
private final StringBuilder jjimage = new StringBuilder();
|
||||
private StringBuilder image = jjimage;
|
||||
private int jjimageLen;
|
||||
private int lengthOfMatch;
|
||||
protected char curChar;
|
||||
/** Constructor. */
|
||||
public ContentTypeParserTokenManager(SimpleCharStream stream){
|
||||
if (SimpleCharStream.staticFlag)
|
||||
throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
|
||||
input_stream = stream;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public ContentTypeParserTokenManager(SimpleCharStream stream, int lexState){
|
||||
this(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream)
|
||||
{
|
||||
jjmatchedPos = jjnewStateCnt = 0;
|
||||
curLexState = defaultLexState;
|
||||
input_stream = stream;
|
||||
ReInitRounds();
|
||||
}
|
||||
private void ReInitRounds()
|
||||
{
|
||||
int i;
|
||||
jjround = 0x80000001;
|
||||
for (i = 3; i-- > 0;)
|
||||
jjrounds[i] = 0x80000000;
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream, int lexState)
|
||||
{
|
||||
ReInit(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Switch to specified lex state. */
|
||||
public void SwitchTo(int lexState)
|
||||
{
|
||||
if (lexState >= 4 || lexState < 0)
|
||||
throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
|
||||
else
|
||||
curLexState = lexState;
|
||||
}
|
||||
|
||||
protected Token jjFillToken()
|
||||
{
|
||||
final Token t;
|
||||
final String curTokenImage;
|
||||
final int beginLine;
|
||||
final int endLine;
|
||||
final int beginColumn;
|
||||
final int endColumn;
|
||||
String im = jjstrLiteralImages[jjmatchedKind];
|
||||
curTokenImage = (im == null) ? input_stream.GetImage() : im;
|
||||
beginLine = input_stream.getBeginLine();
|
||||
beginColumn = input_stream.getBeginColumn();
|
||||
endLine = input_stream.getEndLine();
|
||||
endColumn = input_stream.getEndColumn();
|
||||
t = Token.newToken(jjmatchedKind, curTokenImage);
|
||||
|
||||
t.beginLine = beginLine;
|
||||
t.endLine = endLine;
|
||||
t.beginColumn = beginColumn;
|
||||
t.endColumn = endColumn;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int curLexState = 0;
|
||||
int defaultLexState = 0;
|
||||
int jjnewStateCnt;
|
||||
int jjround;
|
||||
int jjmatchedPos;
|
||||
int jjmatchedKind;
|
||||
|
||||
/** Get the next Token. */
|
||||
public Token getNextToken()
|
||||
{
|
||||
Token specialToken = null;
|
||||
Token matchedToken;
|
||||
int curPos = 0;
|
||||
|
||||
EOFLoop :
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
curChar = input_stream.BeginToken();
|
||||
}
|
||||
catch(java.io.IOException e)
|
||||
{
|
||||
jjmatchedKind = 0;
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
return matchedToken;
|
||||
}
|
||||
image = jjimage;
|
||||
image.setLength(0);
|
||||
jjimageLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(curLexState)
|
||||
{
|
||||
case 0:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_0();
|
||||
break;
|
||||
case 1:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_1();
|
||||
break;
|
||||
case 2:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_2();
|
||||
break;
|
||||
case 3:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_3();
|
||||
break;
|
||||
}
|
||||
if (jjmatchedKind != 0x7fffffff)
|
||||
{
|
||||
if (jjmatchedPos + 1 < curPos)
|
||||
input_stream.backup(curPos - jjmatchedPos - 1);
|
||||
if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
TokenLexicalActions(matchedToken);
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
return matchedToken;
|
||||
}
|
||||
else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
if (specialToken == null)
|
||||
specialToken = matchedToken;
|
||||
else
|
||||
{
|
||||
matchedToken.specialToken = specialToken;
|
||||
specialToken = (specialToken.next = matchedToken);
|
||||
}
|
||||
}
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
continue EOFLoop;
|
||||
}
|
||||
MoreLexicalActions();
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
curPos = 0;
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
try {
|
||||
curChar = input_stream.readChar();
|
||||
continue;
|
||||
}
|
||||
catch (java.io.IOException e1) { }
|
||||
}
|
||||
int error_line = input_stream.getEndLine();
|
||||
int error_column = input_stream.getEndColumn();
|
||||
String error_after = null;
|
||||
boolean EOFSeen = false;
|
||||
try { input_stream.readChar(); input_stream.backup(1); }
|
||||
catch (java.io.IOException e1) {
|
||||
EOFSeen = true;
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
if (curChar == '\n' || curChar == '\r') {
|
||||
error_line++;
|
||||
error_column = 0;
|
||||
}
|
||||
else
|
||||
error_column++;
|
||||
}
|
||||
if (!EOFSeen) {
|
||||
input_stream.backup(1);
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
}
|
||||
throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoreLexicalActions()
|
||||
{
|
||||
jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 9 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 10 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
commentNest = 1;
|
||||
break;
|
||||
case 12 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 13 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
++commentNest;
|
||||
break;
|
||||
case 14 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
--commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
|
||||
break;
|
||||
case 16 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 1);
|
||||
break;
|
||||
case 17 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
void TokenLexicalActions(Token matchedToken)
|
||||
{
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 19 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
|
||||
matchedToken.image = image.substring(0, image.length() - 1);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void jjCheckNAdd(int state)
|
||||
{
|
||||
if (jjrounds[state] != jjround)
|
||||
{
|
||||
jjstateSet[jjnewStateCnt++] = state;
|
||||
jjrounds[state] = jjround;
|
||||
}
|
||||
}
|
||||
private void jjAddStates(int start, int end)
|
||||
{
|
||||
do {
|
||||
jjstateSet[jjnewStateCnt++] = jjnextStates[start];
|
||||
} while (start++ != end);
|
||||
}
|
||||
private void jjCheckNAddTwoStates(int state1, int state2)
|
||||
{
|
||||
jjCheckNAdd(state1);
|
||||
jjCheckNAdd(state2);
|
||||
}
|
||||
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
/**
|
||||
* This exception is thrown when parse errors are encountered.
|
||||
* You can explicitly create objects of this exception type by
|
||||
* calling the method generateParseException in the generated
|
||||
* parser.
|
||||
*
|
||||
* Changes for Mime4J:
|
||||
* extends org.apache.james.mime4j.field.ParseException
|
||||
* added serialVersionUID
|
||||
* added constructor ParseException(Throwable)
|
||||
* default detail message is "Cannot parse field"
|
||||
*/
|
||||
public class ParseException extends org.apache.james.mime4j.dom.field.ParseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* This constructor is used by the method "generateParseException"
|
||||
* in the generated parser. Calling this constructor generates
|
||||
* a new object of this type with the fields "currentToken",
|
||||
* "expectedTokenSequences", and "tokenImage" set. The boolean
|
||||
* flag "specialConstructor" is also set to true to indicate that
|
||||
* this constructor was used to create this object.
|
||||
* This constructor calls its super class with the empty string
|
||||
* to force the "toString" method of parent class "Throwable" to
|
||||
* print the error message in the form:
|
||||
* ParseException: <result of getMessage>
|
||||
*/
|
||||
public ParseException(Token currentTokenVal,
|
||||
int[][] expectedTokenSequencesVal,
|
||||
String[] tokenImageVal
|
||||
)
|
||||
{
|
||||
super("");
|
||||
specialConstructor = true;
|
||||
currentToken = currentTokenVal;
|
||||
expectedTokenSequences = expectedTokenSequencesVal;
|
||||
tokenImage = tokenImageVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following constructors are for use by you for whatever
|
||||
* purpose you can think of. Constructing the exception in this
|
||||
* manner makes the exception behave in the normal way - i.e., as
|
||||
* documented in the class "Throwable". The fields "errorToken",
|
||||
* "expectedTokenSequences", and "tokenImage" do not contain
|
||||
* relevant information. The JavaCC generated code does not use
|
||||
* these constructors.
|
||||
*/
|
||||
|
||||
public ParseException() {
|
||||
super("Cannot parse field");
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(Throwable cause) {
|
||||
super(cause);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
specialConstructor = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This variable determines which constructor was used to create
|
||||
* this object and thereby affects the semantics of the
|
||||
* "getMessage" method (see below).
|
||||
*/
|
||||
protected boolean specialConstructor;
|
||||
|
||||
/**
|
||||
* This is the last token that has been consumed successfully. If
|
||||
* this object has been created due to a parse error, the token
|
||||
* followng this token will (therefore) be the first error token.
|
||||
*/
|
||||
public Token currentToken;
|
||||
|
||||
/**
|
||||
* Each entry in this array is an array of integers. Each array
|
||||
* of integers represents a sequence of tokens (by their ordinal
|
||||
* values) that is expected at this point of the parse.
|
||||
*/
|
||||
public int[][] expectedTokenSequences;
|
||||
|
||||
/**
|
||||
* This is a reference to the "tokenImage" array of the generated
|
||||
* parser within which the parse error occurred. This array is
|
||||
* defined in the generated ...Constants interface.
|
||||
*/
|
||||
public String[] tokenImage;
|
||||
|
||||
/**
|
||||
* This method has the standard behavior when this object has been
|
||||
* created using the standard constructors. Otherwise, it uses
|
||||
* "currentToken" and "expectedTokenSequences" to generate a parse
|
||||
* error message and returns it. If this object has been created
|
||||
* due to a parse error, and you do not catch it (it gets thrown
|
||||
* from the parser), then this method is called during the printing
|
||||
* of the final stack trace, and hence the correct error message
|
||||
* gets displayed.
|
||||
*/
|
||||
public String getMessage() {
|
||||
if (!specialConstructor) {
|
||||
return super.getMessage();
|
||||
}
|
||||
StringBuffer expected = new StringBuffer();
|
||||
int maxSize = 0;
|
||||
for (int i = 0; i < expectedTokenSequences.length; i++) {
|
||||
if (maxSize < expectedTokenSequences[i].length) {
|
||||
maxSize = expectedTokenSequences[i].length;
|
||||
}
|
||||
for (int j = 0; j < expectedTokenSequences[i].length; j++) {
|
||||
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
|
||||
}
|
||||
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
|
||||
expected.append("...");
|
||||
}
|
||||
expected.append(eol).append(" ");
|
||||
}
|
||||
String retval = "Encountered \"";
|
||||
Token tok = currentToken.next;
|
||||
for (int i = 0; i < maxSize; i++) {
|
||||
if (i != 0) retval += " ";
|
||||
if (tok.kind == 0) {
|
||||
retval += tokenImage[0];
|
||||
break;
|
||||
}
|
||||
retval += add_escapes(tok.image);
|
||||
tok = tok.next;
|
||||
}
|
||||
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
|
||||
retval += "." + eol;
|
||||
if (expectedTokenSequences.length == 1) {
|
||||
retval += "Was expecting:" + eol + " ";
|
||||
} else {
|
||||
retval += "Was expecting one of:" + eol + " ";
|
||||
}
|
||||
retval += expected.toString();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The end of line string for this machine.
|
||||
*/
|
||||
protected String eol = System.getProperty("line.separator", "\n");
|
||||
|
||||
/**
|
||||
* Used to convert raw characters to their escaped version
|
||||
* when these raw version cannot be used as part of an ASCII
|
||||
* string literal.
|
||||
*/
|
||||
protected String add_escapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,489 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
|
||||
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
/**
|
||||
* An implementation of interface CharStream, where the stream is assumed to
|
||||
* contain only ASCII characters (without unicode processing).
|
||||
*/
|
||||
|
||||
public class SimpleCharStream
|
||||
{
|
||||
/** Whether parser is static. */
|
||||
public static final boolean staticFlag = false;
|
||||
int bufsize;
|
||||
int available;
|
||||
int tokenBegin;
|
||||
/** Position in buffer. */
|
||||
public int bufpos = -1;
|
||||
protected int bufline[];
|
||||
protected int bufcolumn[];
|
||||
|
||||
protected int column = 0;
|
||||
protected int line = 1;
|
||||
|
||||
protected boolean prevCharIsCR = false;
|
||||
protected boolean prevCharIsLF = false;
|
||||
|
||||
protected java.io.Reader inputStream;
|
||||
|
||||
protected char[] buffer;
|
||||
protected int maxNextCharInd = 0;
|
||||
protected int inBuf = 0;
|
||||
protected int tabSize = 8;
|
||||
|
||||
protected void setTabSize(int i) { tabSize = i; }
|
||||
protected int getTabSize(int i) { return tabSize; }
|
||||
|
||||
|
||||
protected void ExpandBuff(boolean wrapAround)
|
||||
{
|
||||
char[] newbuffer = new char[bufsize + 2048];
|
||||
int newbufline[] = new int[bufsize + 2048];
|
||||
int newbufcolumn[] = new int[bufsize + 2048];
|
||||
|
||||
try
|
||||
{
|
||||
if (wrapAround)
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos -= tokenBegin);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new Error(t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
bufsize += 2048;
|
||||
available = bufsize;
|
||||
tokenBegin = 0;
|
||||
}
|
||||
|
||||
protected void FillBuff() throws java.io.IOException
|
||||
{
|
||||
if (maxNextCharInd == available)
|
||||
{
|
||||
if (available == bufsize)
|
||||
{
|
||||
if (tokenBegin > 2048)
|
||||
{
|
||||
bufpos = maxNextCharInd = 0;
|
||||
available = tokenBegin;
|
||||
}
|
||||
else if (tokenBegin < 0)
|
||||
bufpos = maxNextCharInd = 0;
|
||||
else
|
||||
ExpandBuff(false);
|
||||
}
|
||||
else if (available > tokenBegin)
|
||||
available = bufsize;
|
||||
else if ((tokenBegin - available) < 2048)
|
||||
ExpandBuff(true);
|
||||
else
|
||||
available = tokenBegin;
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
|
||||
{
|
||||
inputStream.close();
|
||||
throw new java.io.IOException();
|
||||
}
|
||||
else
|
||||
maxNextCharInd += i;
|
||||
return;
|
||||
}
|
||||
catch(java.io.IOException e) {
|
||||
--bufpos;
|
||||
backup(0);
|
||||
if (tokenBegin == -1)
|
||||
tokenBegin = bufpos;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/** Start. */
|
||||
public char BeginToken() throws java.io.IOException
|
||||
{
|
||||
tokenBegin = -1;
|
||||
char c = readChar();
|
||||
tokenBegin = bufpos;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
protected void UpdateLineColumn(char c)
|
||||
{
|
||||
column++;
|
||||
|
||||
if (prevCharIsLF)
|
||||
{
|
||||
prevCharIsLF = false;
|
||||
line += (column = 1);
|
||||
}
|
||||
else if (prevCharIsCR)
|
||||
{
|
||||
prevCharIsCR = false;
|
||||
if (c == '\n')
|
||||
{
|
||||
prevCharIsLF = true;
|
||||
}
|
||||
else
|
||||
line += (column = 1);
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r' :
|
||||
prevCharIsCR = true;
|
||||
break;
|
||||
case '\n' :
|
||||
prevCharIsLF = true;
|
||||
break;
|
||||
case '\t' :
|
||||
column--;
|
||||
column += (tabSize - (column % tabSize));
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
bufline[bufpos] = line;
|
||||
bufcolumn[bufpos] = column;
|
||||
}
|
||||
|
||||
/** Read a character. */
|
||||
public char readChar() throws java.io.IOException
|
||||
{
|
||||
if (inBuf > 0)
|
||||
{
|
||||
--inBuf;
|
||||
|
||||
if (++bufpos == bufsize)
|
||||
bufpos = 0;
|
||||
|
||||
return buffer[bufpos];
|
||||
}
|
||||
|
||||
if (++bufpos >= maxNextCharInd)
|
||||
FillBuff();
|
||||
|
||||
char c = buffer[bufpos];
|
||||
|
||||
UpdateLineColumn(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndColumn
|
||||
*/
|
||||
|
||||
public int getColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndLine
|
||||
*/
|
||||
|
||||
public int getLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end column number. */
|
||||
public int getEndColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
/** Get token end line number. */
|
||||
public int getEndLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
/** Get token beginning column number. */
|
||||
public int getBeginColumn() {
|
||||
return bufcolumn[tokenBegin];
|
||||
}
|
||||
|
||||
/** Get token beginning line number. */
|
||||
public int getBeginLine() {
|
||||
return bufline[tokenBegin];
|
||||
}
|
||||
|
||||
/** Backup a number of characters. */
|
||||
public void backup(int amount) {
|
||||
|
||||
inBuf += amount;
|
||||
if ((bufpos -= amount) < 0)
|
||||
bufpos += bufsize;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.Reader dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
if (buffer == null || buffersize != buffer.length)
|
||||
{
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
prevCharIsLF = prevCharIsCR = false;
|
||||
tokenBegin = inBuf = maxNextCharInd = 0;
|
||||
bufpos = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
this(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public SimpleCharStream(java.io.InputStream dstream)
|
||||
{
|
||||
this(dstream, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, 1, 1, 4096);
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream)
|
||||
{
|
||||
ReInit(dstream, 1, 1, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
|
||||
int startcolumn) throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
ReInit(dstream, encoding, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
/** Get token literal value. */
|
||||
public String GetImage()
|
||||
{
|
||||
if (bufpos >= tokenBegin)
|
||||
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
|
||||
else
|
||||
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
|
||||
new String(buffer, 0, bufpos + 1);
|
||||
}
|
||||
|
||||
/** Get the suffix. */
|
||||
public char[] GetSuffix(int len)
|
||||
{
|
||||
char[] ret = new char[len];
|
||||
|
||||
if ((bufpos + 1) >= len)
|
||||
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
|
||||
len - bufpos - 1);
|
||||
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Reset buffer when finished. */
|
||||
public void Done()
|
||||
{
|
||||
buffer = null;
|
||||
bufline = null;
|
||||
bufcolumn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to adjust line and column numbers for the start of a token.
|
||||
*/
|
||||
public void adjustBeginLineColumn(int newLine, int newCol)
|
||||
{
|
||||
int start = tokenBegin;
|
||||
int len;
|
||||
|
||||
if (bufpos >= tokenBegin)
|
||||
{
|
||||
len = bufpos - tokenBegin + inBuf + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
|
||||
}
|
||||
|
||||
int i = 0, j = 0, k = 0;
|
||||
int nextColDiff = 0, columnDiff = 0;
|
||||
|
||||
while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
|
||||
{
|
||||
bufline[j] = newLine;
|
||||
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
columnDiff = nextColDiff;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < len)
|
||||
{
|
||||
bufline[j] = newLine++;
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
|
||||
while (i++ < len)
|
||||
{
|
||||
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
|
||||
bufline[j] = newLine++;
|
||||
else
|
||||
bufline[j] = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
line = bufline[j];
|
||||
column = bufcolumn[j];
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=6c6aad23fd4c0ff4139b17758b7e8610 (do not edit this line) */
|
@ -1,149 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
|
||||
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
/**
|
||||
* Describes the input token stream.
|
||||
*/
|
||||
|
||||
public class Token implements java.io.Serializable {
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* An integer that describes the kind of this token. This numbering
|
||||
* system is determined by JavaCCParser, and a table of these numbers is
|
||||
* stored in the file ...Constants.java.
|
||||
*/
|
||||
public int kind;
|
||||
|
||||
/** The line number of the first character of this Token. */
|
||||
public int beginLine;
|
||||
/** The column number of the first character of this Token. */
|
||||
public int beginColumn;
|
||||
/** The line number of the last character of this Token. */
|
||||
public int endLine;
|
||||
/** The column number of the last character of this Token. */
|
||||
public int endColumn;
|
||||
|
||||
/**
|
||||
* The string image of the token.
|
||||
*/
|
||||
public String image;
|
||||
|
||||
/**
|
||||
* A reference to the next regular (non-special) token from the input
|
||||
* stream. If this is the last token from the input stream, or if the
|
||||
* token manager has not read tokens beyond this one, this field is
|
||||
* set to null. This is true only if this token is also a regular
|
||||
* token. Otherwise, see below for a description of the contents of
|
||||
* this field.
|
||||
*/
|
||||
public Token next;
|
||||
|
||||
/**
|
||||
* This field is used to access special tokens that occur prior to this
|
||||
* token, but after the immediately preceding regular (non-special) token.
|
||||
* If there are no such special tokens, this field is set to null.
|
||||
* When there are more than one such special token, this field refers
|
||||
* to the last of these special tokens, which in turn refers to the next
|
||||
* previous special token through its specialToken field, and so on
|
||||
* until the first special token (whose specialToken field is null).
|
||||
* The next fields of special tokens refer to other special tokens that
|
||||
* immediately follow it (without an intervening regular token). If there
|
||||
* is no such token, this field is null.
|
||||
*/
|
||||
public Token specialToken;
|
||||
|
||||
/**
|
||||
* An optional attribute value of the Token.
|
||||
* Tokens which are not used as syntactic sugar will often contain
|
||||
* meaningful values that will be used later on by the compiler or
|
||||
* interpreter. This attribute value is often different from the image.
|
||||
* Any subclass of Token that actually wants to return a non-null value can
|
||||
* override this method as appropriate.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* No-argument constructor
|
||||
*/
|
||||
public Token() {}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image.
|
||||
*/
|
||||
public Token(int kind)
|
||||
{
|
||||
this(kind, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new token for the specified Image and Kind.
|
||||
*/
|
||||
public Token(int kind, String image)
|
||||
{
|
||||
this.kind = kind;
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Token object, by default. However, if you want, you
|
||||
* can create and return subclass objects based on the value of ofKind.
|
||||
* Simply add the cases to the switch for all those special cases.
|
||||
* For example, if you have a subclass of Token called IDToken that
|
||||
* you want to create if ofKind is ID, simply add something like :
|
||||
*
|
||||
* case MyParserConstants.ID : return new IDToken(ofKind, image);
|
||||
*
|
||||
* to the following switch statement. Then you can cast matchedToken
|
||||
* variable to the appropriate type and use sit in your lexical actions.
|
||||
*/
|
||||
public static Token newToken(int ofKind, String image)
|
||||
{
|
||||
switch(ofKind)
|
||||
{
|
||||
default : return new Token(ofKind, image);
|
||||
}
|
||||
}
|
||||
|
||||
public static Token newToken(int ofKind)
|
||||
{
|
||||
return newToken(ofKind, null);
|
||||
}
|
||||
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=3d41123d7d22080e3366761725b1c1fe (do not edit this line) */
|
@ -1,165 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
|
||||
/* JavaCCOptions: */
|
||||
/****************************************************************
|
||||
* 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.field.contenttype.parser;
|
||||
|
||||
/** Token Manager Error. */
|
||||
public class TokenMgrError extends Error
|
||||
{
|
||||
|
||||
/**
|
||||
* The version identifier for this Serializable class.
|
||||
* Increment only if the <i>serialized</i> form of the
|
||||
* class changes.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/*
|
||||
* Ordinals for various reasons why an Error of this type can be thrown.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lexical error occurred.
|
||||
*/
|
||||
static final int LEXICAL_ERROR = 0;
|
||||
|
||||
/**
|
||||
* An attempt was made to create a second instance of a static token manager.
|
||||
*/
|
||||
static final int STATIC_LEXER_ERROR = 1;
|
||||
|
||||
/**
|
||||
* Tried to change to an invalid lexical state.
|
||||
*/
|
||||
static final int INVALID_LEXICAL_STATE = 2;
|
||||
|
||||
/**
|
||||
* Detected (and bailed out of) an infinite loop in the token manager.
|
||||
*/
|
||||
static final int LOOP_DETECTED = 3;
|
||||
|
||||
/**
|
||||
* Indicates the reason why the exception is thrown. It will have
|
||||
* one of the above 4 values.
|
||||
*/
|
||||
int errorCode;
|
||||
|
||||
/**
|
||||
* Replaces unprintable characters by their escaped (or unicode escaped)
|
||||
* equivalents in the given string
|
||||
*/
|
||||
protected static final String addEscapes(String str) {
|
||||
StringBuffer retval = new StringBuffer();
|
||||
char ch;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
switch (str.charAt(i))
|
||||
{
|
||||
case 0 :
|
||||
continue;
|
||||
case '\b':
|
||||
retval.append("\\b");
|
||||
continue;
|
||||
case '\t':
|
||||
retval.append("\\t");
|
||||
continue;
|
||||
case '\n':
|
||||
retval.append("\\n");
|
||||
continue;
|
||||
case '\f':
|
||||
retval.append("\\f");
|
||||
continue;
|
||||
case '\r':
|
||||
retval.append("\\r");
|
||||
continue;
|
||||
case '\"':
|
||||
retval.append("\\\"");
|
||||
continue;
|
||||
case '\'':
|
||||
retval.append("\\\'");
|
||||
continue;
|
||||
case '\\':
|
||||
retval.append("\\\\");
|
||||
continue;
|
||||
default:
|
||||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
|
||||
String s = "0000" + Integer.toString(ch, 16);
|
||||
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
|
||||
} else {
|
||||
retval.append(ch);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return retval.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a detailed message for the Error when it is thrown by the
|
||||
* token manager to indicate a lexical error.
|
||||
* Parameters :
|
||||
* EOFSeen : indicates if EOF caused the lexical error
|
||||
* curLexState : lexical state in which this error occurred
|
||||
* errorLine : line number when the error occurred
|
||||
* errorColumn : column number when the error occurred
|
||||
* errorAfter : prefix that was seen before this error occurred
|
||||
* curchar : the offending character
|
||||
* Note: You can customize the lexical error message by modifying this method.
|
||||
*/
|
||||
protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
|
||||
return("Lexical error at line " +
|
||||
errorLine + ", column " +
|
||||
errorColumn + ". Encountered: " +
|
||||
(EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
|
||||
"after : \"" + addEscapes(errorAfter) + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* You can also modify the body of this method to customize your error messages.
|
||||
* For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
|
||||
* of end-users concern, so you can return something like :
|
||||
*
|
||||
* "Internal Error : Please file a bug report .... "
|
||||
*
|
||||
* from this method for such cases in the release version of your parser.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructors of various flavors follow.
|
||||
*/
|
||||
|
||||
/** No arg constructor. */
|
||||
public TokenMgrError() {
|
||||
}
|
||||
|
||||
/** Constructor with message and reason. */
|
||||
public TokenMgrError(String message, int reason) {
|
||||
super(message);
|
||||
errorCode = reason;
|
||||
}
|
||||
|
||||
/** Full Constructor. */
|
||||
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
|
||||
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=75c4cf7db7d0ac3344c6bae5c180f189 (do not edit this line) */
|
@ -1,586 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. DateTimeParser.java */
|
||||
/****************************************************************
|
||||
* 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.field.datetime.parser;
|
||||
|
||||
import org.apache.james.mime4j.dom.datetime.DateTime;
|
||||
|
||||
public class DateTimeParser implements DateTimeParserConstants {
|
||||
private static final boolean ignoreMilitaryZoneOffset = true;
|
||||
|
||||
public static void main(String args[]) throws ParseException {
|
||||
while (true) {
|
||||
try {
|
||||
DateTimeParser parser = new DateTimeParser(System.in);
|
||||
parser.parseLine();
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseDigits(Token token) {
|
||||
return Integer.parseInt(token.image, 10);
|
||||
}
|
||||
|
||||
private static int getMilitaryZoneOffset(char c) {
|
||||
if (ignoreMilitaryZoneOffset)
|
||||
return 0;
|
||||
|
||||
c = Character.toUpperCase(c);
|
||||
|
||||
switch (c) {
|
||||
case 'A': return 1;
|
||||
case 'B': return 2;
|
||||
case 'C': return 3;
|
||||
case 'D': return 4;
|
||||
case 'E': return 5;
|
||||
case 'F': return 6;
|
||||
case 'G': return 7;
|
||||
case 'H': return 8;
|
||||
case 'I': return 9;
|
||||
case 'K': return 10;
|
||||
case 'L': return 11;
|
||||
case 'M': return 12;
|
||||
|
||||
case 'N': return -1;
|
||||
case 'O': return -2;
|
||||
case 'P': return -3;
|
||||
case 'Q': return -4;
|
||||
case 'R': return -5;
|
||||
case 'S': return -6;
|
||||
case 'T': return -7;
|
||||
case 'U': return -8;
|
||||
case 'V': return -9;
|
||||
case 'W': return -10;
|
||||
case 'X': return -11;
|
||||
case 'Y': return -12;
|
||||
|
||||
case 'Z': return 0;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Time {
|
||||
private int hour;
|
||||
private int minute;
|
||||
private int second;
|
||||
private int zone;
|
||||
|
||||
public Time(int hour, int minute, int second, int zone) {
|
||||
this.hour = hour;
|
||||
this.minute = minute;
|
||||
this.second = second;
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
public int getHour() { return hour; }
|
||||
public int getMinute() { return minute; }
|
||||
public int getSecond() { return second; }
|
||||
public int getZone() { return zone; }
|
||||
}
|
||||
|
||||
private static class Date {
|
||||
private String year;
|
||||
private int month;
|
||||
private int day;
|
||||
|
||||
public Date(String year, int month, int day) {
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
public String getYear() { return year; }
|
||||
public int getMonth() { return month; }
|
||||
public int getDay() { return day; }
|
||||
}
|
||||
|
||||
final public DateTime parseLine() throws ParseException {
|
||||
DateTime dt;
|
||||
dt = date_time();
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 1:
|
||||
jj_consume_token(1);
|
||||
break;
|
||||
default:
|
||||
jj_la1[0] = jj_gen;
|
||||
;
|
||||
}
|
||||
jj_consume_token(2);
|
||||
{if (true) return dt;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public DateTime parseAll() throws ParseException {
|
||||
DateTime dt;
|
||||
dt = date_time();
|
||||
jj_consume_token(0);
|
||||
{if (true) return dt;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public DateTime date_time() throws ParseException {
|
||||
Date d; Time t;
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
day_of_week();
|
||||
jj_consume_token(3);
|
||||
break;
|
||||
default:
|
||||
jj_la1[1] = jj_gen;
|
||||
;
|
||||
}
|
||||
d = date();
|
||||
t = time();
|
||||
{if (true) return new DateTime(
|
||||
d.getYear(),
|
||||
d.getMonth(),
|
||||
d.getDay(),
|
||||
t.getHour(),
|
||||
t.getMinute(),
|
||||
t.getSecond(),
|
||||
t.getZone());} // time zone offset
|
||||
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public String day_of_week() throws ParseException {
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 4:
|
||||
jj_consume_token(4);
|
||||
break;
|
||||
case 5:
|
||||
jj_consume_token(5);
|
||||
break;
|
||||
case 6:
|
||||
jj_consume_token(6);
|
||||
break;
|
||||
case 7:
|
||||
jj_consume_token(7);
|
||||
break;
|
||||
case 8:
|
||||
jj_consume_token(8);
|
||||
break;
|
||||
case 9:
|
||||
jj_consume_token(9);
|
||||
break;
|
||||
case 10:
|
||||
jj_consume_token(10);
|
||||
break;
|
||||
default:
|
||||
jj_la1[2] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
{if (true) return token.image;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public Date date() throws ParseException {
|
||||
int d, m; String y;
|
||||
d = day();
|
||||
m = month();
|
||||
y = year();
|
||||
{if (true) return new Date(y, m, d);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int day() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(DIGITS);
|
||||
{if (true) return parseDigits(t);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int month() throws ParseException {
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 11:
|
||||
jj_consume_token(11);
|
||||
{if (true) return 1;}
|
||||
break;
|
||||
case 12:
|
||||
jj_consume_token(12);
|
||||
{if (true) return 2;}
|
||||
break;
|
||||
case 13:
|
||||
jj_consume_token(13);
|
||||
{if (true) return 3;}
|
||||
break;
|
||||
case 14:
|
||||
jj_consume_token(14);
|
||||
{if (true) return 4;}
|
||||
break;
|
||||
case 15:
|
||||
jj_consume_token(15);
|
||||
{if (true) return 5;}
|
||||
break;
|
||||
case 16:
|
||||
jj_consume_token(16);
|
||||
{if (true) return 6;}
|
||||
break;
|
||||
case 17:
|
||||
jj_consume_token(17);
|
||||
{if (true) return 7;}
|
||||
break;
|
||||
case 18:
|
||||
jj_consume_token(18);
|
||||
{if (true) return 8;}
|
||||
break;
|
||||
case 19:
|
||||
jj_consume_token(19);
|
||||
{if (true) return 9;}
|
||||
break;
|
||||
case 20:
|
||||
jj_consume_token(20);
|
||||
{if (true) return 10;}
|
||||
break;
|
||||
case 21:
|
||||
jj_consume_token(21);
|
||||
{if (true) return 11;}
|
||||
break;
|
||||
case 22:
|
||||
jj_consume_token(22);
|
||||
{if (true) return 12;}
|
||||
break;
|
||||
default:
|
||||
jj_la1[3] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public String year() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(DIGITS);
|
||||
{if (true) return t.image;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public Time time() throws ParseException {
|
||||
int h, m, s=0, z;
|
||||
h = hour();
|
||||
jj_consume_token(23);
|
||||
m = minute();
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 23:
|
||||
jj_consume_token(23);
|
||||
s = second();
|
||||
break;
|
||||
default:
|
||||
jj_la1[4] = jj_gen;
|
||||
;
|
||||
}
|
||||
z = zone();
|
||||
{if (true) return new Time(h, m, s, z);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int hour() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(DIGITS);
|
||||
{if (true) return parseDigits(t);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int minute() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(DIGITS);
|
||||
{if (true) return parseDigits(t);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int second() throws ParseException {
|
||||
Token t;
|
||||
t = jj_consume_token(DIGITS);
|
||||
{if (true) return parseDigits(t);}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int zone() throws ParseException {
|
||||
Token t, u; int z;
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case OFFSETDIR:
|
||||
t = jj_consume_token(OFFSETDIR);
|
||||
u = jj_consume_token(DIGITS);
|
||||
z=parseDigits(u)*(t.image.equals("-") ? -1 : 1);
|
||||
break;
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case MILITARY_ZONE:
|
||||
z = obs_zone();
|
||||
break;
|
||||
default:
|
||||
jj_la1[5] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
{if (true) return z;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
final public int obs_zone() throws ParseException {
|
||||
Token t; int z;
|
||||
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
|
||||
case 25:
|
||||
jj_consume_token(25);
|
||||
z=0;
|
||||
break;
|
||||
case 26:
|
||||
jj_consume_token(26);
|
||||
z=0;
|
||||
break;
|
||||
case 27:
|
||||
jj_consume_token(27);
|
||||
z=-5;
|
||||
break;
|
||||
case 28:
|
||||
jj_consume_token(28);
|
||||
z=-4;
|
||||
break;
|
||||
case 29:
|
||||
jj_consume_token(29);
|
||||
z=-6;
|
||||
break;
|
||||
case 30:
|
||||
jj_consume_token(30);
|
||||
z=-5;
|
||||
break;
|
||||
case 31:
|
||||
jj_consume_token(31);
|
||||
z=-7;
|
||||
break;
|
||||
case 32:
|
||||
jj_consume_token(32);
|
||||
z=-6;
|
||||
break;
|
||||
case 33:
|
||||
jj_consume_token(33);
|
||||
z=-8;
|
||||
break;
|
||||
case 34:
|
||||
jj_consume_token(34);
|
||||
z=-7;
|
||||
break;
|
||||
case MILITARY_ZONE:
|
||||
t = jj_consume_token(MILITARY_ZONE);
|
||||
z=getMilitaryZoneOffset(t.image.charAt(0));
|
||||
break;
|
||||
default:
|
||||
jj_la1[6] = jj_gen;
|
||||
jj_consume_token(-1);
|
||||
throw new ParseException();
|
||||
}
|
||||
{if (true) return z * 100;}
|
||||
throw new Error("Missing return statement in function");
|
||||
}
|
||||
|
||||
/** Generated Token Manager. */
|
||||
public DateTimeParserTokenManager token_source;
|
||||
SimpleCharStream jj_input_stream;
|
||||
/** Current token. */
|
||||
public Token token;
|
||||
/** Next token. */
|
||||
public Token jj_nt;
|
||||
private int jj_ntk;
|
||||
private int jj_gen;
|
||||
final private int[] jj_la1 = new int[7];
|
||||
static private int[] jj_la1_0;
|
||||
static private int[] jj_la1_1;
|
||||
static {
|
||||
jj_la1_init_0();
|
||||
jj_la1_init_1();
|
||||
}
|
||||
private static void jj_la1_init_0() {
|
||||
jj_la1_0 = new int[] {0x2,0x7f0,0x7f0,0x7ff800,0x800000,0xff000000,0xfe000000,};
|
||||
}
|
||||
private static void jj_la1_init_1() {
|
||||
jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0xf,0xf,};
|
||||
}
|
||||
|
||||
/** Constructor with InputStream. */
|
||||
public DateTimeParser(java.io.InputStream stream) {
|
||||
this(stream, null);
|
||||
}
|
||||
/** Constructor with InputStream and supplied encoding */
|
||||
public DateTimeParser(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source = new DateTimeParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream) {
|
||||
ReInit(stream, null);
|
||||
}
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.InputStream stream, String encoding) {
|
||||
try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public DateTimeParser(java.io.Reader stream) {
|
||||
jj_input_stream = new SimpleCharStream(stream, 1, 1);
|
||||
token_source = new DateTimeParserTokenManager(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(java.io.Reader stream) {
|
||||
jj_input_stream.ReInit(stream, 1, 1);
|
||||
token_source.ReInit(jj_input_stream);
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Constructor with generated Token Manager. */
|
||||
public DateTimeParser(DateTimeParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
/** Reinitialise. */
|
||||
public void ReInit(DateTimeParserTokenManager tm) {
|
||||
token_source = tm;
|
||||
token = new Token();
|
||||
jj_ntk = -1;
|
||||
jj_gen = 0;
|
||||
for (int i = 0; i < 7; i++) jj_la1[i] = -1;
|
||||
}
|
||||
|
||||
private Token jj_consume_token(int kind) throws ParseException {
|
||||
Token oldToken;
|
||||
if ((oldToken = token).next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
if (token.kind == kind) {
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
token = oldToken;
|
||||
jj_kind = kind;
|
||||
throw generateParseException();
|
||||
}
|
||||
|
||||
|
||||
/** Get the next Token. */
|
||||
final public Token getNextToken() {
|
||||
if (token.next != null) token = token.next;
|
||||
else token = token.next = token_source.getNextToken();
|
||||
jj_ntk = -1;
|
||||
jj_gen++;
|
||||
return token;
|
||||
}
|
||||
|
||||
/** Get the specific Token. */
|
||||
final public Token getToken(int index) {
|
||||
Token t = token;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (t.next != null) t = t.next;
|
||||
else t = t.next = token_source.getNextToken();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
private int jj_ntk() {
|
||||
if ((jj_nt=token.next) == null)
|
||||
return (jj_ntk = (token.next=token_source.getNextToken()).kind);
|
||||
else
|
||||
return (jj_ntk = jj_nt.kind);
|
||||
}
|
||||
|
||||
private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
|
||||
private int[] jj_expentry;
|
||||
private int jj_kind = -1;
|
||||
|
||||
/** Generate ParseException. */
|
||||
public ParseException generateParseException() {
|
||||
jj_expentries.clear();
|
||||
boolean[] la1tokens = new boolean[49];
|
||||
if (jj_kind >= 0) {
|
||||
la1tokens[jj_kind] = true;
|
||||
jj_kind = -1;
|
||||
}
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (jj_la1[i] == jj_gen) {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
if ((jj_la1_0[i] & (1<<j)) != 0) {
|
||||
la1tokens[j] = true;
|
||||
}
|
||||
if ((jj_la1_1[i] & (1<<j)) != 0) {
|
||||
la1tokens[32+j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 49; i++) {
|
||||
if (la1tokens[i]) {
|
||||
jj_expentry = new int[1];
|
||||
jj_expentry[0] = i;
|
||||
jj_expentries.add(jj_expentry);
|
||||
}
|
||||
}
|
||||
int[][] exptokseq = new int[jj_expentries.size()][];
|
||||
for (int i = 0; i < jj_expentries.size(); i++) {
|
||||
exptokseq[i] = jj_expentries.get(i);
|
||||
}
|
||||
return new ParseException(token, exptokseq, tokenImage);
|
||||
}
|
||||
|
||||
/** Enable tracing. */
|
||||
final public void enable_tracing() {
|
||||
}
|
||||
|
||||
/** Disable tracing. */
|
||||
final public void disable_tracing() {
|
||||
}
|
||||
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. DateTimeParserConstants.java */
|
||||
/****************************************************************
|
||||
* 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.field.datetime.parser;
|
||||
|
||||
|
||||
/**
|
||||
* Token literal values and constants.
|
||||
* Generated by org.javacc.parser.OtherFilesGen#start()
|
||||
*/
|
||||
public interface DateTimeParserConstants {
|
||||
|
||||
/** End of File. */
|
||||
int EOF = 0;
|
||||
/** RegularExpression Id. */
|
||||
int OFFSETDIR = 24;
|
||||
/** RegularExpression Id. */
|
||||
int MILITARY_ZONE = 35;
|
||||
/** RegularExpression Id. */
|
||||
int WS = 36;
|
||||
/** RegularExpression Id. */
|
||||
int COMMENT = 38;
|
||||
/** RegularExpression Id. */
|
||||
int DIGITS = 46;
|
||||
/** RegularExpression Id. */
|
||||
int QUOTEDPAIR = 47;
|
||||
/** RegularExpression Id. */
|
||||
int ANY = 48;
|
||||
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 0;
|
||||
/** Lexical state. */
|
||||
int INCOMMENT = 1;
|
||||
/** Lexical state. */
|
||||
int NESTED_COMMENT = 2;
|
||||
|
||||
/** Literal token values. */
|
||||
String[] tokenImage = {
|
||||
"<EOF>",
|
||||
"\"\\r\"",
|
||||
"\"\\n\"",
|
||||
"\",\"",
|
||||
"\"Mon\"",
|
||||
"\"Tue\"",
|
||||
"\"Wed\"",
|
||||
"\"Thu\"",
|
||||
"\"Fri\"",
|
||||
"\"Sat\"",
|
||||
"\"Sun\"",
|
||||
"\"Jan\"",
|
||||
"\"Feb\"",
|
||||
"\"Mar\"",
|
||||
"\"Apr\"",
|
||||
"\"May\"",
|
||||
"\"Jun\"",
|
||||
"\"Jul\"",
|
||||
"\"Aug\"",
|
||||
"\"Sep\"",
|
||||
"\"Oct\"",
|
||||
"\"Nov\"",
|
||||
"\"Dec\"",
|
||||
"\":\"",
|
||||
"<OFFSETDIR>",
|
||||
"\"UT\"",
|
||||
"\"GMT\"",
|
||||
"\"EST\"",
|
||||
"\"EDT\"",
|
||||
"\"CST\"",
|
||||
"\"CDT\"",
|
||||
"\"MST\"",
|
||||
"\"MDT\"",
|
||||
"\"PST\"",
|
||||
"\"PDT\"",
|
||||
"<MILITARY_ZONE>",
|
||||
"<WS>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 39>",
|
||||
"\"(\"",
|
||||
"<token of kind 41>",
|
||||
"<token of kind 42>",
|
||||
"\"(\"",
|
||||
"\")\"",
|
||||
"<token of kind 45>",
|
||||
"<DIGITS>",
|
||||
"<QUOTEDPAIR>",
|
||||
"<ANY>",
|
||||
};
|
||||
|
||||
}
|
@ -1,869 +0,0 @@
|
||||
/* Generated By:JavaCC: Do not edit this line. DateTimeParserTokenManager.java */
|
||||
/****************************************************************
|
||||
* 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.field.datetime.parser;
|
||||
import org.apache.james.mime4j.dom.datetime.DateTime;
|
||||
|
||||
/** Token Manager. */
|
||||
public class DateTimeParserTokenManager implements DateTimeParserConstants
|
||||
{
|
||||
// Keeps track of how many levels of comment nesting
|
||||
// we've encountered. This is only used when the 2nd
|
||||
// level is reached, for example ((this)), not (this).
|
||||
// This is because the outermost level must be treated
|
||||
// specially anyway, because the outermost ")" has a
|
||||
// different token type than inner ")" instances.
|
||||
static int commentNest;
|
||||
|
||||
/** Debug output. */
|
||||
public java.io.PrintStream debugStream = System.out;
|
||||
/** Set debug output. */
|
||||
public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
|
||||
private final int jjStopStringLiteralDfa_0(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
case 0:
|
||||
if ((active0 & 0x7fe7cf7f0L) != 0L)
|
||||
{
|
||||
jjmatchedKind = 35;
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
case 1:
|
||||
if ((active0 & 0x7fe7cf7f0L) != 0L)
|
||||
{
|
||||
if (jjmatchedPos == 0)
|
||||
{
|
||||
jjmatchedKind = 35;
|
||||
jjmatchedPos = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_0(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjStopAtPos(int pos, int kind)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = pos;
|
||||
return pos + 1;
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_0()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 10:
|
||||
return jjStopAtPos(0, 2);
|
||||
case 13:
|
||||
return jjStopAtPos(0, 1);
|
||||
case 40:
|
||||
return jjStopAtPos(0, 37);
|
||||
case 44:
|
||||
return jjStopAtPos(0, 3);
|
||||
case 58:
|
||||
return jjStopAtPos(0, 23);
|
||||
case 65:
|
||||
return jjMoveStringLiteralDfa1_0(0x44000L);
|
||||
case 67:
|
||||
return jjMoveStringLiteralDfa1_0(0x60000000L);
|
||||
case 68:
|
||||
return jjMoveStringLiteralDfa1_0(0x400000L);
|
||||
case 69:
|
||||
return jjMoveStringLiteralDfa1_0(0x18000000L);
|
||||
case 70:
|
||||
return jjMoveStringLiteralDfa1_0(0x1100L);
|
||||
case 71:
|
||||
return jjMoveStringLiteralDfa1_0(0x4000000L);
|
||||
case 74:
|
||||
return jjMoveStringLiteralDfa1_0(0x30800L);
|
||||
case 77:
|
||||
return jjMoveStringLiteralDfa1_0(0x18000a010L);
|
||||
case 78:
|
||||
return jjMoveStringLiteralDfa1_0(0x200000L);
|
||||
case 79:
|
||||
return jjMoveStringLiteralDfa1_0(0x100000L);
|
||||
case 80:
|
||||
return jjMoveStringLiteralDfa1_0(0x600000000L);
|
||||
case 83:
|
||||
return jjMoveStringLiteralDfa1_0(0x80600L);
|
||||
case 84:
|
||||
return jjMoveStringLiteralDfa1_0(0xa0L);
|
||||
case 85:
|
||||
return jjMoveStringLiteralDfa1_0(0x2000000L);
|
||||
case 87:
|
||||
return jjMoveStringLiteralDfa1_0(0x40L);
|
||||
default :
|
||||
return jjMoveNfa_0(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveStringLiteralDfa1_0(long active0)
|
||||
{
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) {
|
||||
jjStopStringLiteralDfa_0(0, active0);
|
||||
return 1;
|
||||
}
|
||||
switch(curChar)
|
||||
{
|
||||
case 68:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x550000000L);
|
||||
case 77:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x4000000L);
|
||||
case 83:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x2a8000000L);
|
||||
case 84:
|
||||
if ((active0 & 0x2000000L) != 0L)
|
||||
return jjStopAtPos(1, 25);
|
||||
break;
|
||||
case 97:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0xaa00L);
|
||||
case 99:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x100000L);
|
||||
case 101:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x481040L);
|
||||
case 104:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x80L);
|
||||
case 111:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x200010L);
|
||||
case 112:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x4000L);
|
||||
case 114:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x100L);
|
||||
case 117:
|
||||
return jjMoveStringLiteralDfa2_0(active0, 0x70420L);
|
||||
default :
|
||||
break;
|
||||
}
|
||||
return jjStartNfa_0(0, active0);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa2_0(long old0, long active0)
|
||||
{
|
||||
if (((active0 &= old0)) == 0L)
|
||||
return jjStartNfa_0(0, old0);
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) {
|
||||
jjStopStringLiteralDfa_0(1, active0);
|
||||
return 2;
|
||||
}
|
||||
switch(curChar)
|
||||
{
|
||||
case 84:
|
||||
if ((active0 & 0x4000000L) != 0L)
|
||||
return jjStopAtPos(2, 26);
|
||||
else if ((active0 & 0x8000000L) != 0L)
|
||||
return jjStopAtPos(2, 27);
|
||||
else if ((active0 & 0x10000000L) != 0L)
|
||||
return jjStopAtPos(2, 28);
|
||||
else if ((active0 & 0x20000000L) != 0L)
|
||||
return jjStopAtPos(2, 29);
|
||||
else if ((active0 & 0x40000000L) != 0L)
|
||||
return jjStopAtPos(2, 30);
|
||||
else if ((active0 & 0x80000000L) != 0L)
|
||||
return jjStopAtPos(2, 31);
|
||||
else if ((active0 & 0x100000000L) != 0L)
|
||||
return jjStopAtPos(2, 32);
|
||||
else if ((active0 & 0x200000000L) != 0L)
|
||||
return jjStopAtPos(2, 33);
|
||||
else if ((active0 & 0x400000000L) != 0L)
|
||||
return jjStopAtPos(2, 34);
|
||||
break;
|
||||
case 98:
|
||||
if ((active0 & 0x1000L) != 0L)
|
||||
return jjStopAtPos(2, 12);
|
||||
break;
|
||||
case 99:
|
||||
if ((active0 & 0x400000L) != 0L)
|
||||
return jjStopAtPos(2, 22);
|
||||
break;
|
||||
case 100:
|
||||
if ((active0 & 0x40L) != 0L)
|
||||
return jjStopAtPos(2, 6);
|
||||
break;
|
||||
case 101:
|
||||
if ((active0 & 0x20L) != 0L)
|
||||
return jjStopAtPos(2, 5);
|
||||
break;
|
||||
case 103:
|
||||
if ((active0 & 0x40000L) != 0L)
|
||||
return jjStopAtPos(2, 18);
|
||||
break;
|
||||
case 105:
|
||||
if ((active0 & 0x100L) != 0L)
|
||||
return jjStopAtPos(2, 8);
|
||||
break;
|
||||
case 108:
|
||||
if ((active0 & 0x20000L) != 0L)
|
||||
return jjStopAtPos(2, 17);
|
||||
break;
|
||||
case 110:
|
||||
if ((active0 & 0x10L) != 0L)
|
||||
return jjStopAtPos(2, 4);
|
||||
else if ((active0 & 0x400L) != 0L)
|
||||
return jjStopAtPos(2, 10);
|
||||
else if ((active0 & 0x800L) != 0L)
|
||||
return jjStopAtPos(2, 11);
|
||||
else if ((active0 & 0x10000L) != 0L)
|
||||
return jjStopAtPos(2, 16);
|
||||
break;
|
||||
case 112:
|
||||
if ((active0 & 0x80000L) != 0L)
|
||||
return jjStopAtPos(2, 19);
|
||||
break;
|
||||
case 114:
|
||||
if ((active0 & 0x2000L) != 0L)
|
||||
return jjStopAtPos(2, 13);
|
||||
else if ((active0 & 0x4000L) != 0L)
|
||||
return jjStopAtPos(2, 14);
|
||||
break;
|
||||
case 116:
|
||||
if ((active0 & 0x200L) != 0L)
|
||||
return jjStopAtPos(2, 9);
|
||||
else if ((active0 & 0x100000L) != 0L)
|
||||
return jjStopAtPos(2, 20);
|
||||
break;
|
||||
case 117:
|
||||
if ((active0 & 0x80L) != 0L)
|
||||
return jjStopAtPos(2, 7);
|
||||
break;
|
||||
case 118:
|
||||
if ((active0 & 0x200000L) != 0L)
|
||||
return jjStopAtPos(2, 21);
|
||||
break;
|
||||
case 121:
|
||||
if ((active0 & 0x8000L) != 0L)
|
||||
return jjStopAtPos(2, 15);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
return jjStartNfa_0(1, active0);
|
||||
}
|
||||
private int jjMoveNfa_0(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 4;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0x3ff000000000000L & l) != 0L)
|
||||
{
|
||||
if (kind > 46)
|
||||
kind = 46;
|
||||
jjCheckNAdd(3);
|
||||
}
|
||||
else if ((0x100000200L & l) != 0L)
|
||||
{
|
||||
if (kind > 36)
|
||||
kind = 36;
|
||||
jjCheckNAdd(2);
|
||||
}
|
||||
else if ((0x280000000000L & l) != 0L)
|
||||
{
|
||||
if (kind > 24)
|
||||
kind = 24;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((0x100000200L & l) == 0L)
|
||||
break;
|
||||
kind = 36;
|
||||
jjCheckNAdd(2);
|
||||
break;
|
||||
case 3:
|
||||
if ((0x3ff000000000000L & l) == 0L)
|
||||
break;
|
||||
kind = 46;
|
||||
jjCheckNAdd(3);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((0x7fffbfe07fffbfeL & l) != 0L)
|
||||
kind = 35;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_1(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_1(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_1()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 40);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 38);
|
||||
default :
|
||||
return jjMoveNfa_1(0, 0);
|
||||
}
|
||||
}
|
||||
static final long[] jjbitVec0 = {
|
||||
0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
|
||||
};
|
||||
private int jjMoveNfa_1(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 41)
|
||||
kind = 41;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 39)
|
||||
kind = 39;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 41)
|
||||
kind = 41;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 39)
|
||||
kind = 39;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 41)
|
||||
kind = 41;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 41)
|
||||
kind = 41;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 39)
|
||||
kind = 39;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
private final int jjStopStringLiteralDfa_2(int pos, long active0)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
default :
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private final int jjStartNfa_2(int pos, long active0)
|
||||
{
|
||||
return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
|
||||
}
|
||||
private int jjMoveStringLiteralDfa0_2()
|
||||
{
|
||||
switch(curChar)
|
||||
{
|
||||
case 40:
|
||||
return jjStopAtPos(0, 43);
|
||||
case 41:
|
||||
return jjStopAtPos(0, 44);
|
||||
default :
|
||||
return jjMoveNfa_2(0, 0);
|
||||
}
|
||||
}
|
||||
private int jjMoveNfa_2(int startState, int curPos)
|
||||
{
|
||||
int startsAt = 0;
|
||||
jjnewStateCnt = 3;
|
||||
int i = 1;
|
||||
jjstateSet[0] = startState;
|
||||
int kind = 0x7fffffff;
|
||||
for (;;)
|
||||
{
|
||||
if (++jjround == 0x7fffffff)
|
||||
ReInitRounds();
|
||||
if (curChar < 64)
|
||||
{
|
||||
long l = 1L << curChar;
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 45)
|
||||
kind = 45;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 42)
|
||||
kind = 42;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else if (curChar < 128)
|
||||
{
|
||||
long l = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if (kind > 45)
|
||||
kind = 45;
|
||||
if (curChar == 92)
|
||||
jjstateSet[jjnewStateCnt++] = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (kind > 42)
|
||||
kind = 42;
|
||||
break;
|
||||
case 2:
|
||||
if (kind > 45)
|
||||
kind = 45;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = (curChar & 0xff) >> 6;
|
||||
long l2 = 1L << (curChar & 077);
|
||||
do
|
||||
{
|
||||
switch(jjstateSet[--i])
|
||||
{
|
||||
case 0:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 45)
|
||||
kind = 45;
|
||||
break;
|
||||
case 1:
|
||||
if ((jjbitVec0[i2] & l2) != 0L && kind > 42)
|
||||
kind = 42;
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
} while(i != startsAt);
|
||||
}
|
||||
if (kind != 0x7fffffff)
|
||||
{
|
||||
jjmatchedKind = kind;
|
||||
jjmatchedPos = curPos;
|
||||
kind = 0x7fffffff;
|
||||
}
|
||||
++curPos;
|
||||
if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
|
||||
return curPos;
|
||||
try { curChar = input_stream.readChar(); }
|
||||
catch(java.io.IOException e) { return curPos; }
|
||||
}
|
||||
}
|
||||
static final int[] jjnextStates = {
|
||||
};
|
||||
|
||||
/** Token literal values. */
|
||||
public static final String[] jjstrLiteralImages = {
|
||||
"", "\15", "\12", "\54", "\115\157\156", "\124\165\145", "\127\145\144",
|
||||
"\124\150\165", "\106\162\151", "\123\141\164", "\123\165\156", "\112\141\156",
|
||||
"\106\145\142", "\115\141\162", "\101\160\162", "\115\141\171", "\112\165\156",
|
||||
"\112\165\154", "\101\165\147", "\123\145\160", "\117\143\164", "\116\157\166",
|
||||
"\104\145\143", "\72", null, "\125\124", "\107\115\124", "\105\123\124", "\105\104\124",
|
||||
"\103\123\124", "\103\104\124", "\115\123\124", "\115\104\124", "\120\123\124",
|
||||
"\120\104\124", null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, };
|
||||
|
||||
/** Lexer state names. */
|
||||
public static final String[] lexStateNames = {
|
||||
"DEFAULT",
|
||||
"INCOMMENT",
|
||||
"NESTED_COMMENT",
|
||||
};
|
||||
|
||||
/** Lex State array. */
|
||||
public static final int[] jjnewLexState = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
static final long[] jjtoToken = {
|
||||
0x400fffffffffL,
|
||||
};
|
||||
static final long[] jjtoSkip = {
|
||||
0x5000000000L,
|
||||
};
|
||||
static final long[] jjtoSpecial = {
|
||||
0x1000000000L,
|
||||
};
|
||||
static final long[] jjtoMore = {
|
||||
0x3fa000000000L,
|
||||
};
|
||||
protected SimpleCharStream input_stream;
|
||||
private final int[] jjrounds = new int[4];
|
||||
private final int[] jjstateSet = new int[8];
|
||||
private final StringBuilder jjimage = new StringBuilder();
|
||||
private StringBuilder image = jjimage;
|
||||
private int jjimageLen;
|
||||
private int lengthOfMatch;
|
||||
protected char curChar;
|
||||
/** Constructor. */
|
||||
public DateTimeParserTokenManager(SimpleCharStream stream){
|
||||
if (SimpleCharStream.staticFlag)
|
||||
throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
|
||||
input_stream = stream;
|
||||
}
|
||||
|
||||
/** Constructor. */
|
||||
public DateTimeParserTokenManager(SimpleCharStream stream, int lexState){
|
||||
this(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream)
|
||||
{
|
||||
jjmatchedPos = jjnewStateCnt = 0;
|
||||
curLexState = defaultLexState;
|
||||
input_stream = stream;
|
||||
ReInitRounds();
|
||||
}
|
||||
private void ReInitRounds()
|
||||
{
|
||||
int i;
|
||||
jjround = 0x80000001;
|
||||
for (i = 4; i-- > 0;)
|
||||
jjrounds[i] = 0x80000000;
|
||||
}
|
||||
|
||||
/** Reinitialise parser. */
|
||||
public void ReInit(SimpleCharStream stream, int lexState)
|
||||
{
|
||||
ReInit(stream);
|
||||
SwitchTo(lexState);
|
||||
}
|
||||
|
||||
/** Switch to specified lex state. */
|
||||
public void SwitchTo(int lexState)
|
||||
{
|
||||
if (lexState >= 3 || lexState < 0)
|
||||
throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
|
||||
else
|
||||
curLexState = lexState;
|
||||
}
|
||||
|
||||
protected Token jjFillToken()
|
||||
{
|
||||
final Token t;
|
||||
final String curTokenImage;
|
||||
final int beginLine;
|
||||
final int endLine;
|
||||
final int beginColumn;
|
||||
final int endColumn;
|
||||
String im = jjstrLiteralImages[jjmatchedKind];
|
||||
curTokenImage = (im == null) ? input_stream.GetImage() : im;
|
||||
beginLine = input_stream.getBeginLine();
|
||||
beginColumn = input_stream.getBeginColumn();
|
||||
endLine = input_stream.getEndLine();
|
||||
endColumn = input_stream.getEndColumn();
|
||||
t = Token.newToken(jjmatchedKind, curTokenImage);
|
||||
|
||||
t.beginLine = beginLine;
|
||||
t.endLine = endLine;
|
||||
t.beginColumn = beginColumn;
|
||||
t.endColumn = endColumn;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int curLexState = 0;
|
||||
int defaultLexState = 0;
|
||||
int jjnewStateCnt;
|
||||
int jjround;
|
||||
int jjmatchedPos;
|
||||
int jjmatchedKind;
|
||||
|
||||
/** Get the next Token. */
|
||||
public Token getNextToken()
|
||||
{
|
||||
Token specialToken = null;
|
||||
Token matchedToken;
|
||||
int curPos = 0;
|
||||
|
||||
EOFLoop :
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
curChar = input_stream.BeginToken();
|
||||
}
|
||||
catch(java.io.IOException e)
|
||||
{
|
||||
jjmatchedKind = 0;
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
return matchedToken;
|
||||
}
|
||||
image = jjimage;
|
||||
image.setLength(0);
|
||||
jjimageLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch(curLexState)
|
||||
{
|
||||
case 0:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_0();
|
||||
break;
|
||||
case 1:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_1();
|
||||
break;
|
||||
case 2:
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
jjmatchedPos = 0;
|
||||
curPos = jjMoveStringLiteralDfa0_2();
|
||||
break;
|
||||
}
|
||||
if (jjmatchedKind != 0x7fffffff)
|
||||
{
|
||||
if (jjmatchedPos + 1 < curPos)
|
||||
input_stream.backup(curPos - jjmatchedPos - 1);
|
||||
if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
matchedToken.specialToken = specialToken;
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
return matchedToken;
|
||||
}
|
||||
else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
|
||||
{
|
||||
matchedToken = jjFillToken();
|
||||
if (specialToken == null)
|
||||
specialToken = matchedToken;
|
||||
else
|
||||
{
|
||||
matchedToken.specialToken = specialToken;
|
||||
specialToken = (specialToken.next = matchedToken);
|
||||
}
|
||||
}
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
continue EOFLoop;
|
||||
}
|
||||
MoreLexicalActions();
|
||||
if (jjnewLexState[jjmatchedKind] != -1)
|
||||
curLexState = jjnewLexState[jjmatchedKind];
|
||||
curPos = 0;
|
||||
jjmatchedKind = 0x7fffffff;
|
||||
try {
|
||||
curChar = input_stream.readChar();
|
||||
continue;
|
||||
}
|
||||
catch (java.io.IOException e1) { }
|
||||
}
|
||||
int error_line = input_stream.getEndLine();
|
||||
int error_column = input_stream.getEndColumn();
|
||||
String error_after = null;
|
||||
boolean EOFSeen = false;
|
||||
try { input_stream.readChar(); input_stream.backup(1); }
|
||||
catch (java.io.IOException e1) {
|
||||
EOFSeen = true;
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
if (curChar == '\n' || curChar == '\r') {
|
||||
error_line++;
|
||||
error_column = 0;
|
||||
}
|
||||
else
|
||||
error_column++;
|
||||
}
|
||||
if (!EOFSeen) {
|
||||
input_stream.backup(1);
|
||||
error_after = curPos <= 1 ? "" : input_stream.GetImage();
|
||||
}
|
||||
throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoreLexicalActions()
|
||||
{
|
||||
jjimageLen += (lengthOfMatch = jjmatchedPos + 1);
|
||||
switch(jjmatchedKind)
|
||||
{
|
||||
case 39 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 40 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
commentNest = 1;
|
||||
break;
|
||||
case 42 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
image.deleteCharAt(image.length() - 2);
|
||||
break;
|
||||
case 43 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
++commentNest;
|
||||
break;
|
||||
case 44 :
|
||||
image.append(input_stream.GetSuffix(jjimageLen));
|
||||
jjimageLen = 0;
|
||||
--commentNest; if (commentNest == 0) SwitchTo(INCOMMENT);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void jjCheckNAdd(int state)
|
||||
{
|
||||
if (jjrounds[state] != jjround)
|
||||
{
|
||||
jjstateSet[jjnewStateCnt++] = state;
|
||||
jjrounds[state] = jjround;
|
||||
}
|
||||
}
|
||||
private void jjAddStates(int start, int end)
|
||||
{
|
||||
do {
|
||||
jjstateSet[jjnewStateCnt++] = jjnextStates[start];
|
||||
} while (start++ != end);
|
||||
}
|
||||
private void jjCheckNAddTwoStates(int state1, int state2)
|
||||
{
|
||||
jjCheckNAdd(state1);
|
||||
jjCheckNAdd(state2);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user