View Javadoc

1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.handler.codec.http.multipart;
17  
18  import org.jboss.netty.buffer.ChannelBuffer;
19  import org.jboss.netty.buffer.ChannelBuffers;
20  import org.jboss.netty.handler.codec.http.HttpConstants;
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.nio.ByteBuffer;
28  import java.nio.channels.FileChannel;
29  import java.nio.charset.Charset;
30  
31  /**
32   * Abstract Memory HttpData implementation
33   */
34  public abstract class AbstractMemoryHttpData extends AbstractHttpData {
35  
36      private ChannelBuffer channelBuffer;
37      private int chunkPosition;
38      protected boolean isRenamed;
39  
40      protected AbstractMemoryHttpData(String name, Charset charset, long size) {
41          super(name, charset, size);
42      }
43  
44      public void setContent(ChannelBuffer buffer) throws IOException {
45          if (buffer == null) {
46              throw new NullPointerException("buffer");
47          }
48          long localsize = buffer.readableBytes();
49          if (definedSize > 0 && definedSize < localsize) {
50              throw new IOException("Out of size: " + localsize + " > " +
51                      definedSize);
52          }
53          channelBuffer = buffer;
54          size = localsize;
55          completed = true;
56      }
57  
58      public void setContent(InputStream inputStream) throws IOException {
59          if (inputStream == null) {
60              throw new NullPointerException("inputStream");
61          }
62          ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
63          byte[] bytes = new byte[4096 * 4];
64          int read = inputStream.read(bytes);
65          int written = 0;
66          while (read > 0) {
67              buffer.writeBytes(bytes, 0, read);
68              written += read;
69              read = inputStream.read(bytes);
70          }
71          size = written;
72          if (definedSize > 0 && definedSize < size) {
73              throw new IOException("Out of size: " + size + " > " + definedSize);
74          }
75          channelBuffer = buffer;
76          completed = true;
77      }
78  
79      public void addContent(ChannelBuffer buffer, boolean last)
80              throws IOException {
81          if (buffer != null) {
82              long localsize = buffer.readableBytes();
83              if (definedSize > 0 && definedSize < size + localsize) {
84                  throw new IOException("Out of size: " + (size + localsize) +
85                          " > " + definedSize);
86              }
87              size += localsize;
88              if (channelBuffer == null) {
89                  channelBuffer = buffer;
90              } else {
91                  channelBuffer = ChannelBuffers.wrappedBuffer(
92                          channelBuffer, buffer);
93              }
94          }
95          if (last) {
96              completed = true;
97          } else {
98              if (buffer == null) {
99                  throw new NullPointerException("buffer");
100             }
101         }
102     }
103 
104     public void setContent(File file) throws IOException {
105         if (file == null) {
106             throw new NullPointerException("file");
107         }
108         long newsize = file.length();
109         if (newsize > Integer.MAX_VALUE) {
110             throw new IllegalArgumentException(
111                     "File too big to be loaded in memory");
112         }
113         FileInputStream inputStream = new FileInputStream(file);
114         FileChannel fileChannel = inputStream.getChannel();
115         byte[] array = new byte[(int) newsize];
116         ByteBuffer byteBuffer = ByteBuffer.wrap(array);
117         int read = 0;
118         while (read < newsize) {
119             read += fileChannel.read(byteBuffer);
120         }
121         fileChannel.close();
122         inputStream.close();
123         byteBuffer.flip();
124         channelBuffer = ChannelBuffers.wrappedBuffer(byteBuffer);
125         size = newsize;
126         completed = true;
127     }
128 
129     public void delete() {
130         // nothing to do
131     }
132 
133     public byte[] get() {
134         if (channelBuffer == null) {
135             return new byte[0];
136         }
137         byte[] array = new byte[channelBuffer.readableBytes()];
138         channelBuffer.getBytes(channelBuffer.readerIndex(), array);
139         return array;
140     }
141 
142     public String getString() {
143         return getString(HttpConstants.DEFAULT_CHARSET);
144     }
145 
146     public String getString(Charset encoding) {
147         if (channelBuffer == null) {
148             return "";
149         }
150         if (encoding == null) {
151             encoding = HttpConstants.DEFAULT_CHARSET;
152         }
153         return channelBuffer.toString(encoding);
154     }
155 
156     /**
157      * Utility to go from a In Memory FileUpload
158      * to a Disk (or another implementation) FileUpload
159      * @return the attached ChannelBuffer containing the actual bytes
160      */
161     public ChannelBuffer getChannelBuffer() {
162         return channelBuffer;
163     }
164 
165     public ChannelBuffer getChunk(int length) throws IOException {
166         if (channelBuffer == null || length == 0 || channelBuffer.readableBytes() == 0) {
167             chunkPosition = 0;
168             return ChannelBuffers.EMPTY_BUFFER;
169         }
170         int sizeLeft = channelBuffer.readableBytes() - chunkPosition;
171         if (sizeLeft == 0) {
172             chunkPosition = 0;
173             return ChannelBuffers.EMPTY_BUFFER;
174         }
175         int sliceLength = length;
176         if (sizeLeft < length) {
177             sliceLength = sizeLeft;
178         }
179         ChannelBuffer chunk = channelBuffer.slice(chunkPosition, sliceLength);
180         chunkPosition += sliceLength;
181         return chunk;
182     }
183 
184     public boolean isInMemory() {
185         return true;
186     }
187 
188     public boolean renameTo(File dest) throws IOException {
189         if (dest == null) {
190             throw new NullPointerException("dest");
191         }
192         if (channelBuffer == null) {
193             // empty file
194             dest.createNewFile();
195             isRenamed = true;
196             return true;
197         }
198         int length = channelBuffer.readableBytes();
199         FileOutputStream outputStream = new FileOutputStream(dest);
200         FileChannel fileChannel = outputStream.getChannel();
201         ByteBuffer byteBuffer = channelBuffer.toByteBuffer();
202         int written = 0;
203         while (written < length) {
204             written += fileChannel.write(byteBuffer);
205         }
206         fileChannel.force(false);
207         fileChannel.close();
208         outputStream.close();
209         isRenamed = true;
210         return written == length;
211     }
212 
213     public File getFile() throws IOException {
214         throw new IOException("Not represented by a file");
215     }
216 }