View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider.http4;
18  
19  import java.io.DataInputStream;
20  import java.io.FilterInputStream;
21  import java.io.IOException;
22  import java.net.HttpURLConnection;
23  
24  import org.apache.commons.vfs2.FileSystemException;
25  import org.apache.commons.vfs2.provider.AbstractRandomAccessStreamContent;
26  import org.apache.commons.vfs2.util.MonitorInputStream;
27  import org.apache.commons.vfs2.util.RandomAccessMode;
28  import org.apache.http.HttpResponse;
29  import org.apache.http.client.methods.HttpGet;
30  
31  /**
32   * RandomAccess content using <code>Http4FileObject</code>.
33   */
34  class Http4RandomAccessContent<FS extends Http4FileSystem> extends AbstractRandomAccessStreamContent {
35  
36      protected long filePointer = 0;
37  
38      private final Http4FileObject<FS> fileObject;
39  
40      private DataInputStream dis = null;
41      private MonitorInputStream mis = null;
42  
43      Http4RandomAccessContent(final Http4FileObject<FS> fileObject, final RandomAccessMode mode) {
44          super(mode);
45          this.fileObject = fileObject;
46      }
47  
48      @Override
49      public long getFilePointer() throws IOException {
50          return filePointer;
51      }
52  
53      @Override
54      public void seek(final long pos) throws IOException {
55          if (pos == filePointer) {
56              // no change
57              return;
58          }
59  
60          if (pos < 0) {
61              throw new FileSystemException("vfs.provider/random-access-invalid-position.error", Long.valueOf(pos));
62          }
63  
64          if (dis != null) {
65              close();
66          }
67  
68          filePointer = pos;
69      }
70  
71      @Override
72      protected DataInputStream getDataInputStream() throws IOException {
73          if (dis != null) {
74              return dis;
75          }
76  
77          final HttpGet httpGet = new HttpGet(fileObject.getInternalURI());
78          httpGet.setHeader("Range", "bytes=" + filePointer + "-");
79          final HttpResponse httpResponse = fileObject.executeHttpUriRequest(httpGet);
80          final int status = httpResponse.getStatusLine().getStatusCode();
81  
82          if (status != HttpURLConnection.HTTP_PARTIAL && status != HttpURLConnection.HTTP_OK) {
83              throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
84                      Long.valueOf(filePointer), Integer.valueOf(status));
85          }
86  
87          mis = new MonitoredHttpResponseContentInputStream(httpResponse);
88  
89          // If the range request was ignored
90          if (status == HttpURLConnection.HTTP_OK) {
91              final long skipped = mis.skip(filePointer);
92              if (skipped != filePointer) {
93                  throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
94                          Long.valueOf(filePointer), Integer.valueOf(status));
95              }
96          }
97  
98          dis = new DataInputStream(new FilterInputStream(mis) {
99              @Override
100             public int read() throws IOException {
101                 final int ret = super.read();
102                 if (ret > -1) {
103                     filePointer++;
104                 }
105                 return ret;
106             }
107 
108             @Override
109             public int read(final byte[] b) throws IOException {
110                 final int ret = super.read(b);
111                 if (ret > -1) {
112                     filePointer += ret;
113                 }
114                 return ret;
115             }
116 
117             @Override
118             public int read(final byte[] b, final int off, final int len) throws IOException {
119                 final int ret = super.read(b, off, len);
120                 if (ret > -1) {
121                     filePointer += ret;
122                 }
123                 return ret;
124             }
125         });
126 
127         return dis;
128     }
129 
130     @Override
131     public void close() throws IOException {
132         if (dis != null) {
133             dis.close();
134             dis = null;
135             mis = null;
136         }
137     }
138 
139     @Override
140     public long length() throws IOException {
141         return fileObject.getContent().getSize();
142     }
143 }