← All tasks
javaclaude-code/java-t2 #36Not a task: not reproduced

ZIP Archive Manager (java, written by Claude Code)

envgap__claude-code__java-t2-36

Written by a coding agent; not on GitHubWritten 2026-02-28

01 / FAILURE SIGNATURE

As the study recorded it

No src directory - Java file in project root
Not a benchmark task.
  • In a clean container the reported failure did not reproduce, or the known fix did not make the project run.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
pom.xml
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

claude-code/java-t2 #36 · read the task the agent was given
Claude Code wrote this java project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: ZIP Archive Manager

Write a program that creates, extracts, lists, and modifies ZIP archives with support for compression levels, password protection, file filtering, and split archives.

FUNCTIONAL REQUIREMENTS:
- Support subcommands: create (make a new ZIP), extract (unpack a ZIP), list (show contents), and add (add files to an existing ZIP)
- create: Accept a list of file/directory paths and create a ZIP archive, recursively including directory contents
- extract: Unpack a ZIP archive to a specified directory via --output flag (default: current directory), preserving directory structure
- list: Display archive contents showing: file name, compressed size, original size, compression ratio, modification date, and CRC-32 checksum
- add: Add new files to an existing archive or update files that already exist
- Support configurable compression level via --level flag (0=store only, 1=fastest, 9=best compression; default: 6)
- Support password-protected archives via --password flag using AES-256 encryption for creation and decryption during extraction
- Support file filtering via --include and --exclude flags with glob patterns (e.g., --include "*.txt" --exclude "*.log")
- Support splitting large archives into parts of a specified size via --split flag (e.g., --split 100m for 100MB parts)
- Verify archive integrity via --verify flag: check CRC-32 checksums for all files without extracting
- Print operation summary to console: total files, total original size, total compressed size, overall compression ratio, and time taken
- Save operation log as JSON with --log flag
- If no arguments are given, create a sample directory structure with various file types and sizes, create a ZIP archive from it, list the contents, extract to a new location, and verify the extraction matches the originals by comparing checksums
- Handle errors: corrupted archives, wrong passwords, disk full during extraction, duplicate entries, and path traversal prevention

Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include:
- Source code
- pom.xml with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>zip-archive-manager</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>ZIP Archive Manager</name>
    <description>ZIP archive manager using zip4j and slf4j</description>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>2.11.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>2.0.9</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>ZipArchiveManager</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
README.md
# ZIP Archive Manager (Java - Trial 2)

## Description
A command-line ZIP archive manager that supports creating, extracting, listing, and verifying ZIP archives. Features AES-256 encryption, split archives, multiple compression levels, and structured logging.

## Dependencies
- **zip4j**: Full-featured ZIP library with AES encryption, split archives, and compression control
- **slf4j-api + slf4j-simple**: Structured logging framework for operation tracking

## Usage

### Build
```bash
mvn clean package
```

### Create an archive
```bash
java -jar target/zip-archive-manager-1.0-SNAPSHOT.jar create output.zip file1.txt dir1/ -p secret -l 9
```

### Extract an archive
```bash
java -jar target/zip-archive-manager-1.0-SNAPSHOT.jar extract archive.zip -o output/ -p secret
```

### List archive contents
```bash
java -jar target/zip-archive-manager-1.0-SNAPSHOT.jar list archive.zip -v
```

### Verify archive integrity
```bash
java -jar target/zip-archive-manager-1.0-SNAPSHOT.jar verify archive.zip
```
ZipArchiveManager.java
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.exception.ZipException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ZIP Archive Manager
 * Creates, extracts, lists, and verifies ZIP archives with compression levels,
 * password protection, and split archive support.
 * Uses zip4j for ZIP operations and slf4j for logging.
 */
public class ZipArchiveManager {

    private static final Logger logger = LoggerFactory.getLogger(ZipArchiveManager.class);

    public static void main(String[] args) {
        if (args.length < 1) {
            printUsage();
            System.exit(1);
        }

        String command = args[0].toLowerCase();
        try {
            switch (command) {
                case "create":
                    handleCreate(args);
                    break;
                case "extract":
                    handleExtract(args);
                    break;
                case "list":
                    handleList(args);
                    break;
                case "verify":
                    handleVerify(args);
                    break;
                default:
                    System.err.println("Unknown command: " + command);
                    printUsage();
                    System.exit(1);
            }
        } catch (Exception e) {
            logger.error("Operation failed", e);
            System.err.println("Error: " + e.getMessage());
            System.exit(1);
        }
    }

