Added Javadoc and instructions for contribution

This commit is contained in:
Cametendo
2026-04-24 11:20:25 +02:00
parent cb9b464a99
commit 5dc7d88b7f
12 changed files with 431 additions and 0 deletions

19
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,19 @@
## Contributing
Contributions from the community are welcome! To contribute:
1. Fork the repository.
2. Create a new branch for your feature or bug fix.
3. Make your changes with proper testing.
4. Submit a pull request detailing your modifications.
### Developer Documentation
Developer documentation is generated using JavaDoc. To generate and view the documentation:
```bash
chmod +x generate_javadoc.sh
./generate_javadoc.sh
```
This will create a `docs/` folder with HTML documentation you can view in your browser.

139
generate_javadoc.sh Executable file
View File

@@ -0,0 +1,139 @@
#!/usr/bin/env bash
# --- Generate JavaDoc for cflash ---
# This script generates developer documentation using javadoc.
# If JDK is missing, it prompts the user to install it using the detected package manager.
set -e
SRC_DIR="src/main/java"
DOC_DIR="docs"
# --- Detect package manager ---
detect_package_manager() {
if command -v pacman >/dev/null 2>&1; then
echo "pacman"
elif command -v apt >/dev/null 2>&1; then
echo "apt"
elif command -v dnf >/dev/null 2>&1; then
echo "dnf"
elif command -v yum >/dev/null 2>&1; then
echo "yum"
elif command -v zypper >/dev/null 2>&1; then
echo "zypper"
elif command -v brew >/dev/null 2>&1; then
echo "brew"
elif command -v apk >/dev/null 2>&1; then
echo "apk"
elif command -v emerge >/dev/null 2>&1; then
echo "emerge"
else
echo ""
fi
}
# --- Generate JDK install command ---
jdk_install_command() {
local pm="$1"
case "$pm" in
pacman) echo "pacman -Sy --noconfirm jdk-openjdk" ;;
apt) echo "apt update && apt install -y openjdk-21-jdk || apt install -y default-jdk" ;;
dnf) echo "dnf install -y java-21-openjdk-devel || dnf install -y java-latest-openjdk-devel" ;;
yum) echo "yum install -y java-21-openjdk-devel || yum install -y java-latest-openjdk-devel" ;;
zypper) echo "zypper install -y java-21-openjdk-devel || zypper install -y java-latest-openjdk-devel" ;;
brew) echo "brew install openjdk" ;;
apk) echo "apk add openjdk21" ;;
emerge) echo "emerge dev-java/openjdk-bin" ;;
*) echo "" ;;
esac
}
# --- Check for javadoc ---
if ! command -v javadoc >/dev/null 2>&1; then
echo "Java Development Kit (JDK) with javadoc not found."
PM=$(detect_package_manager)
if [[ -z "$PM" ]]; then
echo "Please install the latest JDK manually and rerun this script."
exit 1
fi
CMD=$(jdk_install_command "$PM")
if [[ $EUID -ne 0 && "$PM" != "brew" ]]; then
echo "Please rerun this script with sudo if you want automatic JDK installation."
exit 1
fi
# Prompt user
read -rp "Do you want to run the following command to install the JDK? [$CMD] (y/n): " ANSWER
case "$ANSWER" in
y|Y)
echo "Installing JDK..."
eval "$CMD"
echo "JDK installed successfully."
;;
*)
echo "JDK installation cancelled. Please install manually and rerun."
exit 1
;;
esac
fi
# --- Check if source directory exists ---
if [[ ! -d "$SRC_DIR" ]]; then
echo -e "\033[31mSource directory '$SRC_DIR' not found!"
echo "Please ensure you're running this script from the project root directory."
exit 1
fi
# --- Generate JavaDoc ---
echo "Generating JavaDoc for cflash..."
rm -rf "$DOC_DIR"
mkdir -p "$DOC_DIR"
# Check if Maven is available
if command -v mvn >/dev/null 2>&1; then
echo "Using Maven to generate JavaDoc with dependencies..."
if mvn javadoc:javadoc -Dquiet=true > /dev/null 2>&1; then
# Copy generated docs from Maven location to our docs directory
if [[ -d "target/reports/apidocs" ]]; then
cp -r target/reports/apidocs/* "$DOC_DIR/"
echo -e "\033[32mJavaDoc generated successfully using Maven!"
echo -e "\033[0m→ Open file://$PWD/$DOC_DIR/index.html to view it."
else
echo -e "\033[31mMaven generated docs but couldn't find them in target/reports/apidocs"
exit 1
fi
else
echo -e "\033[31mMaven JavaDoc generation failed."
exit 1
fi
else
echo "Maven not found. Attempting to generate JavaDoc without dependencies..."
# Try to download JLine dependency manually
JLINE_JAR="$HOME/.m2/repository/org/jline/jline/3.25.1/jline-3.25.1.jar"
if [[ -f "$JLINE_JAR" ]]; then
echo "Found JLine dependency in Maven local repository..."
CLASSPATH="$SRC_DIR:$JLINE_JAR"
else
echo "JLine dependency not found. JavaDoc may have missing links."
CLASSPATH="$SRC_DIR"
fi
if javadoc -quiet -d "$DOC_DIR" \
-sourcepath "$SRC_DIR" \
-classpath "$CLASSPATH" \
-subpackages org.cametendo \
-private \
-author \
-version \
-doctitle "cflash - Disk Image Flashing Utility" \
-windowtitle "cflash Documentation" \
-bottom "Copyright © 2026 Cametendo. All rights reserved." > /dev/null 2>&1; then
echo -e "\033[32mJavaDoc generated successfully!"
echo -e "\033[0m→ Open file://$PWD/$DOC_DIR/index.html to view it."
else
echo -e "\033[31mJavaDoc generation failed. Install Maven for better dependency handling."
echo "Run: apt install maven (Ubuntu/Debian) or pacman -S maven (Arch)"
exit 1
fi
fi

View File

@@ -1,10 +1,32 @@
package org.cametendo;
import java.util.Scanner;
/**
* Utility class for managing block size configuration for disk flashing operations.
*
* <p>This class provides methods to both interactively prompt users for block size selection
* and to map command-line inputs to valid block size values. The default block size is 4M.</p>
*
* @author Cametendo
* @version 1.0
*/
public class BlockSize {
/**
* Default block size string value.
* Set to "4M" as the default block size for flashing operations.
*/
public static String blockSizeString = "4M";
/**
* Maps user input to a valid block size value.
*
* <p>Supports both numeric inputs (1-6) and string inputs (512K,1M,2M,4M,8M,16M).
* If the input is not recognized, returns the default block size.</p>
*
* @param input User input string, either numeric (1-6) or block size string
* @return Valid block size string (512K, 1M, 2M, 4M, 8M, 16M, or default)
*/
public static String mapBlockSize(String input) {
return switch (input) {
case "1", "512K" -> "512K";
@@ -17,6 +39,15 @@ public class BlockSize {
};
}
/**
* Interactively prompts the user to select a block size.
*
* <p>Displays a menu of available block sizes and maps the user's input
* to a valid block size value using {@link #mapBlockSize(String)}.</p>
*
* @param UserInput Scanner object for reading user input
* @return The selected block size string
*/
static String blockSize(Scanner UserInput) {
System.out.println("Choose a block size (Default: 4M)");
System.out.println("512KB (1), 1M (2), 2M (3), 4M (4), 8M (5), 16M (6)");

View File

@@ -3,7 +3,26 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Executes the dd command for disk flashing operations.
*
* <p>This class handles the actual execution of the dd command with the configured
* parameters (input file, output device, block size, and output flags). It provides
* real-time output streaming and calls the OSDetector for completion messages.</p>
*
* @author Cametendo
* @version 1.0
*/
public class Dd {
/**
* Executes the dd command with the configured parameters.
*
* <p>Runs the dd command using sudo with the specified image file, target device,
* block size, and output flags. Streams the command output in real-time to show
* progress. Upon completion, calls {@link OSDetector#wishWell(String)} to display
* a completion message based on the image file name.</p>
*/
public static void dd() {
try {
ProcessBuilder pb = new ProcessBuilder("sudo", "dd", "if=" + FilePathAdd.ImagePath, "of=" + StorageDeviceLister.fullPath, "bs=" + BlockSize.blockSizeString, "status=progress", "oflag=" + OflagHandler.oflagHandleString);

View File

@@ -9,10 +9,32 @@ import org.jline.reader.impl.completer.FileNameCompleter;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
/**
* Handles file path input and validation for disk image files.
*
* <p>This class provides functionality to interactively prompt users for image file paths
* with tab completion support, validate that files exist and are regular files, and
* validate file paths from command-line arguments.</p>
*
* @author Cametendo
* @version 1.0
*/
public class FilePathAdd {
/**
* Stores the validated path to the selected image file.
*/
public static String ImagePath = "";
/**
* Interactively prompts the user to select an image file path.
*
* <p>Uses JLine for enhanced terminal interaction with tab completion support.
* Validates that the selected path points to an existing regular file.</p>
*
* @return The validated path to the selected image file
* @throws IOException If there are I/O errors during terminal setup or file validation
*/
protected static String filePath() throws IOException {
fileQuestion();
@@ -39,6 +61,15 @@ public class FilePathAdd {
}
}
/**
* Validates and returns the full path to an image file.
*
* <p>Takes a file path, validates that it exists and is a regular file,
* and returns the real path. Used for command-line argument validation.</p>
*
* @param ImagePath Path to the image file to validate
* @return Full validated path to the file, or null if invalid
*/
public static String validateAndGetFile(String ImagePath) {
try {
Path path = Path.of(ImagePath);
@@ -54,6 +85,12 @@ public class FilePathAdd {
}
}
/**
* Displays the prompt for file path input.
*
* <p>Informs the user that they should enter the full path to their ISO/image file
* and mentions that tab completion is supported for convenience.</p>
*/
protected static void fileQuestion() {
System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)");
}

View File

@@ -1,7 +1,26 @@
package org.cametendo;
import java.util.Scanner;
/**
* Handles the final confirmation and execution of the disk flashing process.
*
* <p>This class displays the current configuration to the user for confirmation
* before proceeding with the actual flashing operation using the dd command.</p>
*
* @author Cametendo
* @version 1.0
*/
public class Flasher {
/**
* Displays the current flashing configuration and prompts for user confirmation.
*
* <p>Shows the device path, image file path, block size, and output flag that will be used
* for the flashing operation. If the user confirms, proceeds with the flashing process
* by calling {@link Dd#dd()}. If the user cancels, exits the application.</p>
*
* @param UserInput Scanner object for reading user confirmation
*/
public static void flasher(Scanner UserInput) {
String input = "";

View File

@@ -2,7 +2,25 @@ package org.cametendo;
import java.util.Scanner;
/**
* Handles the initial greeting and user confirmation for the cflash application.
*
* <p>This class provides a welcome message and prompts the user to confirm
* whether they want to proceed with flashing an image to a storage device.</p>
*
* @author Cametendo
* @version 1.0
*/
public class Greeting {
/**
* Displays a welcome message and prompts for user confirmation.
*
* <p>Shows the cflash welcome message and asks the user if they want to
* flash an image. If the user declines, exits the application.</p>
*
* @param UserInput Scanner object for reading user confirmation
*/
public static void greeting(Scanner UserInput) {
System.out.println("Welcome to cflash!");
System.out.println("Would you like to flash an image (Y/n)");

View File

@@ -2,7 +2,43 @@ package org.cametendo;
import java.io.IOException;
import java.util.Scanner;
/**
* Main entry point for the cflash application.
*
* <p>cflash is a command-line utility for flashing disk images to storage devices.
* It supports both interactive mode and command-line argument mode for automation.</p>
*
* <p>In interactive mode, the user is guided through device selection, file path input,
* block size configuration, and output flag selection. In command-line mode, all parameters
* can be specified as arguments for automated flashing.</p>
*
* @author Cametendo
* @version 1.0
*/
public class Main {
/**
* Main method that serves as the entry point for the cflash application.
*
* <p>The application can operate in two modes:</p>
* <ul>
* <li>Interactive mode: No arguments provided, user is guided through the process</li>
* <li>Command-line mode: Four arguments provided for automated execution</li>
* </ul>
*
* <p>Command-line arguments format:</p>
* <ol>
* <li>Device name (e.g., "sda" without /dev/ prefix)</li>
* <li>Image file path (absolute or relative path to ISO/image file)</li>
* <li>Block size (1-6 or 512K,1M,2M,4M,8M,16M)</li>
* <li>Output flag (1-4 or direct,dsync,sync,nocache)</li>
* </ol>
*
* @param args Command-line arguments. If 4 arguments are provided, runs in automated mode.
* If no arguments, runs in interactive mode.
* @throws InterruptedException If the flashing process is interrupted
* @throws IOException If there are I/O errors during device/file validation
*/
public static void main(String[] args) throws InterruptedException, IOException {
Scanner UserInput = new Scanner(System.in);
if (args.length == 4) {

View File

@@ -1,8 +1,27 @@
package org.cametendo;
import java.nio.file.Path;
/**
* Detects operating system types from image file names and displays completion messages.
*
* <p>This class analyzes the filename of disk images to identify the operating system
* and displays a personalized completion message with some fun descriptions for various
* Linux distributions, BSD variants, and other operating systems.</p>
*
* @author Cametendo
* @version 1.0
*/
public class OSDetector {
/**
* Analyzes an image file path and displays a personalized completion message.
*
* <p>Extracts the filename from the provided path and attempts to identify the
* operating system based on filename patterns. Displays a fun, personalized message
* wishing the user well with their new OS installation.</p>
*
* @param imagePath Path to the image file that was flashed
*/
public static void wishWell(String imagePath) {
String fileName = Path.of(imagePath).getFileName().toString().toLowerCase();

View File

@@ -1,10 +1,32 @@
package org.cametendo;
import java.util.Scanner;
/**
* Handles output flag (oflag) configuration for the dd command.
*
* <p>This class provides functionality to both interactively prompt users for output flag selection
* and to map command-line inputs to valid oflag values. The default output flag is "direct".</p>
*
* @author Cametendo
* @version 1.0
*/
public class OflagHandler {
/**
* Default output flag string value.
* Set to "direct" as the default output flag for dd operations.
*/
public static String oflagHandleString = "direct";
/**
* Maps user input to a valid output flag value.
*
* <p>Supports both numeric inputs (1-4) and string inputs (direct,dsync,sync,nocache).
* If the input is not recognized, returns the default output flag.</p>
*
* @param input User input string, either numeric (1-4) or output flag string
* @return Valid output flag string (direct, dsync, sync, nocache, or default)
*/
public static String mapOflagHandle(String input) {
return switch (input) {
case "1", "direct" -> "direct";
@@ -15,6 +37,15 @@ public class OflagHandler {
};
}
/**
* Interactively prompts the user to select an output flag.
*
* <p>Displays a menu of available output flags and maps the user's input
* to a valid output flag value using {@link #mapOflagHandle(String)}.</p>
*
* @param UserInput Scanner object for reading user input
* @return The selected output flag string
*/
static String Oflag(Scanner UserInput) {
System.out.println("Choose an Oflag (Default: direct)");
System.out.println("direct (1), dsync (2), sync (3), nocache (4)");

View File

@@ -5,11 +5,38 @@ import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.Scanner;
/**
* Handles storage device detection, listing, and validation for the flashing process.
*
* <p>This class provides functionality to list available storage devices using lsblk,
* validate device paths, and interactively prompt users to select a target device
* for flashing operations.</p>
*
* @author Cametendo
* @version 1.0
*/
public class StorageDeviceLister {
/**
* Stores the selected device name (without /dev/ prefix).
*/
public static String device = "";
/**
* Stores the full validated path to the selected device.
*/
public static String fullPath = "";
/**
* Interactively prompts the user to select a storage device.
*
* <p>Displays a list of available storage devices using the lsblk command,
* then prompts the user to enter a device name. Validates the device path
* and continues prompting until a valid device is selected.</p>
*
* @param UserInput Scanner object for reading user input
* @return The full validated path to the selected device
*/
protected static String deviceCheck(Scanner UserInput) {
deviceList();
@@ -33,6 +60,16 @@ public class StorageDeviceLister {
}
}
/**
* Validates and returns the full path to a storage device.
*
* <p>Takes a device name (without /dev/ prefix), constructs the full path,
* and validates that the device exists and is accessible. Used for command-line
* argument validation.</p>
*
* @param deviceName Device name without /dev/ prefix (e.g., "sda")
* @return Full validated path to the device, or null if invalid
*/
public static String validateAndGetPath(String deviceName) {
try {
Path path = Path.of("/dev/" + deviceName);
@@ -43,6 +80,12 @@ public class StorageDeviceLister {
}
}
/**
* Displays a list of available storage devices using the lsblk command.
*
* <p>Executes the lsblk command to show block devices and their properties,
* then prompts the user to enter a device name for selection.</p>
*/
private static void deviceList() {
try {
ProcessBuilder pb = new ProcessBuilder("lsblk");

View File

@@ -1,5 +1,25 @@
package org.cametendo;
/**
* Utility class for parsing yes/no user responses.
*
* <p>This class provides a simple method to interpret user input as a boolean
* value, accepting various forms of "yes" and treating everything else as "no".</p>
*
* @author Cametendo
* @version 1.0
*/
public class YesNo {
/**
* Parses user input to determine if it represents a "yes" response.
*
* <p>Accepts "Y", "y", and empty string (default) as yes responses.
* All other inputs are treated as no responses.</p>
*
* @param input User input string to parse
* @return true if the input represents a yes response, false otherwise
*/
public static boolean check(String input) {
switch (input) {
case "Y":