Implement destroy() for all ImapElement classes.

- This is to make sure we're not touching any ImapResponse that's
  already been destroyed.

- I didn't add "is it already destroyed?" check to them
  (except for ImapTempFileLiteral), because it can be costly.
  Just let NPE be thrown.

Change-Id: Idc7b88c4844727922841cbad8a106bf781181d45
This commit is contained in:
Makoto Onuki 2010-06-01 13:13:52 -07:00
parent 977a7d206a
commit 0fd444b0b4
6 changed files with 57 additions and 16 deletions

View File

@ -48,6 +48,11 @@ public abstract class ImapElement {
* is out of range.
*/
public static final ImapElement NONE = new ImapElement() {
@Override public void destroy() {
// Don't call super.destroy().
// It's a shared object. We don't want the mDestroyed to be set on this.
}
@Override public boolean isList() {
return false;
}
@ -66,15 +71,31 @@ public abstract class ImapElement {
}
};
private boolean mDestroyed = false;
public abstract boolean isList();
public abstract boolean isString();
protected boolean isDestroyed() {
return mDestroyed;
}
/**
* Clean up the resources used by the instance.
* It's for removing a temp file used by {@link ImapTempFileLiteral}.
*/
public void destroy() {
mDestroyed = true;
}
/**
* Throws {@link RuntimeException} if it's already destroyed.
*/
protected final void checkNotDestroyed() {
if (mDestroyed) {
throw new RuntimeException("Already destroyed");
}
}
/**

View File

@ -26,12 +26,17 @@ public class ImapList extends ImapElement {
* {@link ImapList} representing an empty list.
*/
public static final ImapList EMPTY = new ImapList() {
@Override public void destroy() {
// Don't call super.destroy().
// It's a shared object. We don't want the mDestroyed to be set on this.
}
@Override void add(ImapElement e) {
throw new RuntimeException();
}
};
private final ArrayList<ImapElement> mList = new ArrayList<ImapElement>();
private ArrayList<ImapElement> mList = new ArrayList<ImapElement>();
/* package */ void add(ImapElement e) {
if (e == null) {
@ -164,9 +169,13 @@ public class ImapList extends ImapElement {
@Override
public void destroy() {
for (ImapElement e : mList) {
e.destroy();
if (mList != null) {
for (ImapElement e : mList) {
e.destroy();
}
mList = null;
}
super.destroy();
}
@Override

View File

@ -30,7 +30,7 @@ import java.io.InputStream;
* Subclass of {@link ImapString} used for literals backed by an in-memory byte array.
*/
public class ImapMemoryLiteral extends ImapString {
private final byte[] mData;
private byte[] mData;
/* package */ ImapMemoryLiteral(FixedLengthInputStream in) throws IOException {
// We could use ByteArrayOutputStream and IOUtils.copy, but it'd perform an unnecessary
@ -49,6 +49,12 @@ public class ImapMemoryLiteral extends ImapString {
}
}
@Override
public void destroy() {
mData = null;
super.destroy();
}
@Override
public String getString() {
return Utility.fromAscii(mData);

View File

@ -25,12 +25,18 @@ import java.io.InputStream;
* Subclass of {@link ImapString} used for non literals.
*/
public class ImapSimpleString extends ImapString {
private final String mString;
private String mString;
/* package */ ImapSimpleString(String string) {
mString = (string != null) ? string : "";
}
@Override
public void destroy() {
mString = null;
super.destroy();
}
@Override
public String getString() {
return mString;

View File

@ -38,6 +38,11 @@ public abstract class ImapString extends ImapElement {
private static final byte[] EMPTY_BYTES = new byte[0];
public static final ImapString EMPTY = new ImapString() {
@Override public void destroy() {
// Don't call super.destroy().
// It's a shared object. We don't want the mDestroyed to be set on this.
}
@Override public String getString() {
return "";
}

View File

@ -37,8 +37,6 @@ import java.io.OutputStream;
* Subclass of {@link ImapString} used for literals backed by a temp file.
*/
public class ImapTempFileLiteral extends ImapString {
private boolean mDestroyed = false;
/* package for test */ final File mFile;
/** Size is purely for toString() */
@ -71,12 +69,6 @@ public class ImapTempFileLiteral extends ImapString {
}
}
private void checkNotDestroyed() {
if (mDestroyed) {
throw new RuntimeException("Already destroyed");
}
}
@Override
public InputStream getAsStream() {
checkNotDestroyed();
@ -105,12 +97,14 @@ public class ImapTempFileLiteral extends ImapString {
@Override
public void destroy() {
try {
if (!mDestroyed && mFile.exists()) {
if (!isDestroyed() && mFile.exists()) {
mFile.delete();
}
} finally {
mDestroyed = true;
} catch (RuntimeException re) {
// Just log and ignore.
Log.w(Email.LOG_TAG, "Failed to remove temp file: " + re.getMessage());
}
super.destroy();
}
@Override