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

📄 rmsstorage.java

📁 手机邮箱撒的方式方式方式的
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*MujMail - Simple mail client for J2MECopyright (C) 2006 Nguyen Son Tung <n.sontung@gmail.com>Copyright (C) 2006 Martin Stefan <martin.stefan@centrum.cz>Copyright (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, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */package mujmail;import mujmail.util.Functions;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.util.Vector;import javax.microedition.rms.RecordStore;import mujmail.protocols.MailSender;import mujmail.connections.ConnectionInterface;import mujmail.ui.OKCancelDialog;import mujmail.util.Callback;import mujmail.util.StartupModes;/** * Implementation of {@link ContentStorage} that stores the content * in internal java rms database. *  * Uses class {@link MailDB} to store and load fragments of content * to the RMS database.  *  * Stores the content in more fragments - database records - basically  * each calling of method {@link RMSStorage#addToContent(String, boolean)}  * or {@link #addToContentRaw(byte[], boolean)} stores added content to new * database record. Each database record identified by recordID and is  * represented by class {@link RMSStoragePart} that contains this ID. * Note, that to reduce the number of records per one body part content, * it should be used method {@link ContentStorage#addToContentBuffered(String)} * instead of method {@link ContentStorage#addToContent(String)}. *  * Getting of maximum content from this storage loads the content from * maximum number of database records that can fits into memory. *  * Contains a field for file name of database where the content * is stored. The name of the database is determined when the content is * stored. * Note that for the sake of optimalization, the name of the database is * common for all database records storing the content. That means that * it is not possible to store one content in multiple databases. *  * Provides memory management functions. If the space in database is left * and user has enabled automatic memory management of body part databases, * tries to delete the content of old body parts in order to free the * space in the database and than it try to save the content again.  * It deletes only such such number of body parts that should be  * sufficient to save actual content.  * If automatic memory management of body part databases is not enabled, * discards saving the content and it shows the dialog to user in that  * the user can choose deleting of body parts. *  * @see MailDB *  * @author David Hauzar */public class RMSStorage extends ContentStorage {    /** Flag signals if we want to print debug prints */    private static final boolean DEBUG = false;    private RMSStorageParts rmsStorageParts;    private String DBFileName = null; /** The database in that is stored the content. */    private int numPartToGet = 0;    /** The storage part that will be used for storing next data. It is      * pre-allocated in order to the OutOfMemory exception would not be thrown     * while saving next content. */    private RMSStoragePart nextRMSStoragePart;        /**     * Represents all parts of the content.     */    private static class RMSStorageParts {        private final Vector storageParts = new Vector(1);        private final RMSStorage contentStorage;        /**         * Creates the instance that represents all parts of content.         * @param contentStorage the content storage that parts this object         *  represents.         */        public RMSStorageParts(RMSStorage contentStorage) {            this.contentStorage = contentStorage;        }                        /**         * Loads this storage parts from given input stream (rms database).         * @param inputStream the input stream that contains this storage parts.         * @throws java.lang.Exception         */        public void load(DataInputStream inputStream) throws Exception {            // load content part            int numberOfParts = inputStream.readInt();            for (int i = 0; i < numberOfParts; i++) {                RMSStoragePart storagePart = new RMSStoragePart(contentStorage);                storagePart.load(inputStream);                storageParts.addElement(storagePart);            }                    }                /**         * Saves this storage parts to given output stream (typically rms database).         * @param outputStream         * @throws java.lang.Exception         */        public void save(DataOutputStream outputStream) throws Exception {            outputStream.writeInt(storageParts.size());            for (int i = 0; i < storageParts.size(); i++) {                ((RMSStoragePart) storageParts.elementAt(i)).save(outputStream);            }        }                public void addStoragePart(RMSStoragePart storagePart) {            storageParts.addElement(storagePart);        }                /**         * Delete the content of all storage parts and deletes also this storage         * parts.         */        public void deleteContent() {            for (int i = 0; i < storageParts.size(); i++) {                ((RMSStoragePart) storageParts.elementAt(i)).deleteContent();            }            storageParts.removeAllElements();        }                /**         * Gets the number of storage parts.         * @return the number of storage parts.         */        public int getNumParts() {            return storageParts.size();        }                /**         * Gets given storage path.         * @param i the number of storage part to get.         * @return given storage path.         */        public RMSStoragePart getStoragePart(int i) {            return (RMSStoragePart) storageParts.elementAt(i);        }            }        /**     * Represents one part of content stored in one record in RMS.     */    private static class RMSStoragePart {        private int recordID = -1;        private final RMSStorage contentStorage;        public RMSStoragePart(RMSStorage contentStorage) {            this.contentStorage = contentStorage;        }                  // TODO (Betlista): is it used somewhere ?        public RMSStoragePart(RMSStorage contentStorage, RMSStoragePart copy) {            this.contentStorage = contentStorage;            this.recordID = copy.recordID;        }                public int getRecordID() {            return recordID;        }                private BodyPart getBodyPart() {            return contentStorage.getBodyPart();        }                public String getContent() throws MyException {            return MailDB.loadFragmentOfBodypartContent(contentStorage.DBFileName, getRecordID());        }                public byte[] getContentRaw() throws MyException {           return MailDB.loadFragmentBodypartContentRaw(contentStorage.DBFileName, getRecordID());        }        /**         * Counts the size of bodypart that is saveable to the database.         * If there is not enough space in database, try to delete existing bodyparts         * from database.         * @param size         * @param safeMode         * @return         */        private int countSaveableSizeReleaseMemory(int size, boolean safeMode) throws Exception {            int spaceLeft = safeMode ? Functions.spaceLeft(MailDB.safeModeDBFile) : Functions.spaceLeft(getBodyPart().getBox().getDBFileName());            if (spaceLeft < size) { // we need more space            //if (getBodyPart().getMessageHeader().getBox().getStorage().getSize() >= 3) {                if (!safeMode) {                        // try to delete bodyparts of existing mails to free space in db                        handleProblemWithSavingBodyPart(size - spaceLeft);                }                if (spaceLeft < size) {                    //but the bodypart's format doesnt support shortening - can not be viewed if trimmed                    if (!MessageHeader.canBePartiallySaved(getBodyPart()) || spaceLeft <= 0) {                        return -1;                    }                    return spaceLeft;                }            }            return size;        }        /**         * Displays dialog askingto delete oldest bodyparts from database.         */        private static class DeleteOldestBodyparts implements Callback {            private final MessageHeader savingMessage;            private final long sizeToRelease;            public DeleteOldestBodyparts(MessageHeader savingMessage, long sizeToRelease) {                this.savingMessage = savingMessage;                this.sizeToRelease = sizeToRelease;            }            public void callback(Object called, Object message) {                savingMessage.getBox().deleteOldestBodyParts(sizeToRelease, savingMessage);            }                    }        /**         * Handles the problem with saving bodypart.         *         * This means that if Settings.deleteMailsBodyWhenBodyDBIsFull is true         * it deletes the content of oldest bodyparts to release memory and than         * tryes to save the bodypart again.         * If Settings.deleteMailsBodyWhenBodyDBIsFull is false, it displays the         * dialog to user and asks him if he want to delete headers. Than it         * cancels storing bodypart. That means that in this case it will be         * empty. TODO: it only marks bodypart as empty. Should it also delete it?         *         * @param sizeToRelease         * @return the amount of released space in database.         * @throws java.lang.Exception if it is not possible to save this         *  bodypart now. That means it makes no sence to repeate the action now.         */        private long handleProblemWithSavingBodyPart(long sizeToRelease) throws Exception {            if (Settings.deleteMailsBodyWhenBodyDBIsFull) {                return getBodyPart().getMessageHeader().getBox().deleteOldestBodyParts(sizeToRelease, getBodyPart().getMessageHeader());            } else {                OKCancelDialog dialog = new OKCancelDialog("Database is full",                        "The database is full. Do you want to delete body of oldest mails to release memory in database to be able to fit this bodypart?",                        new DeleteOldestBodyparts(getBodyPart().getMessageHeader(), sizeToRelease));                dialog.showScreen(StartupModes.IN_NEW_THREAD);                throw new MyException(MyException.DB_CANNOT_SAVE_BODY);            }        }                /**         * Saves given content to this storage part.         * If there is not enough space in database, shortens the content.         * @param content the content to be saved.         * @param safeMode         * @return the size of content that was really saved.         */        protected long saveContent(String content, boolean safeMode) throws Exception {            int saveable = countSaveableSizeReleaseMemory(Functions.getStringByteSize(content), safeMode);            if (saveable < Functions.getStringByteSize(content)) {                // TODO: there can occur OutOfMemoryException: handle better                content = content.substring(0, saveable);            }            try {                //throw new MyException(0);                saveContentToDB(content, safeMode);            } catch (MyException e) {                handleProblemWithSavingBodyPart(saveable);                saveContentToDB(content, safeMode);            }            return saveable;        }                /**         * Saves given content to this storage part.         * If there is not enough space in database, shortens the content.         * TODO: shortening content in case of binary data probably makes no sense!!         * @param content the content to be saved.         * @param safeMode         * @return the size of content that was really saved.         */        protected long saveContentRaw(byte[] content, boolean safeMode) throws Exception {            int saveable = countSaveableSizeReleaseMemory(content.length, safeMode);            byte [] decodedBodyBytes = null;            if (saveable < content.length) {                // TODO: there can occur OutOfMemoryException!!!! Handle it better.                decodedBodyBytes = new byte[saveable];                System.arraycopy(content, 0, decodedBodyBytes, 0, saveable);            }            try {                saveContentToDB(decodedBodyBytes, content, safeMode);            } catch (MyException e) {

⌨️ 快捷键说明

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