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