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}