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 }