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 }