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.net.s3.Properties;
016    import railo.runtime.net.s3.PropertiesImpl;
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            @Override
073            public String getScheme() {
074                    return scheme;
075            }
076            
077            public Resource getResource(String path) {
078                    path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path);
079                    S3 s3 = new S3();
080                    RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW);
081                    
082                    
083                    //path=loadWithOldPattern(s3,storage,path);
084                    path=loadWithNewPattern(s3,storage,path);
085                    
086                    return new S3Resource(s3,storage.toInt(),this,path,true);
087            }
088    
089            
090            public static String loadWithNewPattern(S3 s3,RefInteger storage, String path) {
091                    PageContext pc = ThreadLocalPageContext.get();
092                    Properties prop=null; 
093                    if(pc!=null){
094                            prop=pc.getApplicationContext().getS3();
095                    }
096                    if(prop==null) prop=new PropertiesImpl();
097                    
098                    int defaultLocation = prop.getDefaultLocation();
099                    storage.setValue(defaultLocation);
100                    String accessKeyId = prop.getAccessKeyId();
101                    String secretAccessKey = prop.getSecretAccessKey();
102                    
103                    int atIndex=path.indexOf('@');
104                    int slashIndex=path.indexOf('/');
105                    if(slashIndex==-1){
106                            slashIndex=path.length();
107                            path+="/";
108                    }
109                    int index;
110                    
111                    // key/id
112                    if(atIndex!=-1) {
113                            index=path.indexOf(':');
114                            if(index!=-1 && index<atIndex) {
115                                    accessKeyId=path.substring(0,index);
116                                    secretAccessKey=path.substring(index+1,atIndex);
117                                    index=secretAccessKey.indexOf(':');
118                                    if(index!=-1) {
119                                            String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase();
120                                            secretAccessKey=secretAccessKey.substring(0,index);
121                                            //print.out("storage:"+strStorage);
122                                            storage.setValue(S3.toIntStorage(strStorage, defaultLocation));
123                                    }
124                            }
125                            else accessKeyId=path.substring(0,atIndex);
126                    }
127                    path=prettifyPath(path.substring(atIndex+1));
128                    index=path.indexOf('/');
129                    s3.setHost(prop.getHost());
130                    if(index==-1){
131                            if(path.equalsIgnoreCase(S3Constants.HOST) || path.equalsIgnoreCase(prop.getHost())){
132                                    s3.setHost(path);
133                                    path="/";
134                            }
135                    }
136                    else {
137                            String host=path.substring(0,index);
138                            if(host.equalsIgnoreCase(S3Constants.HOST) || host.equalsIgnoreCase(prop.getHost())){
139                                    s3.setHost(host);
140                                    path=path.substring(index);
141                            }
142                    }
143                    
144                    
145                    s3.setSecretAccessKey(secretAccessKey);
146                    s3.setAccessKeyId(accessKeyId);
147                    
148                    return path;
149            }
150    
151            /*public static void main(String[] args) {
152                    // s3://bucket/x/y/sample.txt
153                    // s3://accessKeyId:awsSecretKey@bucket/x/y/sample.txt
154                    String secretAccessKey="R/sOy3hgimrI8D9c0lFHchoivecnOZ8LyVmJpRFQ";
155                    String accessKeyId="1DHC5C5FVD7YEPR4DBG2";
156                    
157                    Properties prop=new Properties();
158                    prop.setAccessKeyId(accessKeyId);
159                    prop.setSecretAccessKey(secretAccessKey);
160                    
161                    
162                    test("s3://"+accessKeyId+":"+secretAccessKey+"@s3.amazonaws.com/dudi/peter.txt");
163                    test("s3://"+accessKeyId+":"+secretAccessKey+"@dudi/peter.txt");
164                    test("s3:///dudi/peter.txt");
165                    test("s3://dudi/peter.txt");
166                    
167                    
168            }
169            
170            
171            
172            private static void test(String path) {
173    
174                    Properties prop=new Properties();
175                    prop.setAccessKeyId("123456");
176                    prop.setSecretAccessKey("abcdefghji");
177                    
178                    
179                    
180                    String scheme="s3";
181                    path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path);
182                    S3 s3 = new S3();
183                    RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW);
184                    path=loadWithNewPattern(s3,prop,storage,path);
185                    
186    
187                    print.o(s3);
188                    print.o(path);
189            }*/
190    
191            private static String prettifyPath(String path) {
192                    path=path.replace('\\','/');
193                    return StringUtil.replace(path, "//", "/", false);
194                    // TODO /aaa/../bbb/
195            }
196            
197            
198            
199    
200            public static String loadWithOldPattern(S3 s3,RefInteger storage, String path) {
201                    
202                    
203                    String accessKeyId = null;
204                    String secretAccessKey = null;
205                    String host = null;
206                    //int port = 21;
207                    
208                    //print.out("raw:"+path);
209                    
210                    int atIndex=path.indexOf('@');
211                    int slashIndex=path.indexOf('/');
212                    if(slashIndex==-1){
213                            slashIndex=path.length();
214                            path+="/";
215                    }
216                    int index;
217                    
218                    // key/id
219                    if(atIndex!=-1) {
220                            index=path.indexOf(':');
221                            if(index!=-1 && index<atIndex) {
222                                    accessKeyId=path.substring(0,index);
223                                    secretAccessKey=path.substring(index+1,atIndex);
224                                    index=secretAccessKey.indexOf(':');
225                                    if(index!=-1) {
226                                            String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase();
227                                            secretAccessKey=secretAccessKey.substring(0,index);
228                                            //print.out("storage:"+strStorage);
229                                            storage.setValue(S3.toIntStorage(strStorage, S3.STORAGE_UNKNOW));
230                                    }
231                            }
232                            else accessKeyId=path.substring(0,atIndex);
233                    }
234                    path=prettifyPath(path.substring(atIndex+1));
235                    index=path.indexOf('/');
236                    if(index==-1){
237                            host=path;
238                            path="/";
239                    }
240                    else {
241                            host=path.substring(0,index);
242                            path=path.substring(index);
243                    }
244                    
245                    s3.setHost(host);
246                    s3.setSecretAccessKey(secretAccessKey);
247                    s3.setAccessKeyId(accessKeyId);
248                    
249                    return path;
250            }
251            @Override
252            public boolean isAttributesSupported() {
253                    return false;
254            }
255    
256            @Override
257            public boolean isCaseSensitive() {
258                    return true;
259            }
260    
261            @Override
262            public boolean isModeSupported() {
263                    return false;
264            }
265    
266            @Override
267            public void lock(Resource res) throws IOException {
268                    lock.lock(res);
269            }
270    
271            @Override
272            public void read(Resource res) throws IOException {
273                    lock.read(res);
274            }
275    
276            public void setResources(Resources res) {
277                    lock=res.createResourceLock(lockTimeout,true);
278            }
279    
280            @Override
281            public void unlock(Resource res) {
282                    lock.unlock(res);
283            }
284    
285            /**
286             * @return the socketTimeout
287             */
288            public int getSocketTimeout() {
289                    return socketTimeout;
290            }
291    
292            /**
293             * @return the lockTimeout
294             */
295            public int getLockTimeout() {
296                    return lockTimeout;
297            }
298    
299            /**
300             * @return the cache
301             */
302            public int getCache() {
303                    return cache;
304            }
305    
306            @Override
307            public Map getArguments() {
308                    return arguments;
309            }
310    
311            
312            
313    
314    }