diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..bef221f --- /dev/null +++ b/CONTRIBUTING.md @@ -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. diff --git a/generate_javadoc.sh b/generate_javadoc.sh new file mode 100755 index 0000000..955e55d --- /dev/null +++ b/generate_javadoc.sh @@ -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 diff --git a/src/main/java/org/cametendo/BlockSize.java b/src/main/java/org/cametendo/BlockSize.java index f1a57d3..1dca793 100644 --- a/src/main/java/org/cametendo/BlockSize.java +++ b/src/main/java/org/cametendo/BlockSize.java @@ -1,10 +1,32 @@ package org.cametendo; import java.util.Scanner; +/** + * Utility class for managing block size configuration for disk flashing operations. + * + *
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.
+ * + * @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. + * + *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.
+ * + * @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. + * + *Displays a menu of available block sizes and maps the user's input + * to a valid block size value using {@link #mapBlockSize(String)}.
+ * + * @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)"); diff --git a/src/main/java/org/cametendo/Dd.java b/src/main/java/org/cametendo/Dd.java index ec916bd..a631b93 100644 --- a/src/main/java/org/cametendo/Dd.java +++ b/src/main/java/org/cametendo/Dd.java @@ -3,7 +3,26 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +/** + * Executes the dd command for disk flashing operations. + * + *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.
+ * + * @author Cametendo + * @version 1.0 + */ public class Dd { + + /** + * Executes the dd command with the configured parameters. + * + *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.
+ */ 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); diff --git a/src/main/java/org/cametendo/FilePathAdd.java b/src/main/java/org/cametendo/FilePathAdd.java index 251e7eb..3f70016 100644 --- a/src/main/java/org/cametendo/FilePathAdd.java +++ b/src/main/java/org/cametendo/FilePathAdd.java @@ -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. + * + *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.
+ * + * @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. + * + *Uses JLine for enhanced terminal interaction with tab completion support. + * Validates that the selected path points to an existing regular file.
+ * + * @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. + * + *Takes a file path, validates that it exists and is a regular file, + * and returns the real path. Used for command-line argument validation.
+ * + * @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. + * + *Informs the user that they should enter the full path to their ISO/image file + * and mentions that tab completion is supported for convenience.
+ */ protected static void fileQuestion() { System.out.println("Please enter the FULL Path of your ISO / Image. (Tab-completion supported)"); } diff --git a/src/main/java/org/cametendo/Flasher.java b/src/main/java/org/cametendo/Flasher.java index 05882b4..f6027ce 100644 --- a/src/main/java/org/cametendo/Flasher.java +++ b/src/main/java/org/cametendo/Flasher.java @@ -1,7 +1,26 @@ package org.cametendo; import java.util.Scanner; +/** + * Handles the final confirmation and execution of the disk flashing process. + * + *This class displays the current configuration to the user for confirmation + * before proceeding with the actual flashing operation using the dd command.
+ * + * @author Cametendo + * @version 1.0 + */ public class Flasher { + + /** + * Displays the current flashing configuration and prompts for user confirmation. + * + *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.
+ * + * @param UserInput Scanner object for reading user confirmation + */ public static void flasher(Scanner UserInput) { String input = ""; diff --git a/src/main/java/org/cametendo/Greeting.java b/src/main/java/org/cametendo/Greeting.java index 11403d5..dc29243 100644 --- a/src/main/java/org/cametendo/Greeting.java +++ b/src/main/java/org/cametendo/Greeting.java @@ -2,7 +2,25 @@ package org.cametendo; import java.util.Scanner; +/** + * Handles the initial greeting and user confirmation for the cflash application. + * + *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.
+ * + * @author Cametendo + * @version 1.0 + */ public class Greeting { + + /** + * Displays a welcome message and prompts for user confirmation. + * + *Shows the cflash welcome message and asks the user if they want to + * flash an image. If the user declines, exits the application.
+ * + * @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)"); diff --git a/src/main/java/org/cametendo/Main.java b/src/main/java/org/cametendo/Main.java index 74c6121..b9c27eb 100644 --- a/src/main/java/org/cametendo/Main.java +++ b/src/main/java/org/cametendo/Main.java @@ -2,7 +2,43 @@ package org.cametendo; import java.io.IOException; import java.util.Scanner; +/** + * Main entry point for the cflash application. + * + *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.
+ * + *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.
+ * + * @author Cametendo + * @version 1.0 + */ public class Main { + + /** + * Main method that serves as the entry point for the cflash application. + * + *The application can operate in two modes:
+ *Command-line arguments format:
+ *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.
+ * + * @author Cametendo + * @version 1.0 + */ public class OSDetector { + /** + * Analyzes an image file path and displays a personalized completion message. + * + *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.
+ * + * @param imagePath Path to the image file that was flashed + */ public static void wishWell(String imagePath) { String fileName = Path.of(imagePath).getFileName().toString().toLowerCase(); diff --git a/src/main/java/org/cametendo/OflagHandler.java b/src/main/java/org/cametendo/OflagHandler.java index 8e03373..39e6457 100644 --- a/src/main/java/org/cametendo/OflagHandler.java +++ b/src/main/java/org/cametendo/OflagHandler.java @@ -1,10 +1,32 @@ package org.cametendo; import java.util.Scanner; +/** + * Handles output flag (oflag) configuration for the dd command. + * + *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".
+ * + * @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. + * + *Supports both numeric inputs (1-4) and string inputs (direct,dsync,sync,nocache). + * If the input is not recognized, returns the default output flag.
+ * + * @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. + * + *Displays a menu of available output flags and maps the user's input + * to a valid output flag value using {@link #mapOflagHandle(String)}.
+ * + * @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)"); diff --git a/src/main/java/org/cametendo/StorageDeviceLister.java b/src/main/java/org/cametendo/StorageDeviceLister.java index cdc2be3..49ec51c 100644 --- a/src/main/java/org/cametendo/StorageDeviceLister.java +++ b/src/main/java/org/cametendo/StorageDeviceLister.java @@ -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. + * + *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.
+ * + * @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. + * + *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.
+ * + * @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. + * + *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.
+ * + * @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. + * + *Executes the lsblk command to show block devices and their properties, + * then prompts the user to enter a device name for selection.
+ */ private static void deviceList() { try { ProcessBuilder pb = new ProcessBuilder("lsblk"); diff --git a/src/main/java/org/cametendo/YesNo.java b/src/main/java/org/cametendo/YesNo.java index 78141ba..31de3ab 100644 --- a/src/main/java/org/cametendo/YesNo.java +++ b/src/main/java/org/cametendo/YesNo.java @@ -1,5 +1,25 @@ package org.cametendo; + +/** + * Utility class for parsing yes/no user responses. + * + *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".
+ * + * @author Cametendo + * @version 1.0 + */ public class YesNo { + + /** + * Parses user input to determine if it represents a "yes" response. + * + *Accepts "Y", "y", and empty string (default) as yes responses. + * All other inputs are treated as no responses.
+ * + * @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":