Author: rdonkin
Date: Sun Nov 30 14:43:10 2008
New Revision: 721917
URL: http://svn.apache.org/viewvc?rev=721917&view=rev
Log:
https://issues.apache.org/jira/browse/MIME4J-88 Make message bodies sharable.
Contributed by Markus Wiederkehr MIME4J-88.
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/SingleBody.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/storage/MultiReferenceStorage.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/SingleBodyCopyTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/storage/MultiReferenceStorageTest.java
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/AbstractBody.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BodyFactory.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageBinaryBody.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageTextBody.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StringTextBody.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/AbstractBody.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/AbstractBody.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/AbstractBody.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/AbstractBody.java
Sun Nov 30 14:43:10 2008
@@ -26,7 +26,9 @@
*
*
* @version $Id: AbstractBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
+ * @deprecated extend [EMAIL PROTECTED] SingleBody} instead
*/
[EMAIL PROTECTED]
public abstract class AbstractBody implements Body {
private Entity parent = null;
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BodyFactory.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BodyFactory.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BodyFactory.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BodyFactory.java
Sun Nov 30 14:43:10 2008
@@ -26,6 +26,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.james.mime4j.message.storage.DefaultStorageProvider;
+import org.apache.james.mime4j.message.storage.MultiReferenceStorage;
import org.apache.james.mime4j.message.storage.Storage;
import org.apache.james.mime4j.message.storage.StorageProvider;
import org.apache.james.mime4j.util.CharsetUtil;
@@ -58,7 +59,7 @@
throw new IllegalArgumentException();
Storage storage = storageProvider.store(is);
- return new StorageBinaryBody(storage);
+ return new StorageBinaryBody(new MultiReferenceStorage(storage));
}
public TextBody textBody(InputStream is) throws IOException {
@@ -66,7 +67,8 @@
throw new IllegalArgumentException();
Storage storage = storageProvider.store(is);
- return new StorageTextBody(storage, MessageUtils.DEFAULT_CHARSET);
+ return new StorageTextBody(new MultiReferenceStorage(storage),
+ MessageUtils.DEFAULT_CHARSET);
}
public TextBody textBody(InputStream is, String mimeCharset)
@@ -78,7 +80,7 @@
Storage storage = storageProvider.store(is);
Charset charset = toJavaCharset(mimeCharset, false);
- return new StorageTextBody(storage, charset);
+ return new StorageTextBody(new MultiReferenceStorage(storage),
charset);
}
public TextBody textBody(String text) {
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/SingleBody.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/SingleBody.java?rev=721917&view=auto
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/SingleBody.java
(added)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/SingleBody.java
Sun Nov 30 14:43:10 2008
@@ -0,0 +1,85 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message;
+
+/**
+ * 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;
+
+ /**
+ * @see org.apache.james.mime4j.message.Body#getParent()
+ */
+ public Entity getParent() {
+ return parent;
+ }
+
+ /**
+ * @see
org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
+ */
+ public void setParent(Entity parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Returns a copy of this <code>SingleBody</code> (optional operation).
+ * <p>
+ * The general contract of this method is as follows:
+ * <ul>
+ * <li>Invoking [EMAIL PROTECTED] #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 (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.message.Disposable#dispose()
+ */
+ public void dispose() {
+ }
+
+}
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageBinaryBody.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageBinaryBody.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageBinaryBody.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageBinaryBody.java
Sun Nov 30 14:43:10 2008
@@ -24,17 +24,17 @@
import java.io.OutputStream;
import org.apache.james.mime4j.decoder.CodecUtil;
-import org.apache.james.mime4j.message.storage.Storage;
+import org.apache.james.mime4j.message.storage.MultiReferenceStorage;
/**
* Binary body backed by a
* [EMAIL PROTECTED] org.apache.james.mime4j.message.storage.Storage}
*/
-class StorageBinaryBody extends AbstractBody implements BinaryBody {
+class StorageBinaryBody extends SingleBody implements BinaryBody {
- private Storage storage = null;
+ private MultiReferenceStorage storage = null;
- public StorageBinaryBody(final Storage storage) {
+ public StorageBinaryBody(final MultiReferenceStorage storage) {
this.storage = storage;
}
@@ -58,6 +58,12 @@
in.close();
}
+ @Override
+ public StorageBinaryBody copy() {
+ storage.addReference();
+ return new StorageBinaryBody(storage);
+ }
+
/**
* Deletes the Storage that holds the content of this binary body.
*
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageTextBody.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageTextBody.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageTextBody.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StorageTextBody.java
Sun Nov 30 14:43:10 2008
@@ -27,17 +27,17 @@
import java.nio.charset.Charset;
import org.apache.james.mime4j.decoder.CodecUtil;
-import org.apache.james.mime4j.message.storage.Storage;
+import org.apache.james.mime4j.message.storage.MultiReferenceStorage;
/**
* Text body backed by a [EMAIL PROTECTED]
org.apache.james.mime4j.message.storage.Storage}.
*/
-class StorageTextBody extends AbstractBody implements TextBody {
+class StorageTextBody extends SingleBody implements TextBody {
- private Storage storage;
+ private MultiReferenceStorage storage;
private Charset charset;
- public StorageTextBody(Storage storage, Charset charset) {
+ public StorageTextBody(MultiReferenceStorage storage, Charset charset) {
this.storage = storage;
this.charset = charset;
}
@@ -62,6 +62,12 @@
in.close();
}
+ @Override
+ public StorageTextBody copy() {
+ storage.addReference();
+ return new StorageTextBody(storage, charset);
+ }
+
/**
* Deletes the Storage that holds the content of this text body.
*
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StringTextBody.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StringTextBody.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StringTextBody.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/StringTextBody.java
Sun Nov 30 14:43:10 2008
@@ -30,7 +30,7 @@
/**
* Text body backed by a <code>String</code>.
*/
-class StringTextBody extends AbstractBody implements TextBody {
+class StringTextBody extends SingleBody implements TextBody {
private final String text;
private final Charset charset;
@@ -71,4 +71,9 @@
writer.flush();
}
+ @Override
+ public StringTextBody copy() {
+ return new StringTextBody(text, charset);
+ }
+
}
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/storage/MultiReferenceStorage.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/storage/MultiReferenceStorage.java?rev=721917&view=auto
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/storage/MultiReferenceStorage.java
(added)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/storage/MultiReferenceStorage.java
Sun Nov 30 14:43:10 2008
@@ -0,0 +1,103 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message.storage;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * <p>A wrapper around another [EMAIL PROTECTED] Storage} that also maintains
a reference
+ * counter. The inner storage gets deleted only if the reference counter
reaches
+ * zero.</p>
+ * <p>Reference counting is used to delete the storage when it is no longer
needed.
+ * So, any users of this class should note:
+ * </p>
+ * <ul>
+ * <li>The reference count is set up one on construction. In all other cases,
+ * [EMAIL PROTECTED] #addReference()} should be called when the storage is
shared.</li>
+ * <li>The caller of [EMAIL PROTECTED] #addReference()} should ensure that {@
+ * link #delete()} is called once and only once.</li>
+ * <li>Sharing the [EMAIL PROTECTED] Storage} instance passed into [EMAIL
PROTECTED] #MultiReferenceStorage(Storage)}
+ * may lead to miscounting and premature deletion</li>
+ * </ul>
+ */
+public class MultiReferenceStorage implements Storage {
+
+ private final Storage storage;
+ private int referenceCounter;
+
+ /**
+ * Creates a new <code>MultiReferenceStorage</code> instance for the given
+ * back-end. The reference counter is initially set to one so the caller
+ * does not have to call [EMAIL PROTECTED] #addReference()} after this
constructor.
+ *
+ * @param storage
+ * storage back-end that should be reference counted.
+ */
+ 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 synchronized void addReference() {
+ if (referenceCounter == 0)
+ throw new IllegalStateException("storage has been deleted");
+
+ referenceCounter++;
+ }
+
+ /**
+ * Decrements the reference counter and deletes the inner
+ * <code>Storage</code> object if the reference counter reaches zero.
+ * <p>
+ * A client that holds a reference to this object must make sure not to
+ * invoke this method a second time.
+ */
+ public synchronized void delete() {
+ if (referenceCounter == 0)
+ return;
+
+ referenceCounter--;
+
+ if (referenceCounter == 0) {
+ storage.delete();
+ }
+ }
+
+ /**
+ * Returns the input stream of the inner <code>Storage</code> object.
+ *
+ * @return an input stream.
+ */
+ public InputStream getInputStream() throws IOException {
+ return storage.getInputStream();
+ }
+
+}
Modified:
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java?rev=721917&r1=721916&r2=721917&view=diff
==============================================================================
---
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java
(original)
+++
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java
Sun Nov 30 14:43:10 2008
@@ -212,7 +212,7 @@
return complete.toString().getBytes();
}
- private static final class DummyBody extends AbstractBody {
+ private static final class DummyBody extends SingleBody {
public boolean disposed = false;
Added:
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/SingleBodyCopyTest.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/SingleBodyCopyTest.java?rev=721917&view=auto
==============================================================================
---
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/SingleBodyCopyTest.java
(added)
+++
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/SingleBodyCopyTest.java
Sun Nov 30 14:43:10 2008
@@ -0,0 +1,129 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mime4j.message.storage.MemoryStorageProvider;
+import org.apache.james.mime4j.message.storage.MultiReferenceStorage;
+import org.apache.james.mime4j.message.storage.Storage;
+import org.apache.james.mime4j.util.MessageUtils;
+
+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,
+ MessageUtils.ASCII);
+ copyTest(body);
+ }
+
+ public void testCopyStringTextBody() throws Exception {
+ SingleBody body = new StringTextBody("test", MessageUtils.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,
+ MessageUtils.ASCII);
+ disposeTest(body, storage);
+ }
+
+ private void copyTest(SingleBody body) throws Exception {
+ Message parent = new Message();
+ 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, Mode.STRICT_ERROR);
+ byte[] expected = expBaos.toByteArray();
+
+ ByteArrayOutputStream actBaos = new ByteArrayOutputStream();
+ actualBody.writeTo(actBaos, Mode.STRICT_ERROR);
+ 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;
+ }
+ }
+
+}
Added:
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/storage/MultiReferenceStorageTest.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/storage/MultiReferenceStorageTest.java?rev=721917&view=auto
==============================================================================
---
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/storage/MultiReferenceStorageTest.java
(added)
+++
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/storage/MultiReferenceStorageTest.java
Sun Nov 30 14:43:10 2008
@@ -0,0 +1,107 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mime4j.message.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;
+ }
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]