001 package railo.commons.io.res.type.http; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.net.URL; 006 007 import org.apache.commons.httpclient.Header; 008 import org.apache.commons.httpclient.HttpMethod; 009 010 import railo.commons.io.IOUtil; 011 import railo.commons.io.res.ContentType; 012 import railo.commons.io.res.Resource; 013 import railo.commons.io.res.ResourceProvider; 014 import railo.commons.io.res.util.ReadOnlyResourceSupport; 015 import railo.commons.io.res.util.ResourceUtil; 016 import railo.commons.lang.StringUtil; 017 import railo.commons.net.HTTPUtil; 018 import railo.runtime.net.proxy.ProxyData; 019 import railo.runtime.net.proxy.ProxyDataImpl; 020 import railo.runtime.op.Caster; 021 022 023 public class HTTPResource extends ReadOnlyResourceSupport { 024 025 private final HTTPResourceProvider provider; 026 private final HTTPConnectionData data; 027 private final String path; 028 private final String name; 029 private HttpMethod http; 030 031 032 public HTTPResource(HTTPResourceProvider provider, HTTPConnectionData data) { 033 this.provider=provider; 034 this.data=data; 035 036 String[] pathName=ResourceUtil.translatePathName(data.path); 037 this.path=pathName[0]; 038 this.name=pathName[1]; 039 040 } 041 042 private HttpMethod getHttpMethod(boolean create) throws IOException { 043 if(create || http==null) { 044 //URL url = HTTPUtil.toURL("http://"+data.host+":"+data.port+"/"+data.path); 045 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 046 // TODO Support for proxy 047 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 048 049 http = HTTPUtil.invoke(url, data.username, data.password, _getTimeout(),null, data.userAgent, 050 pd.getServer(), pd.getPort(),pd.getUsername(), pd.getPassword(), 051 null); 052 } 053 return http; 054 } 055 056 private int getStatusCode() throws IOException { 057 if(http==null) { 058 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 059 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 060 return HTTPUtil.head(url, data.username, data.password, _getTimeout(), 061 null, data.userAgent, 062 pd.getServer(), pd.getPort(),pd.getUsername(), pd.getPassword(), 063 null).getStatusCode(); 064 } 065 return http.getStatusCode(); 066 } 067 068 public ContentType getContentType() throws IOException { 069 if(http==null) { 070 URL url = new URL(provider.getProtocol(),data.host,data.port,data.path); 071 ProxyData pd=data.hasProxyData()?data.proxyData:ProxyDataImpl.NO_PROXY; 072 return HTTPUtil.getContentType(HTTPUtil.head(url, data.username, data.password, _getTimeout(), 073 null, data.userAgent, 074 pd.getServer(), pd.getPort(),pd.getUsername(), pd.getPassword(), 075 null)); 076 } 077 return HTTPUtil.getContentType(http); 078 } 079 080 081 082 public boolean exists() { 083 try { 084 provider.read(this); 085 int code = getStatusCode();//getHttpMethod().getStatusCode(); 086 return code!=404; 087 } 088 catch (IOException e) { 089 return false; 090 } 091 } 092 093 public int statusCode() { 094 try { 095 provider.read(this); 096 return getHttpMethod(false).getStatusCode(); 097 } catch (IOException e) { 098 return 0; 099 } 100 } 101 102 public InputStream getInputStream() throws IOException { 103 //ResourceUtil.checkGetInputStreamOK(this); 104 //provider.lock(this); 105 provider.read(this); 106 HttpMethod method = getHttpMethod(true); 107 try { 108 return IOUtil.toBufferedInputStream(method.getResponseBodyAsStream()); 109 } 110 catch (IOException e) { 111 //provider.unlock(this); 112 throw e; 113 } 114 } 115 116 /** 117 * @see railo.commons.io.res.Resource#getName() 118 */ 119 public String getName() { 120 return name; 121 } 122 123 /** 124 * @see railo.commons.io.res.Resource#getParent() 125 */ 126 public String getParent() { 127 if(isRoot()) return null; 128 return provider.getProtocol().concat("://").concat(data.key()).concat(path.substring(0,path.length()-1)); 129 } 130 131 private boolean isRoot() { 132 return StringUtil.isEmpty(name); 133 } 134 135 /** 136 * @see railo.commons.io.res.Resource#getParentResource() 137 */ 138 public Resource getParentResource() { 139 if(isRoot()) return null; 140 return new HTTPResource(provider, 141 new HTTPConnectionData(data.username,data.password,data.host,data.port,path,data.proxyData,data.userAgent)); 142 } 143 144 /** 145 * @see railo.commons.io.res.Resource#getPath() 146 */ 147 public String getPath() { 148 return provider.getProtocol().concat("://").concat(data.key()).concat(path).concat(name); 149 } 150 151 /** 152 * @see railo.commons.io.res.Resource#getRealResource(java.lang.String) 153 */ 154 public Resource getRealResource(String realpath) { 155 realpath=ResourceUtil.merge(path.concat(name), realpath); 156 if(realpath.startsWith("../"))return null; 157 return new HTTPResource(provider,new HTTPConnectionData(data.username,data.password,data.host,data.port,realpath,data.proxyData,data.userAgent)); 158 } 159 160 /** 161 * @see railo.commons.io.res.Resource#getResourceProvider() 162 */ 163 public ResourceProvider getResourceProvider() { 164 return provider; 165 } 166 167 /** 168 * @see railo.commons.io.res.Resource#isAbsolute() 169 */ 170 public boolean isAbsolute() { 171 return true; 172 } 173 174 /** 175 * @see railo.commons.io.res.Resource#isDirectory() 176 */ 177 public boolean isDirectory() { 178 return false; 179 } 180 181 /** 182 * @see railo.commons.io.res.Resource#isFile() 183 */ 184 public boolean isFile() { 185 return exists(); 186 } 187 188 /** 189 * @see railo.commons.io.res.Resource#isReadable() 190 */ 191 public boolean isReadable() { 192 return exists(); 193 } 194 195 public long lastModified() { 196 int last=0; 197 try { 198 Header cl=getHttpMethod(false).getResponseHeader("last-modified"); 199 if(cl!=null && exists()) last=Caster.toIntValue(cl.getValue(),0); 200 } 201 catch (IOException e) {} 202 return last; 203 } 204 205 public long length() { 206 try { 207 if(!exists()) return 0; 208 //Header content length 209 Header cl=getHttpMethod(false).getResponseHeader("content-length"); 210 if(cl!=null) { 211 int length=Caster.toIntValue(cl.getValue(),-1); 212 if(length!=-1) return length; 213 } 214 215 provider.read(this); 216 HttpMethod method = getHttpMethod(true); 217 InputStream is = method.getResponseBodyAsStream(); 218 byte[] buffer = new byte[1024]; 219 int len; 220 int length=0; 221 while((len = is.read(buffer)) !=-1){ 222 length+=len; 223 } 224 return length; 225 226 227 } catch (IOException e) { 228 return 0; 229 } 230 } 231 232 public Resource[] listResources() { 233 return null; 234 } 235 236 public void setProxyData(ProxyData pd) { 237 this.http=null; 238 this.data.setProxyData(pd); 239 } 240 241 public void setUserAgent(String userAgent) { 242 this.http=null; 243 this.data.userAgent=userAgent; 244 } 245 246 public void setTimeout(int timeout) { 247 this.http=null; 248 data.timeout=timeout; 249 } 250 251 252 private int _getTimeout() { 253 return data.timeout<provider.getSocketTimeout()?data.timeout:provider.getSocketTimeout(); 254 } 255 }