001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2.provider.http4; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.net.URI; 022 023import org.apache.commons.vfs2.FileContentInfoFactory; 024import org.apache.commons.vfs2.FileNotFoundException; 025import org.apache.commons.vfs2.FileSystemException; 026import org.apache.commons.vfs2.FileSystemOptions; 027import org.apache.commons.vfs2.FileType; 028import org.apache.commons.vfs2.RandomAccessContent; 029import org.apache.commons.vfs2.provider.AbstractFileName; 030import org.apache.commons.vfs2.provider.AbstractFileObject; 031import org.apache.commons.vfs2.provider.GenericURLFileName; 032import org.apache.commons.vfs2.util.RandomAccessMode; 033import org.apache.http.Header; 034import org.apache.http.HttpResponse; 035import org.apache.http.HttpStatus; 036import org.apache.http.client.HttpClient; 037import org.apache.http.client.methods.HttpGet; 038import org.apache.http.client.methods.HttpHead; 039import org.apache.http.client.methods.HttpUriRequest; 040import org.apache.http.client.protocol.HttpClientContext; 041import org.apache.http.client.utils.DateUtils; 042import org.apache.http.client.utils.URIUtils; 043import org.apache.http.protocol.HTTP; 044 045/** 046 * A file object backed by Apache HttpComponents HttpClient. 047 * 048 * @param <FS> An {@link Http4FileSystem} subclass 049 * @since 2.3 050 * @deprecated Use {@link org.apache.commons.vfs2.provider.http5}. 051 */ 052@Deprecated 053public class Http4FileObject<FS extends Http4FileSystem> extends AbstractFileObject<FS> { 054 055 /** 056 * URL charset string. 057 */ 058 private final String urlCharset; 059 060 /** 061 * Internal URI mapped to this {@code FileObject}. 062 * For example, the internal URI of {@code http4://example.com/a.txt} is {@code http://example.com/a.txt}. 063 */ 064 private final URI internalURI; 065 066 /** 067 * The last executed HEAD {@code HttpResponse} object. 068 */ 069 private HttpResponse lastHeadResponse; 070 071 /** 072 * Constructs {@code Http4FileObject}. 073 * 074 * @param name file name 075 * @param fileSystem file system 076 * @throws FileSystemException if any error occurs 077 */ 078 protected Http4FileObject(final AbstractFileName name, final FS fileSystem) 079 throws FileSystemException { 080 this(name, fileSystem, Http4FileSystemConfigBuilder.getInstance()); 081 } 082 083 /** 084 * Constructs {@code Http4FileObject}. 085 * 086 * @param name file name 087 * @param fileSystem file system 088 * @param builder {@code Http4FileSystemConfigBuilder} object 089 * @throws FileSystemException if any error occurs 090 */ 091 protected Http4FileObject(final AbstractFileName name, final FS fileSystem, 092 final Http4FileSystemConfigBuilder builder) throws FileSystemException { 093 super(name, fileSystem); 094 final FileSystemOptions fileSystemOptions = fileSystem.getFileSystemOptions(); 095 urlCharset = builder.getUrlCharset(fileSystemOptions); 096 final String pathEncoded = ((GenericURLFileName) name).getPathQueryEncoded(getUrlCharset()); 097 internalURI = URIUtils.resolve(fileSystem.getInternalBaseURI(), pathEncoded); 098 } 099 100 @Override 101 protected void doDetach() throws Exception { 102 lastHeadResponse = null; 103 } 104 105 @Override 106 protected long doGetContentSize() throws Exception { 107 if (lastHeadResponse == null) { 108 return 0L; 109 } 110 111 final Header header = lastHeadResponse.getFirstHeader(HTTP.CONTENT_LEN); 112 113 if (header == null) { 114 // Assume 0 content-length 115 return 0; 116 } 117 118 return Long.parseLong(header.getValue()); 119 } 120 121 @Override 122 protected InputStream doGetInputStream(final int bufferSize) throws Exception { 123 final HttpGet getRequest = new HttpGet(getInternalURI()); 124 final HttpResponse httpResponse = executeHttpUriRequest(getRequest); 125 final int status = httpResponse.getStatusLine().getStatusCode(); 126 127 if (status == HttpStatus.SC_NOT_FOUND) { 128 throw new FileNotFoundException(getName()); 129 } 130 131 if (status != HttpStatus.SC_OK) { 132 throw new FileSystemException("vfs.provider.http/get.error", getName(), Integer.valueOf(status)); 133 } 134 135 return new MonitoredHttpResponseContentInputStream(httpResponse, bufferSize); 136 } 137 138 @Override 139 protected long doGetLastModifiedTime() throws Exception { 140 FileSystemException.requireNonNull(lastHeadResponse, "vfs.provider.http/last-modified.error", getName()); 141 142 final Header header = lastHeadResponse.getFirstHeader("Last-Modified"); 143 144 FileSystemException.requireNonNull(header, "vfs.provider.http/last-modified.error", getName()); 145 146 return DateUtils.parseDate(header.getValue()).getTime(); 147 } 148 149 @Override 150 protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception { 151 return new Http4RandomAccessContent<>(this, mode); 152 } 153 154 @Override 155 protected FileType doGetType() throws Exception { 156 lastHeadResponse = executeHttpUriRequest(new HttpHead(getInternalURI())); 157 final int status = lastHeadResponse.getStatusLine().getStatusCode(); 158 159 if (status == HttpStatus.SC_OK 160 || status == HttpStatus.SC_METHOD_NOT_ALLOWED /* method is not allowed, but resource exist */) { 161 return FileType.FILE; 162 } 163 if (status == HttpStatus.SC_NOT_FOUND || status == HttpStatus.SC_GONE) { 164 return FileType.IMAGINARY; 165 } 166 throw new FileSystemException("vfs.provider.http/head.error", getName(), Integer.valueOf(status)); 167 } 168 169 @Override 170 protected boolean doIsWriteable() throws Exception { 171 return false; 172 } 173 174 @Override 175 protected String[] doListChildren() throws Exception { 176 throw new UnsupportedOperationException("Not implemented."); 177 } 178 179 /** 180 * Execute the request using the given {@code httpRequest} and return a {@code HttpResponse} from the execution. 181 * 182 * @param httpRequest {@code HttpUriRequest} object 183 * @return {@code HttpResponse} from the execution 184 * @throws IOException if IO error occurs 185 * @since 2.5.0 186 */ 187 protected HttpResponse executeHttpUriRequest(final HttpUriRequest httpRequest) throws IOException { 188 final HttpClient httpClient = getAbstractFileSystem().getHttpClient(); 189 final HttpClientContext httpClientContext = getAbstractFileSystem().getHttpClientContext(); 190 return httpClient.execute(httpRequest, httpClientContext); 191 } 192 193 @Override 194 protected FileContentInfoFactory getFileContentInfoFactory() { 195 return new Http4FileContentInfoFactory(); 196 } 197 198 /** 199 * Gets the internal {@code URI} object mapped to this file object. 200 * 201 * @return the internal {@code URI} object mapped to this file object 202 */ 203 protected URI getInternalURI() { 204 return internalURI; 205 } 206 207 /** 208 * Gets the last executed HEAD {@code HttpResponse} object. 209 * 210 * @return the last executed HEAD {@code HttpResponse} object 211 * @throws IOException if IO error occurs 212 */ 213 HttpResponse getLastHeadResponse() throws IOException { 214 if (lastHeadResponse != null) { 215 return lastHeadResponse; 216 } 217 218 return executeHttpUriRequest(new HttpHead(getInternalURI())); 219 } 220 221 /** 222 * Gets URL charset string. 223 * @return URL charset string 224 */ 225 protected String getUrlCharset() { 226 return urlCharset; 227 } 228 229}