DEV Community

Query Filter
Query Filter

Posted on

docker-193

#!/usr/bin/env bash

# ==============================================================================
# Script Name: decompile_lib.sh
# Description: Dynamically locates the IntelliJ Fernflower decompiler engine,
#              identifies source/target Java versions, and decompiles a JAR.
# Usage:       ./decompile_lib.sh <path_to_target_jar> [destination_folder]
# ==============================================================================

# Strict error handling
set -eo pipefail

# --- Configuration & Defaults ---
TARGET_JAR="${1:?Error: Target library JAR path must be provided as the first argument.}"
DEST_FOLDER="${2:-lib}"

# --- Helper Functions ---
log_info()    { echo -e "\033[32m[INFO]\033[0m $*"; }
log_control() { echo -e "\033[36m[VERSION CONTROL]\033[0m $*"; }
log_err()     { echo -e "\033[31m[ERROR]\033[0m $*" >&2; }

cleanup_on_err() {
    local exit_code=$?
    if [ $exit_code -ne 0 ]; then
        log_err "Script failed at step: '$BASH_COMMAND' (Exit Code: $exit_code)"
    fi
}
trap cleanup_on_err EXIT

# --- 1. Validate Target Input ---
if [ ! -f "$TARGET_JAR" ]; then
    log_err "Target JAR file not found: $TARGET_JAR"
    exit 1
fi

# Resolve absolute paths to prevent context loss during directory changes
ABS_TARGET_JAR=$(realpath "$TARGET_JAR")
JAR_FILENAME=$(basename "$ABS_TARGET_JAR")

# --- 2. Dynamic IntelliJ Decompiler Discovery ---
log_info "Locating IntelliJ installation environment..."

# Define potential base installation paths for JetBrains tools on Windows
POSSIBLE_PATHS=(
    "/c/Program Files/JetBrains"
    "/c/Users/$USER/AppData/Local/Programs"
)

INTELLIJ_JAVA=""
INTELLIJ_DECOMPILER_JAR=""

for base_path in "${POSSIBLE_PATHS[@]}"; do
    if [ -d "$base_path" ]; then
        while IFS= read -r idea_path; do
            POTENTIAL_JAVA="$idea_path/jbr/bin/java.exe"
            POTENTIAL_DECOMPILER="$idea_path/plugins/java-decompiler/lib/java-decompiler.jar"

            if [ -f "$POTENTIAL_JAVA" ] && [ -f "$POTENTIAL_DECOMPILER" ]; then
                INTELLIJ_JAVA="$POTENTIAL_JAVA"
                INTELLIJ_DECOMPILER_JAR="$POTENTIAL_DECOMPILER"
                break 2
            fi
        done < <(find "$base_path" -maxdepth 2 -type d -name "IntelliJ IDEA*" 2>/dev/null | sort -r)
    fi
done

if [ -z "$INTELLIJ_JAVA" ] || [ -z "$INTELLIJ_DECOMPILER_JAR" ]; then
    log_err "Could not automatically resolve a valid IntelliJ IDEA installation."
    exit 2
fi

# --- 3. Java Version Inspection Controls ---
echo "------------------------------------------------------------"

# A. Determine SOURCE Java Version from the JAR
# Read the first .class file found in the JAR to check its byte code version
FIRST_CLASS=$(jar tf "$ABS_TARGET_JAR" | grep '\.class$' | head -n 1)

if [ -z "$FIRST_CLASS" ]; then
    SRC_JAVA_VERSION="Unknown (No .class files found)"
else
    # Extract the major version number using javap
    MAJOR_VERSION=$(javap -v -cp "$ABS_TARGET_JAR" "${FIRST_CLASS%.class}" 2>/dev/null | grep "major version:" | awk '{print $3}')

    # Map the bytecode major version to human-readable Java version names
    case "$MAJOR_VERSION" in
        45) SRC_JAVA_VERSION="Java 1.1" ;;
        46) SRC_JAVA_VERSION="Java 1.2" ;;
        47) SRC_JAVA_VERSION="Java 1.3" ;;
        48) SRC_JAVA_VERSION="Java 1.4" ;;
        49) SRC_JAVA_VERSION="Java 5" ;;
        50) SRC_JAVA_VERSION="Java 6" ;;
        51) SRC_JAVA_VERSION="Java 7" ;;
        52) SRC_JAVA_VERSION="Java 8" ;;
        53) SRC_JAVA_VERSION="Java 9" ;;
        54) SRC_JAVA_VERSION="Java 10" ;;
        55) SRC_JAVA_VERSION="Java 11" ;;
        56) SRC_JAVA_VERSION="Java 12" ;;
        57) SRC_JAVA_VERSION="Java 13" ;;
        58) SRC_JAVA_VERSION="Java 14" ;;
        59) SRC_JAVA_VERSION="Java 15" ;;
        60) SRC_JAVA_VERSION="Java 16" ;;
        61) SRC_JAVA_VERSION="Java 17" ;;
        62) SRC_JAVA_VERSION="Java 18" ;;
        63) SRC_JAVA_VERSION="Java 19" ;;
        64) SRC_JAVA_VERSION="Java 20" ;;
        65) SRC_JAVA_VERSION="Java 21" ;;
        66) SRC_JAVA_VERSION="Java 22" ;;
        67) SRC_JAVA_VERSION="Java 23" ;;
        *)  SRC_JAVA_VERSION="Unknown (Major Version: ${MAJOR_VERSION:-N/A})" ;;
    esac
fi

# B. Determine TARGET Java Version from the IntelliJ runtime
TARGET_JAVA_VERSION=$("$INTELLIJ_JAVA" -version 2>&1 | head -n 1 | awk -F '"' '{print $2}')

# Output the control report
log_control "Pipeline Architecture Mapping:"
log_control "   >> SOURCE bytecode format:   $SRC_JAVA_VERSION"
log_control "   >> TARGET decompiler runtime: Java $TARGET_JAVA_VERSION"
echo "------------------------------------------------------------"

# --- 4. Destination Directory Preparation ---
if [ ! -d "$DEST_FOLDER" ]; then
    log_info "Destination folder '$DEST_FOLDER' does not exist. Creating it now..."
    mkdir -p "$DEST_FOLDER"
fi
ABS_DEST_FOLDER=$(realpath "$DEST_FOLDER")

# --- 5. Execution of the Decompiler ---
log_info "Executing ConsoleDecompiler against $JAR_FILENAME..."

"$INTELLIJ_JAVA" -cp "$INTELLIJ_DECOMPILER_JAR" \
    org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler \
    -dgs=true \
    "$ABS_TARGET_JAR" \
    "$ABS_DEST_FOLDER"

# --- 6. Extraction & Verification Pipeline ---
cd "$ABS_DEST_FOLDER"

if [ -f "$JAR_FILENAME" ]; then
    log_info "Extracting generated source archive inside target folder..."
    jar -xvf "$JAR_FILENAME"
    rm "$JAR_FILENAME"

    log_info "--- Disassembled File Inventory Summary ---"
    find . -type f
    log_info "Decompilation pipeline successfully completed."
else
    log_err "Decompiler completed but output file '$JAR_FILENAME' was missing from target directory."
    exit 3
fi
Enter fullscreen mode Exit fullscreen mode

Top comments (0)