<commit_before>package org.carlspring.strongbox.cron.services.impl;

import java.lang.reflect.UndeclaredThrowableException;
import java.util.Iterator;
import java.lang.reflect.UndeclaredThrowableException;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.inject.Inject;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.carlspring.strongbox.cron.config.CronTasksConfigurationFileManager;
import org.carlspring.strongbox.cron.domain.CronTaskConfiguration;
import org.carlspring.strongbox.cron.domain.CronTaskConfigurationDto;
import org.carlspring.strongbox.cron.domain.CronTasksConfigurationDto;
import org.carlspring.strongbox.cron.exceptions.CronTaskConfigurationException;
import org.carlspring.strongbox.cron.services.CronTaskDataService;
import org.carlspring.strongbox.cron.services.support.CronTaskConfigurationSearchCriteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * @author Yougeshwar
 */
@Service
public class CronTaskDataServiceImpl
        implements CronTaskDataService
{

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

    private final ReadWriteLock cronTasksConfigurationLock = new ReentrantReadWriteLock();

    private CronTasksConfigurationFileManager cronTasksConfigurationFileManager;

    /**
     * Yes, this is a state object.
     * It is protected by the {@link #cronTasksConfigurationLock} here
     * and should not be exposed to the world.
     */
    private final CronTasksConfigurationDto configuration;

    @Inject
    public CronTaskDataServiceImpl(CronTasksConfigurationFileManager cronTasksConfigurationFileManager)
    {
        this.cronTasksConfigurationFileManager = cronTasksConfigurationFileManager;
        
        CronTasksConfigurationDto cronTasksConfiguration = cronTasksConfigurationFileManager.read();
        for (Iterator<CronTaskConfigurationDto> iterator = cronTasksConfiguration.getCronTaskConfigurations().iterator(); iterator.hasNext();)
        {
            CronTaskConfigurationDto c = iterator.next();

            logger.debug("Saving cron configuration {}", c);

            String jobClass = c.getProperty("jobClass");
            if (jobClass != null && !jobClass.trim().isEmpty())
            {
                try
                {
                    Class.forName(jobClass);
                }
                catch (ClassNotFoundException e)
                {
                    logger.warn(String.format("Skip configuration, job class not found [%s].", jobClass));
                    iterator.remove();
                }
            }

        }
        
        this.configuration = cronTasksConfiguration;
    }
    
    @Override
    public CronTasksConfigurationDto getTasksConfigurationDto()
    {
        final Lock readLock = cronTasksConfigurationLock.readLock();
        readLock.lock();

        try
        {
            return SerializationUtils.clone(configuration);
        }
        catch (Exception e)
        {
            throw new UndeclaredThrowableException(e);
        }
        finally
        {
            readLock.unlock();
        }
    }

    @Override
    public boolean taskConfigurationexists(String cronTaskConfigurationName)
    {
        return getTaskConfigurationDto(cronTaskConfigurationName) != null;
    }

    @Override
    public CronTaskConfigurationDto getTaskConfigurationDto(String cronTaskConfigurationName)
    {
        final Lock readLock = cronTasksConfigurationLock.readLock();
        readLock.lock();
<commit_msg>SB-1242: merge<commit_after>package org.carlspring.strongbox.cron.services.impl;

import java.lang.reflect.UndeclaredThrowableException;
import java.util.Iterator;
import java.lang.reflect.UndeclaredThrowableException;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.inject.Inject;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.carlspring.strongbox.cron.config.CronTasksConfigurationFileManager;
import org.carlspring.strongbox.cron.domain.CronTaskConfiguration;
import org.carlspring.strongbox.cron.domain.CronTaskConfigurationDto;
import org.carlspring.strongbox.cron.domain.CronTasksConfigurationDto;
import org.carlspring.strongbox.cron.exceptions.CronTaskConfigurationException;
import org.carlspring.strongbox.cron.services.CronTaskDataService;
import org.carlspring.strongbox.cron.services.support.CronTaskConfigurationSearchCriteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * @author Yougeshwar
 */
@Service
public class CronTaskDataServiceImpl
        implements CronTaskDataService
{

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

    private final ReadWriteLock cronTasksConfigurationLock = new ReentrantReadWriteLock();

    private CronTasksConfigurationFileManager cronTasksConfigurationFileManager;

    /**
     * Yes, this is a state object.
     * It is protected by the {@link #cronTasksConfigurationLock} here
     * and should not be exposed to the world.
     */
    private final CronTasksConfigurationDto configuration;

    @Inject
    public CronTaskDataServiceImpl(CronTasksConfigurationFileManager cronTasksConfigurationFileManager)
    {
        this.cronTasksConfigurationFileManager = cronTasksConfigurationFileManager;
        
        CronTasksConfigurationDto cronTasksConfiguration = cronTasksConfigurationFileManager.read();
        for (Iterator<CronTaskConfigurationDto> iterator = cronTasksConfiguration.getCronTaskConfigurations().iterator(); iterator.hasNext();)
        {
            CronTaskConfigurationDto c = iterator.next();

            logger.debug("Saving cron configuration {}", c);

            String jobClass = c.getProperty("jobClass");
            if (jobClass != null && !jobClass.trim().isEmpty())
            {
                try
                {
                    Class.forName(jobClass);
                }
                catch (ClassNotFoundException e)
                {
                    logger.warn(String.format("Skip configuration, job class not found [%s].", jobClass));
                    iterator.remove();
                }
            }

        }
        
        this.configuration = cronTasksConfiguration;
    }
    
    @Override
    public CronTasksConfigurationDto getTasksConfigurationDto()
    {
        final Lock readLock = cronTasksConfigurationLock.readLock();
        readLock.lock();

        try
        {
            return SerializationUtils.clone(configuration);
        }
        catch (Exception e)
        {
            throw new UndeclaredThrowableException(e);
        }
        finally
        {
            readLock.unlock();
        }
    }

    @Override
    public CronTaskConfigurationDto getTaskConfigurationDto(String cronTaskConfigurationName)
    {
        final Lock readLock = cronTasksConfigurationLock.readLock();
        readLock.lock();

{'fraction_non_alphanumeric': 0.08119218910585817, 'fraction_numerical': 0.001541623843782117, 'mean_word_length': 3.251774986346259, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '6822533', 'n_tokens_mistral': 2061, 'n_tokens_neox': 2005, 'n_words': 367}