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 *
10
* http://www.apache.org/licenses/LICENSE-2.0 *
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
****************************************************************/
20
package org.apache.james.mime4j.storage;
22
import java.io.ByteArrayInputStream;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.SequenceInputStream;
27
import org.apache.james.mime4j.util.ByteArrayBuffer;
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.
37
* StorageProvider tempStore = new TempFileStorageProvider();
38
* StorageProvider provider = new ThresholdStorageProvider(tempStore, 4096);
39
* DefaultStorageProvider.setInstance(provider);
42
public class ThresholdStorageProvider extends AbstractStorageProvider {
44
private final StorageProvider backend;
45
private final int thresholdSize;
48
* Creates a new <code>ThresholdStorageProvider</code> for the given
49
* back-end using a threshold size of 2048 bytes.
51
public ThresholdStorageProvider(StorageProvider backend) {
56
* Creates a new <code>ThresholdStorageProvider</code> for the given
57
* back-end and threshold size.
60
* used to store the remainder of the data if the threshold size
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
67
public ThresholdStorageProvider(StorageProvider backend, int thresholdSize) {
69
throw new IllegalArgumentException();
70
if (thresholdSize < 1)
71
throw new IllegalArgumentException();
73
this.backend = backend;
74
this.thresholdSize = thresholdSize;
77
public StorageOutputStream createStorageOutputStream() {
78
return new ThresholdStorageOutputStream();
81
private final class ThresholdStorageOutputStream extends
84
private final ByteArrayBuffer head;
85
private StorageOutputStream tail;
87
public ThresholdStorageOutputStream() {
88
final int bufferSize = Math.min(thresholdSize, 1024);
89
head = new ByteArrayBuffer(bufferSize);
93
public void close() throws IOException {
101
protected void write0(byte[] buffer, int offset, int length)
103
int remainingHeadSize = thresholdSize - head.length();
104
if (remainingHeadSize > 0) {
105
int n = Math.min(remainingHeadSize, length);
106
head.append(buffer, offset, n);
113
tail = backend.createStorageOutputStream();
115
tail.write(buffer, offset, length);
120
protected Storage toStorage0() throws IOException {
122
return new MemoryStorageProvider.MemoryStorage(head.buffer(),
125
return new ThresholdStorage(head.buffer(), head.length(), tail
131
private static final class ThresholdStorage implements Storage {
134
private final int headLen;
135
private Storage tail;
137
public ThresholdStorage(byte[] head, int headLen, Storage tail) {
139
this.headLen = headLen;
143
public void delete() {
151
public InputStream getInputStream() throws IOException {
153
throw new IllegalStateException("storage has been deleted");
155
InputStream headStream = new ByteArrayInputStream(head, 0, headLen);
156
InputStream tailStream = tail.getInputStream();
157
return new SequenceInputStream(headStream, tailStream);