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          checkSize(localsize);
50          if (definedSize > 0 && definedSize < localsize) {
51              throw new IOException("Out of size: " + localsize + " > " +
52                      definedSize);
53          }
54          channelBuffer = buffer;
55          size = localsize;
56          completed = true;
57      }
58  
59      public void setContent(InputStream inputStream) throws IOException {
60          if (inputStream == null) {
61              throw new NullPointerException("inputStream");
62          }
63          ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
64          byte[] bytes = new byte[4096 * 4];
65          int read = inputStream.read(bytes);
66          int written = 0;
67          while (read > 0) {
68              buffer.writeBytes(bytes, 0, read);
69              written += read;
70              checkSize(written);
71              read = inputStream.read(bytes);
72          }
73          size = written;
74          if (definedSize > 0 && definedSize < size) {
75              throw new IOException("Out of size: " + size + " > " + definedSize);
76          }
77          channelBuffer = buffer;
78          completed = true;
79      }
80  
81      public void addContent(ChannelBuffer buffer, boolean last)
82              throws IOException {
83          if (buffer != null) {
84              long localsize = buffer.readableBytes();
85              checkSize(size + localsize);
86              if (definedSize > 0 && definedSize < size + localsize) {
87                  throw new IOException("Out of size: " + (size + localsize) +
88                          " > " + definedSize);
89              }
90              size += localsize;
91              if (channelBuffer == null) {
92                  channelBuffer = buffer;
93              } else {
94                  channelBuffer = ChannelBuffers.wrappedBuffer(
95                          channelBuffer, buffer);
96              }
97          }
98          if (last) {
99              completed = true;
100         } else {
101             if (buffer == null) {
102                 throw new NullPointerException("buffer");
103             }
104         }
105     }
106 
107     public void setContent(File file) throws IOException {
108         if (file == null) {
109             throw new NullPointerException("file");
110         }
111         long newsize = file.length();
112         if (newsize > Integer.MAX_VALUE) {
113             throw new IllegalArgumentException(
114                     "File too big to be loaded in memory");
115         }
116         checkSize(newsize);
117         FileInputStream inputStream = new FileInputStream(file);
118         FileChannel fileChannel = inputStream.getChannel();
119         byte[] array = new byte[(int) newsize];
120         ByteBuffer byteBuffer = ByteBuffer.wrap(array);
121         int read = 0;
122         while (read < newsize) {
123             read += fileChannel.read(byteBuffer);
124         }
125         fileChannel.close();
126         inputStream.close();
127         byteBuffer.flip();
128         channelBuffer = ChannelBuffers.wrappedBuffer(byteBuffer);
129         size = newsize;
130         completed = true;
131     }
132 
133     public void delete() {
134         // nothing to do
135     }
136 
137     public byte[] get() {
138         if (channelBuffer == null) {
139             return new byte[0];
140         }
141         byte[] array = new byte[channelBuffer.readableBytes()];
142         channelBuffer.getBytes(channelBuffer.readerIndex(), array);
143         return array;
144     }
145 
146     public String getString() {
147         return getString(HttpConstants.DEFAULT_CHARSET);
148     }
149 
150     public String getString(Charset encoding) {
151         if (channelBuffer == null) {
152             return "";
153         }
154         if (encoding == null) {
155             encoding = HttpConstants.DEFAULT_CHARSET;
156         }
157         return channelBuffer.toString(encoding);
158     }
159 
160     /**
161      * Utility to go from a In Memory FileUpload
162      * to a Disk (or another implementation) FileUpload
163      * @return the attached ChannelBuffer containing the actual bytes
164      */
165     public ChannelBuffer getChannelBuffer() {
166         return channelBuffer;
167     }
168 
169     public ChannelBuffer getChunk(int length) throws IOException {
170         if (channelBuffer == null || length == 0 || channelBuffer.readableBytes() == 0) {
171             chunkPosition = 0;
172             return ChannelBuffers.EMPTY_BUFFER;
173         }
174         int sizeLeft = channelBuffer.readableBytes() - chunkPosition;
175         if (sizeLeft == 0) {
176             chunkPosition = 0;
177             return ChannelBuffers.EMPTY_BUFFER;
178         }
179         int sliceLength = length;
180         if (sizeLeft < length) {
181             sliceLength = sizeLeft;
182         }
183         ChannelBuffer chunk = channelBuffer.slice(chunkPosition, sliceLength);
184         chunkPosition += sliceLength;
185         return chunk;
186     }
187 
188     public boolean isInMemory() {
189         return true;
190     }
191 
192     public boolean renameTo(File dest) throws IOException {
193         if (dest == null) {
194             throw new NullPointerException("dest");
195         }
196         if (channelBuffer == null) {
197             // empty file
198             dest.createNewFile();
199             isRenamed = true;
200             return true;
201         }
202         int length = channelBuffer.readableBytes();
203         FileOutputStream outputStream = new FileOutputStream(dest);
204         FileChannel fileChannel = outputStream.getChannel();
205         ByteBuffer byteBuffer = channelBuffer.toByteBuffer();
206         int written = 0;
207         while (written < length) {
208             written += fileChannel.write(byteBuffer);
209         }
210         fileChannel.force(false);
211         fileChannel.close();
212         outputStream.close();
213         isRenamed = true;
214         return written == length;
215     }
216 
217     public File getFile() throws IOException {
218         throw new IOException("Not represented by a file");
219     }
220 }