diff --git a/README.md b/README.md
index af0466b..c1748e4 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ To use the plugin, insert the following configuration into the plugins section o
org.atp-fivt
export-maven-plugin
- 1.1
+ 1.2
Name_Surname.zip
diff --git a/pom.xml b/pom.xml
index 55c66a8..870aeaa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.atp-fivt
export-maven-plugin
- 1.1
+ 1.2
maven-plugin
Maven project export plugin
@@ -48,13 +48,6 @@
10.25.0
-
-
- ossrh
- https://oss.sonatype.org/service/local/staging/deploy/maven2/
-
-
-
org.eclipse.jgit
@@ -156,6 +149,45 @@
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.3.1
+
+
+ attach-sources
+
+ prepare-package
+
+
+ jar-no-fork
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.6.3
+
+
+ ${maven.compiler.target}
+ none
+ false
+
+
+
+ attach-javadoc
+ prepare-package
+
+ jar
+
+
+
+
+
+
org.apache.maven.plugins
maven-gpg-plugin
@@ -171,14 +203,14 @@
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.7.0
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.7.0
true
- ossrh
- https://oss.sonatype.org/
- true
+ central
+ true
+ validated
diff --git a/src/main/java/org/atpfivt/ExportMojo.java b/src/main/java/org/atpfivt/ExportMojo.java
index 00d7bb2..0e7fb96 100644
--- a/src/main/java/org/atpfivt/ExportMojo.java
+++ b/src/main/java/org/atpfivt/ExportMojo.java
@@ -11,6 +11,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
@@ -18,6 +19,8 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
+import static org.atpfivt.StripMarkedSections.stripMarkedSections;
+
/**
* Goal which exports the project into zip file respecting .gitignore.
*/
@@ -33,6 +36,9 @@ public final class ExportMojo extends AbstractMojo {
@Parameter(defaultValue = "export.zip")
private String zipFileName;
+ @Parameter(defaultValue = "false")
+ private boolean stripMarked;
+
void setBaseDirectory(File baseDirectory) {
this.baseDirectory = baseDirectory;
}
@@ -45,10 +51,15 @@ void setZipFileName(String zipFileName) {
this.zipFileName = zipFileName;
}
+ void setStripMarked(boolean stripMarked) {
+ this.stripMarked = stripMarked;
+ }
+
private boolean isNotInBuildDirectory(Path path) {
return !path.startsWith(buildDirectory.toPath());
}
+
public void execute()
throws MojoExecutionException {
Path buildPath = buildDirectory.toPath();
@@ -65,7 +76,26 @@ public void execute()
for (Path path : pathList) {
URI relativePath = basePath.toUri().relativize(path.toUri());
zos.putNextEntry(new ZipEntry(relativePath.toString()));
- Files.copy(path, zos);
+ String fileName = path.getFileName().toString();
+ if (stripMarked && fileName.endsWith(".java")) {
+ /* ----- JAVA SOURCE: strip //[[ … //]] blocks ----- */
+ String src = Files.readString(path, StandardCharsets.UTF_8);
+ String cleaned = stripMarkedSections(src);
+ if (cleaned.length() != src.length()) {
+ getLog().info("Stripped file: " + path);
+ }
+ zos.write(cleaned.getBytes(StandardCharsets.UTF_8));
+
+ } else if (stripMarked && "pom.xml".equals(fileName)) {
+ /* ----- POM: remove the export-plugin marker ----- */
+ String pom = Files.readString(path, StandardCharsets.UTF_8);
+ String cleaned = pom.replace("true", "");
+ zos.write(cleaned.getBytes(StandardCharsets.UTF_8));
+
+ } else {
+ /* ----- Everything else copied verbatim ----- */
+ Files.copy(path, zos);
+ }
zos.closeEntry();
}
}
diff --git a/src/main/java/org/atpfivt/StripMarkedSections.java b/src/main/java/org/atpfivt/StripMarkedSections.java
new file mode 100644
index 0000000..92489f6
--- /dev/null
+++ b/src/main/java/org/atpfivt/StripMarkedSections.java
@@ -0,0 +1,27 @@
+package org.atpfivt;
+
+final class StripMarkedSections {
+ private StripMarkedSections() {
+
+ }
+ static String stripMarkedSections(String src) {
+ StringBuilder out = new StringBuilder(src.length());
+ int cursor = 0;
+
+ while (cursor < src.length()) {
+ int open = src.indexOf("//[[", cursor);
+ if (open == -1) { // no more markers
+ out.append(src, cursor, src.length());
+ break;
+ }
+ out.append(src, cursor, open); // keep text before "[["
+ int close = src.indexOf("//]]", open + 4);
+ if (close == -1) { // unmatched start → keep the rest
+ out.append(src, open, src.length());
+ break;
+ }
+ cursor = close + 4; // jump past "]]" and continue
+ }
+ return out.toString();
+ }
+}
diff --git a/src/test/java/org/atpfivt/ExportMojoTest.java b/src/test/java/org/atpfivt/ExportMojoTest.java
index 683e4e1..49d7d01 100644
--- a/src/test/java/org/atpfivt/ExportMojoTest.java
+++ b/src/test/java/org/atpfivt/ExportMojoTest.java
@@ -5,19 +5,18 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
class ExportMojoTest {
private ExportMojo exportMojo;
@@ -50,6 +49,10 @@ void exportSavesFilesRespectingTheGitignore() throws MojoExecutionException, IOE
ZipEntry nextEntry;
while ((nextEntry = zipInputStream.getNextEntry()) != null) {
filenames.add(nextEntry.getName());
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ zipInputStream.transferTo(baos);
+ assertTrue(baos.toString(StandardCharsets.UTF_8).contains("test"));
+ }
}
}
assertEquals(Set.of("a", "b", ".gitignore", "src/foo"), filenames);
@@ -67,11 +70,83 @@ void exportOmitsTargetEvenIfNoGitignoreProvided() throws MojoExecutionException,
ZipEntry nextEntry;
while ((nextEntry = zipInputStream.getNextEntry()) != null) {
filenames.add(nextEntry.getName());
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ zipInputStream.transferTo(baos);
+ assertEquals("test", baos.toString(StandardCharsets.UTF_8));
+ }
}
}
assertEquals(Set.of("a", "b", "a.ignoreme"), filenames);
}
+
+ @Test
+ void exportStripsMarkedSectionsAndPomTag() throws MojoExecutionException, IOException {
+ /* ── Arrange: project structure ─────────────────────────────────────────── */
+ // Java source with two marked regions
+ String javaSrc =
+ "public class StudentExercise {\n" +
+ " //[[\n" +
+ " private int answer = 42;\n" +
+ " //]]\n" +
+ " public void solve() {\n" +
+ " //[[\n" +
+ " System.out.println(answer);\n" +
+ " //]]\n" +
+ " }\n" +
+ "}\n";
+ Files.writeString(root.resolve("StudentExercise.java"), javaSrc, StandardCharsets.UTF_8);
+
+ // POM with the marker flag
+ String pom =
+ "\n" +
+ " 4.0.0\n" +
+ " example\n" +
+ " exercise\n" +
+ " 1.0-SNAPSHOT\n" +
+ " \n" +
+ " true\n" +
+ " \n" +
+ "\n";
+ Files.writeString(root.resolve("pom.xml"), pom, StandardCharsets.UTF_8);
+
+ // Enable strip-marked mode
+ exportMojo.setStripMarked(true);
+
+ /* ── Act: run the mojo ──────────────────────────────────────────────────── */
+ exportMojo.execute();
+
+ /* ── Assert: check the produced ZIP ─────────────────────────────────────── */
+ Map zipContents = new HashMap<>();
+ try (ZipInputStream zis = new ZipInputStream(
+ new FileInputStream(target.resolve("export.zip").toFile()),
+ StandardCharsets.UTF_8)) {
+
+ ZipEntry entry;
+ while ((entry = zis.getNextEntry()) != null) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ zis.transferTo(baos);
+ zipContents.put(entry.getName(), baos.toString(StandardCharsets.UTF_8));
+ }
+ }
+
+ // 1. ZIP contains the expected files
+ assertEquals(Set.of("StudentExercise.java", "pom.xml"), zipContents.keySet());
+
+ // 2. Java source has no \\[[ or \\]] and the secret implementation vanished
+ String strippedJava = zipContents.get("StudentExercise.java");
+ assertFalse(strippedJava.contains("//[["), "Markers must be removed");
+ assertFalse(strippedJava.contains("//]]"), "Markers must be removed");
+ assertFalse(strippedJava.contains("answer = 42"), "Hidden code must be removed");
+ assertFalse(strippedJava.contains("println"), "Second hidden block must be removed");
+
+ // 3. pom.xml no longer contains the marker element
+ String strippedPom = zipContents.get("pom.xml");
+ assertFalse(strippedPom.contains("true"),
+ "pom.xml should not expose the stripMarked flag to students");
+ }
+
+
@AfterEach
void tearDown() throws IOException {
Files.walk(root)
diff --git a/src/test/java/org/atpfivt/StripMarkedSectionsTest.java b/src/test/java/org/atpfivt/StripMarkedSectionsTest.java
new file mode 100644
index 0000000..6e96b60
--- /dev/null
+++ b/src/test/java/org/atpfivt/StripMarkedSectionsTest.java
@@ -0,0 +1,35 @@
+package org.atpfivt;
+
+import org.junit.jupiter.api.Test;
+
+import static org.atpfivt.StripMarkedSections.stripMarkedSections;
+import static org.junit.jupiter.api.Assertions.*;
+
+class StripMarkedSectionsTest {
+
+ @Test
+ void noMarkers() {
+ String src = "public class Foo { }";
+ assertEquals(src, stripMarkedSections(src));
+ }
+
+ @Test
+ void oneMarker() {
+ String src = "before //[[hidden//]] after";
+ String expected = "before after";
+ assertEquals(expected, stripMarkedSections(src));
+ }
+
+ @Test
+ void multipleMarkers() {
+ String src = "a //[[x//]] b //[[y//]] c";
+ String expected = "a b c";
+ assertEquals(expected, stripMarkedSections(src));
+ }
+
+ @Test
+ void unmatchedStart() {
+ String src = "keep //[[oops";
+ assertEquals(src, stripMarkedSections(src));
+ }
+}
\ No newline at end of file