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
20
21
22 package org.apache.james.smtpserver;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26
27 /**
28 * Wraps an underlying input stream, limiting the allowable size
29 * of incoming data. The size limit is configured in the conf file,
30 * and when the limit is reached, a MessageSizeException is thrown.
31 */
32 public class SizeLimitedInputStream extends InputStream {
33 /**
34 * Maximum number of bytes to read.
35 */
36 private long maxmessagesize = 0;
37 /**
38 * Running total of bytes read from wrapped stream.
39 */
40 private long bytesread = 0;
41
42 /**
43 * InputStream that will be wrapped.
44 */
45 private InputStream in = null;
46
47 /**
48 * Constructor for the stream. Wraps an underlying stream.
49 * @param in InputStream to use as basis for new Stream.
50 * @param maxmessagesize Message size limit, in Kilobytes
51 */
52 public SizeLimitedInputStream(InputStream in, long maxmessagesize) {
53 this.in = in;
54 this.maxmessagesize = maxmessagesize;
55 }
56
57 /**
58 * Overrides the read method of InputStream to call the read() method of the
59 * wrapped input stream.
60 * @throws IOException Throws a MessageSizeException, which is a sub-type of IOException
61 * @return Returns the number of bytes read.
62 */
63 public int read(byte[] b, int off, int len) throws IOException {
64 int l = in.read(b, off, len);
65
66 bytesread += l;
67
68 if (maxmessagesize > 0 && bytesread > maxmessagesize) {
69 throw new MessageSizeException();
70 }
71
72 return l;
73 }
74
75 /**
76 * Overrides the read method of InputStream to call the read() method of the
77 * wrapped input stream.
78 * @throws IOException Throws a MessageSizeException, which is a sub-type of IOException.
79 * @return Returns the int character value of the byte read.
80 */
81 public int read() throws IOException {
82 if (maxmessagesize > 0 && bytesread <= maxmessagesize) {
83 bytesread++;
84 return in.read();
85 } else {
86 throw new MessageSizeException();
87 }
88 }
89 }