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