package railo.commons.io.res.type.s3; import java.io.IOException; import java.util.Map; import railo.commons.io.res.Resource; import railo.commons.io.res.ResourceLock; import railo.commons.io.res.ResourceProvider; import railo.commons.io.res.Resources; import railo.commons.lang.StringUtil; import railo.commons.lang.types.RefInteger; import railo.commons.lang.types.RefIntegerImpl; import railo.runtime.PageContext; import railo.runtime.engine.ThreadLocalPageContext; import railo.runtime.net.s3.Properties; import railo.runtime.net.s3.PropertiesImpl; public final class S3ResourceProvider implements ResourceProvider { private int socketTimeout=-1; private int lockTimeout=20000; private int cache=20000; private ResourceLock lock; private String scheme="s3"; private Map arguments; /** * initalize ram resource * @param scheme * @param arguments * @return RamResource */ public ResourceProvider init(String scheme,Map arguments) { if(!StringUtil.isEmpty(scheme))this.scheme=scheme; if(arguments!=null) { this.arguments=arguments; // socket-timeout String strTimeout = (String) arguments.get("socket-timeout"); if(strTimeout!=null) { socketTimeout=toIntValue(strTimeout,socketTimeout); } // lock-timeout strTimeout=(String) arguments.get("lock-timeout"); if(strTimeout!=null) { lockTimeout=toIntValue(strTimeout,lockTimeout); } // cache String strCache=(String) arguments.get("cache"); if(strCache!=null) { cache=toIntValue(strCache,cache); } } return this; } private int toIntValue(String str, int defaultValue) { try{ return Integer.parseInt(str); } catch(Throwable t){ return defaultValue; } } @Override public String getScheme() { return scheme; } public Resource getResource(String path) { path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path); S3 s3 = new S3(); RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW); //path=loadWithOldPattern(s3,storage,path); path=loadWithNewPattern(s3,storage,path); return new S3Resource(s3,storage.toInt(),this,path,true); } public static String loadWithNewPattern(S3 s3,RefInteger storage, String path) { PageContext pc = ThreadLocalPageContext.get(); Properties prop=null; if(pc!=null){ prop=pc.getApplicationContext().getS3(); } if(prop==null) prop=new PropertiesImpl(); int defaultLocation = prop.getDefaultLocation(); storage.setValue(defaultLocation); String accessKeyId = prop.getAccessKeyId(); String secretAccessKey = prop.getSecretAccessKey(); int atIndex=path.indexOf('@'); int slashIndex=path.indexOf('/'); if(slashIndex==-1){ slashIndex=path.length(); path+="/"; } int index; // key/id if(atIndex!=-1) { index=path.indexOf(':'); if(index!=-1 && index<atIndex) { accessKeyId=path.substring(0,index); secretAccessKey=path.substring(index+1,atIndex); index=secretAccessKey.indexOf(':'); if(index!=-1) { String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase(); secretAccessKey=secretAccessKey.substring(0,index); //print.out("storage:"+strStorage); storage.setValue(S3.toIntStorage(strStorage, defaultLocation)); } } else accessKeyId=path.substring(0,atIndex); } path=prettifyPath(path.substring(atIndex+1)); index=path.indexOf('/'); s3.setHost(prop.getHost()); if(index==-1){ if(path.equalsIgnoreCase(S3Constants.HOST) || path.equalsIgnoreCase(prop.getHost())){ s3.setHost(path); path="/"; } } else { String host=path.substring(0,index); if(host.equalsIgnoreCase(S3Constants.HOST) || host.equalsIgnoreCase(prop.getHost())){ s3.setHost(host); path=path.substring(index); } } s3.setSecretAccessKey(secretAccessKey); s3.setAccessKeyId(accessKeyId); return path; } /*public static void main(String[] args) { // s3://bucket/x/y/sample.txt // s3://accessKeyId:awsSecretKey@bucket/x/y/sample.txt String secretAccessKey="R/sOy3hgimrI8D9c0lFHchoivecnOZ8LyVmJpRFQ"; String accessKeyId="1DHC5C5FVD7YEPR4DBG2"; Properties prop=new Properties(); prop.setAccessKeyId(accessKeyId); prop.setSecretAccessKey(secretAccessKey); test("s3://"+accessKeyId+":"+secretAccessKey+"@s3.amazonaws.com/dudi/peter.txt"); test("s3://"+accessKeyId+":"+secretAccessKey+"@dudi/peter.txt"); test("s3:///dudi/peter.txt"); test("s3://dudi/peter.txt"); } private static void test(String path) { Properties prop=new Properties(); prop.setAccessKeyId("123456"); prop.setSecretAccessKey("abcdefghji"); String scheme="s3"; path=railo.commons.io.res.util.ResourceUtil.removeScheme(scheme, path); S3 s3 = new S3(); RefInteger storage=new RefIntegerImpl(S3.STORAGE_UNKNOW); path=loadWithNewPattern(s3,prop,storage,path); print.o(s3); print.o(path); }*/ private static String prettifyPath(String path) { path=path.replace('\\','/'); return StringUtil.replace(path, "//", "/", false); // TODO /aaa/../bbb/ } public static String loadWithOldPattern(S3 s3,RefInteger storage, String path) { String accessKeyId = null; String secretAccessKey = null; String host = null; //int port = 21; //print.out("raw:"+path); int atIndex=path.indexOf('@'); int slashIndex=path.indexOf('/'); if(slashIndex==-1){ slashIndex=path.length(); path+="/"; } int index; // key/id if(atIndex!=-1) { index=path.indexOf(':'); if(index!=-1 && index<atIndex) { accessKeyId=path.substring(0,index); secretAccessKey=path.substring(index+1,atIndex); index=secretAccessKey.indexOf(':'); if(index!=-1) { String strStorage=secretAccessKey.substring(index+1).trim().toLowerCase(); secretAccessKey=secretAccessKey.substring(0,index); //print.out("storage:"+strStorage); storage.setValue(S3.toIntStorage(strStorage, S3.STORAGE_UNKNOW)); } } else accessKeyId=path.substring(0,atIndex); } path=prettifyPath(path.substring(atIndex+1)); index=path.indexOf('/'); if(index==-1){ host=path; path="/"; } else { host=path.substring(0,index); path=path.substring(index); } s3.setHost(host); s3.setSecretAccessKey(secretAccessKey); s3.setAccessKeyId(accessKeyId); return path; } @Override public boolean isAttributesSupported() { return false; } @Override public boolean isCaseSensitive() { return true; } @Override public boolean isModeSupported() { return false; } @Override public void lock(Resource res) throws IOException { lock.lock(res); } @Override public void read(Resource res) throws IOException { lock.read(res); } public void setResources(Resources res) { lock=res.createResourceLock(lockTimeout,true); } @Override public void unlock(Resource res) { lock.unlock(res); } /** * @return the socketTimeout */ public int getSocketTimeout() { return socketTimeout; } /** * @return the lockTimeout */ public int getLockTimeout() { return lockTimeout; } /** * @return the cache */ public int getCache() { return cache; } @Override public Map getArguments() { return arguments; } }