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    }