⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 contentstorage.java

📁 手机邮箱撒的方式方式方式的
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*MujMail - Simple mail client for J2MECopyright (C) 2008 David Hauzar <david.hauzar.mujmail@gmail.com>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, bufferContent to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */package mujmail;import mujmail.util.Decode;import mujmail.util.OutputBuffer;import mujmail.protocols.MailSender;import mujmail.connections.ConnectionInterface;import java.io.DataInputStream;import java.io.DataOutputStream;import mujmail.util.Functions;/** * Persistently stores the content of body part. Part of  * <code>BodyPart</code>. *   * It is possible to incrementally add the content to existing * content without keeping existent content in heap memory. This is  * important for example when reading the content from SMTP connection. *  * Provides methods for adding content to the storage, for * buffered adding content to the storage - this case the content * is stored when more content for storing is collected - as well * as methods for reading or deleting the content. * Than provides information about the content contained in this * storage.    *  * Object of this type is contained in object {@link BodyPart}. *  * This object is stored persistently in RMS database. It's loading * and saving does object of instance {@link BodyPart} that * contains this storage. *  * @author David Hauzar */public abstract class ContentStorage {    /** Flag signals if we want to print debug prints */    private static final boolean DEBUG = false;    public static final String SOURCE_FILE = "ContentStorage";    //private static final long MAX_SIZE_OF_BODYPART = Long.MAX_VALUE;    private long size = 0;    private BodyPart bodyPart;    private final BufferedContentAdder buffer = new BufferedContentAdder();        /**     *      * @param bodyPart the body part which content is stored in this storage     */    protected ContentStorage(BodyPart bodyPart){        this.bodyPart = bodyPart;    }        /**     * Gets the name of the bodypart which content this storage holds.     * @return the name of the bodypart that content this storage holds.     */    protected String getName() {        return bodyPart.getHeader().getName();    }    /**     *      * @param bodyPart the body part which content is stored in this storage     * @param size the size of the content stored in the storage     */    protected ContentStorage(BodyPart bodyPart, long size) {        this.bodyPart = bodyPart;        this.size = size;    }        /**     * It is important to lower the likelihood of throwing OutOfMemory exception     * while calling method addToContent or addToContentRaw. This means that     * allocating objects in these methods is undesirable. This method should     * preallocate objects needed in addToContent or addToContentRaw.     *      * It is ensured that this method will be called after saving the content      * to the storage and releasing the data kept in the buffer so it is     * unlikely to OutOfMemoryException to be thrown there.     */    protected abstract void preallocateToNextSaving();        /**     *      * @return true if the content is yet preallocated to next saving.     */    protected abstract boolean preallocatedToNextSaving();        /**     * Ensures that te objects are really preallocated before calling addToContent     * or addToContentRaw.     */    private void ensurePrealocating() {        if (!preallocatedToNextSaving()) {            preallocateToNextSaving();        }    }    /**     * Initialize class by copying another instance.     * If copyMode is DEEP_COPY copies the content.     * Note that if the mode is SHALLOW_COPY it the body part which content     * will is stored in this ContentStorage should be in the same box as original     * storage.     * @param bp the body part which content is stored in this storage     * @param copy AttachmentPart instance to copy     * @param copyMode defines copying mode     */    protected ContentStorage(BodyPart bodyPart, ContentStorage copy, CopyingModes copyMode) {        this.bodyPart = bodyPart;        if (copyMode == CopyingModes.NO_COPY) {            // the instance is yet created            return;        }        if (copyMode == CopyingModes.DEEP_COPY) {            addContent(copy, false);            return;        }    }        /**     * Creates new instance of storage of type identified with given     * number.     * @param storageTypeNumber the number which identify the storage type     *  of which we want to create an instance     * @return the storage of given type     */    public static ContentStorage createStorageInstance(BodyPart bodyPart, byte storageTypeNumber) {        //#ifdef MUJMAIL_FS        if (storageTypeNumber == StorageTypes.FS_STORAGE.getStorageTypeNumber()) {            return new FSStorage(bodyPart);        }        //#endif        if (storageTypeNumber == StorageTypes.RMS_STORAGE.getStorageTypeNumber()) {            return new RMSStorage(bodyPart);        }        throw new RuntimeException("not implemented storage type");    }    /**     * Gets the body part which content is stored in the storage.     * @return     */    protected BodyPart getBodyPart() { return bodyPart; }    /**     * Returns the storage type of given storage     * @return     */    public abstract StorageTypes getStorageType();    /**     * Returns new instance of storage which is copy of this instance     * of the storage.     * @return new instance of storage which is copy of this instance     */    public abstract ContentStorage copy(BodyPart bp, CopyingModes copyMode);    /**     * Checks whether it is allowed to make a copy of this instance with given     * copy mode.     * @param bp     * @param copyMode     */    protected boolean checkCopy(BodyPart bp, CopyingModes copyMode) {        if (copyMode == CopyingModes.SHALLOW_COPY && bp.getBox() != getBodyPart().getBox()) {            return false;        }        return true;    }    /**     * Loads information about this storage from input stream (of RMS database).     * Does not load the content of storage, loads only information about     * the storage.     * @param inputStream the input stream in which are stored information     *  about this storage.     * @throws java.lang.Exception can occur while reading inputStream     */    public void loadStorage(DataInputStream inputStream) throws Exception {        setSize( inputStream.readLong() );    }    /**     * Saves information about this storage to output stream (RMS database)     * Does not save the content of the storage, saves only information about     * this storage.     * @param outputStream the output stream to which the information about     *  this body part will be saved     * @throws java.lang.Exception can occur while writing to the outputStream     */    public void saveStorageHeader(DataOutputStream outputStream) throws Exception {        outputStream.writeLong(getSize());    }    /**     * Deletes the content of this bodypart.     */    public void deleteContent() {        setSize(0);        buffer.clearCache();        if (!bodyPart.convertedContentMode()) {             bodyPart.setBodyState(BodyPart.BS_EMPTY);        }                deleteContentFromStorage();    }        /**     * Deletes the content from storage. Called from method      * {@link #deleteContent()}}.     */    protected abstract void deleteContentFromStorage();    public void addContent(ContentStorage copy, boolean safeMode) {        // TODO: redefine this method in class RMS storage        // in case of RMS store it can be make too big records because         // getContent() or getContentRaw() returns not content from one record         // but from the maximum number of records that can be in RAM memory        try {            if (copy.isContentRaw()) {               addToContentEnsurePreallocating(copy.getContentRaw(), safeMode);               while (!copy.willReturnFirstContent()) {                   addToContentEnsurePreallocating(copy.getContentRaw(), safeMode);               }            } else {                addToContentEnsurePreallocating(copy.getContent(), safeMode);                while (!copy.willReturnFirstContent()) {                   addToContentEnsurePreallocating(copy.getContent(), safeMode);                }            }        } catch (Throwable e) {            getBodyPart().setBodyState(BodyPart.BS_EMPTY);            size = 0;            getBodyPart().getBox().report("+" + e.getMessage() + getBodyPart().getMessageHeader().getSubject(), SOURCE_FILE); //dont notice the user about the error        }    }        protected String conditionallyAppend(String appendTo, String append, boolean shouldAppend) {        if (shouldAppend) {            return appendTo + append;        } else {            return appendTo;        }    }        /**     * According to the encoding and charset of the bodypart that content this     * storage stores, decode given data.     * @param data the data to be decoded     * @return data decoded according to encoding and charset of the bodypart     *  that stores this storage.     * @throws mujmail.MyException     */    private String decodeNotRawBodypartData(String data) throws MyException {        if (bodyPart.getHeader().getEncoding() == BodyPart.ENC_BASE64) {            return Decode.decodeBase64(data, bodyPart.getHeader().getCharSet());        } else if (bodyPart.getHeader().getEncoding() == BodyPart.ENC_QUOTEDPRINTABLE) {            return Decode.decodeQuotedPrintable(data, bodyPart.getHeader().getCharSet());        } else if (bodyPart.getHeader().getEncoding() == BodyPart.ENC_8BIT || bodyPart.getHeader().getCharSet() != BodyPart.CH_NORMAL) { //8bit or not usascii            return Decode.decode8bitCharset(data, bodyPart.getHeader().getCharSet());        } else { // 7- bit charset 	            return data;        }    }        /**     * <p>     * Adds given string to the storage.     * Writes data not necessary immediately but only if bigger content for writing     * is collected.     * Note that it is necessary to call method {@link #flushBuffer()} to store data      * persistently before reading it.     * </p>     * <p>     * Stores it according to encoding of the body part which content this storage     * stores either as a raw data or as a text data.     * </p>     * @param bf the string which content store.     */    public void addToContentBuffered(String bf) throws Exception {        buffer.bufferContent(bf);    }        /**     * Adds given string to the storage.     * Writes immediately.     *      * Stores it according to encoding of the body part which content this storage     * stores either as a raw data or as a text data.     * @param bf the string which content store.     */    public void addToContent(String bf) throws Exception {        addToContentBuffered(bf);        flushBuffer();            }        /**     * Stores data written in a buffer persistently. The data can be stored in     * buffer when method addToContentBuffered is called.     * @throws java.lang.Exception     */    public void flushBuffer() throws Exception {        buffer.flush();    }    /**     * Returns true if the content stored in this storage is raw data.     * @return true if the content stored in this storage is raw data     */    public boolean isContentRaw() {        if (getBodyPart().convertedContentMode()) {            return true;        } else {            return (bodyPart.getHeader().getEncoding() == BodyPart.ENC_BASE64 &&                     bodyPart.getHeader().getCharSet() == BodyPart.CH_NORMAL) ?                         true :                         false;        }    }    /**     * Adds given string to the content of the bodypart.     * If passed content cannot be saved tries to shorten the content and     * save it partially.     *     * This method neither sets the size of the bodypart nor the state of the     * bodypart. This is done by methods inside class <code>ContentStorage<code/>     * that calls this method.     *      * This is a low-level method, saves bodypart always as a text data regardless     * of the body part header. More high level method is addToContent(String).     *     * Before calling this method, method {@link #ensurePrealocating} is always     * called.     *      * @param content the content of the bodypart     * @param safeMode if save mode is true, the content will be not saved     *  to new persistent storage, but to temporary one     * @return the size of content that was added to the content.     *  content.length if all the content was written.     */    protected abstract long addToContent(String content, boolean safeMode) throws Exception;    /**     * Checks whether the size of bydypart with added content would be less or     * equal than given limit.     * If the size of bodypart with added content and the bodypart is not      * partially savebale. If it is partially saveable, sets its state to      * <code>BodyPart.BS_PARTIAL</code>. Than, it throws and exception.     *     * @param sizeOfAdded the size of added content to bodypart     * @throws java.lang.Exception if the size of bodypart with added content     *  is bigger than the limit.     */    /*     * TODO: (David) this method is no more needed since the size of bodypart     * is now checked while downloading the mail.    private void checkSizeOfBodyPart(long sizeOfAdded) throws Exception {        if (getSize() + sizeOfAdded > MAX_SIZE_OF_BODYPART) {             if (!MessageHeader.canBePartiallySaved(getBodyPart())) {                deleteContent();            } else {                getBodyPart().setBodyState(BodyPart.BS_PARTIAL);            }            throw new Exception("The size of this bodypart is larger than given limit.");        }    }     */    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -