diff --git a/jenkins/hello-world/pom.xml b/jenkins/hello-world/pom.xml
new file mode 100644
index 0000000000..15cf2f8e34
--- /dev/null
+++ b/jenkins/hello-world/pom.xml
@@ -0,0 +1,89 @@
+
+
+ 4.0.0
+
+ org.jenkins-ci.plugins
+ plugin
+ 2.33
+
+
+ jenkins-hello-world
+ 1.0-SNAPSHOT
+ hpi
+
+
+ 2.7.3
+
+ Hello World Plugin
+ A sample Jenkins Hello World plugin
+ https://wiki.jenkins-ci.org/display/JENKINS/TODO+Plugin
+
+
+ MIT License
+ http://opensource.org/licenses/MIT
+
+
+
+
+ org.jenkins-ci.plugins
+ structs
+ 1.7
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-step-api
+ 2.12
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-cps
+ 2.39
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-job
+ 2.11.2
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-basic-steps
+ 2.6
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-durable-task-step
+ 2.13
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-api
+ 2.20
+ test
+
+
+ org.jenkins-ci.plugins.workflow
+ workflow-support
+ 2.14
+ test
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
+
+
+ repo.jenkins-ci.org
+ https://repo.jenkins-ci.org/public/
+
+
+
diff --git a/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStats.java b/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStats.java
new file mode 100644
index 0000000000..67af636bb4
--- /dev/null
+++ b/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStats.java
@@ -0,0 +1,20 @@
+package com.baeldung.jenkins.helloworld;
+
+public class ProjectStats {
+
+ private final int classesNumber;
+ private final int linesNumber;
+
+ public ProjectStats(int classesNumber, int linesNumber) {
+ this.classesNumber = classesNumber;
+ this.linesNumber = linesNumber;
+ }
+
+ public int getClassesNumber() {
+ return classesNumber;
+ }
+
+ public int getLinesNumber() {
+ return linesNumber;
+ }
+}
diff --git a/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStatsBuildWrapper.java b/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStatsBuildWrapper.java
new file mode 100644
index 0000000000..9a7213c76f
--- /dev/null
+++ b/jenkins/hello-world/src/main/java/com/baeldung/jenkins/helloworld/ProjectStatsBuildWrapper.java
@@ -0,0 +1,123 @@
+package com.baeldung.jenkins.helloworld;
+
+import hudson.Extension;
+import hudson.FilePath;
+import hudson.Launcher;
+import hudson.model.AbstractBuild;
+import hudson.model.AbstractProject;
+import hudson.model.BuildListener;
+import hudson.tasks.BuildWrapper;
+import hudson.tasks.BuildWrapperDescriptor;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+import javax.annotation.Nonnull;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.Stack;
+
+public class ProjectStatsBuildWrapper extends BuildWrapper {
+
+ private static final String REPORT_TEMPLATE_PATH = "/stats.html";
+ private static final String PROJECT_NAME_VAR = "$PROJECT_NAME$";
+ private static final String CLASSES_NUMBER_VAR = "$CLASSES_NUMBER$";
+ private static final String LINES_NUMBER_VAR = "$LINES_NUMBER$";
+
+ @DataBoundConstructor
+ public ProjectStatsBuildWrapper() {
+ }
+
+ @Override
+ public Environment setUp(AbstractBuild build, final Launcher launcher, BuildListener listener) {
+ return new Environment() {
+ @Override
+ public boolean tearDown(AbstractBuild build, BuildListener listener)
+ throws IOException, InterruptedException
+ {
+ ProjectStats stats = buildStats(build.getWorkspace());
+ String report = generateReport(build.getProject().getDisplayName(), stats);
+ File artifactsDir = build.getArtifactsDir();
+ if (!artifactsDir.isDirectory()) {
+ boolean success = artifactsDir.mkdirs();
+ if (!success) {
+ listener.getLogger().println("Can't create artifacts directory at "
+ + artifactsDir.getAbsolutePath());
+ }
+ }
+ String path = artifactsDir.getCanonicalPath() + REPORT_TEMPLATE_PATH;
+ try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),
+ StandardCharsets.UTF_8))) {
+ writer.write(report);
+ }
+ return super.tearDown(build, listener);
+ }
+ };
+ }
+
+ private static ProjectStats buildStats(FilePath root) throws IOException, InterruptedException {
+ int classesNumber = 0;
+ int linesNumber = 0;
+ Stack toProcess = new Stack<>();
+ toProcess.push(root);
+ while (!toProcess.isEmpty()) {
+ FilePath path = toProcess.pop();
+ if (path.isDirectory()) {
+ toProcess.addAll(path.list());
+ } else if (path.getName().endsWith(".java")) {
+ classesNumber++;
+ linesNumber += countLines(path);
+ }
+ }
+ return new ProjectStats(classesNumber, linesNumber);
+ }
+
+ private static int countLines(FilePath path) throws IOException, InterruptedException {
+ byte[] buffer = new byte[1024];
+ int result = 1;
+ try (InputStream in = path.read()) {
+ while (true) {
+ int read = in.read(buffer);
+ if (read < 0) {
+ return result;
+ }
+ for (int i = 0; i < read; i++) {
+ if (buffer[i] == '\n') {
+ result++;
+ }
+ }
+ }
+ }
+ }
+
+ private static String generateReport(String projectName, ProjectStats stats) throws IOException {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ try (InputStream in = ProjectStatsBuildWrapper.class.getResourceAsStream(REPORT_TEMPLATE_PATH)) {
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) >= 0) {
+ bOut.write(buffer, 0, read);
+ }
+ }
+ String content = new String(bOut.toByteArray(), StandardCharsets.UTF_8);
+ content = content.replace(PROJECT_NAME_VAR, projectName);
+ content = content.replace(CLASSES_NUMBER_VAR, String.valueOf(stats.getClassesNumber()));
+ content = content.replace(LINES_NUMBER_VAR, String.valueOf(stats.getLinesNumber()));
+ return content;
+ }
+
+ @Extension
+ public static final class DescriptorImpl extends BuildWrapperDescriptor {
+
+ @Override
+ public boolean isApplicable(AbstractProject, ?> item) {
+ return true;
+ }
+
+ @Nonnull
+ @Override
+ public String getDisplayName() {
+ return "Construct project stats during build";
+ }
+
+ }
+
+}
diff --git a/jenkins/hello-world/src/main/resources/stats.html b/jenkins/hello-world/src/main/resources/stats.html
new file mode 100644
index 0000000000..2a14b5de3f
--- /dev/null
+++ b/jenkins/hello-world/src/main/resources/stats.html
@@ -0,0 +1,20 @@
+
+
+
+
+ $PROJECT_NAME$
+
+
+Project $PROJECT_NAME$:
+
+
+ | Classes number |
+ Lines number |
+
+
+ | $CLASSES_NUMBER$ |
+ $LINES_NUMBER$ |
+
+
+
+
\ No newline at end of file