<commit_before>// ============================================================================
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// https://github.com/Talend/data-prep/blob/master/LICENSE
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================

package org.talend.dataprep.transformation.service.export;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import org.talend.dataprep.api.export.ExportParameters;
import org.talend.dataprep.api.preparation.PreparationMessage;
import org.talend.dataprep.exception.TDPException;
import org.talend.dataprep.exception.error.PreparationErrorCodes;
import org.talend.dataprep.transformation.cache.CacheKeyGenerator;
import org.talend.dataprep.transformation.cache.TransformationCacheKey;
import org.talend.dataprep.transformation.service.BaseExportStrategy;
import org.talend.dataprep.transformation.service.ExportUtils;

/**
 * A {@link BaseExportStrategy strategy} to reuse previous preparation export if available (if no previous content found
 * {@link #accept(ExportParameters)} returns <code>false</code>).
 */
@Component
public class CachedExportStrategy extends BaseSampleExportStrategy {

    @Autowired
    private CacheKeyGenerator cacheKeyGenerator;

    @Override
    public boolean accept(ExportParameters parameters) {
        if (parameters == null) {
            return false;
        }
        if (parameters.getContent() != null) {
            return false;
        }
        if (StringUtils.isEmpty(parameters.getPreparationId())) {
            return false;
        }
        try {
            final TransformationCacheKey contentKey = getCacheKey(parameters);
            return contentCache.has(contentKey);
        } catch (TDPException e) {
            if (e.getCode() == PreparationErrorCodes.UNABLE_TO_READ_PREPARATION) {
                return false;
            }
            throw e;
        }
    }

    @Override
    public StreamingResponseBody execute(ExportParameters parameters) {
        final TransformationCacheKey contentKey = getCacheKey(parameters);
        ExportUtils.setExportHeaders(parameters.getExportName(), getFormat(parameters.getExportType()));
        return outputStream -> IOUtils.copy(contentCache.get(contentKey), outputStream);
    }

    private TransformationCacheKey getCacheKey(ExportParameters parameters) {
        final PreparationMessage preparation = getPreparation(parameters.getPreparationId());<commit_msg>fix(TDP-4018): fix file leak in previously cached export strategy.<commit_after>// ============================================================================
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// https://github.com/Talend/data-prep/blob/master/LICENSE
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================

package org.talend.dataprep.transformation.service.export;

import java.io.InputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import org.talend.dataprep.api.export.ExportParameters;
import org.talend.dataprep.api.preparation.PreparationMessage;
import org.talend.dataprep.exception.TDPException;
import org.talend.dataprep.exception.error.PreparationErrorCodes;
import org.talend.dataprep.transformation.cache.CacheKeyGenerator;
import org.talend.dataprep.transformation.cache.TransformationCacheKey;
import org.talend.dataprep.transformation.service.BaseExportStrategy;
import org.talend.dataprep.transformation.service.ExportUtils;

/**
 * A {@link BaseExportStrategy strategy} to reuse previous preparation export if available (if no previous content found
 * {@link #accept(ExportParameters)} returns <code>false</code>).
 */
@Component
public class CachedExportStrategy extends BaseSampleExportStrategy {

    @Autowired
    private CacheKeyGenerator cacheKeyGenerator;

    @Override
    public boolean accept(ExportParameters parameters) {
        if (parameters == null) {
            return false;
        }
        if (parameters.getContent() != null) {
            return false;
        }
        if (StringUtils.isEmpty(parameters.getPreparationId())) {
            return false;
        }
        try {
            final TransformationCacheKey contentKey = getCacheKey(parameters);
            return contentCache.has(contentKey);
        } catch (TDPException e) {
            if (e.getCode() == PreparationErrorCodes.UNABLE_TO_READ_PREPARATION) {
                return false;
            }
            throw e;
        }
    }

    @Override
    public StreamingResponseBody execute(ExportParameters parameters) {
        final TransformationCacheKey contentKey = getCacheKey(parameters);
        ExportUtils.setExportHeaders(parameters.getExportName(), getFormat(parameters.getExportType()));
        return outputStream -> {
            try (InputStream cachedContent = contentCache.get(contentKey)) {
                IOUtils.copy(cachedContent, outputStream);
            }
        };
    }

    private TransformationCacheKey getCacheKey(ExportParameters parameters) {
        final PreparationMessage preparation = getPreparation(parameters.getPreparationId());
{'fraction_non_alphanumeric': 0.13835639273212202, 'fraction_numerical': 0.005334222370395066, 'mean_word_length': 3.8504446240905414, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '540244', 'n_tokens_mistral': 1571, 'n_tokens_neox': 1503, 'n_words': 331}