001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.io.res.type.http; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.net.URL; 024 025import lucee.commons.io.IOUtil; 026import lucee.commons.io.res.ContentType; 027import lucee.commons.io.res.Resource; 028import lucee.commons.io.res.ResourceProvider; 029import lucee.commons.io.res.util.ReadOnlyResourceSupport; 030import lucee.commons.io.res.util.ResourceUtil; 031import lucee.commons.lang.StringUtil; 032import lucee.commons.net.http.HTTPEngine; 033import lucee.commons.net.http.HTTPResponse; 034import lucee.commons.net.http.Header; 035import lucee.runtime.net.proxy.ProxyData; 036import lucee.runtime.net.proxy.ProxyDataImpl; 037import lucee.runtime.op.Caster; 038 039 040public class HTTPResource extends ReadOnlyResourceSupport { 041 042 private final HTTPResourceProvider provider; 043 private final HTTPConnectionData data; 044 private final String path; 045 private final String name; 046 private HTTPResponse http; 047 048 049 public HTTPResource(HTTPResourceProvider provider, HTTPConnectionData data) { 050 this.provider=provider; 051 this.data=data; 052 053 String[] pathName=ResourceUtil.translatePathName(data.path); 054 this.path=pathName[0]; 055 this.name=pathName[1]; 056 057 } 058 059 private HTTPResponse getHTTPResponse(boolean create) throws IOException { 060 if(create || http==null) { 061 //URL url = HTTPUtil.toURL("http://"+data.host+":"+data.port+"/"+data.path); 062 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 063 // TODO Support for proxy 064 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 065 066 http = HTTPEngine.get(url, data.username, data.password, _getTimeout(),HTTPEngine.MAX_REDIRECT,null, data.userAgent, 067 pd, 068 null); 069 } 070 return http; 071 } 072 073 private int getStatusCode() throws IOException { 074 if(http==null) { 075 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 076 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 077 return HTTPEngine.head(url, data.username, data.password, _getTimeout(),HTTPEngine.MAX_REDIRECT, 078 null, data.userAgent, 079 pd, 080 null).getStatusCode(); 081 } 082 return http.getStatusCode(); 083 } 084 085 public ContentType getContentType() throws IOException { 086 if(http==null) { 087 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 088 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 089 return HTTPEngine.head(url, data.username, data.password, _getTimeout(),HTTPEngine.MAX_REDIRECT, 090 null, data.userAgent, 091 pd, 092 null).getContentType(); 093 } 094 return http.getContentType(); 095 } 096 097 098 099 public boolean exists() { 100 try { 101 provider.read(this); 102 int code = getStatusCode();//getHttpMethod().getStatusCode(); 103 return code!=404; 104 } 105 catch (IOException e) { 106 return false; 107 } 108 } 109 110 public int statusCode() { 111 try { 112 provider.read(this); 113 return getHTTPResponse(false).getStatusCode(); 114 } catch (IOException e) { 115 return 0; 116 } 117 } 118 119 public InputStream getInputStream() throws IOException { 120 //ResourceUtil.checkGetInputStreamOK(this); 121 //provider.lock(this); 122 provider.read(this); 123 HTTPResponse method = getHTTPResponse(true); 124 try { 125 return IOUtil.toBufferedInputStream(method.getContentAsStream()); 126 } 127 catch (IOException e) { 128 //provider.unlock(this); 129 throw e; 130 } 131 } 132 133 @Override 134 public String getName() { 135 return name; 136 } 137 138 @Override 139 public String getParent() { 140 if(isRoot()) return null; 141 return provider.getProtocol().concat("://").concat(data.key()).concat(path.substring(0,path.length()-1)); 142 } 143 144 private boolean isRoot() { 145 return StringUtil.isEmpty(name); 146 } 147 148 @Override 149 public Resource getParentResource() { 150 if(isRoot()) return null; 151 return new HTTPResource(provider, 152 new HTTPConnectionData(data.username,data.password,data.host,data.port,path,data.proxyData,data.userAgent)); 153 } 154 155 @Override 156 public String getPath() { 157 return provider.getProtocol().concat("://").concat(data.key()).concat(path).concat(name); 158 } 159 160 @Override 161 public Resource getRealResource(String realpath) { 162 realpath=ResourceUtil.merge(path.concat(name), realpath); 163 if(realpath.startsWith("../"))return null; 164 return new HTTPResource(provider,new HTTPConnectionData(data.username,data.password,data.host,data.port,realpath,data.proxyData,data.userAgent)); 165 } 166 167 @Override 168 public ResourceProvider getResourceProvider() { 169 return provider; 170 } 171 172 @Override 173 public boolean isAbsolute() { 174 return true; 175 } 176 177 @Override 178 public boolean isDirectory() { 179 return false; 180 } 181 182 @Override 183 public boolean isFile() { 184 return exists(); 185 } 186 187 @Override 188 public boolean isReadable() { 189 return exists(); 190 } 191 192 public long lastModified() { 193 int last=0; 194 try { 195 Header cl=getHTTPResponse(false).getLastHeaderIgnoreCase("last-modified"); 196 if(cl!=null && exists()) last=Caster.toIntValue(cl.getValue(),0); 197 } 198 catch (IOException e) {} 199 return last; 200 } 201 202 public long length() { 203 try { 204 if(!exists()) return 0; 205 return getHTTPResponse(false).getContentLength(); 206 } 207 catch (IOException e) { 208 return 0; 209 } 210 } 211 212 public Resource[] listResources() { 213 return null; 214 } 215 216 public void setProxyData(ProxyData pd) { 217 this.http=null; 218 this.data.setProxyData(pd); 219 } 220 221 public void setUserAgent(String userAgent) { 222 this.http=null; 223 this.data.userAgent=userAgent; 224 } 225 226 public void setTimeout(int timeout) { 227 this.http=null; 228 data.timeout=timeout; 229 } 230 231 232 private int _getTimeout() { 233 return data.timeout<provider.getSocketTimeout()?data.timeout:provider.getSocketTimeout(); 234 } 235}