Repository: objectionary/eo
Issue: Home.java:47-48: Prohibit absolute paths in methods...

The puzzle `1352-39528ceb` from #1352 has to be resolved: 

https://github.com/objectionary/eo/blob/09faccc4fba201855269a0b61108053e460c21f3/eo-maven-plugin/src/main/java/org/eolang/maven/Home.java#L47-L48

The puzzle was created by rultor on 31-Oct-22. 

Estimate: 30 minutes,  role: DEV. 

If you have any technical questions, don't ask me, submit new tickets instead. The task will be \\"done\\" when the problem is fixed and the text of the puzzle is _removed_ from the source code. Here is more about [PDD](http://www.yegor256.com/2009/03/04/pdd.html) and [about me](http://www.yegor256.com/2017/04/05/pdd-in-action.html). 


Changed files:
eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChCompoundTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/dependencies/DcsJsonTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/util/HomeTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/ProbeMojoTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChTextTest.java, eo-maven-plugin/src/test/java/org/eolang/maven/PullMojoTest.java, eo-maven-plugin/src/main/java/org/eolang/maven/OptimizeMojo.java, eo-maven-plugin/src/main/java/org/eolang/maven/util/Home.java

diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizeMojo.java b/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizeMojo.java
index 42739f725..ad19809eb 100644
--- a/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizeMojo.java
+++ b/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizeMojo.java
@@ -264,7 +264,7 @@ public final class OptimizeMojo extends SafeMojo implements CompilationStep {
         );
         new Home(dir).save(
             xml.toString(),
-            target
+            dir.relativize(target)
         );
         Logger.debug(
             this, "Optimized %s (program:%s) to %s",
diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/util/Home.java b/eo-maven-plugin/src/main/java/org/eolang/maven/util/Home.java
index c2b302591..e10108887 100644
--- a/eo-maven-plugin/src/main/java/org/eolang/maven/util/Home.java
+++ b/eo-maven-plugin/src/main/java/org/eolang/maven/util/Home.java
@@ -28,7 +28,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import org.cactoos.Bytes;
 import org.cactoos.Input;
 import org.cactoos.Text;
@@ -43,8 +42,6 @@ import org.cactoos.scalar.LengthOf;
  * Base location for files.
  *
  * @since 0.27
- * @todo #1352:30min Prohibit absolute paths in methods `save`, `load`, `exists`.
- *  Throw an exception in case absolut path is given for these methods.
  */
 @SuppressWarnings("PMD.TooManyMethods")
 public final class Home {
@@ -53,13 +50,6 @@ public final class Home {
      */
     private final Path cwd;
 
-    /**
-     * Ctor.
-     */
-    public Home() {
-        this(Paths.get(""));
-    }
-
     /**
      * Ctor.
      *
@@ -119,9 +109,10 @@ public final class Home {
      * @param input Input
      * @param path Cwd-relative path to file
      * @throws IOException If fails
+     * @throws IllegalArgumentException If give path is absolute
      */
     public void save(final Input input, final Path path) throws IOException {
-        final Path target = this.absolute(path);
+        final Path target = this.absolute(this.onlyRelative(path));
         if (target.toFile().getParentFile().mkdirs()) {
             Logger.debug(
                 this, "Directory created: %s",
@@ -157,9 +148,10 @@ public final class Home {
      *
      * @param path Cwd-relative path to file
      * @return True if exists
+     * @throws IllegalArgumentException If give path is absolute
      */
     public boolean exists(final Path path) {
-        return Files.exists(this.absolute(path));
+        return Files.exists(this.absolute(this.onlyRelative(path)));
     }
 
     /**
@@ -169,9 +161,10 @@ public final class Home {
      * @return Bytes of file
      * @throws IOException if method can't find the file by path or
      *  if some exception happens during reading the file
+     * @throws IllegalArgumentException If give path is absolute
      */
     public Bytes load(final Path path) throws IOException {
-        return new BytesOf(Files.readAllBytes(this.absolute(path)));
+        return new BytesOf(Files.readAllBytes(this.absolute(this.onlyRelative(path))));
     }
 
     /**
@@ -183,4 +176,23 @@ public final class Home {
     public Path absolute(final Path path) {
         return this.cwd.resolve(path);
     }
+
+    /**
+     * Verifies that given path is relative and throws exception if not.
+     * @param path Path to be verified
+     * @return Given path if it's relative
+     * @throws IllegalArgumentException If given path is Absolute
+     */
+    private Path onlyRelative(final Path path) {
+        if (path.isAbsolute()) {
+            throw new IllegalArgumentException(
+                String.format(
+                    "Path must be relative to base %s but absolute given: %s",
+                    this.cwd,
+                    path
+                )
+            );
+        }
+        return path;
+    }
 }
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/ProbeMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/ProbeMojoTest.java
index ce49c5fec..915269e36 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/ProbeMojoTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/ProbeMojoTest.java
@@ -26,6 +26,7 @@ package org.eolang.maven;
 import com.yegor256.tojos.MnCsv;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.LinkedList;
 import org.cactoos.io.ResourceOf;
 import org.cactoos.text.TextOf;
@@ -67,9 +68,9 @@ final class ProbeMojoTest {
 
     @Test
     void findsProbesViaOfflineHashFile(@TempDir final Path temp) throws IOException {
-        new Home().save(
+        new Home(temp).save(
             new ResourceOf("org/eolang/maven/commits/tags.txt"),
-            temp.resolve("tags.txt")
+            Paths.get("tags.txt")
         );
         MatcherAssert.assertThat(
             ProbeMojoTest.firstEntry(
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/PullMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/PullMojoTest.java
index a56942277..b0dc852f2 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/PullMojoTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/PullMojoTest.java
@@ -94,7 +94,7 @@ final class PullMojoTest {
                     new ResourceOf("org/eolang/maven/simple-io.eo")
                 )
             ),
-            program
+            temp.relativize(program)
         );
         Catalogs.INSTANCE.make(temp.resolve("eo-foreign.json"), "json")
             .add("foo.src")
@@ -144,9 +144,9 @@ final class PullMojoTest {
 
     @Test
     void pullsUsingOfflineHashFile(@TempDir final Path temp) throws IOException {
-        new Home().save(
+        new Home(temp).save(
             new ResourceOf("org/eolang/maven/commits/tags.txt"),
-            temp.resolve("tags.txt")
+            Paths.get("tags.txt")
         );
         final Path target = temp.resolve("target");
         final Path foreign = temp.resolve("eo-foreign.json");
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java
index c1f2300db..eaf8fe6ee 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/UnplaceMojoTest.java
@@ -27,6 +27,7 @@ import com.yegor256.tojos.Tojo;
 import com.yegor256.tojos.Tojos;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.SecureRandom;
 import java.util.Collections;
 import java.util.List;
@@ -235,11 +236,13 @@ final class UnplaceMojoTest {
      * @throws IOException If fails.
      */
     private static Path clazz(final Path temp) throws IOException {
-        final Path path = temp.resolve(
-            String.format("a/b/c/%d_foo.class", new SecureRandom().nextInt())
+        final Path path =
+            Paths.get(String.format("a/b/c/%d_foo.class", new SecureRandom().nextInt()));
+        new Home(temp).save(
+            () -> UUID.randomUUID().toString(),
+            path
         );
-        new Home().save(() -> UUID.randomUUID().toString(), path);
-        return path;
+        return temp.resolve(path);
     }
 
     /**
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/dependencies/DcsJsonTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/dependencies/DcsJsonTest.java
index 43ef75790..72bdc552a 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/dependencies/DcsJsonTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/dependencies/DcsJsonTest.java
@@ -25,6 +25,7 @@ package org.eolang.maven.dependencies;
 
 import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import org.cactoos.io.ResourceOf;
 import org.cactoos.scalar.LengthOf;
 import org.eolang.maven.util.Home;
@@ -60,11 +61,11 @@ final class DcsJsonTest {
     private Path file(final Path tmp, final String name) {
         try {
             final Path res = tmp.resolve(name);
-            new Home().save(
+            new Home(tmp).save(
                 new ResourceOf(
                     String.format("org/eolang/maven/dependencies/%s", name)
                 ),
-                res
+                Paths.get(name)
             );
             return res;
         } catch (final IOException ex) {
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChCompoundTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChCompoundTest.java
index 878de6e9c..9d5843b9b 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChCompoundTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChCompoundTest.java
@@ -26,6 +26,7 @@ package org.eolang.maven.hash;
 
 import java.io.IOException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import org.cactoos.io.ResourceOf;
 import org.eolang.maven.OnlineCondition;
 import org.eolang.maven.util.Home;
@@ -70,7 +71,10 @@ final class ChCompoundTest {
     @Test
     void getsCommitHashValueFromFile(@TempDir final Path temp) throws IOException {
         final Path file = temp.resolve("tags.txt");
-        new Home().save(new ResourceOf("org/eolang/maven/commits/tags.txt"), file);
+        new Home(temp).save(
+            new ResourceOf("org/eolang/maven/commits/tags.txt"),
+            Paths.get("tags.txt")
+        );
         MatcherAssert.assertThat(
             new ChCompound(
                 file,
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChTextTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChTextTest.java
index 1a35f3b4f..5713425f6 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChTextTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/hash/ChTextTest.java
@@ -51,7 +51,10 @@ class ChTextTest {
     @BeforeAll
     static void setUp(@TempDir final Path dir) throws IOException {
         ChTextTest.file = dir.resolve("tags.txt");
-        new Home().save(new ResourceOf("org/eolang/maven/commits/tags.txt"), ChTextTest.file);
+        new Home(dir).save(
+            new ResourceOf("org/eolang/maven/commits/tags.txt"),
+            dir.relativize(ChTextTest.file)
+        );
     }
 
     @ParameterizedTest
diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/util/HomeTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/util/HomeTest.java
index 94e1d4045..45ce38d0b 100644
--- a/eo-maven-plugin/src/test/java/org/eolang/maven/util/HomeTest.java
+++ b/eo-maven-plugin/src/test/java/org/eolang/maven/util/HomeTest.java
@@ -50,20 +50,21 @@ final class HomeTest {
     @ValueSource(ints = {0, 100, 1_000, 10_000})
     @ParameterizedTest
     void saves(final int size, @TempDir final Path temp) throws IOException {
-        final Path resolve = temp.resolve("1.txt");
+        final Path resolve = Paths.get("1.txt");
         final String content = new UncheckedText(new Randomized(size)).asString();
         new Home(temp).save(content, resolve);
         MatcherAssert.assertThat(
-            new UncheckedText(new TextOf(resolve)).asString(),
+            new UncheckedText(new TextOf(temp.resolve(resolve))).asString(),
             Matchers.is(content)
         );
     }
 
     @Test
     void exists(@TempDir final Path temp) throws IOException {
-        Files.write(temp.resolve("file.txt"), "any content".getBytes());
+        final Path path = Paths.get("file.txt");
+        Files.write(temp.resolve(path), "any content".getBytes());
         MatcherAssert.assertThat(
-            new Home(temp).exists(Paths.get("file.txt")),
+            new Home(temp).exists(path),
             Matchers.is(true)
         );
     }
@@ -109,7 +110,7 @@ final class HomeTest {
     void loadsBytesFromExistingFile(@TempDir final Path temp) throws IOException {
         final Home home = new Home(temp);
         final String content = "bar";
-        final Path subfolder = temp.resolve("subfolder").resolve("foo.txt");
+        final Path subfolder = Paths.get("subfolder", "foo.txt");
         home.save(content, subfolder);
         MatcherAssert.assertThat(
             new TextOf(home.load(subfolder)),
@@ -121,7 +122,15 @@ final class HomeTest {
     void loadsFromAbsentFile(@TempDir final Path temp) {
         Assertions.assertThrows(
             NoSuchFileException.class,
-            () -> new Home(temp).load(temp.resolve("nonexistent"))
+            () -> new Home(temp).load(Paths.get("nonexistent"))
+        );
+    }
+
+    @Test
+    void throwsExceptionOnAbsolute(@TempDir final Path temp) {
+        Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> new Home(temp).exists(Paths.get("/tmp/file.txt"))
         );
     }
 }