<commit_before>package org.testcontainers.hivemq;

import com.github.dockerjava.api.command.InspectContainerResponse;
import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class HiveMQContainer extends GenericContainer<HiveMQContainer> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HiveMQContainer.class);

    private static final DockerImageName DEFAULT_HIVEMQ_EE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq4");

    private static final DockerImageName DEFAULT_HIVEMQ_CE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq-ce");

    private static final int DEBUGGING_PORT = 9000;

    private static final int MQTT_PORT = 1883;

    private static final int CONTROL_CENTER_PORT = 8080;

    @SuppressWarnings("OctalInteger")
    private static final int MODE = 0777;

    @NotNull
    private static final Pattern EXTENSION_ID_PATTERN = Pattern.compile("<id>(.+?)</id>");

    @NotNull
    private final ConcurrentHashMap<String, CountDownLatch> containerOutputLatches = new ConcurrentHashMap<>();

    private boolean controlCenterEnabled = false;

    private boolean debugging = false;

    @NotNull
    private final Set<String> prepackagedExtensionsToRemove = new HashSet<>();

    private boolean removeAllPrepackagedExtensions = false;

    @NotNull
    private final WaitAllStrategy waitStrategy = new WaitAllStrategy();

    public HiveMQContainer(final @NotNull DockerImageName dockerImageName) {
        super(dockerImageName);
        dockerImageName.assertCompatibleWith(DEFAULT_HIVEMQ_CE_IMAGE_NAME, DEFAULT_HIVEMQ_EE_IMAGE_NAME);

        addExposedPort(MQTT_PORT);

        waitStrategy.withStrategy(new LogMessageWaitStrategy().withRegEx("(.*)Started HiveMQ in(.*)"));
        waitingFor(waitStrategy);

        withLogConsumer(outputFrame -> {
            final String utf8String = outputFrame.getUtf8String();
            if (debugging && utf8String.startsWith("Listening for transport dt_socket at address:")) {
                System.out.println("Listening for transport dt_socket at address: " + getMappedPort(DEBUGGING_PORT));
            }
            if (!containerOutputLatches.isEmpty()) {
                containerOutputLatches.forEach((regEx, latch) -> {
                    if (outputFrame.getUtf8String().matches("(?s)" + regEx)) {
                        LOGGER.debug("Container Output '{}' matched RegEx '{}'", utf8String, regEx);
                        latch.countDown();
                    } else {
                        LOGGER.debug("Container Output '{}' did not match RegEx '{}'", utf8String, regEx);
                    }
                });
            }
        });

        final HashMap<String, String> tmpFs = new HashMap<>();
        if (dockerImageName.isCompatibleWith(DEFAULT_HIVEMQ_EE_IMAGE_NAME)) {
            tmpFs.put("/opt/hivemq/audit", "rw");
            tmpFs.put("/opt/hivemq/backup", "rw");
        }

        tmpFs.put("/opt/hivemq/log", "rw");
        tmpFs.put("/opt/hivemq/data", "rw");
        withTmpFs(tmpFs);
    }

    @Override
    protected void configure() {
        final String removeCommand;
        withCreateContainerCmdModifier(it -> it.withEntrypoint("/bin/sh"));

        if (removeAllPrepackagedExtensions || !prepackagedExtensionsToRemove.isEmpty()) {
            if (removeAllPrepackagedExtensions) {
                removeCommand = "rm -rf /opt/hivemq/extensions/** &&";
            } else {
                removeCommand =
                    prepackagedExtensionsToRemove
                        .stream()
                        .map(extensionId -> "rm -rf /opt/hivemq/extensions/" + extensionId + "&&")
                        .collect(Collectors.joining());
            }
        } else {
            removeCommand = "";
        }
        setCommand(
            "-c",
            removeCommand +
            "cp -r '/opt/hivemq/temp-extensions/'* /opt/hivemq/extensions/ " +
            "; rm -rf /opt/hivemq/temp-extensions/** " +
            "&& chmod -R 777 /opt/hivemq/extensions " +<commit_msg>[HiveMQ] do not delete /opt/hivemq/temp-extensions in startup command (#5509)<commit_after>package org.testcontainers.hivemq;

import com.github.dockerjava.api.command.InspectContainerResponse;
import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import org.testcontainers.containers.wait.strategy.WaitAllStrategy;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class HiveMQContainer extends GenericContainer<HiveMQContainer> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HiveMQContainer.class);

    private static final DockerImageName DEFAULT_HIVEMQ_EE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq4");

    private static final DockerImageName DEFAULT_HIVEMQ_CE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq-ce");

    private static final int DEBUGGING_PORT = 9000;

    private static final int MQTT_PORT = 1883;

    private static final int CONTROL_CENTER_PORT = 8080;

    @SuppressWarnings("OctalInteger")
    private static final int MODE = 0777;

    @NotNull
    private static final Pattern EXTENSION_ID_PATTERN = Pattern.compile("<id>(.+?)</id>");

    @NotNull
    private final ConcurrentHashMap<String, CountDownLatch> containerOutputLatches = new ConcurrentHashMap<>();

    private boolean controlCenterEnabled = false;

    private boolean debugging = false;

    @NotNull
    private final Set<String> prepackagedExtensionsToRemove = new HashSet<>();

    private boolean removeAllPrepackagedExtensions = false;

    @NotNull
    private final WaitAllStrategy waitStrategy = new WaitAllStrategy();

    public HiveMQContainer(final @NotNull DockerImageName dockerImageName) {
        super(dockerImageName);
        dockerImageName.assertCompatibleWith(DEFAULT_HIVEMQ_CE_IMAGE_NAME, DEFAULT_HIVEMQ_EE_IMAGE_NAME);

        addExposedPort(MQTT_PORT);

        waitStrategy.withStrategy(new LogMessageWaitStrategy().withRegEx("(.*)Started HiveMQ in(.*)"));
        waitingFor(waitStrategy);

        withLogConsumer(outputFrame -> {
            final String utf8String = outputFrame.getUtf8String();
            if (debugging && utf8String.startsWith("Listening for transport dt_socket at address:")) {
                System.out.println("Listening for transport dt_socket at address: " + getMappedPort(DEBUGGING_PORT));
            }
            if (!containerOutputLatches.isEmpty()) {
                containerOutputLatches.forEach((regEx, latch) -> {
                    if (outputFrame.getUtf8String().matches("(?s)" + regEx)) {
                        LOGGER.debug("Container Output '{}' matched RegEx '{}'", utf8String, regEx);
                        latch.countDown();
                    } else {
                        LOGGER.debug("Container Output '{}' did not match RegEx '{}'", utf8String, regEx);
                    }
                });
            }
        });

        final HashMap<String, String> tmpFs = new HashMap<>();
        if (dockerImageName.isCompatibleWith(DEFAULT_HIVEMQ_EE_IMAGE_NAME)) {
            tmpFs.put("/opt/hivemq/audit", "rw");
            tmpFs.put("/opt/hivemq/backup", "rw");
        }

        tmpFs.put("/opt/hivemq/log", "rw");
        tmpFs.put("/opt/hivemq/data", "rw");
        withTmpFs(tmpFs);
    }

    @Override
    protected void configure() {
        final String removeCommand;
        withCreateContainerCmdModifier(it -> it.withEntrypoint("/bin/sh"));

        if (removeAllPrepackagedExtensions || !prepackagedExtensionsToRemove.isEmpty()) {
            if (removeAllPrepackagedExtensions) {
                removeCommand = "rm -rf /opt/hivemq/extensions/** &&";
            } else {
                removeCommand =
                    prepackagedExtensionsToRemove
                        .stream()
                        .map(extensionId -> "rm -rf /opt/hivemq/extensions/" + extensionId + "&&")
                        .collect(Collectors.joining());
            }
        } else {
            removeCommand = "";
        }
        setCommand(
            "-c",
            removeCommand +
            "cp -r '/opt/hivemq/temp-extensions/'* /opt/hivemq/extensions/ " +
            "; chmod -R 777 /opt/hivemq/extensions " +
{'fraction_non_alphanumeric': 0.106629392971246, 'fraction_numerical': 0.006190095846645367, 'mean_word_length': 2.9734232447441493, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7394091', 'n_tokens_mistral': 2933, 'n_tokens_neox': 2774, 'n_words': 531}