package org.xmlsh.aws; import java.io.IOException; import java.util.List; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import net.sf.saxon.s9api.SaxonApiException; import org.xmlsh.aws.util.AWSS3Command; import org.xmlsh.aws.util.S3Path; import org.xmlsh.core.CoreException; import org.xmlsh.core.Options; import org.xmlsh.core.OutputPort; import org.xmlsh.core.UnexpectedException; import org.xmlsh.core.XValue; import org.xmlsh.util.Util; import com.amazonaws.AmazonClientException; import com.amazonaws.services.s3.model.Bucket; import com.amazonaws.services.s3.model.ListMultipartUploadsRequest; import com.amazonaws.services.s3.model.ListObjectsRequest; import com.amazonaws.services.s3.model.MultipartUpload; import com.amazonaws.services.s3.model.MultipartUploadListing; import com.amazonaws.services.s3.model.ObjectListing; import com.amazonaws.services.s3.model.S3ObjectSummary; public class s3ls extends AWSS3Command { private boolean bLongListing; private String mDelim; /** * @param args * @throws IOException */ @Override public int run(List<XValue> args) throws Exception { Options opts = getOptions("delim:,r=recurse,l=long,m=multipart"); parseOptions(opts, args); args = opts.getRemainingArgs(); setSerializeOpts(this.getSerializeOpts(opts)); bLongListing = opts.hasOpt("l"); try { getS3Client(opts); } catch (UnexpectedException e) { usage( e.getLocalizedMessage() ); return 1; } mDelim = opts.getOptString("delim", "/" ); if( opts.hasOpt("r") ) mDelim = null ; int ret; switch(args.size()){ case 0: ret = listBuckets(); break; case 1: if( opts.hasOpt("m")) ret =listMultipart( args.get(0).toString()); else ret = list( args.get(0).toString()); break; default : usage(); return 1; } return ret; } private int listBuckets() throws IOException, XMLStreamException, SaxonApiException, CoreException { OutputPort stdout = getStdout(); mWriter = stdout.asXMLStreamWriter(getSerializeOpts()); startDocument(); startElement("s3ls"); traceCall("listBuckets"); List<Bucket> buckets = mAmazon.listBuckets(); for( Bucket bucket : buckets ){ startElement("bucket"); attribute("name", bucket.getName()); if( bLongListing ) { attribute("create-date",Util.formatXSDateTime(bucket.getCreationDate())); attribute("owner", bucket.getOwner().getDisplayName()); } endElement(); } endElement(); endDocument(); closeWriter(); stdout.writeSequenceTerminator(getSerializeOpts()); stdout.release(); return 0; } private int listMultipart(String s) throws XMLStreamException, IOException, SaxonApiException, CoreException { S3Path path = new S3Path(s); if( ! path.hasBucket()){ usage(); return 1; } OutputPort stdout = getStdout(); XMLStreamWriter writer = stdout.asXMLStreamWriter(getSerializeOpts()); writePath(path, writer); ListMultipartUploadsRequest request = getListMultipartRequest( path , mDelim ); MultipartUploadListing list = mAmazon.listMultipartUploads(request); do { List<String> prefixes = list.getCommonPrefixes(); if( prefixes != null && prefixes.size() > 0 ){ for( String p : prefixes ){ writer.writeStartElement("directory"); writer.writeAttribute("name",p); writer.writeEndElement(); } } List<MultipartUpload> uploads = list.getMultipartUploads(); for ( MultipartUpload obj : uploads ){ writer.writeStartElement("file"); writer.writeAttribute("key",obj.getKey()); if( bLongListing ){ writer.writeAttribute("initiated",Util.formatXSDateTime(obj.getInitiated())); writer.writeAttribute("initiator",obj.getInitiator().getId()); writer.writeAttribute("uploadId", obj.getUploadId()); writer.writeAttribute("owner", obj.getOwner().getDisplayName()); writer.writeAttribute("storage-class" , obj.getStorageClass() ); } writer.writeEndElement(); } if( list.isTruncated()){ request.setUploadIdMarker(list.getUploadIdMarker()); request.setKeyMarker( list.getKeyMarker()); list = mAmazon.listMultipartUploads(request); } else break; } while( true ); writer.writeEndElement(); writer.writeEndDocument(); writer.flush(); writer.close(); stdout.writeSequenceTerminator(getSerializeOpts()); stdout.release(); return 0; } private int list(String s) throws IOException, XMLStreamException, SaxonApiException, AmazonClientException, CoreException { S3Path path = new S3Path(s); if( ! path.hasBucket()){ usage(); return 1; } OutputPort stdout = getStdout(); XMLStreamWriter writer = stdout.asXMLStreamWriter(getSerializeOpts()); writePath(path, writer); ListObjectsRequest request = getListRequest( path ,mDelim ); traceCall("listObjects"); ObjectListing list = mAmazon.listObjects(request); do { List<String> prefixes = list.getCommonPrefixes(); if( prefixes != null && prefixes.size() > 0 ){ for( String p : prefixes ){ writer.writeStartElement("directory"); writer.writeAttribute("name",p); writer.writeEndElement(); } } List<S3ObjectSummary> objs = list.getObjectSummaries(); for ( S3ObjectSummary obj : objs ){ writer.writeStartElement("file"); writer.writeAttribute("key",obj.getKey()); if( bLongListing ){ writer.writeAttribute("size", Long.toString(obj.getSize() )); writer.writeAttribute("md5" , obj.getETag() ); writer.writeAttribute("mod-date", Util.formatXSDateTime(obj.getLastModified()) ); writer.writeAttribute("owner", obj.getOwner().getDisplayName()); writer.writeAttribute("storage-class" , obj.getStorageClass() ); } writer.writeEndElement(); } if( list.isTruncated()){ // String marker = list.getNextMarker(); list = mAmazon.listNextBatchOfObjects(list); } else break; } while( true ); writer.writeEndElement(); writer.writeEndDocument(); writer.flush(); writer.close(); stdout.writeSequenceTerminator(getSerializeOpts()); stdout.release(); return 0; } private void writePath(S3Path path, XMLStreamWriter writer) throws XMLStreamException { writer.writeStartDocument(); writer.writeStartElement(getName()); writer.writeAttribute("bucket" , path.getBucket() ); writer.writeAttribute("prefix", Util.notNull(path.getPrefix())); writer.writeAttribute("delim", Util.notNull(mDelim) ); } @Override public void usage() { super.usage("Usage: s3ls [options] [bucket/prefix]"); } }