com.goeuro.sync4j.sync.LockFile Maven / Gradle / Ivy
package com.goeuro.sync4j.sync;
import com.goeuro.sync4j.fs.LoosePath;
import com.goeuro.sync4j.fs.Path;
import com.goeuro.sync4j.fs.Paths;
import com.goeuro.sync4j.utils.Applications;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import java.io.*;
import java.time.OffsetDateTime;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import static com.goeuro.sync4j.fs.Paths.normalize;
import static com.goeuro.sync4j.fs.Paths.open;
import static com.goeuro.sync4j.sync.LockFileContent.lockFileContent;
import static com.goeuro.sync4j.utils.IOStreams.closeQuietly;
import static java.util.Optional.*;
@Immutable
public class LockFile {
@Nonnull
public static Builder lockFile(@Nonnull Path file) {
return new Builder<>(file);
}
@Nonnull
private final Path file;
protected LockFile(
@Nonnull Path file
) {
this.file = file;
}
public void delete() {
Paths.delete(file());
}
public void write(@Nonnull LockFileContent content) {
try (final InputStream is = createPropertiesAsInputStream(content)) {
Paths.write(file(), is);
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
@Nonnull
protected Properties createPropertiesFor(@Nonnull LockFileContent content) {
final Properties properties = new Properties();
properties.setProperty("id", content.id().toString());
properties.setProperty("lastPing", content.lastPing().toString());
content.owner().ifPresent(owner -> properties.setProperty("owner", owner));
properties.setProperty("agent.name", Applications.name());
properties.setProperty("agent.version", Applications.version());
properties.setProperty("agent.buildTimestamp", Applications.buildTimestamp().toString());
return properties;
}
@Nonnull
protected byte[] createPropertiesAsBytesFor(@Nonnull LockFileContent content) throws IOException {
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
createPropertiesFor(content).store(baos, null);
return baos.toByteArray();
}
}
@Nonnull
protected InputStream createPropertiesAsInputStream(@Nonnull LockFileContent content) throws IOException {
final byte[] bytes = createPropertiesAsBytesFor(content);
return new ByteArrayInputStream(bytes);
}
@Nonnull
public Optional read() {
try {
final Optional stream = tryOpenInputStream();
try {
return stream
.flatMap(this::parse);
} finally {
closeQuietly(stream);
}
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
@Nonnull
protected Optional tryOpenInputStream() throws IOException {
return open(file());
}
@Nonnull
protected Optional parse(@Nonnull InputStream is) {
try {
final Properties properties = new Properties();
properties.load(is);
return parse(properties);
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
@Nonnull
protected Optional parse(@Nonnull Properties properties) throws IOException {
final Optional id = ofNullable(properties.getProperty("id")).map(UUID::fromString);
final Optional lastPing = ofNullable(properties.getProperty("lastPing")).map(OffsetDateTime::parse);
final Optional owner = ofNullable(properties.getProperty("owner"));
if (!id.isPresent() || !lastPing.isPresent()) {
return empty();
}
return of(lockFileContent()
.withId(id)
.lastPingedAt(lastPing)
.withOwner(owner)
.build());
}
@Nonnull
protected Path file() {
return file;
}
@Override
public String toString() {
return getClass().getSimpleName() + ":" + file();
}
public static class Builder {
@Nonnull
private final Path file;
protected Builder(
@Nonnull Path file
) {
this.file = normalize(file)
.orElseThrow(() -> new IllegalArgumentException("Illegal path provided: " + file));
}
@Nonnull
public LockFile build() {
return new LockFile<>(
file
);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy