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.http;
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.httpclient.methods.GetMethod;
25  import org.apache.commons.vfs2.FileSystemException;
26  import org.apache.commons.vfs2.provider.AbstractRandomAccessStreamContent;
27  import org.apache.commons.vfs2.util.MonitorInputStream;
28  import org.apache.commons.vfs2.util.RandomAccessMode;
29  
30  /**
31   * RandomAccess content using HTTP.
32   */
33  final class HttpRandomAccessContent<FS extends HttpFileSystem> extends AbstractRandomAccessStreamContent {
34  
35      protected long filePointer;
36  
37      private final HttpFileObject<FS> fileObject;
38      private final HttpFileSystem fileSystem;
39  
40      private DataInputStream dataInputStream;
41      private MonitorInputStream monitorInputStream;
42  
43      HttpRandomAccessContent(final HttpFileObject<FS> fileObject, final RandomAccessMode mode) {
44          super(mode);
45  
46          this.fileObject = fileObject;
47          fileSystem = (HttpFileSystem) this.fileObject.getFileSystem();
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 GetMethod getMethod = new GetMethod();
66          fileObject.setupMethod(getMethod);
67          getMethod.setRequestHeader("Range", "bytes=" + filePointer + "-");
68          final int status = fileSystem.getClient().executeMethod(getMethod);
69          if (status != HttpURLConnection.HTTP_PARTIAL && status != HttpURLConnection.HTTP_OK) {
70              throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
71                      Long.valueOf(filePointer), Integer.valueOf(status));
72          }
73  
74          monitorInputStream = new HttpFileObject.HttpInputStream(getMethod);
75          // If the range request was ignored
76          if (status == HttpURLConnection.HTTP_OK) {
77              final long skipped = monitorInputStream.skip(filePointer);
78              if (skipped != filePointer) {
79                  throw new FileSystemException("vfs.provider.http/get-range.error", fileObject.getName(),
80                          Long.valueOf(filePointer), Integer.valueOf(status));
81              }
82          }
83          dataInputStream = new DataInputStream(new FilterInputStream(monitorInputStream) {
84              @Override
85              public int read() throws IOException {
86                  final int ret = super.read();
87                  if (ret > -1) {
88                      filePointer++;
89                  }
90                  return ret;
91              }
92  
93              @Override
94              public int read(final byte[] b) throws IOException {
95                  final int ret = super.read(b);
96                  if (ret > -1) {
97                      filePointer += ret;
98                  }
99                  return ret;
100             }
101 
102             @Override
103             public int read(final byte[] b, final int off, final int len) throws IOException {
104                 final int ret = super.read(b, off, len);
105                 if (ret > -1) {
106                     filePointer += ret;
107                 }
108                 return ret;
109             }
110         });
111 
112         return dataInputStream;
113     }
114 
115     @Override
116     public long getFilePointer() throws IOException {
117         return filePointer;
118     }
119 
120     @Override
121     public long length() throws IOException {
122         return fileObject.getContent().getSize();
123     }
124 
125     @Override
126     public void seek(final long pos) throws IOException {
127         if (pos == filePointer) {
128             // no change
129             return;
130         }
131 
132         if (pos < 0) {
133             throw new FileSystemException("vfs.provider/random-access-invalid-position.error", Long.valueOf(pos));
134         }
135         if (dataInputStream != null) {
136             close();
137         }
138 
139         filePointer = pos;
140     }
141 }