source: contrib/MailArchiver/sources/vendor/mime4j/custom/storage/src/main/java/org/apache/james/mime4j/storage/ThresholdStorageProvider.java @ 6785

Revision 6785, 5.5 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
1/****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one   *
3 * or more contributor license agreements.  See the NOTICE file *
4 * distributed with this work for additional information        *
5 * regarding copyright ownership.  The ASF licenses this file   *
6 * to you under the Apache License, Version 2.0 (the            *
7 * "License"); you may not use this file except in compliance   *
8 * with the License.  You may obtain a copy of the License at   *
9 *                                                              *
10 *   http://www.apache.org/licenses/LICENSE-2.0                 *
11 *                                                              *
12 * Unless required by applicable law or agreed to in writing,   *
13 * software distributed under the License is distributed on an  *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15 * KIND, either express or implied.  See the License for the    *
16 * specific language governing permissions and limitations      *
17 * under the License.                                           *
18 ****************************************************************/
19
20package org.apache.james.mime4j.storage;
21
22import java.io.ByteArrayInputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.SequenceInputStream;
26
27import org.apache.james.mime4j.util.ByteArrayBuffer;
28
29/**
30 * A {@link StorageProvider} that keeps small amounts of data in memory and
31 * writes the remainder to another <code>StorageProvider</code> (the back-end)
32 * if a certain threshold size gets exceeded.
33 * <p>
34 * Example usage:
35 *
36 * <pre>
37 * StorageProvider tempStore = new TempFileStorageProvider();
38 * StorageProvider provider = new ThresholdStorageProvider(tempStore, 4096);
39 * DefaultStorageProvider.setInstance(provider);
40 * </pre>
41 */
42public class ThresholdStorageProvider extends AbstractStorageProvider {
43
44    private final StorageProvider backend;
45    private final int thresholdSize;
46
47    /**
48     * Creates a new <code>ThresholdStorageProvider</code> for the given
49     * back-end using a threshold size of 2048 bytes.
50     */
51    public ThresholdStorageProvider(StorageProvider backend) {
52        this(backend, 2048);
53    }
54
55    /**
56     * Creates a new <code>ThresholdStorageProvider</code> for the given
57     * back-end and threshold size.
58     *
59     * @param backend
60     *            used to store the remainder of the data if the threshold size
61     *            gets exceeded.
62     * @param thresholdSize
63     *            determines how much bytes are kept in memory before that
64     *            back-end storage provider is used to store the remainder of
65     *            the data.
66     */
67    public ThresholdStorageProvider(StorageProvider backend, int thresholdSize) {
68        if (backend == null)
69            throw new IllegalArgumentException();
70        if (thresholdSize < 1)
71            throw new IllegalArgumentException();
72
73        this.backend = backend;
74        this.thresholdSize = thresholdSize;
75    }
76
77    public StorageOutputStream createStorageOutputStream() {
78        return new ThresholdStorageOutputStream();
79    }
80
81    private final class ThresholdStorageOutputStream extends
82            StorageOutputStream {
83
84        private final ByteArrayBuffer head;
85        private StorageOutputStream tail;
86
87        public ThresholdStorageOutputStream() {
88            final int bufferSize = Math.min(thresholdSize, 1024);
89            head = new ByteArrayBuffer(bufferSize);
90        }
91
92        @Override
93        public void close() throws IOException {
94            super.close();
95
96            if (tail != null)
97                tail.close();
98        }
99
100        @Override
101        protected void write0(byte[] buffer, int offset, int length)
102                throws IOException {
103            int remainingHeadSize = thresholdSize - head.length();
104            if (remainingHeadSize > 0) {
105                int n = Math.min(remainingHeadSize, length);
106                head.append(buffer, offset, n);
107                offset += n;
108                length -= n;
109            }
110
111            if (length > 0) {
112                if (tail == null)
113                    tail = backend.createStorageOutputStream();
114
115                tail.write(buffer, offset, length);
116            }
117        }
118
119        @Override
120        protected Storage toStorage0() throws IOException {
121            if (tail == null)
122                return new MemoryStorageProvider.MemoryStorage(head.buffer(),
123                        head.length());
124
125            return new ThresholdStorage(head.buffer(), head.length(), tail
126                    .toStorage());
127        }
128
129    }
130
131    private static final class ThresholdStorage implements Storage {
132
133        private byte[] head;
134        private final int headLen;
135        private Storage tail;
136
137        public ThresholdStorage(byte[] head, int headLen, Storage tail) {
138            this.head = head;
139            this.headLen = headLen;
140            this.tail = tail;
141        }
142
143        public void delete() {
144            if (head != null) {
145                head = null;
146                tail.delete();
147                tail = null;
148            }
149        }
150
151        public InputStream getInputStream() throws IOException {
152            if (head == null)
153                throw new IllegalStateException("storage has been deleted");
154
155            InputStream headStream = new ByteArrayInputStream(head, 0, headLen);
156            InputStream tailStream = tail.getInputStream();
157            return new SequenceInputStream(headStream, tailStream);
158        }
159
160    }
161}
Note: See TracBrowser for help on using the repository browser.