View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * 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.http2;
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  
30  /**
31   * Abstract Memory HttpData implementation
32   *
33   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
34   * @author Andy Taylor (andy.taylor@jboss.org)
35   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
36   * @author <a href="http://openr66.free.fr/">Frederic Bregier</a>
37   *
38   */
39  public abstract class AbstractMemoryHttpData extends AbstractHttpData implements HttpData {
40  
41      private ChannelBuffer channelBuffer = null;
42  
43      private int chunkPosition = 0;
44  
45      protected boolean isRenamed = false;
46  
47      public AbstractMemoryHttpData(String name, Charset charset, long size)
48              throws NullPointerException, IllegalArgumentException {
49          super(name, charset, size);
50      }
51  
52      public void setContent(ChannelBuffer buffer) throws IOException {
53          if (buffer == null) {
54              throw new NullPointerException("buffer");
55          }
56          long localsize = buffer.readableBytes();
57          if (definedSize > 0 && definedSize < localsize) {
58              throw new IOException("Out of size: " + localsize + " > " +
59                      definedSize);
60          }
61          channelBuffer = buffer;
62          size = localsize;
63          completed = true;
64      }
65  
66      public void setContent(InputStream inputStream) throws IOException {
67          if (inputStream == null) {
68              throw new NullPointerException("inputStream");
69          }
70          ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
71          byte[] bytes = new byte[4096*4];
72          int read = inputStream.read(bytes);
73          int written = 0;
74          while (read > 0) {
75              buffer.writeBytes(bytes);
76              written += read;
77              read = inputStream.read(bytes);
78          }
79          size = written;
80          if (definedSize > 0 && definedSize < size) {
81              throw new IOException("Out of size: " + size + " > " + definedSize);
82          }
83          channelBuffer = buffer;
84          completed = true;
85      }
86  
87      public void addContent(ChannelBuffer buffer, boolean last)
88              throws IOException {
89          if (buffer != null) {
90              long localsize = buffer.readableBytes();
91              if (definedSize > 0 && definedSize < size + localsize) {
92                  throw new IOException("Out of size: " + (size + localsize) +
93                          " > " + definedSize);
94              }
95              size += localsize;
96              if (channelBuffer == null) {
97                  channelBuffer = buffer;
98              } else {
99                  channelBuffer = ChannelBuffers.wrappedBuffer(
100                         channelBuffer, buffer);
101             }
102         }
103         if (last) {
104             completed = true;
105         } else {
106             if (buffer == null) {
107                 throw new NullPointerException("buffer");
108             }
109         }
110     }
111 
112     public void setContent(File file) throws IOException {
113         if (file == null) {
114             throw new NullPointerException("file");
115         }
116         long newsize = file.length();
117         if (newsize > Integer.MAX_VALUE) {
118             throw new IllegalArgumentException(
119                     "File too big to be loaded in memory");
120         }
121         FileInputStream inputStream = new FileInputStream(file);
122         FileChannel fileChannel = inputStream.getChannel();
123         byte[] array = new byte[(int) newsize];
124         ByteBuffer byteBuffer = ByteBuffer.wrap(array);
125         int read = 0;
126         while (read < newsize) {
127             read += fileChannel.read(byteBuffer);
128         }
129         fileChannel.close();
130         byteBuffer.flip();
131         channelBuffer = ChannelBuffers.wrappedBuffer(byteBuffer);
132         size = newsize;
133         completed = true;
134     }
135 
136     public void delete() {
137         // nothing to do
138     }
139 
140     public byte[] get() {
141         if (channelBuffer == null) {
142             return new byte[0];
143         }
144         byte[] array = new byte[channelBuffer.readableBytes()];
145         channelBuffer.getBytes(channelBuffer.readerIndex(), array);
146         return array;
147     }
148 
149     public String getString() {
150         return getString(HttpCodecUtil.DEFAULT_CHARSET);
151     }
152 
153     public String getString(Charset encoding) {
154         if (channelBuffer == null) {
155             return "";
156         }
157         if (encoding == null) {
158             return getString(HttpCodecUtil.DEFAULT_CHARSET);
159         }
160         return channelBuffer.toString(encoding);
161     }
162 
163     /**
164      * Utility to go from a In Memory FileUpload
165      * to a Disk (or another implementation) FileUpload
166      * @return the attached ChannelBuffer containing the actual bytes
167      */
168     public ChannelBuffer getChannelBuffer() {
169         return channelBuffer;
170     }
171 
172     public ChannelBuffer getChunk(int length) throws IOException {
173         if (channelBuffer == null || length == 0 || channelBuffer.readableBytes() == 0) {
174             chunkPosition = 0;
175             return ChannelBuffers.EMPTY_BUFFER;
176         }
177         int sizeLeft = channelBuffer.readableBytes() - chunkPosition;
178         if (sizeLeft == 0) {
179             chunkPosition = 0;
180             return ChannelBuffers.EMPTY_BUFFER;
181         }
182         int sliceLength = length;
183         if (sizeLeft < length) {
184             sliceLength = sizeLeft;
185         }
186         ChannelBuffer chunk = channelBuffer.slice(chunkPosition, sliceLength);
187         chunkPosition += sliceLength;
188         return chunk;
189     }
190 
191     public boolean isInMemory() {
192         return true;
193     }
194 
195     public boolean renameTo(File dest) throws IOException {
196         if (dest == null) {
197             throw new NullPointerException("dest");
198         }
199         if (channelBuffer == null) {
200             // empty file
201             dest.createNewFile();
202             isRenamed = true;
203             return true;
204         }
205         int length = channelBuffer.readableBytes();
206         FileOutputStream outputStream = new FileOutputStream(dest);
207         FileChannel fileChannel = outputStream.getChannel();
208         ByteBuffer byteBuffer = channelBuffer.toByteBuffer();
209         int written = 0;
210         while (written < length) {
211             written += fileChannel.write(byteBuffer);
212         }
213         fileChannel.force(false);
214         fileChannel.close();
215         isRenamed = true;
216         return written == length;
217     }
218 
219     public File getFile() throws IOException {
220         throw new IOException("Not represented by a file");
221     }
222 }