001    package railo.commons.io.res.type.s3;
002    
003    import java.io.IOException;
004    import java.util.Map;
005    
006    import railo.commons.io.res.Resource;
007    import railo.commons.io.res.ResourceLock;
008    import railo.commons.io.res.ResourceProvider;
009    import railo.commons.io.res.Resources;
010    import railo.commons.lang.StringUtil;
011    import railo.commons.lang.types.RefInteger;
012    import railo.commons.lang.types.RefIntegerImpl;
013    import railo.runtime.PageContext;
014    import railo.runtime.engine.ThreadLocalPageContext;
015    import railo.runtime.listener.ApplicationContextPro;
016    import railo.runtime.net.s3.Properties;
017    
018    public final class S3ResourceProvider implements ResourceProvider {
019            
020            
021            private int socketTimeout=-1;
022            private int lockTimeout=20000;
023            private int cache=20000;
024            private ResourceLock lock;
025            private String scheme="s3";
026            private Map arguments;
027    
028            
029    
030            
031            /**
032             * initalize ram resource
033             * @param scheme
034             * @param arguments
035             * @return RamResource
036             */
037            public ResourceProvider init(String scheme,Map arguments) {
038                    if(!StringUtil.isEmpty(scheme))this.scheme=scheme;
039                    
040                    if(arguments!=null) {
041                            this.arguments=arguments;
042                            // socket-timeout
043                            String strTimeout = (String) arguments.get("socket-timeout");
044                            if(strTimeout!=null) {
045                                    socketTimeout=toIntValue(strTimeout,socketTimeout);
046                            }
047                            // lock-timeout
048                            strTimeout=(String) arguments.get("lock-timeout");
049                            if(strTimeout!=null) {
050                                    lockTimeout=toIntValue(strTimeout,lockTimeout);
051                            }
052                            // cache
053                            String strCache=(String) arguments.get("cache");
054                            if(strCache!=null) {
055                                    cache=toIntValue(strCache,cache);
056                            }
057                    }
058                    
059                    return this;
060            }
061    
062            private int toIntValue(String str, int defaultValue) {
063                    try{
064                            return Integer.parseInt(str);
065                    }
066                    catch(Throwable t){
067                            return defaultValue;
068                    }
069            }
070    
071    
072            /**
073             * @see railo.commons.io.res.ResourceProvider#getScheme()
074             */
075            public String getScheme() {
076                    return scheme;
077            }
078            
079            public Resource getResource(String path) {
080                    path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path);
081                    S3 s3 = new S3();
082                    RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW);
083                    
084                    
085                    //path=loadWithOldPattern(s3,storage,path);
086                    path=loadWithNewPattern(s3,storage,path);
087                    
088                    return new S3Resource(s3,storage.toInt(),this,path,true);
089            }
090    
091            
092            public static String loadWithNewPattern(S3 s3,RefInteger storage, String path) {
093                    PageContext pc = ThreadLocalPageContext.get();
094                    Properties prop=null; 
095                    if(pc!=null){
096                            prop=((ApplicationContextPro)pc.getApplicationContext()).getS3();
097                    }
098                    if(prop==null) prop=new Properties();
099                    
100                    int defaultLocation = prop.getDefaultLocation();
101                    storage.setValue(defaultLocation);
102                    String accessKeyId = prop.getAccessKeyId();
103                    String secretAccessKey = prop.getSecretAccessKey();
104                    
105                    int atIndex=path.indexOf('@');
106                    int slashIndex=path.indexOf('/');
107                    if(slashIndex==-1){
108                            slashIndex=path.length();
109                            path+="/";
110                    }
111                    int index;
112                    
113                    // key/id
114                    if(atIndex!=-1) {
115                            index=path.indexOf(':');
116                            if(index!=-1 && index<atIndex) {
117                                    accessKeyId=path.substring(0,index);
118                                    secretAccessKey=path.substring(index+1,atIndex);
119                                    index=secretAccessKey.indexOf(':');
120                                    if(index!=-1) {
121                                            String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase();
122                                            secretAccessKey=secretAccessKey.substring(0,index);
123                                            //print.out("storage:"+strStorage);
124                                            storage.setValue(S3.toIntStorage(strStorage, defaultLocation));
125                                    }
126                            }
127                            else accessKeyId=path.substring(0,atIndex);
128                    }
129                    path=prettifyPath(path.substring(atIndex+1));
130                    index=path.indexOf('/');
131                    s3.setHost(prop.getHost());
132                    if(index==-1){
133                            if(path.equalsIgnoreCase(S3Constants.HOST) || path.equalsIgnoreCase(prop.getHost())){
134                                    s3.setHost(path);
135                                    path="/";
136                            }
137                    }
138                    else {
139                            String host=path.substring(0,index);
140                            if(host.equalsIgnoreCase(S3Constants.HOST) || host.equalsIgnoreCase(prop.getHost())){
141                                    s3.setHost(host);
142                                    path=path.substring(index);
143                            }
144                    }
145                    
146                    
147                    s3.setSecretAccessKey(secretAccessKey);
148                    s3.setAccessKeyId(accessKeyId);
149                    
150                    return path;
151            }
152    
153            /*public static void main(String[] args) {
154                    // s3://bucket/x/y/sample.txt
155                    // s3://accessKeyId:awsSecretKey@bucket/x/y/sample.txt
156                    String secretAccessKey="R/sOy3hgimrI8D9c0lFHchoivecnOZ8LyVmJpRFQ";
157                    String accessKeyId="1DHC5C5FVD7YEPR4DBG2";
158                    
159                    Properties prop=new Properties();
160                    prop.setAccessKeyId(accessKeyId);
161                    prop.setSecretAccessKey(secretAccessKey);
162                    
163                    
164                    test("s3://"+accessKeyId+":"+secretAccessKey+"@s3.amazonaws.com/dudi/peter.txt");
165                    test("s3://"+accessKeyId+":"+secretAccessKey+"@dudi/peter.txt");
166                    test("s3:///dudi/peter.txt");
167                    test("s3://dudi/peter.txt");
168                    
169                    
170            }
171            
172            
173            
174            private static void test(String path) {
175    
176                    Properties prop=new Properties();
177                    prop.setAccessKeyId("123456");
178                    prop.setSecretAccessKey("abcdefghji");
179                    
180                    
181                    
182                    String scheme="s3";
183                    path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path);
184                    S3 s3 = new S3();
185                    RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW);
186                    path=loadWithNewPattern(s3,prop,storage,path);
187                    
188    
189                    print.o(s3);
190                    print.o(path);
191            }*/
192    
193            private static String prettifyPath(String path) {
194                    path=path.replace('\\','/');
195                    return StringUtil.replace(path, "//", "/", false);
196                    // TODO /aaa/../bbb/
197            }
198            
199            
200            
201    
202            public static String loadWithOldPattern(S3 s3,RefInteger storage, String path) {
203                    
204                    
205                    String accessKeyId = null;
206                    String secretAccessKey = null;
207                    String host = null;
208                    //int port = 21;
209                    
210                    //print.out("raw:"+path);
211                    
212                    int atIndex=path.indexOf('@');
213                    int slashIndex=path.indexOf('/');
214                    if(slashIndex==-1){
215                            slashIndex=path.length();
216                            path+="/";
217                    }
218                    int index;
219                    
220                    // key/id
221                    if(atIndex!=-1) {
222                            index=path.indexOf(':');
223                            if(index!=-1 && index<atIndex) {
224                                    accessKeyId=path.substring(0,index);
225                                    secretAccessKey=path.substring(index+1,atIndex);
226                                    index=secretAccessKey.indexOf(':');
227                                    if(index!=-1) {
228                                            String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase();
229                                            secretAccessKey=secretAccessKey.substring(0,index);
230                                            //print.out("storage:"+strStorage);
231                                            storage.setValue(S3.toIntStorage(strStorage, S3.STORAGE_UNKNOW));
232                                    }
233                            }
234                            else accessKeyId=path.substring(0,atIndex);
235                    }
236                    path=prettifyPath(path.substring(atIndex+1));
237                    index=path.indexOf('/');
238                    if(index==-1){
239                            host=path;
240                            path="/";
241                    }
242                    else {
243                            host=path.substring(0,index);
244                            path=path.substring(index);
245                    }
246                    
247                    s3.setHost(host);
248                    s3.setSecretAccessKey(secretAccessKey);
249                    s3.setAccessKeyId(accessKeyId);
250                    
251                    return path;
252            }
253            /**
254             * @see railo.commons.io.res.ResourceProvider#isAttributesSupported()
255             */
256            public boolean isAttributesSupported() {
257                    return false;
258            }
259    
260            /**
261             * @see railo.commons.io.res.ResourceProvider#isCaseSensitive()
262             */
263            public boolean isCaseSensitive() {
264                    return true;
265            }
266    
267            /**
268             * @see railo.commons.io.res.ResourceProvider#isModeSupported()
269             */
270            public boolean isModeSupported() {
271                    return false;
272            }
273    
274            /**
275             * @see railo.commons.io.res.ResourceProvider#lock(railo.commons.io.res.Resource)
276             */
277            public void lock(Resource res) throws IOException {
278                    lock.lock(res);
279            }
280    
281            /**
282             * @see railo.commons.io.res.ResourceProvider#read(railo.commons.io.res.Resource)
283             */
284            public void read(Resource res) throws IOException {
285                    lock.read(res);
286            }
287    
288            public void setResources(Resources res) {
289                    lock=res.createResourceLock(lockTimeout,true);
290            }
291    
292            /**
293             * @see railo.commons.io.res.ResourceProvider#unlock(railo.commons.io.res.Resource)
294             */
295            public void unlock(Resource res) {
296                    lock.unlock(res);
297            }
298    
299            /**
300             * @return the socketTimeout
301             */
302            public int getSocketTimeout() {
303                    return socketTimeout;
304            }
305    
306            /**
307             * @return the lockTimeout
308             */
309            public int getLockTimeout() {
310                    return lockTimeout;
311            }
312    
313            /**
314             * @return the cache
315             */
316            public int getCache() {
317                    return cache;
318            }
319    
320            /**
321             * @see railo.commons.io.res.ResourceProvider#getArguments()
322             */
323            public Map getArguments() {
324                    return arguments;
325            }
326    
327            
328            
329    
330    }