apache-mime4j-project-0.7.2/ 0000755 0000000 0000000 00000000000 11702050564 014266 5 ustar root root apache-mime4j-project-0.7.2/storage/ 0000755 0000000 0000000 00000000000 11702050530 015723 5 ustar root root apache-mime4j-project-0.7.2/storage/src/ 0000755 0000000 0000000 00000000000 11702050530 016512 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/ 0000755 0000000 0000000 00000000000 11702050530 017436 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/ 0000755 0000000 0000000 00000000000 11702050530 020357 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/ 0000755 0000000 0000000 00000000000 11702050530 021146 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/ 0000755 0000000 0000000 00000000000 11702050530 022367 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/ 0000755 0000000 0000000 00000000000 11702050530 023466 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/ 0000755 0000000 0000000 00000000000 11702050530 024653 5 ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/ 0000755 0000000 0000000 00000000000 11702050530 026317 5 ustar root root ././@LongLink 0000000 0000000 0000000 00000000157 00000000000 011570 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/TempFileStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/TempFileStoragePro0000644 0000000 0000000 00000015014 11702050530 031756 0 ustar root root /****************************************************************
* 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.storage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* A {@link StorageProvider} that stores the data in temporary files. The files
* are stored either in a user-specified directory or the default temporary-file
* directory (specified by system property java.io.tmpdir
).
*
* Example usage: * *
* File directory = new File("/tmp/mime4j"); * StorageProvider provider = new TempFileStorageProvider(directory); * DefaultStorageProvider.setInstance(provider); **/ public class TempFileStorageProvider extends AbstractStorageProvider { private static final String DEFAULT_PREFIX = "m4j"; private final String prefix; private final String suffix; private final File directory; /** * Equivalent to using constructor *
TempFileStorageProvider("m4j", null, null)
.
*/
public TempFileStorageProvider() {
this(DEFAULT_PREFIX, null, null);
}
/**
* Equivalent to using constructor
* TempFileStorageProvider("m4j", null, directory)
.
*/
public TempFileStorageProvider(File directory) {
this(DEFAULT_PREFIX, null, directory);
}
/**
* Creates a new TempFileStorageProvider
using the given
* values.
*
* @param prefix
* prefix for generating the temporary file's name; must be at
* least three characters long.
* @param suffix
* suffix for generating the temporary file's name; may be
* null
to use the suffix ".tmp"
.
* @param directory
* the directory in which the file is to be created, or
* null
if the default temporary-file directory is
* to be used (specified by the system property
* java.io.tmpdir
).
* @throws IllegalArgumentException
* if the given prefix is less than three characters long or the
* given directory does not exist and cannot be created (if it
* is not null
).
*/
public TempFileStorageProvider(String prefix, String suffix, File directory) {
if (prefix == null || prefix.length() < 3)
throw new IllegalArgumentException("invalid prefix");
if (directory != null && !directory.isDirectory()
&& !directory.mkdirs())
throw new IllegalArgumentException("invalid directory");
this.prefix = prefix;
this.suffix = suffix;
this.directory = directory;
}
public StorageOutputStream createStorageOutputStream() throws IOException {
File file = File.createTempFile(prefix, suffix, directory);
file.deleteOnExit();
return new TempFileStorageOutputStream(file);
}
private static final class TempFileStorageOutputStream extends
StorageOutputStream {
private File file;
private OutputStream out;
public TempFileStorageOutputStream(File file) throws IOException {
this.file = file;
this.out = new FileOutputStream(file);
}
@Override
public void close() throws IOException {
super.close();
out.close();
}
@Override
protected void write0(byte[] buffer, int offset, int length)
throws IOException {
out.write(buffer, offset, length);
}
@Override
protected Storage toStorage0() throws IOException {
// out has already been closed because toStorage calls close
return new TempFileStorage(file);
}
}
private static final class TempFileStorage implements Storage {
private File file;
private static final Set* A wrapper around another {@link Storage} that also maintains a reference * counter. The inner storage gets deleted only if the reference counter reaches * zero. *
** Reference counting is used to delete the storage when it is no longer needed. * So, any users of this class should note: *
*MultiReferenceStorage
instance for the given
* back-end. The reference counter is initially set to one so the caller
* does not have to call {@link #addReference()} after this constructor.
*
* @param storage
* storage back-end that should be reference counted.
* @throws IllegalArgumentException
* when storage is null
*/
public MultiReferenceStorage(Storage storage) {
if (storage == null)
throw new IllegalArgumentException();
this.storage = storage;
this.referenceCounter = 1; // caller holds first reference
}
/**
* Increments the reference counter.
*
* @throws IllegalStateException
* if the reference counter is zero which implies that the
* backing storage has already been deleted.
*/
public void addReference() {
incrementCounter();
}
/**
* Decrements the reference counter and deletes the inner
* Storage
object if the reference counter reaches zero.
*
* A client that holds a reference to this object must make sure not to
* invoke this method a second time.
*
* @throws IllegalStateException
* if the reference counter is zero which implies that the
* backing storage has already been deleted.
*/
public void delete() {
if (decrementCounter()) {
storage.delete();
}
}
/**
* Returns the input stream of the inner Storage
object.
*
* @return an input stream.
*/
public InputStream getInputStream() throws IOException {
return storage.getInputStream();
}
/**
* Synchronized increment of reference count.
*
* @throws IllegalStateException
* when counter is already zero
*/
private synchronized void incrementCounter() {
if (referenceCounter == 0)
throw new IllegalStateException("storage has been deleted");
referenceCounter++;
}
/**
* Synchronized decrement of reference count.
*
* @return true when counter has reached zero, false otherwise
* @throws IllegalStateException
* when counter is already zero
*/
private synchronized boolean decrementCounter() {
if (referenceCounter == 0)
throw new IllegalStateException("storage has been deleted");
return --referenceCounter == 0;
}
}
././@LongLink 0000000 0000000 0000000 00000000160 00000000000 011562 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/ThresholdStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/ThresholdStoragePr0000644 0000000 0000000 00000012742 11702050530 032033 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import org.apache.james.mime4j.util.ByteArrayBuffer;
/**
* A {@link StorageProvider} that keeps small amounts of data in memory and
* writes the remainder to another StorageProvider
(the back-end)
* if a certain threshold size gets exceeded.
*
* Example usage: * *
* StorageProvider tempStore = new TempFileStorageProvider(); * StorageProvider provider = new ThresholdStorageProvider(tempStore, 4096); * DefaultStorageProvider.setInstance(provider); **/ public class ThresholdStorageProvider extends AbstractStorageProvider { private final StorageProvider backend; private final int thresholdSize; /** * Creates a new
ThresholdStorageProvider
for the given
* back-end using a threshold size of 2048 bytes.
*/
public ThresholdStorageProvider(StorageProvider backend) {
this(backend, 2048);
}
/**
* Creates a new ThresholdStorageProvider
for the given
* back-end and threshold size.
*
* @param backend
* used to store the remainder of the data if the threshold size
* gets exceeded.
* @param thresholdSize
* determines how much bytes are kept in memory before that
* back-end storage provider is used to store the remainder of
* the data.
*/
public ThresholdStorageProvider(StorageProvider backend, int thresholdSize) {
if (backend == null)
throw new IllegalArgumentException();
if (thresholdSize < 1)
throw new IllegalArgumentException();
this.backend = backend;
this.thresholdSize = thresholdSize;
}
public StorageOutputStream createStorageOutputStream() {
return new ThresholdStorageOutputStream();
}
private final class ThresholdStorageOutputStream extends
StorageOutputStream {
private final ByteArrayBuffer head;
private StorageOutputStream tail;
public ThresholdStorageOutputStream() {
final int bufferSize = Math.min(thresholdSize, 1024);
head = new ByteArrayBuffer(bufferSize);
}
@Override
public void close() throws IOException {
super.close();
if (tail != null)
tail.close();
}
@Override
protected void write0(byte[] buffer, int offset, int length)
throws IOException {
int remainingHeadSize = thresholdSize - head.length();
if (remainingHeadSize > 0) {
int n = Math.min(remainingHeadSize, length);
head.append(buffer, offset, n);
offset += n;
length -= n;
}
if (length > 0) {
if (tail == null)
tail = backend.createStorageOutputStream();
tail.write(buffer, offset, length);
}
}
@Override
protected Storage toStorage0() throws IOException {
if (tail == null)
return new MemoryStorageProvider.MemoryStorage(head.buffer(),
head.length());
return new ThresholdStorage(head.buffer(), head.length(), tail
.toStorage());
}
}
private static final class ThresholdStorage implements Storage {
private byte[] head;
private final int headLen;
private Storage tail;
public ThresholdStorage(byte[] head, int headLen, Storage tail) {
this.head = head;
this.headLen = headLen;
this.tail = tail;
}
public void delete() {
if (head != null) {
head = null;
tail.delete();
tail = null;
}
}
public InputStream getInputStream() throws IOException {
if (head == null)
throw new IllegalStateException("storage has been deleted");
InputStream headStream = new ByteArrayInputStream(head, 0, headLen);
InputStream tailStream = tail.getInputStream();
return new SequenceInputStream(headStream, tailStream);
}
}
}
././@LongLink 0000000 0000000 0000000 00000000147 00000000000 011567 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageProvider.ja0000644 0000000 0000000 00000004472 11702050530 031761 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
/**
* Provides a strategy for storing the contents of an InputStream
* or retrieving the content written to an OutputStream
.
*/
public interface StorageProvider {
/**
* Stores the contents of the given InputStream
.
*
* @param in stream containing the data to store.
* @return a {@link Storage} instance that can be used to retrieve the
* stored content.
* @throws IOException if an I/O error occurs.
*/
Storage store(InputStream in) throws IOException;
/**
* Creates a {@link StorageOutputStream} where data to be stored can be
* written to. Subsequently the user can call
* {@link StorageOutputStream#toStorage() toStorage()} on that object to get
* a {@link Storage} instance that holds the data that has been written.
*
* @return a {@link StorageOutputStream} where data can be written to.
* @throws IOException
* if an I/O error occurs.
*/
StorageOutputStream createStorageOutputStream() throws IOException;
}
././@LongLink 0000000 0000000 0000000 00000000156 00000000000 011567 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/DefaultStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/DefaultStorageProv0000644 0000000 0000000 00000006460 11702050530 032030 0 ustar root root /****************************************************************
* 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.storage;
/**
* Allows for a default {@link StorageProvider} instance to be configured on an
* application level.
*
* The default instance can be set by either calling
* {@link #setInstance(StorageProvider)} when the application starts up or by
* setting the system property
* org.apache.james.mime4j.defaultStorageProvider
to the class
* name of a StorageProvider
implementation.
*
* If neither option is used or if the class instantiation fails this class
* provides a pre-configured default instance.
*/
public class DefaultStorageProvider {
/** Value is org.apache.james.mime4j.defaultStorageProvider
*/
public static final String DEFAULT_STORAGE_PROVIDER_PROPERTY =
"org.apache.james.mime4j.defaultStorageProvider";
private static volatile StorageProvider instance = null;
static {
initialize();
}
private DefaultStorageProvider() {
}
/**
* Returns the default {@link StorageProvider} instance.
*
* @return the default {@link StorageProvider} instance.
*/
public static StorageProvider getInstance() {
return instance;
}
/**
* Sets the default {@link StorageProvider} instance.
*
* @param instance
* the default {@link StorageProvider} instance.
*/
public static void setInstance(StorageProvider instance) {
if (instance == null) {
throw new IllegalArgumentException();
}
DefaultStorageProvider.instance = instance;
}
private static void initialize() {
String clazz = System.getProperty(DEFAULT_STORAGE_PROVIDER_PROPERTY);
try {
if (clazz != null) {
instance = (StorageProvider) Class.forName(clazz).newInstance();
}
} catch (Exception e) {
}
if (instance == null) {
StorageProvider backend = new TempFileStorageProvider();
instance = new ThresholdStorageProvider(backend, 1024);
}
}
// for unit tests only
static void reset() {
instance = null;
initialize();
}
}
././@LongLink 0000000 0000000 0000000 00000000153 00000000000 011564 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageOutputStream.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageOutputStrea0000644 0000000 0000000 00000014135 11702050530 032072 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.OutputStream;
/**
* This class implements an output stream that can be used to create a
* {@link Storage} object. An instance of this class is obtained by calling
* {@link StorageProvider#createStorageOutputStream()}. The user can then write
* data to this instance and invoke {@link #toStorage()} to retrieve a
* {@link Storage} object that contains the data that has been written.
*
* Note that the StorageOutputStream
does not have to be closed
* explicitly because {@link #toStorage()} invokes {@link #close()} if
* necessary. Also note that {@link #toStorage()} may be invoked only once. One
* StorageOutputStream
can create only one Storage
* instance.
*/
public abstract class StorageOutputStream extends OutputStream {
private byte[] singleByte;
private boolean closed;
private boolean usedUp;
/**
* Sole constructor.
*/
protected StorageOutputStream() {
}
/**
* Closes this output stream if it has not already been closed and returns a
* {@link Storage} object which contains the bytes that have been written to
* this output stream.
*
* Note that this method may not be invoked a second time. This is because
* for some implementations it is not possible to create another
* Storage
object that can be read from and deleted
* independently (e.g. if the implementation writes to a file).
*
* @return a Storage
object as described above.
* @throws IOException
* if an I/O error occurs.
* @throws IllegalStateException
* if this method has already been called.
*/
public final Storage toStorage() throws IOException {
if (usedUp)
throw new IllegalStateException(
"toStorage may be invoked only once");
if (!closed)
close();
usedUp = true;
return toStorage0();
}
@Override
public final void write(int b) throws IOException {
if (closed)
throw new IOException("StorageOutputStream has been closed");
if (singleByte == null)
singleByte = new byte[1];
singleByte[0] = (byte) b;
write0(singleByte, 0, 1);
}
@Override
public final void write(byte[] buffer) throws IOException {
if (closed)
throw new IOException("StorageOutputStream has been closed");
if (buffer == null)
throw new NullPointerException();
if (buffer.length == 0)
return;
write0(buffer, 0, buffer.length);
}
@Override
public final void write(byte[] buffer, int offset, int length)
throws IOException {
if (closed)
throw new IOException("StorageOutputStream 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, length);
}
/**
* Closes this output stream. Subclasses that override this method have to
* invoke super.close()
.
*
* This implementation never throws an {@link IOException} but a subclass
* might.
*
* @throws IOException
* if an I/O error occurs.
*/
@Override
public void close() throws IOException {
closed = true;
}
/**
* Has to implemented by a concrete subclass to write bytes from the given
* byte array to this StorageOutputStream
. This method gets
* called by {@link #write(int)}, {@link #write(byte[])} and
* {@link #write(byte[], int, int)}. All the required preconditions have
* already been checked by these methods, including the check if the output
* stream has already been closed.
*
* @param buffer
* buffer containing bytes to write.
* @param offset
* start offset in the buffer.
* @param length
* number of bytes to write.
* @throws IOException
* if an I/O error occurs.
*/
protected abstract void write0(byte[] buffer, int offset, int length)
throws IOException;
/**
* Has to be implemented by a concrete subclass to create a {@link Storage}
* object from the bytes that have been written to this
* StorageOutputStream
. This method gets called by
* {@link #toStorage()} after the preconditions have been checked. The
* implementation can also be sure that this methods gets invoked only once.
*
* @return a Storage
object as described above.
* @throws IOException
* if an I/O error occurs.
*/
protected abstract Storage toStorage0() throws IOException;
}
././@LongLink 0000000 0000000 0000000 00000000155 00000000000 011566 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/MemoryStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/MemoryStorageProvi0000644 0000000 0000000 00000005652 11702050530 032067 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.james.mime4j.util.ByteArrayBuffer;
/**
* A {@link StorageProvider} that stores the data entirely in memory.
*
* Example usage: * *
* StorageProvider provider = new MemoryStorageProvider(); * DefaultStorageProvider.setInstance(provider); **/ public class MemoryStorageProvider extends AbstractStorageProvider { /** * Creates a new
MemoryStorageProvider
.
*/
public MemoryStorageProvider() {
}
public StorageOutputStream createStorageOutputStream() {
return new MemoryStorageOutputStream();
}
private static final class MemoryStorageOutputStream extends
StorageOutputStream {
ByteArrayBuffer bab = new ByteArrayBuffer(1024);
@Override
protected void write0(byte[] buffer, int offset, int length)
throws IOException {
bab.append(buffer, offset, length);
}
@Override
protected Storage toStorage0() throws IOException {
return new MemoryStorage(bab.buffer(), bab.length());
}
}
static final class MemoryStorage implements Storage {
private byte[] data;
private final int count;
public MemoryStorage(byte[] data, int count) {
this.data = data;
this.count = count;
}
public InputStream getInputStream() throws IOException {
if (data == null)
throw new IllegalStateException("storage has been deleted");
return new ByteArrayInputStream(data, 0, count);
}
public void delete() {
data = null;
}
}
}
apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/Storage.java 0000644 0000000 0000000 00000004523 11702050530 030572 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
/**
* Can be used to read data that has been stored by a {@link StorageProvider}.
*/
public interface Storage {
/**
* Returns an InputStream
that can be used to read the stored
* data. The input stream should be closed by the caller when it is no
* longer needed.
*
* Note: The stream should NOT be wrapped in a
* BufferedInputStream
by the caller. If the implementing
* Storage
creates a stream which would benefit from being
* buffered it is the Storage
's responsibility to wrap it.
*
* @return an InputStream
for reading the stored data.
* @throws IOException
* if an I/O error occurs.
* @throws IllegalStateException
* if this Storage
instance has been deleted.
*/
InputStream getInputStream() throws IOException;
/**
* Deletes the data held by this Storage
as soon as possible.
* Deleting an already deleted Storage
has no effect.
*/
void delete();
}
././@LongLink 0000000 0000000 0000000 00000000155 00000000000 011566 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/CipherStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/CipherStorageProvi0000644 0000000 0000000 00000014463 11702050530 032031 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
/**
* A {@link StorageProvider} that transparently scrambles and unscrambles the
* data stored by another StorageProvider
.
*
*
* Example usage: * *
* StorageProvider mistrusted = new TempFileStorageProvider(); * StorageProvider enciphered = new CipherStorageProvider(mistrusted); * StorageProvider provider = new ThresholdStorageProvider(enciphered); * DefaultStorageProvider.setInstance(provider); **/ public class CipherStorageProvider extends AbstractStorageProvider { private final StorageProvider backend; private final String algorithm; private final KeyGenerator keygen; /** * Creates a new
CipherStorageProvider
for the given back-end
* using the Blowfish cipher algorithm.
*
* @param backend
* back-end storage strategy to encrypt.
*/
public CipherStorageProvider(StorageProvider backend) {
this(backend, "Blowfish");
}
/**
* Creates a new CipherStorageProvider
for the given back-end
* and cipher algorithm.
*
* @param backend
* back-end storage strategy to encrypt.
* @param algorithm
* the name of the symmetric block cipher algorithm such as
* "Blowfish", "AES" or "RC2".
*/
public CipherStorageProvider(StorageProvider backend, String algorithm) {
if (backend == null)
throw new IllegalArgumentException();
try {
this.backend = backend;
this.algorithm = algorithm;
this.keygen = KeyGenerator.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
}
public StorageOutputStream createStorageOutputStream() throws IOException {
SecretKeySpec skeySpec = getSecretKeySpec();
return new CipherStorageOutputStream(backend
.createStorageOutputStream(), algorithm, skeySpec);
}
private SecretKeySpec getSecretKeySpec() {
byte[] raw = keygen.generateKey().getEncoded();
return new SecretKeySpec(raw, algorithm);
}
private static final class CipherStorageOutputStream extends
StorageOutputStream {
private final StorageOutputStream storageOut;
private final String algorithm;
private final SecretKeySpec skeySpec;
private final CipherOutputStream cipherOut;
public CipherStorageOutputStream(StorageOutputStream out,
String algorithm, SecretKeySpec skeySpec) throws IOException {
try {
this.storageOut = out;
this.algorithm = algorithm;
this.skeySpec = skeySpec;
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
this.cipherOut = new CipherOutputStream(out, cipher);
} catch (GeneralSecurityException e) {
throw (IOException) new IOException().initCause(e);
}
}
@Override
public void close() throws IOException {
super.close();
cipherOut.close();
}
@Override
protected void write0(byte[] buffer, int offset, int length)
throws IOException {
cipherOut.write(buffer, offset, length);
}
@Override
protected Storage toStorage0() throws IOException {
// cipherOut has already been closed because toStorage calls close
Storage encrypted = storageOut.toStorage();
return new CipherStorage(encrypted, algorithm, skeySpec);
}
}
private static final class CipherStorage implements Storage {
private Storage encrypted;
private final String algorithm;
private final SecretKeySpec skeySpec;
public CipherStorage(Storage encrypted, String algorithm,
SecretKeySpec skeySpec) {
this.encrypted = encrypted;
this.algorithm = algorithm;
this.skeySpec = skeySpec;
}
public void delete() {
if (encrypted != null) {
encrypted.delete();
encrypted = null;
}
}
public InputStream getInputStream() throws IOException {
if (encrypted == null)
throw new IllegalStateException("storage has been deleted");
try {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
InputStream in = encrypted.getInputStream();
return new CipherInputStream(in, cipher);
} catch (GeneralSecurityException e) {
throw (IOException) new IOException().initCause(e);
}
}
}
}
././@LongLink 0000000 0000000 0000000 00000000151 00000000000 011562 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageBinaryBody.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageBinaryBody.0000644 0000000 0000000 00000004737 11702050530 031722 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.james.mime4j.codec.CodecUtil;
import org.apache.james.mime4j.dom.BinaryBody;
/**
* Binary body backed by a
* {@link org.apache.james.mime4j.storage.Storage}
*/
class StorageBinaryBody extends BinaryBody {
private MultiReferenceStorage storage;
public StorageBinaryBody(final MultiReferenceStorage storage) {
this.storage = storage;
}
@Override
public InputStream getInputStream() throws IOException {
return storage.getInputStream();
}
@Override
public void writeTo(OutputStream out) throws IOException {
if (out == null)
throw new IllegalArgumentException();
InputStream in = storage.getInputStream();
CodecUtil.copy(in, out);
in.close();
}
@Override
public StorageBinaryBody copy() {
storage.addReference();
return new StorageBinaryBody(storage);
}
/**
* Deletes the Storage that holds the content of this binary body.
*
* @see org.apache.james.mime4j.dom.Disposable#dispose()
*/
@Override
public void dispose() {
if (storage != null) {
storage.delete();
storage = null;
}
}
}
././@LongLink 0000000 0000000 0000000 00000000152 00000000000 011563 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageBodyFactory.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageBodyFactory0000644 0000000 0000000 00000026466 11702050530 032032 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.BinaryBody;
import org.apache.james.mime4j.dom.Disposable;
import org.apache.james.mime4j.dom.SingleBody;
import org.apache.james.mime4j.dom.TextBody;
import org.apache.james.mime4j.message.BodyFactory;
import org.apache.james.mime4j.util.CharsetUtil;
/**
* Factory for creating message bodies.
*/
public class StorageBodyFactory implements BodyFactory {
private static final Charset FALLBACK_CHARSET = CharsetUtil.DEFAULT_CHARSET;
private final StorageProvider storageProvider;
private final DecodeMonitor monitor;
/**
* Creates a new BodyFactory
instance that uses the default
* storage provider for creating message bodies from input streams.
*/
public StorageBodyFactory() {
this(null, null);
}
/**
* Creates a new BodyFactory
instance that uses the given
* storage provider for creating message bodies from input streams.
*
* @param storageProvider
* a storage provider or null
to use the default
* one.
*/
public StorageBodyFactory(
final StorageProvider storageProvider,
final DecodeMonitor monitor) {
this.storageProvider =
storageProvider != null ? storageProvider : DefaultStorageProvider.getInstance();
this.monitor =
monitor != null ? monitor : DecodeMonitor.SILENT;
}
/**
* Returns the StorageProvider
this BodyFactory
* uses to create message bodies from input streams.
*
* @return a StorageProvider
.
*/
public StorageProvider getStorageProvider() {
return storageProvider;
}
/**
* Creates a {@link BinaryBody} that holds the content of the given input
* stream.
*
* @param is
* input stream to create a message body from.
* @return a binary body.
* @throws IOException
* if an I/O error occurs.
*/
public BinaryBody binaryBody(InputStream is) throws IOException {
if (is == null)
throw new IllegalArgumentException();
Storage storage = storageProvider.store(is);
return new StorageBinaryBody(new MultiReferenceStorage(storage));
}
/**
* Creates a {@link BinaryBody} that holds the content of the given
* {@link Storage}.
*
* Note that the caller must not invoke {@link Storage#delete() delete()} on
* the given Storage
object after it has been passed to this
* method. Instead the message body created by this method takes care of
* deleting the storage when it gets disposed of (see
* {@link Disposable#dispose()}).
*
* @param storage
* storage to create a message body from.
* @return a binary body.
* @throws IOException
* if an I/O error occurs.
*/
public BinaryBody binaryBody(Storage storage) throws IOException {
if (storage == null)
throw new IllegalArgumentException();
return new StorageBinaryBody(new MultiReferenceStorage(storage));
}
/**
* Creates a {@link TextBody} that holds the content of the given input
* stream.
*
* "us-ascii" is used to decode the byte content of the
* Storage
into a character stream when calling
* {@link TextBody#getReader() getReader()} on the returned object.
*
* @param is
* input stream to create a message body from.
* @return a text body.
* @throws IOException
* if an I/O error occurs.
*/
public TextBody textBody(InputStream is) throws IOException {
if (is == null)
throw new IllegalArgumentException();
Storage storage = storageProvider.store(is);
return new StorageTextBody(new MultiReferenceStorage(storage),
CharsetUtil.DEFAULT_CHARSET);
}
/**
* Creates a {@link TextBody} that holds the content of the given input
* stream.
*
* The charset corresponding to the given MIME charset name is used to * decode the byte content of the input stream into a character stream when * calling {@link TextBody#getReader() getReader()} on the returned object. * If the MIME charset has no corresponding Java charset or the Java charset * cannot be used for decoding then "us-ascii" is used instead. * * @param is * input stream to create a message body from. * @param mimeCharset * name of a MIME charset. * @return a text body. * @throws IOException * if an I/O error occurs. */ public TextBody textBody(InputStream is, String mimeCharset) throws IOException { if (is == null) throw new IllegalArgumentException(); if (mimeCharset == null) throw new IllegalArgumentException(); Storage storage = storageProvider.store(is); Charset charset = toJavaCharset(mimeCharset, false, monitor); return new StorageTextBody(new MultiReferenceStorage(storage), charset); } /** * Creates a {@link TextBody} that holds the content of the given * {@link Storage}. *
* "us-ascii" is used to decode the byte content of the
* Storage
into a character stream when calling
* {@link TextBody#getReader() getReader()} on the returned object.
*
* Note that the caller must not invoke {@link Storage#delete() delete()} on
* the given Storage
object after it has been passed to this
* method. Instead the message body created by this method takes care of
* deleting the storage when it gets disposed of (see
* {@link Disposable#dispose()}).
*
* @param storage
* storage to create a message body from.
* @return a text body.
* @throws IOException
* if an I/O error occurs.
*/
public TextBody textBody(Storage storage) throws IOException {
if (storage == null)
throw new IllegalArgumentException();
return new StorageTextBody(new MultiReferenceStorage(storage),
CharsetUtil.DEFAULT_CHARSET);
}
/**
* Creates a {@link TextBody} that holds the content of the given
* {@link Storage}.
*
* The charset corresponding to the given MIME charset name is used to
* decode the byte content of the Storage
into a character
* stream when calling {@link TextBody#getReader() getReader()} on the
* returned object. If the MIME charset has no corresponding Java charset or
* the Java charset cannot be used for decoding then "us-ascii" is
* used instead.
*
* Note that the caller must not invoke {@link Storage#delete() delete()} on
* the given Storage
object after it has been passed to this
* method. Instead the message body created by this method takes care of
* deleting the storage when it gets disposed of (see
* {@link Disposable#dispose()}).
*
* @param storage
* storage to create a message body from.
* @param mimeCharset
* name of a MIME charset.
* @return a text body.
* @throws IOException
* if an I/O error occurs.
*/
public TextBody textBody(Storage storage, String mimeCharset)
throws IOException {
if (storage == null)
throw new IllegalArgumentException();
if (mimeCharset == null)
throw new IllegalArgumentException();
Charset charset = toJavaCharset(mimeCharset, false, monitor);
return new StorageTextBody(new MultiReferenceStorage(storage), charset);
}
/**
* Creates a {@link TextBody} that holds the content of the given string.
*
* "us-ascii" is used to encode the characters of the string into * a byte stream when calling * {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on * the returned object. * * @param text * text to create a message body from. * @return a text body. */ public TextBody textBody(String text) { if (text == null) throw new IllegalArgumentException(); return new StringTextBody(text, CharsetUtil.DEFAULT_CHARSET); } /** * Creates a {@link TextBody} that holds the content of the given string. *
* The charset corresponding to the given MIME charset name is used to
* encode the characters of the string into a byte stream when calling
* {@link SingleBody#writeTo(java.io.OutputStream) writeTo(OutputStream)} on
* the returned object. If the MIME charset has no corresponding Java
* charset or the Java charset cannot be used for encoding then
* "us-ascii" is used instead.
*
* @param text
* text to create a message body from.
* @param mimeCharset
* name of a MIME charset.
* @return a text body.
*/
public TextBody textBody(String text, String mimeCharset) {
if (text == null)
throw new IllegalArgumentException();
if (mimeCharset == null)
throw new IllegalArgumentException();
Charset charset = toJavaCharset(mimeCharset, true, monitor);
return new StringTextBody(text, charset);
}
private static Charset toJavaCharset(
final String mimeCharset,
boolean forEncoding,
final DecodeMonitor monitor) {
Charset charset = CharsetUtil.lookup(mimeCharset);
if (charset == null) {
if (monitor.isListening()) {
monitor.warn(
"MIME charset '" + mimeCharset + "' has no "
+ "corresponding Java charset", "Using "
+ FALLBACK_CHARSET + " instead.");
}
return FALLBACK_CHARSET;
}
return charset;
}
}
././@LongLink 0000000 0000000 0000000 00000000157 00000000000 011570 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/AbstractStorageProvider.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/AbstractStoragePro0000644 0000000 0000000 00000005121 11702050530 032012 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
import org.apache.james.mime4j.codec.CodecUtil;
/**
* Abstract implementation of {@link StorageProvider} that implements
* {@link StorageProvider#store(InputStream) store(InputStream)} by copying the
* input stream to a {@link StorageOutputStream} obtained from
* {@link StorageProvider#createStorageOutputStream() createStorageOutputStream()}.
*/
public abstract class AbstractStorageProvider implements StorageProvider {
/**
* Sole constructor.
*/
protected AbstractStorageProvider() {
}
/**
* This implementation creates a {@link StorageOutputStream} by calling
* {@link StorageProvider#createStorageOutputStream() createStorageOutputStream()}
* and copies the content of the given input stream to that output stream.
* It then calls {@link StorageOutputStream#toStorage()} on the output
* stream and returns this object.
*
* @param in
* stream containing the data to store.
* @return a {@link Storage} instance that can be used to retrieve the
* stored content.
* @throws IOException
* if an I/O error occurs.
*/
public final Storage store(InputStream in) throws IOException {
StorageOutputStream out = createStorageOutputStream();
CodecUtil.copy(in, out);
return out.toStorage();
}
}
././@LongLink 0000000 0000000 0000000 00000000147 00000000000 011567 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageTextBody.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StorageTextBody.ja0000644 0000000 0000000 00000005015 11702050530 031723 0 ustar root root /****************************************************************
* 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.storage;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import org.apache.james.mime4j.dom.TextBody;
/**
* Text body backed by a {@link org.apache.james.mime4j.storage.Storage}.
*/
class StorageTextBody extends TextBody {
private MultiReferenceStorage storage;
private Charset charset;
public StorageTextBody(MultiReferenceStorage storage, Charset charset) {
this.storage = storage;
this.charset = charset;
}
@Override
public String getMimeCharset() {
return charset.name();
}
@Override
public Reader getReader() throws IOException {
return new InputStreamReader(storage.getInputStream(), charset);
}
@Override
public InputStream getInputStream() throws IOException {
return storage.getInputStream();
}
@Override
public StorageTextBody copy() {
storage.addReference();
return new StorageTextBody(storage, charset);
}
/**
* Deletes the Storage that holds the content of this text body.
*
* @see org.apache.james.mime4j.dom.Disposable#dispose()
*/
@Override
public void dispose() {
if (storage != null) {
storage.delete();
storage = null;
}
}
}
././@LongLink 0000000 0000000 0000000 00000000146 00000000000 011566 L ustar root root apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StringTextBody.java apache-mime4j-project-0.7.2/storage/src/main/java/org/apache/james/mime4j/storage/StringTextBody.jav0000644 0000000 0000000 00000005423 11702050530 031756 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.nio.charset.Charset;
import org.apache.james.mime4j.dom.TextBody;
/**
* Text body backed by a
Apache James Mime4J is developed by the
Apache James team but now has a
dedicated mailing list.
Apache James Mime4J provides a parser,
The parser only deals with the structure of the message stream.
It won't do any decoding of base64 or quoted-printable encoded
header fields and bodies. This is intentional - the parser
should only provide the most basic functionality needed to build
more complex parsers. However, mime4j does include facilities to
decode bodies and fields and the The parser has been designed to be extremely tolerant against
messages violating the standards. It has been tested using a
large corpus (>5000) of e-mail messages. As a benchmark
the widely used perl mime4j can also be used to build a tree representation of an
e-mail message using the
Go to the download
pages and download the most recent
release in your preferred format, either
Go to the download
pages and download the most recent
release in your preferred format, either
Issue the following commands in a shell:
String
.
*/
class StringTextBody extends TextBody {
private final String text;
private final Charset charset;
public StringTextBody(final String text, Charset charset) {
this.text = text;
this.charset = charset;
}
@Override
public String getMimeCharset() {
return charset.name();
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(text.getBytes(charset.name()));
}
@Override
public Reader getReader() throws IOException {
return new StringReader(text);
}
@Override
public void writeTo(OutputStream out) throws IOException {
if (out == null)
throw new IllegalArgumentException();
Reader reader = new StringReader(text);
Writer writer = new OutputStreamWriter(out, charset);
char buffer[] = new char[1024];
while (true) {
int nChars = reader.read(buffer);
if (nChars == -1)
break;
writer.write(buffer, 0, nChars);
}
reader.close();
writer.flush();
}
@Override
public StringTextBody copy() {
return new StringTextBody(text, charset);
}
}
apache-mime4j-project-0.7.2/storage/src/test/ 0000755 0000000 0000000 00000000000 11702050530 017471 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/ 0000755 0000000 0000000 00000000000 11702050530 020412 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/ 0000755 0000000 0000000 00000000000 11702050530 021201 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/ 0000755 0000000 0000000 00000000000 11702050530 022422 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/ 0000755 0000000 0000000 00000000000 11702050530 023521 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/ 0000755 0000000 0000000 00000000000 11702050530 024706 5 ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/ 0000755 0000000 0000000 00000000000 11702050530 026352 5 ustar root root ././@LongLink 0000000 0000000 0000000 00000000152 00000000000 011563 L ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/SingleBodyCopyTest.java apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/SingleBodyCopyTest0000644 0000000 0000000 00000011567 11702050530 032041 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import junit.framework.TestCase;
import org.apache.james.mime4j.dom.SingleBody;
import org.apache.james.mime4j.message.MessageImpl;
import org.apache.james.mime4j.util.CharsetUtil;
public class SingleBodyCopyTest extends TestCase {
public void testCopyStorageBinaryBody() throws Exception {
Storage storage = new MemoryStorageProvider()
.store(new ByteArrayInputStream("test".getBytes()));
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
SingleBody body = new StorageBinaryBody(multiReferenceStorage);
copyTest(body);
}
public void testCopyStorageTextBody() throws Exception {
Storage storage = new MemoryStorageProvider()
.store(new ByteArrayInputStream("test".getBytes()));
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
SingleBody body = new StorageTextBody(multiReferenceStorage,
CharsetUtil.US_ASCII);
copyTest(body);
}
public void testCopyStringTextBody() throws Exception {
SingleBody body = new StringTextBody("test", CharsetUtil.US_ASCII);
copyTest(body);
}
public void testDisposeStorageBinaryBody() throws Exception {
Storage storage = new MemoryStorageProvider()
.store(new ByteArrayInputStream("test".getBytes()));
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
SingleBody body = new StorageBinaryBody(multiReferenceStorage);
disposeTest(body, storage);
}
public void testDisposeStorageTextBody() throws Exception {
Storage storage = new MemoryStorageProvider()
.store(new ByteArrayInputStream("test".getBytes()));
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
SingleBody body = new StorageTextBody(multiReferenceStorage,
CharsetUtil.US_ASCII);
disposeTest(body, storage);
}
private void copyTest(SingleBody body) throws Exception {
MessageImpl parent = new MessageImpl();
parent.setBody(body);
SingleBody copy = body.copy();
assertNotNull(copy);
assertNotSame(body, copy);
assertSame(parent, body.getParent());
assertNull(copy.getParent());
sameContentTest(body, copy);
}
private void sameContentTest(SingleBody expectedBody, SingleBody actualBody)
throws Exception {
ByteArrayOutputStream expBaos = new ByteArrayOutputStream();
expectedBody.writeTo(expBaos);
byte[] expected = expBaos.toByteArray();
ByteArrayOutputStream actBaos = new ByteArrayOutputStream();
actualBody.writeTo(actBaos);
byte[] actual = actBaos.toByteArray();
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], actual[i]);
}
}
private void disposeTest(SingleBody body, Storage storage) throws Exception {
assertTrue(storageIsReadable(storage));
SingleBody copy = body.copy();
assertTrue(storageIsReadable(storage));
body.dispose();
assertTrue(storageIsReadable(storage));
copy.dispose();
assertFalse(storageIsReadable(storage));
}
private boolean storageIsReadable(Storage storage) throws Exception {
try {
storage.getInputStream().close();
return true;
} catch (IllegalStateException e) {
return false;
}
}
}
././@LongLink 0000000 0000000 0000000 00000000162 00000000000 011564 L ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/DefaultStorageProviderTest.java apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/DefaultStorageProv0000644 0000000 0000000 00000004772 11702050530 032067 0 ustar root root /****************************************************************
* 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.storage;
import junit.framework.TestCase;
public class DefaultStorageProviderTest extends TestCase {
@Override
protected void tearDown() throws Exception {
System.getProperties().remove(
DefaultStorageProvider.DEFAULT_STORAGE_PROVIDER_PROPERTY);
DefaultStorageProvider.reset();
}
public void testDefaultInstance() throws Exception {
System.getProperties().remove(
DefaultStorageProvider.DEFAULT_STORAGE_PROVIDER_PROPERTY);
DefaultStorageProvider.reset();
StorageProvider instance = DefaultStorageProvider.getInstance();
assertTrue(instance instanceof ThresholdStorageProvider);
}
public void testSetDefaultProperty() throws Exception {
System.setProperty(
DefaultStorageProvider.DEFAULT_STORAGE_PROVIDER_PROPERTY,
MemoryStorageProvider.class.getName());
DefaultStorageProvider.reset();
StorageProvider instance = DefaultStorageProvider.getInstance();
assertTrue(instance instanceof MemoryStorageProvider);
}
public void testSetter() throws Exception {
StorageProvider instance = new MemoryStorageProvider();
DefaultStorageProvider.setInstance(instance);
assertSame(instance, DefaultStorageProvider.getInstance());
}
}
././@LongLink 0000000 0000000 0000000 00000000161 00000000000 011563 L ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/MultiReferenceStorageTest.java apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/MultiReferenceStor0000644 0000000 0000000 00000007300 11702050530 032056 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.TestCase;
public class MultiReferenceStorageTest extends TestCase {
public void testForwardsGetInputStream() throws Exception {
DummyStorage storage = new DummyStorage();
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
assertEquals(ByteArrayInputStream.class, multiReferenceStorage
.getInputStream().getClass());
}
public void testSingleReference() throws Exception {
DummyStorage storage = new DummyStorage();
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
assertFalse(storage.deleted);
multiReferenceStorage.delete();
assertTrue(storage.deleted);
}
public void testMultiReference() throws Exception {
DummyStorage storage = new DummyStorage();
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
multiReferenceStorage.addReference();
multiReferenceStorage.delete();
assertFalse(storage.deleted);
multiReferenceStorage.delete();
assertTrue(storage.deleted);
}
public void testGetInputStreamOnDeleted() throws Exception {
DummyStorage storage = new DummyStorage();
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
multiReferenceStorage.delete();
try {
multiReferenceStorage.getInputStream();
fail();
} catch (IllegalStateException expected) {
}
}
public void testAddReferenceOnDeleted() throws Exception {
DummyStorage storage = new DummyStorage();
MultiReferenceStorage multiReferenceStorage = new MultiReferenceStorage(
storage);
multiReferenceStorage.delete();
try {
multiReferenceStorage.addReference();
fail();
} catch (IllegalStateException expected) {
}
}
private static final class DummyStorage implements Storage {
public boolean deleted = false;
public InputStream getInputStream() throws IOException {
if (deleted)
throw new IllegalStateException("deleted");
return new ByteArrayInputStream("dummy".getBytes());
}
public void delete() {
deleted = true;
}
}
}
././@LongLink 0000000 0000000 0000000 00000000153 00000000000 011564 L ustar root root apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/StorageProviderTest.java apache-mime4j-project-0.7.2/storage/src/test/java/org/apache/james/mime4j/storage/StorageProviderTes0000644 0000000 0000000 00000012146 11702050530 032074 0 ustar root root /****************************************************************
* 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.storage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.james.mime4j.codec.CodecUtil;
import junit.framework.TestCase;
public class StorageProviderTest extends TestCase {
public void testMemoryStorageProvider() throws Exception {
StorageProvider provider = new MemoryStorageProvider();
testReadWrite(provider, 0);
testReadWrite(provider, 1);
testReadWrite(provider, 1024);
testReadWrite(provider, 20000);
testDelete(provider);
}
public void testTempFileStorageProvider() throws Exception {
StorageProvider provider = new TempFileStorageProvider();
testReadWrite(provider, 0);
testReadWrite(provider, 1);
testReadWrite(provider, 1024);
testReadWrite(provider, 20000);
testDelete(provider);
}
public void testThresholdStorageProvider() throws Exception {
final int threshold = 5000;
StorageProvider backend = new TempFileStorageProvider();
StorageProvider provider = new ThresholdStorageProvider(backend,
threshold);
testReadWrite(provider, 0);
testReadWrite(provider, 1);
testReadWrite(provider, threshold - 1);
testReadWrite(provider, threshold);
testReadWrite(provider, threshold + 1);
testReadWrite(provider, 2 * threshold);
testReadWrite(provider, 10 * threshold);
testDelete(provider);
}
public void testCipherStorageProvider() throws Exception {
StorageProvider backend = new TempFileStorageProvider();
StorageProvider provider = new CipherStorageProvider(backend);
testReadWrite(provider, 0);
testReadWrite(provider, 1);
testReadWrite(provider, 1024);
testReadWrite(provider, 20000);
testDelete(provider);
}
private void testReadWrite(StorageProvider provider, int size)
throws IOException {
testStore(provider, size);
testCreateStorageOutputStream(provider, size);
}
private void testStore(StorageProvider provider, int size)
throws IOException {
byte[] data = createData(size);
assertEquals(size, data.length);
Storage storage = provider.store(new ByteArrayInputStream(data));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CodecUtil.copy(storage.getInputStream(), baos);
verifyData(data, baos.toByteArray());
}
private void testCreateStorageOutputStream(StorageProvider provider,
int size) throws IOException {
byte[] data = createData(size);
assertEquals(size, data.length);
StorageOutputStream out = provider.createStorageOutputStream();
CodecUtil.copy(new ByteArrayInputStream(data), out);
Storage storage = out.toStorage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CodecUtil.copy(storage.getInputStream(), baos);
verifyData(data, baos.toByteArray());
}
private void verifyData(byte[] expected, byte[] actual) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], actual[i]);
}
}
private byte[] createData(int size) {
byte[] data = new byte[size];
for (int i = 0; i < size; i++) {
data[i] = (byte) i;
}
return data;
}
private void testDelete(StorageProvider provider) throws IOException {
Storage storage = provider.store(new ByteArrayInputStream(
createData(512)));
storage.delete();
// getInputStream has to throw an IllegalStateException
try {
storage.getInputStream();
fail();
} catch (IllegalStateException expected) {
}
// invoking delete a second time should not have any effect
storage.delete();
}
}
apache-mime4j-project-0.7.2/storage/src/reporting-site/ 0000755 0000000 0000000 00000000000 11702050530 021465 5 ustar root root apache-mime4j-project-0.7.2/storage/src/reporting-site/site.xml 0000644 0000000 0000000 00000001756 11702050530 023164 0 ustar root root
MimeStreamParser
, for e-mail message streams in plain rfc822 and MIME
format. The parser uses a callback mechanism to report parsing
events such as the start of an entity header, the start of a
body, etc. If you are familiar with the SAX XML parser interface
you should have no problem getting started with mime4j. Message
class
described below handles decoding of fields and bodies
transparently. MIME::Tools
parser has been used. mime4j and MIME:Tools rarely differ
(<25 in those 5000). When they do (which only occurs
for illegally formatted spam messages) we think mime4j does a
better job. Message
class. Using this facility mime4j automatically handles the
decoding of fields and bodies and uses temporary files for large
attachments. This representation is similar to the
representation constructed by the JavaMail API:s but is more
tolerant to messages violating the standards.
Document
Description
Download
Before you can start using mime4j, you'll have to
download the distribution to your system (unless you
plan on building the project from source). This
document provides links to the various distributions
available.
Building mime4j
Describes how to build mime4j from the sources.
james-mime4j-x.y.tar.gz
or james-mime4j-x.y.zip
.
Extracting the archive will create the directory
james-mime4j-x.y/
which contains the mime4j jar file and
the API docs.james-mime4j-x.y-src.tar.gz
or james-mime4j-x.y-src.zip
.
Extracting the archived sources will create the directory
james-mime4j-x.y/
.
svn checkout http://svn.apache.org/repos/asf/james/mime4j/trunk james-mime4j
You will need to download and install Maven before building the sources. The build has been tested with version 2.0 of Maven so use this or a later version if possible.
One of the main differences between Maven and plain ant is that Maven manages external dependencies for your projects and (at least in theory) you should no longer have to store third-party jar files in your source code tree. It maintains a local repository of versioned libraries and shares them between your Maven projects. If it can't find the necessary files there it will attempt to download them from the main Maven repository at www.ibiblio.org/maven. So to use the Maven build, you need to have a network connection available for the inital download of the project dependencies.
Once Maven has been installed, building the project should be as simple as typing
cd james-mime4j-x.y/ (cd james-mime4j/ if sources come from
Subversion)
mvn package
from the command line. Maven will
automatically run all test cases for you and create the
jar file in the target
directory.
To install the jar into your local Maven repository run
mvn install
To generate an Eclipse project from the sources run
mvn eclipse:eclipse
NOTE! Mime4j uses JavaCC to generate parsers for
header fields. If you're using an old version of maven eclipse pluing
mvn eclipse:eclipse
could have problems
generating proper source folders for the JavaCC generated code.
After running mvn eclipse:eclipse
you must manually
add target/generated-sources/javacc
and
target/generated-sources/jjtree
as source folders
under Project -> Properties in Eclipse.
For more information on using Maven, have a look at the Maven web site.
The Mime4j distribution includes samples
which demonstrate how the library could be used. This section
gives you a short review of those samples. For more information
you should download the distribution and study the sample sources.
The samples are in the examples/
sub-directory.
Sample | Description |
---|---|
org.apache.james.mime4j.samples.tree.MessageTree
|
Displays a tree of the contents of a
Mime4j Message object in a Swing GUI.
To try it out run
The output is very useful if
you want the study the structure of MIME messages.
|
org.apache.james.mime4j.samples.transform.TransformMessage
|
Illustrate how to transform a message into another message without modifying the original. |
org.apache.james.mime4j.samples.dom.TextPlainMessage
|
Illustrate the use of Mime4j DOM API. This example generates a message very similar to the one from RFC 5322 Appendix A.1.1. |
org.apache.james.mime4j.samples.dom.MultipartMessage
|
Illustrate the use of Mime4j DOM API. This example creates a multipart/mixed message that consists of a text/plain and an image/png part. The image is created on the fly; a similar technique can be used to create PDF or XML attachments, for example. |