    private static void handleCreate(String[] args) throws ZipException, IOException {
        if (args.length < 3) {
            System.err.println("Usage: create <output.zip> <source...> [-p password] [-l level] [-s splitSize]");
            return;
        }

        String outputPath = args[1];
        List<String> sources = new ArrayList<>();
        String password = null;
        int level = 5;
        long splitSize = 0;

        int i = 2;
        while (i < args.length) {
            switch (args[i]) {
                case "-p":
                    password = args[++i];
                    break;
                case "-l":
                    level = Integer.parseInt(args[++i]);
                    break;
                case "-s":
                    splitSize = Long.parseLong(args[++i]);
                    break;
                default:
                    sources.add(args[i]);
            }
            i++;
        }

        createArchive(outputPath, sources, password, level, splitSize);
    }

    private static void handleExtract(String[] args) throws ZipException {
        if (args.length < 2) {
            System.err.println("Usage: extract <archive.zip> [-o outputDir] [-p password]");
            return;
        }

        String archivePath = args[1];
        String outputDir = ".";
        String password = null;

        for (int i = 2; i < args.length; i++) {
            if ("-o".equals(args[i]) && i + 1 < args.length) {
                outputDir = args[++i];
            } else if ("-p".equals(args[i]) && i + 1 < args.length) {
                password = args[++i];
            }
        }

        extractArchive(archivePath, outputDir, password);
    }

    private static void handleList(String[] args) throws ZipException {
        if (args.length < 2) {
            System.err.println("Usage: list <archive.zip> [-v] [-p password]");
            return;
        }

        String archivePath = args[1];
        boolean verbose = false;
        String password = null;

        for (int i = 2; i < args.length; i++) {
            if ("-v".equals(args[i])) verbose = true;
            else if ("-p".equals(args[i]) && i + 1 < args.length) password = args[++i];
        }

        listArchive(archivePath, verbose, password);
    }

    private static void handleVerify(String[] args) throws ZipException {
        if (args.length < 2) {
            System.err.println("Usage: verify <archive.zip> [-p password]");
            return;
        }

        String archivePath = args[1];
        String password = null;

        for (int i = 2; i < args.length; i++) {
            if ("-p".equals(args[i]) && i + 1 < args.length) password = args[++i];
        }

        verifyArchive(archivePath, password);
    }

    public static void createArchive(String outputPath, List<String> sources,
                                     String password, int level, long splitSize)
            throws ZipException, IOException {
        logger.info("Creating archive: {}", outputPath);

        ZipParameters parameters = new ZipParameters();
        parameters.setCompressionMethod(CompressionMethod.DEFLATE);
        parameters.setCompressionLevel(mapCompressionLevel(level));

        if (password != null && !password.isEmpty()) {
            parameters.setEncryptFiles(true);
            parameters.setEncryptionMethod(EncryptionMethod.AES);
            parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
            logger.info("AES-256 encryption enabled");
        }

        List<File> filesToAdd = collectFiles(sources);
        logger.info("Collected {} files for archiving", filesToAdd.size());

        ZipFile zipFile;
        if (password != null && !password.isEmpty()) {
            zipFile = new ZipFile(outputPath, password.toCharArray());
        } else {
            zipFile = new ZipFile(outputPath);
        }

        if (splitSize > 0) {
            zipFile.createSplitZipFile(filesToAdd, parameters, true, splitSize);
            logger.info("Split archive created with split size: {} bytes", splitSize);
        } else {
            int count = 0;
            for (File file : filesToAdd) {
                if (file.isDirectory()) {
                    zipFile.addFolder(file, parameters);
                } else {
                    zipFile.addFile(file, parameters);
                }
                count++;
                System.out.printf("\rAdding files: %d/%d", count, filesToAdd.size());
            }
            System.out.println();
        }

        long archiveSize = new File(outputPath).length();
        System.out.printf("Archive created: %s (%,d bytes, %d files)%n",
                outputPath, archiveSize, filesToAdd.size());
        logger.info("Archive created successfully: {} ({} bytes)", outputPath, archiveSize);
    }

    public static void extractArchive(String archivePath, String outputDir,
                                       String password) throws ZipException {
        logger.info("Extracting archive: {} to {}", archivePath, outputDir);

        ZipFile zipFile;
        if (password != null && !password.isEmpty()) {
            zipFile = new ZipFile(archivePath, password.toCharArray());
        } else {
            zipFile = new ZipFile(archivePath);
        }

        if (!zipFile.isValidZipFile()) {
            throw new ZipException("Invalid ZIP file: " + archivePath);
        }

        List<FileHeader> headers = zipFile.getFileHeaders();
        int total = headers.size();

        zipFile.extractAll(outputDir);

        System.out.printf("Extracted %d entries to %s%n", total, outputDir);
        logger.info("Extraction complete: {} entries", total);
    }

