001package org.kuali.common.devops.archive.sweep; 002 003import static java.lang.String.format; 004import static java.util.Arrays.asList; 005import static org.kuali.common.util.Encodings.UTF8; 006import static org.kuali.common.util.base.Precondition.checkNotBlank; 007import static org.kuali.common.util.log.Loggers.newLogger; 008 009import java.io.File; 010import java.io.IOException; 011import java.util.List; 012 013import org.kuali.common.core.build.ValidatingBuilder; 014import org.kuali.common.core.cli.api.CommandLineService; 015import org.kuali.common.core.cli.api.ExecRequest; 016import org.kuali.common.core.cli.api.StringStreamConsumer; 017import org.kuali.common.core.cli.plexus.PlexusCLIService; 018import org.kuali.common.core.validate.annotation.IdiotProofImmutable; 019import org.slf4j.Logger; 020 021import com.google.common.base.Optional; 022 023@IdiotProofImmutable 024public final class S3FileSystem { 025 026 private static final Logger logger = newLogger(); 027 028 private final File basedir; 029 private final String bucket; 030 private final CommandLineService cli; 031 private final String encoding; 032 033 public void unmount() { 034 if (isMounted()) { 035 String mountPoint = getMountPoint(); 036 List<String> args = asList("umount", "-f", mountPoint); 037 info("unmount -> %s", mountPoint); 038 cli.execute("sudo", args); 039 } 040 } 041 042 public void mount() { 043 if (!isMounted()) { 044 String mountPoint = getMountPoint(); 045 List<String> args = asList(bucket, mountPoint); 046 info("mount -> s3fs %s %s", bucket, mountPoint); 047 cli.execute("s3fs", args); 048 } 049 } 050 051 private String getMountPoint() { 052 return basedir.getPath() + "/" + bucket; 053 } 054 055 private boolean isMounted() { 056 StringStreamConsumer consumer = new StringStreamConsumer(encoding); 057 ExecRequest request = ExecRequest.builder("mount").redirectOutput(consumer).build(); 058 cli.execute(request); 059 String token = getMountPoint(); 060 Optional<String> optional = consumer.getOutput(); 061 checkNotBlank(optional, "mount output"); 062 String output = optional.get(); 063 boolean mounted = output.contains(token); 064 return mounted; 065 } 066 067 private S3FileSystem(Builder builder) { 068 this.basedir = builder.basedir; 069 this.bucket = builder.bucket; 070 this.cli = builder.cli; 071 this.encoding = builder.encoding; 072 } 073 074 public static S3FileSystem build(File basedir, String bucket) throws IOException { 075 return builder().withBasedir(basedir).withBucket(bucket).build(); 076 } 077 078 public static Builder builder() { 079 return new Builder(); 080 } 081 082 public static class Builder extends ValidatingBuilder<S3FileSystem> { 083 084 private String bucket; 085 private File basedir; 086 private CommandLineService cli = new PlexusCLIService(); 087 private String encoding = UTF8; 088 089 public Builder withBasedir(File basedir) { 090 this.basedir = basedir; 091 return this; 092 } 093 094 public Builder withBucket(String bucket) { 095 this.bucket = bucket; 096 return this; 097 } 098 099 public Builder withCli(CommandLineService cli) { 100 this.cli = cli; 101 return this; 102 } 103 104 public Builder withEncoding(String encoding) { 105 this.encoding = encoding; 106 return this; 107 } 108 109 @Override 110 public S3FileSystem build() { 111 return validate(new S3FileSystem(this)); 112 } 113 } 114 115 public File getBasedir() { 116 return basedir; 117 } 118 119 public String getBucket() { 120 return bucket; 121 } 122 123 public CommandLineService getCli() { 124 return cli; 125 } 126 127 public String getEncoding() { 128 return encoding; 129 } 130 131 private void info(String msg, Object... args) { 132 logger.info((args == null || args.length == 0) ? msg : format(msg, args)); 133 } 134 135}