summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollection.java45
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java17
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectElement.java59
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/ObjectIdentifier.java1
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java4
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java1
-rw-r--r--src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java81
-rw-r--r--src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java4
-rw-r--r--src/test/sha2561
9 files changed, 189 insertions, 24 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollection.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollection.java
index d5d766a..e0ef4f7 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollection.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollection.java
@@ -1,31 +1,50 @@
package com.keuin.kbackupfabric.util.backup.incremental;
-import com.keuin.kbackupfabric.util.backup.incremental.identifier.ObjectIdentifier;
-
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
public class ObjectCollection {
private final String name;
- private final Set<ObjectIdentifier> elements;
- private final Set<ObjectCollection> subCollections;
+ private final Map<String, ObjectElement> elements;
+ private final Map<String, ObjectCollection> subCollections;
- ObjectCollection(String name, Set<ObjectIdentifier> elements, Set<ObjectCollection> subCollections) {
+ ObjectCollection(String name, Set<ObjectElement> elements, Map<String, ObjectCollection> subCollections) {
this.name = Objects.requireNonNull(name);
- this.elements = Objects.requireNonNull(elements);
- this.subCollections = Objects.requireNonNull(subCollections);
+ this.elements = new HashMap<>();
+ for (ObjectElement e : elements) {
+ Objects.requireNonNull(e);
+ if (this.elements.put(e.getName(), e) != null) {
+ throw new IllegalStateException("elements conflict with the same name");
+ }
+ }
+ this.subCollections = new HashMap<>(Objects.requireNonNull(subCollections));
}
public String getName() {
return name;
}
- public Set<ObjectIdentifier> getElements() {
- return elements;
+ public Set<ObjectElement> getElementSet() {
+ return new HashSet<>(elements.values());
+ }
+
+ public Map<String, ObjectElement> getElementMap() {
+ return Collections.unmodifiableMap(elements);
+ }
+
+ public ObjectElement getElement(String name) {
+ return elements.get(name);
+ }
+
+ public Set<ObjectCollection> getSubCollectionSet() {
+ return new HashSet<>(subCollections.values());
+ }
+
+ public Map<String, ObjectCollection> getSubCollectionMap() {
+ return Collections.unmodifiableMap(subCollections);
}
- public Set<ObjectCollection> getSubCollections() {
- return subCollections;
+ public ObjectCollection getSubCollection(String name) {
+ return subCollections.get(name);
}
@Override
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
index 8b974db..be9e426 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactory.java
@@ -7,10 +7,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
/**
* Incremental backup is implemented as git-like file collection.
@@ -26,19 +23,21 @@ public class ObjectCollectionFactory <T extends ObjectIdentifier> {
}
public ObjectCollection fromDirectory(File directory) throws IOException {
- final Set<ObjectIdentifier> subFiles = new HashSet<>();
- final Set<ObjectCollection> subCollections = new HashSet<>();
+ final Set<ObjectElement> subFiles = new HashSet<>();
+ final Map<String, ObjectCollection> subCollections = new HashMap<>();
if (!Objects.requireNonNull(directory).isDirectory())
throw new IllegalArgumentException("given file is not a directory");
- for (Iterator<Path> iter = Files.walk(directory.toPath()).iterator(); iter.hasNext();) {
+ for (Iterator<Path> iter = Files.walk(directory.toPath(), 1).iterator(); iter.hasNext();) {
Path path = iter.next();
+ if (Files.isSameFile(path, directory.toPath()))
+ continue;
File file = path.toFile();
if (file.isDirectory()) {
- subCollections.add(fromDirectory(file));
+ subCollections.put(file.getName(), fromDirectory(file));
} else {
- subFiles.add(identifierFactory.fromFile(file));
+ subFiles.add(new ObjectElement(file.getName(), identifierFactory.fromFile(file)));
}
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectElement.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectElement.java
new file mode 100644
index 0000000..1232fb9
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectElement.java
@@ -0,0 +1,59 @@
+package com.keuin.kbackupfabric.util.backup.incremental;
+
+import com.keuin.kbackupfabric.util.backup.incremental.identifier.ObjectIdentifier;
+
+import java.util.Objects;
+
+/**
+ * Representing a file in a ObjectCollection.
+ * Immutable.
+ */
+public class ObjectElement {
+ private final String name;
+ private final ObjectIdentifier identifier;
+
+ public ObjectElement(String name, ObjectIdentifier identifier) {
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(identifier);
+ this.name = name;
+ this.identifier = identifier;
+ }
+
+ /**
+ * Get file name.
+ * @return the file name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get file identifier, which is considered to be different between files with different contents.
+ * @return the identifier.
+ */
+ public ObjectIdentifier getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ObjectElement that = (ObjectElement) o;
+ return name.equals(that.name) &&
+ identifier.equals(that.identifier);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, identifier);
+ }
+
+ @Override
+ public String toString() {
+ return "ObjectElement{" +
+ "name='" + name + '\'' +
+ ", identifier=" + identifier +
+ '}';
+ }
+}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/ObjectIdentifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/ObjectIdentifier.java
index 62798e1..6744616 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/ObjectIdentifier.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/ObjectIdentifier.java
@@ -4,6 +4,7 @@ package com.keuin.kbackupfabric.util.backup.incremental.identifier;
* The identifier distinguishing files in the object collection.
* It should be based on cryptographic hash function in order to prevent possible attacks to the backup system.
* All identifiers should be immutable and implement their own equals method.
+ * Immutable.
*/
public interface ObjectIdentifier {
String getIdentification();
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
index 9f56b0e..64716ed 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256Identifier.java
@@ -7,6 +7,10 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
+/**
+ * Identifier based on sha256.
+ * Immutable.
+ */
public class Sha256Identifier extends SingleHashIdentifier {
private static final int SHA256_LENGTH = 32;
diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
index 62ba47c..3b96f79 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/SingleHashIdentifier.java
@@ -8,6 +8,7 @@ import java.util.Arrays;
/**
* A simple identifier based on a single hash function.
+ * Immutable.
*/
public abstract class SingleHashIdentifier implements ObjectIdentifier {
diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java
new file mode 100644
index 0000000..60a42cf
--- /dev/null
+++ b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java
@@ -0,0 +1,81 @@
+package com.keuin.kbackupfabric.util.backup.incremental;
+
+import com.keuin.kbackupfabric.util.backup.incremental.identifier.Sha256Identifier;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+public class ObjectCollectionFactoryTest {
+
+ private void validate(ObjectCollection collection, List<String> subCollections, Map<String, String> subElements) {
+ assertEquals(subCollections.size(), collection.getSubCollectionMap().size());
+ assertEquals(subElements.size(), collection.getElementSet().size());
+ for (Map.Entry<String, ObjectCollection> c : collection.getSubCollectionMap().entrySet()) {
+ assertEquals(c.getKey(), c.getValue().getName());
+ assertTrue(subCollections.contains(c.getKey()));
+ }
+ for (Map.Entry<String, ObjectElement> entry : collection.getElementMap().entrySet()) {
+// assertTrue(subElements.contains(e.getIdentification()));
+ assertEquals(subElements.get(entry.getKey()), entry.getValue().getIdentifier().getIdentification());
+ }
+ }
+
+ @Test
+ public void fromDirectory() {
+ try {
+ ObjectCollectionFactory<Sha256Identifier> factory =
+ new ObjectCollectionFactory<>(Sha256Identifier.getFactory());
+ ObjectCollection collection =
+ factory.fromDirectory(new File("./testfile/ObjectCollectionFactoryTest"));
+
+ assertEquals("ObjectCollectionFactoryTest", collection.getName());
+ assertEquals(3, collection.getSubCollectionMap().size());
+ assertEquals(2, collection.getElementSet().size());
+
+ final Map<String, String> elements = new HashMap<>();
+
+ // check root dir
+ elements.put("a", "261CA0D59FEE8FD169802BB8030A07CF23E5C1593FA81A16C6D0A8CF27DAA2ED");
+ elements.put("b", "B3FED75012C4969DC63A50EBC4E745FF77E4A06E0B04720EF71EF033032EBAF7");
+ validate(collection, Arrays.asList("1", "2", "3"), elements);
+ elements.clear();
+
+ // check `1`
+ elements.put("a", "E8620F35A5DB33B1257CC51245DDACDA8AF3E0D431A8A38473575E468BCBD0BD");
+ elements.put("b", "19EE41585A674274891DE5A4B365DBAB9C49C576AB6F86CD515B683724D2DBBD");
+ validate(collection.getSubCollectionMap().get("1"), Arrays.asList("11", "12"), elements);
+ elements.clear();
+
+ // check `2`
+ validate(collection.getSubCollectionMap().get("2"), Collections.emptyList(), Collections.emptyMap());
+
+ // check `3`
+ validate(collection.getSubCollectionMap().get("3"), Collections.emptyList(), Collections.emptyMap());
+
+ // check `11`
+ validate(collection.getSubCollectionMap().get("1").getSubCollectionMap().get("11"), Collections.singletonList("111"), Collections.emptyMap());
+
+ // check `111`
+ elements.put("a", "1EDBE882A757E1FAFCA77A9D3BE3FF5D2BB3E2037B238C865F1F957C431F43B4");
+ elements.put("b", "30BA7CD8B4AD93A8B3826CD8D1518790924EEBB930EC04DF7DFB03A50B17D7BC");
+ validate(
+ collection.getSubCollectionMap().get("1").getSubCollectionMap().get("11").getSubCollectionMap().get("111"),
+ Collections.emptyList(),
+ elements
+ );
+ elements.clear();
+
+ // check `12`
+ validate(collection.getSubCollectionMap().get("1").getSubCollectionMap().get("12"), Collections.emptyList(), Collections.emptyMap());
+
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java
index 2296e01..53e92e2 100644
--- a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java
+++ b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java
@@ -6,17 +6,19 @@ import java.io.File;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
public class Sha256IdentifierTest {
@Test
public void fromFile() {
try {
- Sha256Identifier sha256 = Sha256Identifier.fromFile(new File("./src/test/sha256"));
+ Sha256Identifier sha256 = Sha256Identifier.fromFile(new File("./testfile/Sha256IdentifierTest"));
String str = sha256.getIdentification().toUpperCase();
assertEquals("315F5BDB76D078C43B8AC0064E4A0164612B1FCE77C869345BFC94C75894EDD3", str);
} catch (IOException e) {
e.printStackTrace();
+ fail();
}
}
diff --git a/src/test/sha256 b/src/test/sha256
deleted file mode 100644
index 5dd01c1..0000000
--- a/src/test/sha256
+++ /dev/null
@@ -1 +0,0 @@
-Hello, world! \ No newline at end of file