001 package railo.commons.io.res.type.s3; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.io.UnsupportedEncodingException; 006 import java.net.HttpURLConnection; 007 import java.net.MalformedURLException; 008 import java.net.URL; 009 import java.security.InvalidKeyException; 010 import java.security.NoSuchAlgorithmException; 011 import java.util.ArrayList; 012 import java.util.HashMap; 013 import java.util.Iterator; 014 import java.util.List; 015 import java.util.Map; 016 import java.util.TimeZone; 017 018 import javax.crypto.Mac; 019 import javax.crypto.spec.SecretKeySpec; 020 021 import org.apache.commons.collections.map.ReferenceMap; 022 import org.apache.commons.httpclient.Header; 023 import org.apache.commons.httpclient.HttpMethod; 024 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; 025 import org.apache.commons.httpclient.methods.RequestEntity; 026 import org.xml.sax.SAXException; 027 028 import railo.commons.lang.Md5; 029 import railo.commons.lang.StringUtil; 030 import railo.commons.net.URLEncoder; 031 import railo.loader.util.Util; 032 import railo.runtime.engine.ThreadLocalPageContext; 033 import railo.runtime.exp.PageException; 034 import railo.runtime.op.Caster; 035 import railo.runtime.type.dt.DateTime; 036 037 public final class S3 implements S3Constants { 038 039 private static final String DEFAULT_URL="s3.amazonaws.com"; 040 041 private String secretAccessKey; 042 private String accessKeyId; 043 private TimeZone timezone; 044 private String host; 045 046 047 private static final Map<String,S3Info> infos=new ReferenceMap(); 048 private static final Map<String,AccessControlPolicy> acps=new ReferenceMap(); 049 050 public String toString(){ 051 return "secretAccessKey:"+secretAccessKey+";accessKeyId:"+accessKeyId+";host:"+host+";timezone:"+ 052 (timezone==null?"":timezone.getID()); 053 } 054 055 public String hash() { 056 try { 057 return Md5.getDigestAsString(toString()); 058 } catch (IOException e) { 059 return null; 060 } 061 } 062 063 public S3(String secretAccessKey, String accessKeyId,TimeZone tz) { 064 host=DEFAULT_URL; 065 this.secretAccessKey = secretAccessKey; 066 this.accessKeyId = accessKeyId; 067 this.timezone = tz; 068 //testFinal(); 069 } 070 071 072 073 public S3() { 074 075 //testFinal(); 076 } 077 078 /** 079 * @return the secretAccessKey 080 * @throws S3Exception 081 */ 082 String getSecretAccessKeyValidate() throws S3Exception { 083 if(StringUtil.isEmpty(secretAccessKey)) 084 throw new S3Exception("secretAccessKey is not defined, define in application.cfc (s3.awsSecretKey) or as part of the path."); 085 return secretAccessKey; 086 } 087 088 /** 089 * @return the accessKeyId 090 * @throws S3Exception 091 */ 092 String getAccessKeyIdValidate() throws S3Exception { 093 if(StringUtil.isEmpty(accessKeyId)) 094 throw new S3Exception("accessKeyId is not defined, define in application.cfc (this.s3.accessKeyId) or as part of the path."); 095 return accessKeyId; 096 } 097 098 String getSecretAccessKey() { 099 return secretAccessKey; 100 } 101 102 /** 103 * @return the accessKeyId 104 * @throws S3Exception 105 */ 106 String getAccessKeyId() { 107 return accessKeyId; 108 } 109 110 /** 111 * @return the tz 112 */ 113 TimeZone getTimeZone() { 114 if(timezone==null)timezone=ThreadLocalPageContext.getTimeZone(); 115 return timezone; 116 } 117 118 private static byte[] HMAC_SHA1(String key, String message,String charset) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { 119 120 SecretKeySpec sks = new SecretKeySpec(key.getBytes(charset),"HmacSHA1"); 121 Mac mac = Mac.getInstance(sks.getAlgorithm()); 122 mac.init(sks); 123 mac.update(message.getBytes(charset)); 124 return mac.doFinal(); 125 126 } 127 128 private static String createSignature(String str, String secretAccessKey,String charset) throws InvalidKeyException, NoSuchAlgorithmException, IOException { 129 //str=StringUtil.replace(str, "\\n", String.valueOf((char)10), false); 130 byte[] digest = HMAC_SHA1(secretAccessKey,str,charset); 131 try { 132 return Caster.toB64(digest); 133 } catch (Throwable t) { 134 throw new IOException(t.getMessage()); 135 } 136 } 137 138 public InputStream listBucketsRaw() throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 139 String dateTimeString = Util.toHTTPTimeString(); 140 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/", getSecretAccessKeyValidate(), "iso-8859-1"); 141 142 HttpMethod method = railo.commons.net.HTTPUtil.invoke(new URL("http://"+host), null, null, -1, null, "Railo", null, -1, null, null, 143 new Header[]{ 144 new Header("Date",dateTimeString), 145 new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature) 146 } 147 ); 148 return method.getResponseBodyAsStream(); 149 150 } 151 152 153 public HttpMethod head(String bucketName, String objectName) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 154 bucketName=checkBucket(bucketName); 155 boolean hasObj=!StringUtil.isEmpty(objectName); 156 if(hasObj)objectName=checkObjectName(objectName); 157 158 String dateTimeString = Util.toHTTPTimeString(); 159 String signature = createSignature("HEAD\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:""), getSecretAccessKeyValidate(), "iso-8859-1"); 160 161 162 List<Header> headers=new ArrayList<Header>(); 163 headers.add(new Header("Date",dateTimeString)); 164 headers.add(new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 165 headers.add(new Header("Host",bucketName+"."+host)); 166 167 String strUrl="http://"+bucketName+"."+host+"/"; 168 //if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 169 if(hasObj) { 170 strUrl+=objectName; 171 } 172 HttpMethod method = railo.commons.net.HTTPUtil.head(new URL(strUrl), null, null, -1, null, "Railo", null, -1, null, null,(Header[])headers.toArray(new Header[headers.size()])); 173 return method; 174 175 } 176 177 178 179 180 public InputStream aclRaw(String bucketName, String objectName) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 181 bucketName=checkBucket(bucketName); 182 boolean hasObj=!StringUtil.isEmpty(objectName); 183 if(hasObj)objectName=checkObjectName(objectName); 184 185 String dateTimeString = Util.toHTTPTimeString(); 186 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:"")+"?acl", getSecretAccessKeyValidate(), "iso-8859-1"); 187 188 189 List<Header> headers=new ArrayList<Header>(); 190 headers.add(new Header("Date",dateTimeString)); 191 headers.add(new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 192 headers.add(new Header("Host",bucketName+"."+host)); 193 194 String strUrl="http://"+bucketName+"."+host+"/"; 195 //if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 196 if(hasObj) { 197 strUrl+=objectName; 198 } 199 strUrl+="?acl"; 200 201 HttpMethod method = railo.commons.net.HTTPUtil.invoke(new URL(strUrl), null, null, -1, null, "Railo", null, -1, null, null,(Header[])headers.toArray(new Header[headers.size()])); 202 return method.getResponseBodyAsStream(); 203 204 } 205 206 public AccessControlPolicy getAccessControlPolicy(String bucketName, String objectName) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 207 InputStream raw = aclRaw(bucketName,objectName); 208 //print.o(IOUtil.toString(raw, null)); 209 ACLFactory factory=new ACLFactory(raw, this); 210 return factory.getAccessControlPolicy(); 211 } 212 213 214 215 216 public void setAccessControlPolicy(String bucketName, String objectName,AccessControlPolicy acp) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 217 bucketName=checkBucket(bucketName); 218 boolean hasObj=!StringUtil.isEmpty(objectName); 219 if(hasObj)objectName=checkObjectName(objectName); 220 221 222 ByteArrayRequestEntity re = new ByteArrayRequestEntity(acp.toXMLString().getBytes("iso-8859-1"),"text/html"); 223 224 225 String dateTimeString = Util.toHTTPTimeString(); 226 227 228 String cs = "PUT\n\n"+re.getContentType()+"\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:"")+"?acl"; 229 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 230 Header[] headers = new Header[]{ 231 new Header("Content-Type",re.getContentType()), 232 new Header("Content-Length",Long.toString(re.getContentLength())), 233 new Header("Date",dateTimeString), 234 new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 235 }; 236 237 String strUrl="http://"+bucketName+"."+host+"/"; 238 if(hasObj) { 239 strUrl+=objectName; 240 } 241 strUrl+="?acl"; 242 243 244 245 HttpMethod method = railo.commons.net.HTTPUtil.put(new URL(strUrl), null, null, -1, null, 246 "Railo", null, -1, null, null,headers,re); 247 if(method.getStatusCode()!=200){ 248 new ErrorFactory(method.getResponseBodyAsStream()); 249 } 250 251 252 } 253 254 255 256 257 258 259 public InputStream listContentsRaw(String bucketName,String prefix,String marker,int maxKeys) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 260 bucketName=checkBucket(bucketName); 261 String dateTimeString = Util.toHTTPTimeString(); 262 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/", getSecretAccessKeyValidate(), "iso-8859-1"); 263 264 265 List<Header> headers=new ArrayList<Header>(); 266 headers.add(new Header("Date",dateTimeString)); 267 headers.add(new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 268 headers.add(new Header("Host",bucketName+"."+host)); 269 270 ///if(!StringUtil.isEmpty(prefix)) headers.add(new Header("prefix",prefix)); 271 //if(!StringUtil.isEmpty(marker)) headers.add(new Header("marker",marker)); 272 //if(maxKeys>=0) headers.add(new Header("max-keys",Caster.toString(maxKeys))); 273 274 String strUrl="http://"+bucketName+"."+host+"/"; 275 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 276 277 278 char amp='?'; 279 if(!Util.isEmpty(prefix)){ 280 strUrl+=amp+"prefix="+encodeEL(prefix); 281 amp='&'; 282 } 283 if(!Util.isEmpty(marker)) { 284 strUrl+=amp+"marker="+encodeEL(marker); 285 amp='&'; 286 } 287 if(maxKeys!=-1) { 288 strUrl+=amp+"max-keys="+maxKeys; 289 amp='&'; 290 } 291 292 HttpMethod method = railo.commons.net.HTTPUtil.invoke(new URL(strUrl), null, null, -1, null, "Railo", null, -1, null, null,(Header[])headers.toArray(new Header[headers.size()])); 293 return method.getResponseBodyAsStream(); 294 } 295 296 297 public Content[] listContents(String bucketName,String prefix) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 298 String marker=null,last=null; 299 ContentFactory factory; 300 Content[] contents; 301 List<Content[]> list = new ArrayList<Content[]>(); 302 int size=0; 303 while(true) { 304 factory = new ContentFactory(listContentsRaw(bucketName, prefix, marker, -1),this); 305 contents = factory.getContents(); 306 list.add(contents); 307 size+=contents.length; 308 if(factory.isTruncated() && contents.length>0) { 309 last=marker; 310 marker=contents[contents.length-1].getKey(); 311 if(marker.equals(last))break; 312 } 313 else break; 314 } 315 316 if(list.size()==1) return (Content[]) list.get(0); 317 if(list.size()==0) return new Content[0]; 318 319 Content[] rtn=new Content[size]; 320 Iterator<Content[]> it = list.iterator(); 321 int index=0; 322 while(it.hasNext()) { 323 contents=it.next(); 324 for(int i=0;i<contents.length;i++) { 325 rtn[index++]=contents[i]; 326 } 327 } 328 329 return rtn; 330 } 331 332 public Content[] listContents(String bucketName,String prefix,String marker,int maxKeys) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 333 InputStream raw = listContentsRaw(bucketName, prefix, marker, maxKeys); 334 //print.o(IOUtil.toString(raw, null)); 335 ContentFactory factory = new ContentFactory(raw,this); 336 return factory.getContents(); 337 } 338 339 public Bucket[] listBuckets() throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 340 InputStream raw = listBucketsRaw(); 341 //print.o(IOUtil.toString(raw, null)); 342 BucketFactory factory = new BucketFactory(raw,this); 343 return factory.getBuckets(); 344 } 345 346 public void putBuckets(String bucketName,int acl, int storage) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 347 String strXML = ""; 348 if(storage==STORAGE_EU) { 349 strXML="<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>"; 350 } 351 352 byte[] barr = strXML.getBytes("iso-8859-1"); 353 put(bucketName, null, acl,new ByteArrayRequestEntity(barr,"text/html")); 354 } 355 356 /*public void putObject(String bucketName,String objectName,int acl,Resource res) throws IOException, InvalidKeyException, NoSuchAlgorithmException, PageException, SAXException, EncoderException { 357 String contentType = IOUtil.getMymeType(res, "application"); 358 InputStream is = null; 359 try { 360 is = res.getInputStream(); 361 put(bucketName, objectName, acl, is, contentType); 362 } 363 finally { 364 IOUtil.closeEL(is); 365 } 366 }*/ 367 /* 368 public void put(String bucketName,String objectName,int acl, InputStream is,long length, String contentType) throws IOException, InvalidKeyException, NoSuchAlgorithmException, PageException, SAXException, EncoderException { 369 put(bucketName, objectName, acl, HTTPUtil.toRequestEntity(is),length, contentType); 370 }*/ 371 372 public void put(String bucketName,String objectName,int acl, RequestEntity re) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 373 bucketName=checkBucket(bucketName); 374 objectName=checkObjectName(objectName); 375 376 String dateTimeString = Util.toHTTPTimeString(); 377 // Create a canonical string to send based on operation requested 378 String cs = "PUT\n\n"+re.getContentType()+"\n"+dateTimeString+"\nx-amz-acl:"+toStringACL(acl)+"\n/"+bucketName+"/"+objectName; 379 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 380 Header[] headers = new Header[]{ 381 new Header("Content-Type",re.getContentType()), 382 new Header("Content-Length",Long.toString(re.getContentLength())), 383 new Header("Date",dateTimeString), 384 new Header("x-amz-acl",toStringACL(acl)), 385 new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 386 }; 387 388 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 389 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 390 391 392 393 HttpMethod method = railo.commons.net.HTTPUtil.put(new URL(strUrl), null, null, -1, null, 394 "Railo", null, -1, null, null,headers,re); 395 if(method.getStatusCode()!=200){ 396 new ErrorFactory(method.getResponseBodyAsStream()); 397 } 398 399 400 } 401 402 public HttpURLConnection preput(String bucketName,String objectName,int acl, String contentType) throws IOException, InvalidKeyException, NoSuchAlgorithmException { 403 bucketName=checkBucket(bucketName); 404 objectName=checkObjectName(objectName); 405 406 String dateTimeString = Util.toHTTPTimeString(); 407 // Create a canonical string to send based on operation requested 408 String cs = "PUT\n\n"+contentType+"\n"+dateTimeString+"\nx-amz-acl:"+toStringACL(acl)+"\n/"+bucketName+"/"+objectName; 409 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 410 411 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 412 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 413 414 URL url = new URL(strUrl); 415 416 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 417 conn.setRequestMethod("PUT"); 418 419 conn.setFixedLengthStreamingMode(227422142); 420 conn.setDoOutput(true); 421 conn.setUseCaches(false); 422 conn.setRequestProperty("CONTENT-TYPE", contentType); 423 conn.setRequestProperty("USER-AGENT", "S3 Resource"); 424 //conn.setRequestProperty("Transfer-Encoding", "chunked" ); 425 conn.setRequestProperty("Date", dateTimeString); 426 conn.setRequestProperty("x-amz-acl", toStringACL(acl)); 427 conn.setRequestProperty("Authorization", "AWS "+getAccessKeyIdValidate()+":"+signature); 428 return conn; 429 } 430 431 public String getObjectLink(String bucketName,String objectName,int secondsValid) throws InvalidKeyException, NoSuchAlgorithmException, IOException { 432 bucketName=checkBucket(bucketName); 433 objectName=checkObjectName(objectName); 434 435 //String dateTimeString = GetHttpTimeString.invoke(); 436 long epoch = (System.currentTimeMillis()/1000)+(secondsValid); 437 String cs = "GET\n\n\n"+epoch+"\n/"+bucketName+"/"+objectName; 438 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 439 440 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 441 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 442 443 444 return strUrl+"?AWSAccessKeyId="+getAccessKeyIdValidate()+"&Expires="+epoch+"&Signature="+signature; 445 } 446 447 public InputStream getInputStream(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 448 return getData(bucketName, objectName).getResponseBodyAsStream(); 449 } 450 451 public Map<String, String> getMetadata(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 452 HttpMethod method = getData(bucketName, objectName); 453 Header[] headers = method.getResponseHeaders(); 454 Map<String,String> rtn=new HashMap<String, String>(); 455 String name; 456 if(headers!=null)for(int i=0;i<headers.length;i++){ 457 name=headers[i].getName(); 458 if(name.startsWith("x-amz-meta-")) 459 rtn.put(name.substring(11), headers[i].getValue()); 460 } 461 return rtn; 462 } 463 464 private HttpMethod getData(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 465 bucketName=checkBucket(bucketName); 466 objectName=checkObjectName(objectName); 467 468 String dateTimeString = Util.toHTTPTimeString(); 469 //long epoch = (System.currentTimeMillis()/1000)+6000; 470 String cs = "GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+objectName; 471 472 473 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 474 475 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 476 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 477 URL url = new URL(strUrl); 478 479 480 HttpMethod method = railo.commons.net.HTTPUtil.invoke(url, null, null, -1, null, "Railo", null, -1, null, null, 481 new Header[]{ 482 new Header("Date",dateTimeString), 483 new Header("Host",bucketName+"."+host), 484 new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature) 485 } 486 ); 487 if(method.getStatusCode()!=200) 488 new ErrorFactory(method.getResponseBodyAsStream()); 489 return method; 490 } 491 492 493 494 495 public void delete(String bucketName, String objectName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 496 bucketName=checkBucket(bucketName); 497 objectName = checkObjectName(objectName); 498 499 String dateTimeString = Util.toHTTPTimeString(); 500 // Create a canonical string to send based on operation requested 501 String cs ="DELETE\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+objectName; 502 //print.out(cs); 503 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 504 505 Header[] headers = new Header[]{ 506 new Header("Date",dateTimeString), 507 new Header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 508 }; 509 510 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 511 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 512 513 514 515 HttpMethod method = railo.commons.net.HTTPUtil.delete(new URL(strUrl), null, null, -1, null, "Railo", null, -1, null, null,headers); 516 517 if(method.getStatusCode()!=200) 518 new ErrorFactory(method.getResponseBodyAsStream()); 519 } 520 521 522 523 524 525 526 // -------------------------------- 527 public static String toStringACL(int acl) throws S3Exception { 528 switch(acl) { 529 case ACL_AUTH_READ:return "authenticated-read"; 530 case ACL_PUBLIC_READ:return "public-read"; 531 case ACL_PRIVATE:return "private"; 532 case ACL_PUBLIC_READ_WRITE:return "public-read-write"; 533 } 534 throw new S3Exception("invalid acl definition"); 535 } 536 537 public static String toStringStorage(int storage) throws S3Exception { 538 String s = toStringStorage(storage, null); 539 if(s==null) 540 throw new S3Exception("invalid storage definition"); 541 return s; 542 } 543 public static String toStringStorage(int storage, String defaultValue) { 544 switch(storage) { 545 case STORAGE_EU:return "eu"; 546 case STORAGE_US:return "us"; 547 case STORAGE_US_WEST:return "us-west"; 548 } 549 return defaultValue; 550 } 551 552 public static int toIntACL(String acl) throws S3Exception { 553 acl=acl.toLowerCase().trim(); 554 if("public-read".equals(acl)) return ACL_PUBLIC_READ; 555 if("private".equals(acl)) return ACL_PRIVATE; 556 if("public-read-write".equals(acl)) return ACL_PUBLIC_READ_WRITE; 557 if("authenticated-read".equals(acl)) return ACL_AUTH_READ; 558 559 if("public_read".equals(acl)) return ACL_PUBLIC_READ; 560 if("public_read_write".equals(acl)) return ACL_PUBLIC_READ_WRITE; 561 if("authenticated_read".equals(acl)) return ACL_AUTH_READ; 562 563 if("publicread".equals(acl)) return ACL_PUBLIC_READ; 564 if("publicreadwrite".equals(acl)) return ACL_PUBLIC_READ_WRITE; 565 if("authenticatedread".equals(acl)) return ACL_AUTH_READ; 566 567 throw new S3Exception("invalid acl value, valid values are [public-read, private, public-read-write, authenticated-read]"); 568 } 569 570 public static int toIntStorage(String storage) throws S3Exception { 571 int s=toIntStorage(storage,-1); 572 if(s==-1) 573 throw new S3Exception("invalid storage value, valid values are [eu,us,us-west]"); 574 return s; 575 } 576 public static int toIntStorage(String storage, int defaultValue) { 577 storage=storage.toLowerCase().trim(); 578 if("us".equals(storage)) return STORAGE_US; 579 if("usa".equals(storage)) return STORAGE_US; 580 if("eu".equals(storage)) return STORAGE_EU; 581 582 if("u.s.".equals(storage)) return STORAGE_US; 583 if("u.s.a.".equals(storage)) return STORAGE_US; 584 if("europe.".equals(storage)) return STORAGE_EU; 585 if("euro.".equals(storage)) return STORAGE_EU; 586 if("e.u.".equals(storage)) return STORAGE_EU; 587 if("united states of america".equals(storage)) return STORAGE_US; 588 589 if("us-west".equals(storage)) return STORAGE_US_WEST; 590 if("usa-west".equals(storage)) return STORAGE_US_WEST; 591 592 593 return defaultValue; 594 } 595 596 597 private String checkObjectName(String objectName) throws UnsupportedEncodingException { 598 if(Util.isEmpty(objectName)) return ""; 599 if(objectName.startsWith("/"))objectName=objectName.substring(1); 600 return encode(objectName); 601 } 602 603 private String checkBucket(String name) { 604 /*if(!Decision.isVariableName(name)) 605 throw new S3Exception("invalid bucket name definition ["+name+"], name should only contain letters, digits, dashes and underscores"); 606 607 if(name.length()<3 || name.length()>255) 608 throw new S3Exception("invalid bucket name definition ["+name+"], the length of a bucket name must be between 3 and 255"); 609 */ 610 611 return encodeEL(name); 612 } 613 614 private String encodeEL(String name) { 615 try { 616 return encode(name); 617 618 } catch (UnsupportedEncodingException e) { 619 return name; 620 } 621 } 622 private String encode(String name) throws UnsupportedEncodingException { 623 return URLEncoder.encode(name,"UTF-8"); 624 } 625 626 /** 627 * @param secretAccessKey the secretAccessKey to set 628 */ 629 public void setSecretAccessKey(String secretAccessKey) { 630 this.secretAccessKey = secretAccessKey; 631 } 632 633 /** 634 * @param accessKeyId the accessKeyId to set 635 */ 636 public void setAccessKeyId(String accessKeyId) { 637 this.accessKeyId = accessKeyId; 638 } 639 640 /** 641 * @param url the url to set 642 */ 643 public void setHost(String host) { 644 this.host=host; 645 } 646 647 public String getHost() { 648 return host; 649 } 650 651 public S3Info getInfo(String path) { 652 return (S3Info) infos.get(toKey(path)); 653 } 654 655 public void setInfo(String path,S3Info info) { 656 infos.put(toKey(path),info); 657 } 658 659 public AccessControlPolicy getACP(String path) { 660 return acps.get(toKey(path)); 661 } 662 663 public void setACP(String path,AccessControlPolicy acp) { 664 acps.put(toKey(path),acp); 665 } 666 667 public void releaseCache(String path) { 668 Object k = toKey(path); 669 infos.remove(k); 670 acps.remove(k); 671 } 672 673 674 675 private String toKey(String path) { 676 return toString()+":"+path.toLowerCase(); 677 } 678 679 public static DateTime toDate(String strDate, TimeZone tz) throws PageException { 680 if(strDate.endsWith("Z")) 681 strDate=strDate.substring(0,strDate.length()-1); 682 return Caster.toDate(strDate, tz); 683 } 684 } 685 686 687 688 689