#!/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
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)