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.http5;
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.hc.client5.http.classic.methods.HttpGet;
29  import org.apache.hc.core5.http.ClassicHttpResponse;
30  
31  /**
32   * RandomAccess content using {@code Http5FileObject}.
33   *
34   * @param <FS> Type of HttpFileSystem.
35   */
36  final class Http5RandomAccessContent<FS extends Http5FileSystem> extends AbstractRandomAccessStreamContent {
37  
38      protected long filePointer;
39  
40      private final Http5FileObject<FS> fileObject;
41  
42      private DataInputStream dataInputStream;
43      private MonitorInputStream monitorInputStream;
44  
45      Http5RandomAccessContent(final Http5FileObject<FS> fileObject, final RandomAccessMode mode) {
46          super(mode);
47          this.fileObject = fileObject;
48      }
49  
50      @Override
51      public void close() throws IOException {
52          if (dataInputStream != null) {
53              dataInputStream.close();
54              dataInputStream = null;
55              monitorInputStream = null;
56          }
57      }
58  
59      @Override
60      protected DataInputStream getDataInputStream() throws IOException {
61          if (dataInputStream != null) {
62              return dataInputStream;
63          }
64  
65          final HttpGet httpGet = new HttpGet(fileObject.getInternalURI());
66          httpGet.setHeader("Range", "bytes=" + filePointer + "-");
67          final ClassicHttpResponse httpResponse = fileObject.executeHttpUriRequest(httpGet);
68          final int status = httpResponse.getCode();
69  
70          if (status != HttpURLConnection.HTTP_PARTIAL && status != HttpURLConnection.HTTP_OK) {
71              throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
72                      Long.valueOf(filePointer), Integer.valueOf(status));
73          }
74  
75          monitorInputStream = new MonitoredHttpResponseContentInputStream(httpResponse);
76  
77          // If the range request was ignored
78          if (status == HttpURLConnection.HTTP_OK) {
79              final long skipped = monitorInputStream.skip(filePointer);
80              if (skipped != filePointer) {
81                  throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
82                          Long.valueOf(filePointer), Integer.valueOf(status));
83              }
84          }
85  
86          dataInputStream = new DataInputStream(new FilterInputStream(monitorInputStream) {
87              @Override
88              public int read() throws IOException {
89                  final int ret = super.read();
90                  if (ret > -1) {
91                      filePointer++;
92                  }
93                  return ret;
94              }
95  
96              @Override
97              public int read(final byte[] b) throws IOException {
98                  final int ret = super.read(b);
99                  if (ret > -1) {
100                     filePointer += ret;
101                 }
102                 return ret;
103             }
104 
105             @Override
106             public int read(final byte[] b, final int off, final int len) throws IOException {
107                 final int ret = super.read(b, off, len);
108                 if (ret > -1) {
109                     filePointer += ret;
110                 }
111                 return ret;
112             }
113         });
114 
115         return dataInputStream;
116     }
117 
118     @Override
119     public long getFilePointer() throws IOException {
120         return filePointer;
121     }
122 
123     @Override
124     public long length() throws IOException {
125         return fileObject.getContent().getSize();
126     }
127 
128     @Override
129     public void seek(final long pos) throws IOException {
130         if (pos == filePointer) {
131             // no change
132             return;
133         }
134 
135         if (pos < 0) {
136             throw new FileSystemException("vfs.provider/random-access-invalid-position.error", Long.valueOf(pos));
137         }
138 
139         if (dataInputStream != null) {
140             close();
141         }
142 
143         filePointer = pos;
144     }
145 }