    public static void listArchive(String archivePath, boolean verbose,
                                    String password) throws ZipException {
        logger.info("Listing archive: {}", archivePath);

        ZipFile zipFile;
        if (password != null && !password.isEmpty()) {
            zipFile = new ZipFile(archivePath, password.toCharArray());
        } else {
            zipFile = new ZipFile(archivePath);
        }

        List<FileHeader> headers = zipFile.getFileHeaders();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        long totalOriginal = 0;
        long totalCompressed = 0;

        if (verbose) {
            System.out.printf("%-40s %12s %12s %7s %20s %s%n",
                    "Name", "Size", "Compressed", "Ratio", "Modified", "Method");
            System.out.println("-".repeat(100));
        }

        for (FileHeader header : headers) {
            long original = header.getUncompressedSize();
            long compressed = header.getCompressedSize();
            totalOriginal += original;
            totalCompressed += compressed;

            if (verbose) {
                double ratio = original > 0 ? (1.0 - (double) compressed / original) * 100 : 0;
                String dateStr = sdf.format(new Date(header.getLastModifiedTimeEpoch()));
                String method = header.getCompressionMethod().name();
                String name = header.getFileName();
                if (name.length() > 40) name = "..." + name.substring(name.length() - 37);

                System.out.printf("%-40s %,12d %,12d %6.1f%% %20s %s%n",
                        name, original, compressed, ratio, dateStr, method);
            } else {
                System.out.println(header.getFileName());
            }
        }

        if (verbose) {
            System.out.println("-".repeat(100));
            double overallRatio = totalOriginal > 0
                    ? (1.0 - (double) totalCompressed / totalOriginal) * 100 : 0;
            System.out.printf("Total: %d files, %,d -> %,d bytes (%.1f%% compression)%n",
                    headers.size(), totalOriginal, totalCompressed, overallRatio);
        }
    }

    public static void verifyArchive(String archivePath, String password) throws ZipException {
        logger.info("Verifying archive: {}", archivePath);

        ZipFile zipFile;
        if (password != null && !password.isEmpty()) {
            zipFile = new ZipFile(archivePath, password.toCharArray());
        } else {
            zipFile = new ZipFile(archivePath);
        }

        if (!zipFile.isValidZipFile()) {
            System.out.println("Verification FAILED: Invalid ZIP file.");
            return;
        }

        List<FileHeader> headers = zipFile.getFileHeaders();
        int errorCount = 0;

        for (FileHeader header : headers) {
            try {
                zipFile.getInputStream(header).close();
            } catch (Exception e) {
                errorCount++;
                System.out.printf("  Error: %s - %s%n", header.getFileName(), e.getMessage());
                logger.warn("Verification error for {}: {}", header.getFileName(), e.getMessage());
            }
        }

        if (errorCount == 0) {
            System.out.printf("Verification OK: %d files checked.%n", headers.size());
        } else {
            System.out.printf("Verification FAILED: %d errors found.%n", errorCount);
        }
    }

    private static List<File> collectFiles(List<String> sources) throws IOException {
        List<File> files = new ArrayList<>();
        for (String source : sources) {
            Path path = Paths.get(source);
            if (Files.isRegularFile(path)) {
                files.add(path.toFile());
            } else if (Files.isDirectory(path)) {
                Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                        files.add(file.toFile());
                        return FileVisitResult.CONTINUE;
                    }
                });
            } else {
                logger.warn("Skipping non-existent path: {}", source);
            }
        }
        return files;
    }

    private static CompressionLevel mapCompressionLevel(int level) {
        if (level <= 1) return CompressionLevel.FASTEST;
        if (level <= 3) return CompressionLevel.FAST;
        if (level <= 6) return CompressionLevel.NORMAL;
        if (level <= 8) return CompressionLevel.HIGHER;
        return CompressionLevel.MAXIMUM;
    }

    private static void printUsage() {
        System.out.println("ZIP Archive Manager - Using zip4j + slf4j");
        System.out.println();
        System.out.println("Commands:");
        System.out.println("  create <output.zip> <source...> [-p password] [-l level] [-s splitSize]");
        System.out.println("  extract <archive.zip> [-o outputDir] [-p password]");
        System.out.println("  list <archive.zip> [-v] [-p password]");
        System.out.println("  verify <archive.zip> [-p password]");
    }
}