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 java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.nio.ByteBuffer;
24  import java.nio.channels.FileChannel;
25  import java.nio.charset.Charset;
26  
27  import org.jboss.netty.buffer.ChannelBuffer;
28  import org.jboss.netty.buffer.ChannelBuffers;
29  import org.jboss.netty.handler.codec.http.HttpConstants;
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      public 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);
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         byteBuffer.flip();
123         channelBuffer = ChannelBuffers.wrappedBuffer(byteBuffer);
124         size = newsize;
125         completed = true;
126     }
127 
128     public void delete() {
129         // nothing to do
130     }
131 
132     public byte[] get() {
133         if (channelBuffer == null) {
134             return new byte[0];
135         }
136         byte[] array = new byte[channelBuffer.readableBytes()];
137         channelBuffer.getBytes(channelBuffer.readerIndex(), array);
138         return array;
139     }
140 
141     public String getString() {
142         return getString(HttpConstants.DEFAULT_CHARSET);
143     }
144 
145     public String getString(Charset encoding) {
146         if (channelBuffer == null) {
147             return "";
148         }
149         if (encoding == null) {
150             return getString(HttpConstants.DEFAULT_CHARSET);
151         }
152         return channelBuffer.toString(encoding);
153     }
154 
155     /**
156      * Utility to go from a In Memory FileUpload
157      * to a Disk (or another implementation) FileUpload
158      * @return the attached ChannelBuffer containing the actual bytes
159      */
160     public ChannelBuffer getChannelBuffer() {
161         return channelBuffer;
162     }
163 
164     public ChannelBuffer getChunk(int length) throws IOException {
165         if (channelBuffer == null || length == 0 || channelBuffer.readableBytes() == 0) {
166             chunkPosition = 0;
167             return ChannelBuffers.EMPTY_BUFFER;
168         }
169         int sizeLeft = channelBuffer.readableBytes() - chunkPosition;
170         if (sizeLeft == 0) {
171             chunkPosition = 0;
172             return ChannelBuffers.EMPTY_BUFFER;
173         }
174         int sliceLength = length;
175         if (sizeLeft < length) {
176             sliceLength = sizeLeft;
177         }
178         ChannelBuffer chunk = channelBuffer.slice(chunkPosition, sliceLength);
179         chunkPosition += sliceLength;
180         return chunk;
181     }
182 
183     public boolean isInMemory() {
184         return true;
185     }
186 
187     public boolean renameTo(File dest) throws IOException {
188         if (dest == null) {
189             throw new NullPointerException("dest");
190         }
191         if (channelBuffer == null) {
192             // empty file
193             dest.createNewFile();
194             isRenamed = true;
195             return true;
196         }
197         int length = channelBuffer.readableBytes();
198         FileOutputStream outputStream = new FileOutputStream(dest);
199         FileChannel fileChannel = outputStream.getChannel();
200         ByteBuffer byteBuffer = channelBuffer.toByteBuffer();
201         int written = 0;
202         while (written < length) {
203             written += fileChannel.write(byteBuffer);
204         }
205         fileChannel.force(false);
206         fileChannel.close();
207         isRenamed = true;
208         return written == length;
209     }
210 
211     public File getFile() throws IOException {
212         throw new IOException("Not represented by a file");
213     }
214 }