/**
 * Copyright (c) 2011-2012 EBM WebSourcing, 2012-2024 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.bc.filetransfer;

import static com.jayway.awaitility.Awaitility.await;

import java.io.File;
import java.io.FilenameFilter;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.logging.LogRecord;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.MessageExchange.Role;
import javax.jbi.messaging.MessagingException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.attachment.AttachmentUnmarshaller;
import javax.xml.namespace.QName;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.ow2.easywsdl.wsdl.api.abstractItf.AbsItfOperation.MEPPatternConstants;
import org.ow2.petals.bc.filetransfer.service.provide.exception.ListingDirectoryException;
import org.ow2.petals.bc.filetransfer.util.FileTransferUtils;
import org.ow2.petals.bc.filetransfer.util.exception.UnexistingTargetDirectoryException;
import org.ow2.petals.commons.log.FlowAttributesExchangeHelper;
import org.ow2.petals.commons.log.FlowLogData;
import org.ow2.petals.commons.log.Level;
import org.ow2.petals.component.framework.junit.Message;
import org.ow2.petals.component.framework.junit.RequestMessage;
import org.ow2.petals.component.framework.junit.ResponseMessage;
import org.ow2.petals.component.framework.junit.StatusMessage;
import org.ow2.petals.component.framework.junit.helpers.ServiceProviderImplementation;
import org.ow2.petals.component.framework.junit.impl.message.FaultToConsumerMessage;
import org.ow2.petals.component.framework.junit.impl.message.RequestToProviderMessage;
import org.ow2.petals.component.framework.junit.impl.message.ResponseToConsumerMessage;
import org.ow2.petals.component.framework.junit.impl.message.StatusToConsumerMessage;
import org.ow2.petals.component.framework.listener.AbstractListener;
import org.ow2.petals.component.framework.logger.ConsumeExtFlowStepEndLogData;
import org.ow2.petals.component.framework.logger.ConsumeExtFlowStepFailureLogData;
import org.ow2.petals.component.framework.logger.ProvideExtFlowStepFailureLogData;
import org.ow2.petals.component.framework.util.jaxb.JBIAttachmentUnmarshaller;
import org.ow2.petals.components.filetransfer.version_5.AttachmentsType;
import org.ow2.petals.components.filetransfer.version_5.CheckFileType;
import org.ow2.petals.components.filetransfer.version_5.DelType;
import org.ow2.petals.components.filetransfer.version_5.DirResponse;
import org.ow2.petals.components.filetransfer.version_5.DirType;
import org.ow2.petals.components.filetransfer.version_5.GetAsAttachmentResponse;
import org.ow2.petals.components.filetransfer.version_5.GetResponseType;
import org.ow2.petals.components.filetransfer.version_5.GetType;
import org.ow2.petals.components.filetransfer.version_5.MgetResponse;
import org.ow2.petals.components.filetransfer.version_5.MgetType;
import org.ow2.petals.components.filetransfer.version_5.Mput;
import org.ow2.petals.components.filetransfer.version_5.NoFileFound;
import org.ow2.petals.components.filetransfer.version_5.ObjectFactory;
import org.ow2.petals.components.filetransfer.version_5.XmlFileExpected;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.ebmwebsourcing.easycommons.stream.EasyByteArrayOutputStream;
import com.ebmwebsourcing.easycommons.xml.SourceHelper;
import com.jayway.awaitility.Awaitility;
import com.jayway.awaitility.Duration;

/**
 * Unit test of the BC Filetransfer processing external events and message exchanges
 * 
 * @author Christophe DENEUX - Linagora
 * @author Marc Jambert - EBM WebSourcing
 */
public class FileTransferComponentTest extends SimpleTestEnvironment {

    private static final Unmarshaller UNMARSHALLER;

    @Rule
    public final TemporaryFolder consumesFolder = new TemporaryFolder();

    @Rule
    public final TemporaryFolder providesFolder = new TemporaryFolder();

    @Rule
    public final TemporaryFolder backupFolder = new TemporaryFolder();

    static {
        try {
            final JAXBContext context = JAXBContext
                    .newInstance(org.ow2.petals.components.filetransfer.version_5.ObjectFactory.class);
            UNMARSHALLER = context.createUnmarshaller();
        } catch (final JAXBException e) {
            throw new RuntimeException("Error initializing JaxB context", e);
        }
    }

    /**
     * <p>
     * Check the processing of a proxy usecase base on the operation 'put':
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation using a MEP InOnly,</li>
     * <li>on operation 'put' of a FileTransfer provider,</li>
     * <li>where the output directory exists.</li>
     * </ul>
     * <p>
     * At startup of the unit test, the directory where files are listen does not exist. The service unit should be
     * correctly started with a warning message about the unexisting directory. After to have create the directory, the
     * restart the service unit and file processing is successfully.
     * </p>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs during all processing,</li>
     * <li>the file is correctly processed,</li>
     * <li>and a file is written in the output directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void proxyPut() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.getRoot();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String listeningFolderName = "sub-folder";
        final File listeningDirectory = new File(this.consumesFolder.getRoot(), listeningFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesPut(listeningDirectory, FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        COMPONENT_UNDER_TEST.stopService(SU_CONSUMER_NAME);
        this.consumesFolder.newFolder(listeningFolderName);
        COMPONENT_UNDER_TEST.startService(SU_CONSUMER_NAME);

        // We create the external event that fires the SU consume
        final File file = createXmlFile(listeningDirectory);

        // We intercept the exchange sent by the SU consume through a facade service
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage facadeRequest) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, facadeRequest.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.PUT_OPERATION,
                        facadeRequest.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_ONLY.value(), facadeRequest.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, facadeRequest.getMessageExchange().getRole());

                // We forward the service request to the provider part of the proxy usecase
                final RequestMessage request = new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME,
                        facadeRequest);
                FlowAttributesExchangeHelper.setFlowAttributes(request.getMessageExchange(),
                        FlowAttributesExchangeHelper.getFlowAttributes(facadeRequest.getMessageExchange()));
                final StatusMessage status = COMPONENT.sendAndGetStatusAsExternalProvider(request);

                final String[] list = expectedOutputDir.list(new FilenameFilter() {
                    @Override
                    public boolean accept(File dir, String name) {
                        return name.startsWith(expectedFilenameBegin + "-") && name.endsWith(".xml");
                    }
                });

                assertEquals(1, list.length);
                assertEquals(ExchangeStatus.DONE, status.getStatus());

                // We return the expected status to the SU consume
                return new StatusToConsumerMessage(facadeRequest, status);
            }

            @Override
            public boolean statusExpected() {
                // No status is expected by this facade service provider because of InOnly pattern, the status is
                // directly returned to the consumer by this facade service provider
                return false;
            }
        });

        // Wait that the consumer part receive the status DONE
        final int expectedMonitLogNb = 8;
        final int expectedConsumeExtRow = expectedMonitLogNb - 1; // The processing of the status DONE generate the last
                                                                  // MONIT trace of the flow
        await().atMost(Duration.ONE_MINUTE).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == expectedMonitLogNb && logs.get(expectedConsumeExtRow).getParameters().length == 1
                        && logs.get(expectedConsumeExtRow).getParameters()[0] instanceof ConsumeExtFlowStepEndLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(expectedMonitLogNb, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData facadeProviderFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_PUT, monitLogs.get(1));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(facadeProviderFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_PUT, monitLogs.get(2));
        final FlowLogData providerExtFlowLogData = assertMonitProviderExtBeginLog(providerFlowLogData,
                monitLogs.get(3));
        assertEquals(expectedOutputDir.getAbsolutePath(),
                providerExtFlowLogData.get(FiletransferProvideExtFlowStepBeginLogData.DEST_DIR_NAME_KEY));
        assertTrue(providerExtFlowLogData.get(FiletransferProvideExtFlowStepBeginLogData.FILE_NAMES_KEY).toString()
                .startsWith(expectedFilenameBegin));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(4));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(5));
        assertMonitProviderEndLog(facadeProviderFlowLogData, monitLogs.get(6));
        assertMonitConsumerExtEndLog(consumeExtFlowLogData, monitLogs.get(7));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a proxy usecase base on the operation 'put':
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation using Mep 'InOnly',</li>
     * <li>on operation 'put' of a FileTransfer provider,</li>
     * <li>where the output directory does no more exist before to process the message exchange.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs on the provider side because of the missing output directory,</li>
     * <li>the file use as external event is backed-up,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void proxyPutWithFailure() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.newFolder();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesPut(this.consumesFolder.getRoot(), FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(this.consumesFolder.getRoot());

        // We intercept the exchange sent by the SU consume through a facade service
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage facadeRequest) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, facadeRequest.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.PUT_OPERATION,
                        facadeRequest.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_ONLY.value(), facadeRequest.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, facadeRequest.getMessageExchange().getRole());

                // Before to forward the request, we remove the output directory to create an error
                assertTrue(expectedOutputDir.delete());

                // We forward the service request to the provider part of the proxy usecase
                final RequestMessage request = new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME,
                        facadeRequest);
                FlowAttributesExchangeHelper.setFlowAttributes(request.getMessageExchange(),
                        FlowAttributesExchangeHelper.getFlowAttributes(facadeRequest.getMessageExchange()));
                final StatusMessage status = COMPONENT.sendAndGetStatusAsExternalProvider(request);

                assertFalse(expectedOutputDir.exists());
                assertEquals(ExchangeStatus.ERROR, status.getStatus());

                // We return the expected status to the SU consume
                return new StatusToConsumerMessage(facadeRequest, status);
            }

            @Override
            public boolean statusExpected() {
                // No status is expected by this facade service provider because of InOnly pattern, the status is
                // directly returned to the consumer by this facade service provider
                return false;
            }
        }, 3000);

        // Wait that the consumer part receive the status DONE
        final int expectedMonitLogNb = 8;
        final int expectedConsumeExtRow = expectedMonitLogNb - 1; // The processing of the status DONE generate the last
                                                                  // MONIT trace of the flow
        await().atMost(Duration.ONE_MINUTE).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == expectedMonitLogNb && logs.get(expectedConsumeExtRow).getParameters().length == 1
                        && logs.get(expectedConsumeExtRow)
                                .getParameters()[0] instanceof ConsumeExtFlowStepFailureLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(expectedMonitLogNb, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData facadeProviderFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_PUT, monitLogs.get(1));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(facadeProviderFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_PUT, monitLogs.get(2));
        final FlowLogData providerExtFlowLogData = assertMonitProviderExtBeginLog(providerFlowLogData,
                monitLogs.get(3));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(4));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(5));
        assertMonitProviderFailureLog(facadeProviderFlowLogData, monitLogs.get(6));
        assertMonitConsumerExtFailureLog(consumeExtFlowLogData, monitLogs.get(7));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a proxy usecase base on the operation 'put':
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation using Mep 'InOnly',</li>
     * <li>on operation 'put' of a FileTransfer provider,</li>
     * <li>a timeout occurs during the service provider invocation.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs on the consumer side because of the timeout,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void proxyPutWithTimeout() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.newFolder();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesPut(this.consumesFolder.getRoot(), FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(this.consumesFolder.getRoot());

        // We intercept the exchange sent by the SU consume through a facade service
        final RequestMessage facadeRequest = COMPONENT_UNDER_TEST.pollRequestFromConsumer();
        assertEquals(ExchangeStatus.ACTIVE, facadeRequest.getMessageExchange().getStatus());
        assertEquals(FileTransferConstants.PUT_OPERATION,
                facadeRequest.getMessageExchange().getOperation().getLocalPart());
        assertEquals(MEPPatternConstants.IN_ONLY.value(), facadeRequest.getMessageExchange().getPattern());
        assertEquals(Role.PROVIDER, facadeRequest.getMessageExchange().getRole());

        // Wait that a timeout occurs
        Thread.sleep((long) (DEFAULT_TIMEOUT * 1.5));

        // Wait that the consumer part receive the status DONE
        final int expectedMonitLogNb = 3;
        final int expectedConsumeExtRow = expectedMonitLogNb - 1; // The processing of the timeout generates the last
                                                                  // MONIT trace of the flow
        await().atMost(Duration.ONE_MINUTE).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == expectedMonitLogNb && logs.get(expectedConsumeExtRow).getParameters().length == 1
                        && logs.get(expectedConsumeExtRow)
                                .getParameters()[0] instanceof ConsumeExtFlowStepFailureLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(expectedMonitLogNb, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_PUT, monitLogs.get(1));
        assertMonitConsumerExtTimeoutLog(DEFAULT_TIMEOUT, TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_PUT,
                consumeExtFlowLogData, monitLogs.get(2));

        // Assertion about the timeout warning message
        final List<LogRecord> warnRecords = IN_MEMORY_LOG_HANDLER.getAllRecords(java.util.logging.Level.WARNING);
        assertEquals(1, warnRecords.size());
        assertEquals(
                String.format(AbstractListener.TIMEOUT_WARN_LOG_MSG_PATTERN, DEFAULT_TIMEOUT, TEST_ITF.toString(),
                        TEST_SVC.toString(), TEST_EP, TEST_OP_PUT.toString(),
                        consumeExtFlowLogData.get(FlowLogData.FLOW_INSTANCE_ID_PROPERTY_NAME),
                        consumeExtFlowLogData.get(FlowLogData.FLOW_STEP_ID_PROPERTY_NAME)),
                warnRecords.get(0).getMessage());

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a proxy usecase base on the operation 'mput':
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation using a MEP InOnly,</li>
     * <li>on operation 'mput' of a FileTransfer provider,</li>
     * <li>only one attachement to be able to use 'base-msg' with variable 'attachment',</li>
     * <li>where the output directory exists.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs during all processing,</li>
     * <li>the files are correctly processed,</li>
     * <li>and files are written in the output directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void proxyMput() throws Exception {

        final String expectedFilename = "mput-filename.xml";
        final File expectedOutputDir = this.providesFolder.getRoot();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String listeningFolderName = "sub-folder";
        final File listeningDirectory = this.consumesFolder.newFolder(listeningFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesMput(listeningDirectory, FileTransferConstants.ENUM_TRANSFER_MODE_ATTACHMENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilename));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(listeningDirectory, expectedFilename);

        // We intercept the exchange sent by the SU consume through a facade service
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage facadeRequest) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, facadeRequest.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.MPUT_OPERATION,
                        facadeRequest.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_ONLY.value(), facadeRequest.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, facadeRequest.getMessageExchange().getRole());

                // We forward the service request to the provider part of the proxy usecase
                final RequestMessage request = new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME,
                        facadeRequest);
                FlowAttributesExchangeHelper.setFlowAttributes(request.getMessageExchange(),
                        FlowAttributesExchangeHelper.getFlowAttributes(facadeRequest.getMessageExchange()));
                final StatusMessage status = COMPONENT.sendAndGetStatusAsExternalProvider(request);

                final String[] list = expectedOutputDir.list(new FilenameFilter() {
                    @Override
                    public boolean accept(final File dir, final String name) {
                        return name.equals(expectedFilename);
                    }
                });

                assertEquals(1, list.length);
                assertEquals(ExchangeStatus.DONE, status.getStatus());

                // We return the expected status to the SU consume
                return new StatusToConsumerMessage(facadeRequest, status);
            }

            @Override
            public boolean statusExpected() {
                // No status is expected by this facade service provider because of InOnly pattern, the status is
                // directly returned to the consumer by this facade service provider
                return false;
            }
        });

        // Wait that the consumer part receive the status DONE
        final int expectedMonitLogNb = 8;
        final int expectedConsumeExtRow = expectedMonitLogNb - 1; // The processing of the status DONE generate the last
                                                                  // MONIT trace of the flow
        await().atMost(Duration.ONE_MINUTE).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == expectedMonitLogNb && logs.get(expectedConsumeExtRow).getParameters().length == 1
                        && logs.get(expectedConsumeExtRow).getParameters()[0] instanceof ConsumeExtFlowStepEndLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(expectedMonitLogNb, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData facadeProviderFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_MPUT, monitLogs.get(1));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(facadeProviderFlowLogData, TEST_ITF,
                TEST_SVC, TEST_EP, TEST_OP_MPUT, monitLogs.get(2));
        final FlowLogData providerExtFlowLogData = assertMonitProviderExtBeginLog(providerFlowLogData,
                monitLogs.get(3));
        assertEquals(expectedOutputDir.getAbsolutePath(),
                providerExtFlowLogData.get(FiletransferProvideExtFlowStepBeginLogData.DEST_DIR_NAME_KEY));
        assertTrue(providerExtFlowLogData.get(FiletransferProvideExtFlowStepBeginLogData.FILE_NAMES_KEY).toString()
                .contains(expectedFilename));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(4));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(5));
        assertMonitProviderEndLog(facadeProviderFlowLogData, monitLogs.get(6));
        assertMonitConsumerExtEndLog(consumeExtFlowLogData, monitLogs.get(7));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a service consumer linked to a In-Out service provider:
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation with MEP In-Out,</li>
     * <li>an response OUT is returned by the service provider.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is correctly processed,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void consumeInOutServiceProvider_nominal() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.getRoot();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String listeningFolderName = "sub-folder";
        final File listeningDirectory = new File(this.consumesFolder.getRoot(), listeningFolderName);
        this.consumesFolder.newFolder(listeningFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesGet(listeningDirectory, FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(listeningDirectory);

        // We intercept the exchange sent by the SU consume through a facade service
        final String expectedResponse = "<response/>";
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage request) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, request.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.GET_OPERATION,
                        request.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_OUT.value(), request.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, request.getMessageExchange().getRole());

                return new ResponseToConsumerMessage(request, expectedResponse.getBytes());
            }

            @Override
            public void handleStatus(final StatusMessage status) throws Exception {
                assertEquals(ExchangeStatus.DONE, status.getStatus());
            }
        });

        // Wait end of file processing
        Awaitility.await().atMost(30, TimeUnit.SECONDS).until(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == 4 && logs.get(3).getParameters().length == 1
                        && logs.get(3).getParameters()[0] instanceof ConsumeExtFlowStepEndLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF, TEST_SVC,
                TEST_EP, TEST_OP_GET, monitLogs.get(1));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(2));
        assertMonitConsumerExtEndLog(consumeExtFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a service consumer linked to a In-Out service provider:
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation with MEP In-Out,</li>
     * <li>an error is returned by the service provider.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void consumeInOutServiceProvider_error() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.getRoot();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String listeningFolderName = "sub-folder";
        final File listeningDirectory = new File(this.consumesFolder.getRoot(), listeningFolderName);
        this.consumesFolder.newFolder(listeningFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesGet(listeningDirectory, FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(listeningDirectory);

        // We intercept the exchange sent by the SU consume through a facade service
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage request) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, request.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.GET_OPERATION,
                        request.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_OUT.value(), request.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, request.getMessageExchange().getRole());

                return new StatusToConsumerMessage(request,
                        new MessagingException("Error processing the file " + file.getAbsolutePath()));
            }

            @Override
            public boolean statusExpected() {
                return false;
            }
        });

        // Wait end of file processing
        Awaitility.await().atMost(30, TimeUnit.SECONDS).until(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == 4 && logs.get(3).getParameters().length == 1
                        && logs.get(3).getParameters()[0] instanceof ConsumeExtFlowStepFailureLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF, TEST_SVC,
                TEST_EP, TEST_OP_GET, monitLogs.get(1));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(2));
        assertMonitConsumerExtFailureLog(consumeExtFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Check the processing of a service consumer linked to a In-Out service provider:
     * </p>
     * <ul>
     * <li>an external event (a file in a directory) launch a service invocation with MEP In-Out,</li>
     * <li>a fault is returned by the service provider.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>a fault error occurs,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void consumeInOutServiceProvider_fault() throws Exception {

        final String expectedFilenameBegin = "put-filename";
        final File expectedOutputDir = this.providesFolder.getRoot();

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String listeningFolderName = "sub-folder";
        final File listeningDirectory = new File(this.consumesFolder.getRoot(), listeningFolderName);
        this.consumesFolder.newFolder(listeningFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_CONSUMER_NAME,
                createConsumesGet(listeningDirectory, FileTransferConstants.ENUM_TRANSFER_MODE_CONTENT));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(expectedOutputDir, expectedFilenameBegin + ".xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        // We create the external event that fires the SU consume
        final File file = createXmlFile(listeningDirectory);

        // We intercept the exchange sent by the SU consume through a facade service
        final String expectedResponse = "<response/>";
        COMPONENT.receiveAsExternalProvider(new ServiceProviderImplementation() {
            @Override
            public Message provides(final RequestMessage request) throws Exception {

                assertFalse(file.exists());
                assertEquals(ExchangeStatus.ACTIVE, request.getMessageExchange().getStatus());
                assertEquals(FileTransferConstants.GET_OPERATION,
                        request.getMessageExchange().getOperation().getLocalPart());
                assertEquals(MEPPatternConstants.IN_OUT.value(), request.getMessageExchange().getPattern());
                assertEquals(Role.PROVIDER, request.getMessageExchange().getRole());

                return new FaultToConsumerMessage(request, expectedResponse.getBytes());
            }

            @Override
            public void handleStatus(final StatusMessage status) throws Exception {
                assertEquals(ExchangeStatus.DONE, status.getStatus());
            }
        });

        // Wait end of file processing
        Awaitility.await().atMost(30, TimeUnit.SECONDS).until(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                final List<LogRecord> logs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
                if (logs.size() == 4 && logs.get(3).getParameters().length == 1
                        && logs.get(3).getParameters()[0] instanceof ConsumeExtFlowStepFailureLogData) {
                    return true;
                } else {
                    return false;
                }
            }
        });

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData consumeExtFlowLogData = assertMonitConsumerExtBeginLog(monitLogs.get(0));
        assertEquals(file.getAbsolutePath(),
                consumeExtFlowLogData.get(FileTransferConsumeFlowStepBeginLogData.FILEPATH_KEY));
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(consumeExtFlowLogData, TEST_ITF, TEST_SVC,
                TEST_EP, TEST_OP_GET, monitLogs.get(1));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(2));
        assertMonitConsumerExtFailureLog(consumeExtFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_CONSUMER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_CONSUMER_NAME));
        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is correctly retrieved,</li>
     * <li>the file is correctly moved in the backup directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void get() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToGet = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = filePrefix + "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<GetResponseType> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        GetResponseType.class);
                assertNotNull(outPayload.getValue());
                assertNotNull(outPayload.getValue().getAny());
                assertTrue(outPayload.getValue().getAny().get(0) instanceof Element);
                final Element fileContentRootElt = (Element) outPayload.getValue().getAny().get(0);
                assertEquals(new QName(TEST_NS, FileTransferConstants.PUT_OPERATION), buildQName(fileContentRootElt));
                assertEquals("blablabla", fileContentRootElt.getTextContent());

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertFalse("File to read already exists in the initial folder", fileToGet.exists());
        assertEquals("File to read not moved in backup directory", 1,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file without moving it:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is correctly retrieved,</li>
     * <li>the file read is not moved,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getReadOnly() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToGet = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", true));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = filePrefix + "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload.
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<GetResponseType> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        GetResponseType.class);
                assertNotNull(outPayload.getValue());
                assertNotNull(outPayload.getValue().getAny());
                assertTrue(outPayload.getValue().getAny().get(0) instanceof Element);
                final Element fileContentRootElt = (Element) outPayload.getValue().getAny().get(0);
                assertEquals(new QName(TEST_NS, FileTransferConstants.PUT_OPERATION), buildQName(fileContentRootElt));
                assertEquals("blablabla", fileContentRootElt.getTextContent());

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertTrue("File to read no more exists in the initial folder", fileToGet.exists());
        assertEquals("File to read moved in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern,</li>
     * <li>the file is not found (ie. no file matches the file pattern).</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>a fault occurs about the file not found,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getFileNotFound() throws Exception {

        final String filePrefix = "testFile";
        final File fileToGet = File.createTempFile(filePrefix, ".xml", this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = FilenameUtils.removeExtension(fileToGet.getName()) + ".txt";
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNotNull("A fault is not returned", response.getFault());
        assertEquals(0, response.getFaultAttachmentNames().size());
        assertNull(response.getOut());

        // Assert the content of the response fault
        final Object faultObj;
        synchronized (UNMARSHALLER) {
            faultObj = UNMARSHALLER.unmarshal(response.getFault());
        }
        assertNotNull(faultObj);
        assertTrue(faultObj instanceof NoFileFound);
        assertEquals(filePattern, ((NoFileFound) faultObj).getFilename());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertTrue("File to read no more exists in the initial folder", fileToGet.exists());
        assertEquals("File to read moved in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern,</li>
     * <li>the file is not an XML file.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>a fault occurs about the non XML file,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getNotXMLFile() throws Exception {

        final String filePrefix = "testFile";
        final File fileToGet = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = FilenameUtils.removeExtension(fileToGet.getName()) + ".txt";
        payload.setFilename(filePattern);

        // Invoke the service provider
        final StatusMessage response = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNotNull("A fault is not returned", response.getFault());
        assertEquals(0, response.getFaultAttachmentNames().size());
        assertNull(response.getOut());

        // Assert the content of the response fault
        final Object faultObj;
        synchronized (UNMARSHALLER) {
            faultObj = UNMARSHALLER.unmarshal(response.getFault());
        }
        assertNotNull(faultObj);
        assertTrue(faultObj instanceof XmlFileExpected);
        assertEquals(filePattern, ((XmlFileExpected) faultObj).getFilename());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertTrue("File to read no more exists in the initial folder", fileToGet.exists());
        assertEquals("File to read moved in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided with its complete filename (no file pattern),</li>
     * <li>an error occurs reading the file to get.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>The error is returned as fault,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getWithFailure() throws Exception {

        final File fileToGet = this.providesFolder.newFile();
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        payload.setFilename(fileToGet.getName());

        // Before to invoke the service provider, we make the file to get unreadable
        fileToGet.setReadable(false);

        // Invoke the service provider
        final StatusMessage response = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNull(response.getOut());
        assertNotNull(response.getError());

        // Assert the content of the response error
        assertTrue(response.getError().getMessage().contains(fileToGet.getName()));
        assertTrue(response.getError().getMessage().contains("can not be read"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), fileToGet.getName(), monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'get' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void getTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String fileNameToGet = "a-file.txt";
        payload.setFilename(fileNameToGet);

        // Invoke the service provider
        final StatusMessage responseFault = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("An OUT-payload is returned", responseFault.getOut());
        assertNull("A fault is returned", responseFault.getFault());
        assertNotNull(responseFault.getError());

        // Assert the content of the response error
        assertTrue(responseFault.getError() instanceof UnexistingTargetDirectoryException);
        assertTrue(responseFault.getError().getMessage().contains(targetDirectory.getName()));
        assertTrue(responseFault.getError().getMessage()
                .contains("The target directory where files are read/written does not exist"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, fileNameToGet, monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        createXmlFile(targetDirectory, fileNameToGet);
        IN_MEMORY_LOG_HANDLER.clear();
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createGet(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_GET,
                monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, fileNameToGet, monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));
    }

    /**
     * <p>
     * Invoke the operation 'getAsAttachment' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is correctly retrieved,</li>
     * <li>the file is correctly moved in the backup directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getAsAttachment() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToGet = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = filePrefix + "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT.sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_GET_AS_ATTACHMENT, MEPPatternConstants.IN_OUT.value(),
                new ObjectFactory().createGetAsAttachment(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(1, response.getOutAttachmentNames().size());

        // Assert the content of the response payload. We must use the JBI attachment unmarshaller to be able to
        // validate that the response contains files optimized with MTOM
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<GetAsAttachmentResponse> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        GetAsAttachmentResponse.class);
                assertNotNull(outPayload.getValue());
                assertNotNull(outPayload.getValue().getFileContent());
                assertEquals(fileToGet.getName(), outPayload.getValue().getFileContent().getName());

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET_AS_ATTACHMENT, monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertFalse("File to read already exists in the initial folder", fileToGet.exists());
        assertEquals("File to read not moved in backup directory", 1,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'getAsAttachment' on the provider side to retrieve a file without moving it:
     * </p>
     * <ul>
     * <li>the file to get is provided as a file pattern.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is correctly retrieved,</li>
     * <li>the file is not moved,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getAsAttachmentReadOnly() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToGet = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        // Setup assertions
        assertTrue("File to read does not exists in the initial folder", fileToGet.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", true));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = filePrefix + "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT.sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_GET_AS_ATTACHMENT, MEPPatternConstants.IN_OUT.value(),
                new ObjectFactory().createGetAsAttachment(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(1, response.getOutAttachmentNames().size());

        // Assert the content of the response payload. We must use the JBI attachment unmarshaller to be able to
        // validate that the response contains files optimized with MTOM
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<GetAsAttachmentResponse> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        GetAsAttachmentResponse.class);
                assertNotNull(outPayload.getValue());
                assertNotNull(outPayload.getValue().getFileContent());
                assertEquals(fileToGet.getName(), outPayload.getValue().getFileContent().getName());

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET_AS_ATTACHMENT, monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        // Assertion about the file
        assertTrue("File to read no more exists in the initial folder", fileToGet.exists());
        assertEquals("File to read moved in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'getAsAttachment' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the file to get is provided with its complete filename (no file pattern),</li>
     * <li>an error occurs reading the file to get.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>The error is returned as fault,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void getAsAttachmentWithFailure() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToGet = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(fileToGet.getParentFile(), fileToGet.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final GetType payload = new GetType();
        final String filePattern = filePrefix + "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Before to invoke the service provider, we make the file to get unreadable
        fileToGet.setReadable(false);

        // Invoke the service provider
        final StatusMessage response = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_GET_AS_ATTACHMENT, MEPPatternConstants.IN_OUT.value(),
                new ObjectFactory().createGetAsAttachment(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNull(response.getOut());
        assertNotNull(response.getError());

        // Assert the content of the response error
        assertTrue(response.getError().getMessage().contains(fileToGet.getName()));
        assertTrue(response.getError().getMessage().contains("can not be read"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET_AS_ATTACHMENT, monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'getAsAttachment' on the provider side to retrieve a file:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void getAsAttachmentTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final String fileNameToGet = "a-file.txt";

        final GetType payload = new GetType();
        payload.setFilename(fileNameToGet);

        // Invoke the service provider
        final StatusMessage responseError = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(
                COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_GET_AS_ATTACHMENT, MEPPatternConstants.IN_OUT.value(),
                new ObjectFactory().createGetAsAttachment(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("An OUT-payload is returned", responseError.getOut());
        assertNull("A fault is returned", responseError.getFault());
        assertNotNull("An error is not returned", responseError.getError());

        // Assert the content of the response error
        assertTrue(responseError.getError() instanceof UnexistingTargetDirectoryException);
        assertEquals(targetDirectory,
                ((UnexistingTargetDirectoryException) responseError.getError()).getUnexistingDirectory());
        assertTrue(((UnexistingTargetDirectoryException) responseError.getError()).getMessage()
                .contains(targetDirectory.getAbsolutePath()));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET_AS_ATTACHMENT, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, fileNameToGet, monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        createXmlFile(targetDirectory, fileNameToGet);
        IN_MEMORY_LOG_HANDLER.clear();
        final ResponseMessage response = COMPONENT.sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_GET_AS_ATTACHMENT, MEPPatternConstants.IN_OUT.value(),
                new ObjectFactory().createGetAsAttachment(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNull("An error is returned", response.getError());
        assertNotNull(response.getOut());
        assertEquals(1, response.getOutAttachmentNames().size());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_GET_AS_ATTACHMENT, monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, fileNameToGet, monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));
    }

    /**
     * <p>
     * Invoke the operation 'dir' on the provider side to retrieve a directory content:
     * </p>
     * <ul>
     * <li>a valid wild card expression is given.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the list of files matching the wild card expression and contained in the directory are correctly retrieved,
     * </li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void dirWithWildCard() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";

        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final FileTime createTime1 = FileTime.from(Instant.now());
        final FileTime lastModifiedTime1 = FileTime.from(Instant.now());
        final FileTime lastAccessTime1 = FileTime.from(Instant.now());
        Files.getFileAttributeView(file1.toPath(), BasicFileAttributeView.class).setTimes(lastModifiedTime1,
                lastAccessTime1, createTime1);

        final File file2 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());
        final FileTime createTime2 = FileTime.from(Instant.now());
        final FileTime lastModifiedTime2 = FileTime.from(Instant.now());
        final FileTime lastAccessTime2 = FileTime.from(Instant.now());
        Files.getFileAttributeView(file2.toPath(), BasicFileAttributeView.class).setTimes(lastModifiedTime2,
                lastAccessTime2, createTime2);

        final File file3 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file3.getParentFile(), file3.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DirType payload = new DirType();
        final String filePattern = "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        final Object dirRespObj = UNMARSHALLER.unmarshal(response.getOut());
        assertTrue(dirRespObj instanceof DirResponse);
        final DirResponse dirResp = (DirResponse) dirRespObj;
        assertNotNull(dirResp.getFile());
        assertEquals(2, dirResp.getFile().size());
        boolean fileFound1 = false;
        boolean fileFound2 = false;
        for (final org.ow2.petals.components.filetransfer.version_5.DirResponse.File file : dirResp.getFile()) {
            assertNotNull(file.getFilename());
            if (file.getFilename().equals(file1.getName())) {
                fileFound1 = true;
                assertNotNull(file.getCreationTime());
                assertEquals(file.getCreationTime().toGregorianCalendar().toInstant(), createTime1.toInstant());
                assertNotNull(file.getLastModifiedTime());
                assertEquals(file.getLastModifiedTime().toGregorianCalendar().toInstant(),
                        lastModifiedTime1.toInstant());
                assertNotNull(file.getLastAccessTime());
                assertEquals(file.getLastAccessTime().toGregorianCalendar().toInstant(), lastAccessTime1.toInstant());
            } else if (file.getFilename().equals(file2.getName())) {
                fileFound2 = true;
                assertNotNull(file.getCreationTime());
                assertEquals(file.getCreationTime().toGregorianCalendar().toInstant(), createTime2.toInstant());
                assertNotNull(file.getLastModifiedTime());
                assertEquals(file.getLastModifiedTime().toGregorianCalendar().toInstant(),
                        lastModifiedTime2.toInstant());
                assertNotNull(file.getLastAccessTime());
                assertEquals(file.getLastAccessTime().toGregorianCalendar().toInstant(), lastAccessTime2.toInstant());
            } else {
                fail("Unexpected file found: " + file.getFilename());
            }
        }
        assertTrue("File " + file1.getName() + " not found", fileFound1);
        assertTrue("File " + file2.getName() + " not found", fileFound2);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DIR,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'dir' on the provider side to retrieve a directory content:
     * </p>
     * <ul>
     * <li>an empty wild card expression is given.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the list of files contained in the directory is correctly retrieved,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void dirWithEmptyWildCard() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());
        final File file3 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file3.getParentFile(), file3.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DirType payload = new DirType();
        payload.setFilename("");

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        final Object dirRespObj = UNMARSHALLER.unmarshal(response.getOut());
        assertTrue(dirRespObj instanceof DirResponse);
        final DirResponse dirResp = (DirResponse) dirRespObj;
        assertNotNull(dirResp.getFile());
        assertEquals(3, dirResp.getFile().size());
        boolean fileFound1 = false;
        boolean fileFound2 = false;
        boolean fileFound3 = false;
        for (final org.ow2.petals.components.filetransfer.version_5.DirResponse.File file : dirResp.getFile()) {
            assertNotNull(file.getFilename());
            if (file.getFilename().equals(file1.getName())) {
                fileFound1 = true;
            } else if (file.getFilename().equals(file2.getName())) {
                fileFound2 = true;
            } else if (file.getFilename().equals(file3.getName())) {
                fileFound3 = true;
            } else {
                fail("Unexpected file found: " + file.getFilename());
            }
        }
        assertTrue("File " + file1.getName() + " not found", fileFound1);
        assertTrue("File " + file2.getName() + " not found", fileFound2);
        assertTrue("File " + file3.getName() + " not found", fileFound3);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DIR,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), "*", monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'dir' on the provider side to retrieve a directory content:
     * </p>
     * <ul>
     * <li>no wild card expression is given.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the list of files contained in the directory is correctly retrieved,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void dirWithoutWildCard() throws Exception {

        final String filePrefix = "testFile";
        final File file1 = File.createTempFile(filePrefix, ".xml", this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DirType payload = new DirType();

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        final Object dirRespObj = UNMARSHALLER.unmarshal(response.getOut());
        assertTrue(dirRespObj instanceof DirResponse);
        final DirResponse dirResp = (DirResponse) dirRespObj;
        assertNotNull(dirResp.getFile());
        assertEquals(2, dirResp.getFile().size());
        boolean fileFound1 = false;
        boolean fileFound2 = false;
        for (final org.ow2.petals.components.filetransfer.version_5.DirResponse.File file : dirResp.getFile()) {
            assertNotNull(file.getFilename());
            if (file.getFilename().equals(file1.getName())) {
                fileFound1 = true;
            } else if (file.getFilename().equals(file2.getName())) {
                fileFound2 = true;
            } else {
                fail("Unexpected file found: " + file.getFilename());
            }
        }
        assertTrue("File " + file1.getName() + " not found", fileFound1);
        assertTrue("File " + file2.getName() + " not found", fileFound2);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DIR,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), "*", monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'dir' on the provider side to retrieve a directory content:
     * </p>
     * <ul>
     * <li>no wild card expression is given,</li>
     * <li>an error occurs listing files.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs,</li>
     * <li>a fault is returned,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void dirWithFailure() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DirType payload = new DirType();

        // Before to invoke the service provider, we make the directory not readable to generate an error
        this.providesFolder.getRoot().setReadable(false);

        // Invoke the service provider
        final StatusMessage response = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNull(response.getOut());
        assertNotNull(response.getError());

        // Assert the content of the response error
        assertTrue(response.getError() instanceof ListingDirectoryException);
        assertTrue(response.getError().getMessage().contains(this.providesFolder.getRoot().getName()));
        assertTrue(response.getError().getMessage().contains("can not be listed"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DIR,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), "*", monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'dir' on the provider side to retrieve a directory content:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void dirTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DirType payload = new DirType();
        payload.setFilename("*");

        // Invoke the service provider
        final StatusMessage responseFault = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("An OUT-payload is returned", responseFault.getOut());
        assertNull("A fault is returned", responseFault.getFault());
        assertNotNull(responseFault.getError());

        // Assert the content of the response error
        assertTrue(responseFault.getError() instanceof UnexistingTargetDirectoryException);
        assertTrue(responseFault.getError().getMessage().contains(targetDirectory.getName()));
        assertTrue(responseFault.getError().getMessage()
                .contains("The target directory where files are read/written does not exist"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_DIR, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, "*", monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        IN_MEMORY_LOG_HANDLER.clear();
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DIR,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createDir(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DIR,
                monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, "*", monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));
    }

    /**
     * <p>
     * Invoke the operation 'del' on the provider side to delete a directory content:
     * </p>
     * <ul>
     * <li>a valid wild card expression is given.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the list of files matching the wild card and contained in the directory are correctly deleted,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void delWithWildCard() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());
        final File file3 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file3.getParentFile(), file3.getName());

        assertTrue(file1.exists());
        assertTrue(file2.exists());
        assertTrue(file3.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DelType payload = new DelType();
        final String filePattern = "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Invoke the service provider
        final StatusMessage status = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DEL,
                        MEPPatternConstants.IN_ONLY.value(), new ObjectFactory().createDel(payload), MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.DONE, status.getStatus());

        // Assert that files are deleted
        assertFalse(file1.exists());
        assertFalse(file2.exists());
        assertTrue(file3.exists());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DEL,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'del' on the provider side to delete a directory content:
     * </p>
     * <ul>
     * <li>a valid wild card expression is given,</li>
     * <li>an error occurs deleting files.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs,</li>
     * <li>all files are deleted expect the one for which the error occurs,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void delWithFailure() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());

        assertTrue(file1.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DelType payload = new DelType();
        final String filePattern = "*" + fileSuffix;
        payload.setFilename(filePattern);

        // Before to invoke the service provider, we make the directory not writable to generate an error
        this.providesFolder.getRoot().setWritable(false);

        try {
            // Invoke the service provider
            final StatusMessage status = COMPONENT
                    .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DEL,
                            MEPPatternConstants.IN_ONLY.value(), new ObjectFactory().createDel(payload), MARSHALLER));

            // Assert the content of the status
            assertEquals(ExchangeStatus.ERROR, status.getStatus());

            // Assert that files are deleted
            assertTrue(file1.exists());

            // Assertions about MONIT traces
            final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
            assertEquals(4, monitLogs.size());
            final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                    TEST_OP_DEL, monitLogs.get(0));
            final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                    this.providesFolder.getRoot(), filePattern, monitLogs.get(1));
            assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
            assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

            COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
            assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
        } finally {
            // We restore the directory making it writable
            this.providesFolder.getRoot().setWritable(true);
        }
    }

    /**
     * <p>
     * Invoke the operation 'del' on the provider side to delete a directory content:
     * </p>
     * <ul>
     * <li>an empty wild card expression is given.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>no files is deleted,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void delWithEmptyWildCard() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DelType payload = new DelType();
        payload.setFilename("");

        // Invoke the service provider
        final StatusMessage status = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DEL,
                        MEPPatternConstants.IN_ONLY.value(), new ObjectFactory().createDel(payload), MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.DONE, status.getStatus());

        // Assert that no file was deleted
        assertTrue(file1.exists());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DEL,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), "", monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'del' on the provider side to delete a directory content:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void delTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final DelType payload = new DelType();
        payload.setFilename("*");

        // Invoke the service provider
        final StatusMessage statusFault = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DEL,
                        MEPPatternConstants.IN_ONLY.value(), new ObjectFactory().createDel(payload), MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.ERROR, statusFault.getStatus());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_DEL, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, "*", monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        IN_MEMORY_LOG_HANDLER.clear();
        final StatusMessage status = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_DEL,
                        MEPPatternConstants.IN_ONLY.value(), new ObjectFactory().createDel(payload), MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.DONE, status.getStatus());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_DEL,
                monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, "*", monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));
    }

    /**
     * <p>
     * Invoke the operation 'checkFile' on the provider side to check a file:
     * </p>
     * <ul>
     * <li>the existing file is relative to the SU directory.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is checked as existing,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void checkFileRelative() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final CheckFileType payload = new CheckFileType();
        payload.setFilename(file1.getName());

        // Invoke the service provider
        final ResponseMessage response = COMPONENT.sendAndGetResponse(
                new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_CHECKFILE,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createCheckFile(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        final Document responseDoc = SourceHelper.toDocument(response.getOut());
        assertNotNull(responseDoc);
        final Element rootElt = responseDoc.getDocumentElement();
        assertNotNull(rootElt);
        assertEquals(EXPECTED_OP_CHECKFILE_ELT_ROOT, buildQName(rootElt));
        final NodeList filenameNodes = responseDoc.getElementsByTagNameNS(EXPECTED_NODE_FILENAME.getNamespaceURI(),
                EXPECTED_NODE_FILENAME.getLocalPart());
        assertEquals(1, filenameNodes.getLength());
        assertEquals(file1.getAbsolutePath(), filenameNodes.item(0).getTextContent());
        final NodeList fileExistNodes = responseDoc.getElementsByTagNameNS(EXPECTED_NODE_EXIST.getNamespaceURI(),
                EXPECTED_NODE_EXIST.getLocalPart());
        assertEquals(1, fileExistNodes.getLength());
        assertEquals("true", fileExistNodes.item(0).getTextContent());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_CHECKFILE, monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), file1.getName(), monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'checkFile' on the provider side to check a file:
     * </p>
     * <ul>
     * <li>the unexisting file is absolute to the SU directory.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the file is checked as not existing,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void checkFileAbsolute() throws Exception {

        final File file1 = this.providesFolder.newFile("unexisting-file.xml");
        assertTrue(file1.delete());
        assertFalse(file1.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final CheckFileType payload = new CheckFileType();
        payload.setFilename(file1.getAbsolutePath());

        // Invoke the service provider
        final ResponseMessage response = COMPONENT.sendAndGetResponse(
                new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_CHECKFILE,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createCheckFile(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(0, response.getOutAttachmentNames().size());

        // Assert the content of the response payload
        final Document responseDoc = SourceHelper.toDocument(response.getOut());
        assertNotNull(responseDoc);
        final Element rootElt = responseDoc.getDocumentElement();
        assertNotNull(rootElt);
        assertEquals(EXPECTED_OP_CHECKFILE_ELT_ROOT, buildQName(rootElt));
        final NodeList filenameNodes = responseDoc.getElementsByTagNameNS(EXPECTED_NODE_FILENAME.getNamespaceURI(),
                EXPECTED_NODE_FILENAME.getLocalPart());
        assertEquals(1, filenameNodes.getLength());
        assertEquals(file1.getAbsolutePath(), filenameNodes.item(0).getTextContent());
        final NodeList fileExistNodes = responseDoc.getElementsByTagNameNS(EXPECTED_NODE_EXIST.getNamespaceURI(),
                EXPECTED_NODE_EXIST.getLocalPart());
        assertEquals(1, fileExistNodes.getLength());
        assertEquals("false", fileExistNodes.item(0).getTextContent());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_CHECKFILE, monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), file1.getAbsolutePath(), monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'checkFile' on the provider side to check a file:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void checkFileTargetDirDoesNotExist() throws Exception {

        final String fileName = "testFile.xml";

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final CheckFileType payload = new CheckFileType();
        payload.setFilename(fileName);

        // Invoke the service provider
        final StatusMessage responseFault = COMPONENT.sendAndGetStatus(
                new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_CHECKFILE,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createCheckFile(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("An OUT-payload is returned", responseFault.getOut());
        assertNull("A fault is returned", responseFault.getFault());
        assertNotNull(responseFault.getError());

        // Assert the content of the response error
        assertTrue(responseFault.getError() instanceof UnexistingTargetDirectoryException);
        assertTrue(responseFault.getError().getMessage().contains(targetDirectory.getName()));
        assertTrue(responseFault.getError().getMessage()
                .contains("The target directory where files are read/written does not exist"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_CHECKFILE, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, fileName, monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        IN_MEMORY_LOG_HANDLER.clear();
        createXmlFile(targetDirectory, fileName);
        final ResponseMessage succeededResponse = COMPONENT.sendAndGetResponse(
                new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_CHECKFILE,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createCheckFile(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", succeededResponse.getFault());
        assertNotNull(succeededResponse.getOut());
        assertEquals(0, succeededResponse.getOutAttachmentNames().size());

        // Assertions about MONIT traces
        final List<LogRecord> succeededMonitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, succeededMonitLogs.size());
        final FlowLogData providerFlowLogDataSucceeded = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_CHECKFILE, succeededMonitLogs.get(0));
        final FlowLogData providerExtFlowLogDataSucceeded = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataSucceeded, targetDirectory, fileName, succeededMonitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogDataSucceeded, succeededMonitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogDataSucceeded, succeededMonitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mput' on the provider side to push several files.
     * </p>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the list of files matching the wild card and contained in the directory are correctly deleted,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mput() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToPut1 = File.createTempFile(filePrefix, fileSuffix, this.consumesFolder.getRoot());
        createXmlFile(fileToPut1.getParentFile(), fileToPut1.getName());
        assertTrue(fileToPut1.exists());
        final File fileToPut2 = File.createTempFile(filePrefix, ".txt", this.consumesFolder.getRoot());
        createXmlFile(fileToPut2.getParentFile(), fileToPut2.getName());
        assertTrue(fileToPut2.exists());

        final File expectedFile1 = new File(this.providesFolder.getRoot(), fileToPut1.getName());
        assertFalse("Expected file exists", expectedFile1.exists());
        final File expectedFile2 = new File(this.providesFolder.getRoot(), fileToPut2.getName());
        assertFalse("Expected file exists", expectedFile2.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final Mput payload = new Mput();
        final AttachmentsType attachments = new AttachmentsType();
        payload.setAttachments(attachments);
        attachments.getFilename().add(new DataHandler(new FileDataSource(fileToPut1)));
        attachments.getFilename().add(new DataHandler(new FileDataSource(fileToPut2)));

        // Invoke the service provider
        final StatusMessage status = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_MPUT, MEPPatternConstants.IN_ONLY.value(), payload, MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.DONE, status.getStatus());

        // Assert that files are put
        assertTrue(new File(this.providesFolder.getRoot(), fileToPut1.getName()).exists());
        assertTrue(new File(this.providesFolder.getRoot(), fileToPut2.getName()).exists());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MPUT,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { fileToPut1.getName(), fileToPut2.getName() },
                monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mput' on the provider side to push several files:
     * </p>
     * <ul>
     * <li>an error occurs pushing files.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mputWithFailure() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File fileToPut = File.createTempFile(filePrefix, fileSuffix, this.consumesFolder.getRoot());
        createXmlFile(fileToPut.getParentFile(), fileToPut.getName());
        assertTrue(fileToPut.exists());

        final File expectedFile = new File(this.providesFolder.getRoot(), fileToPut.getName());
        assertFalse("Expected file exists", expectedFile.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final Mput payload = new Mput();
        final AttachmentsType attachments = new AttachmentsType();
        payload.setAttachments(attachments);
        final DataSource dataSource1 = new FileDataSource(fileToPut);
        attachments.getFilename().add(new DataHandler(dataSource1));

        // Before to invoke the service provider, we make the directory not writable to generate an error
        this.providesFolder.getRoot().setWritable(false);

        // Invoke the service provider
        final StatusMessage status = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_MPUT, MEPPatternConstants.IN_ONLY.value(), payload, MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.ERROR, status.getStatus());

        // Assert that files are put
        assertFalse(expectedFile.exists());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MPUT,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { fileToPut.getName() }, monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mput' on the provider side to push several files:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void mputTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final File fileToPut = File.createTempFile("file", ".txt", this.consumesFolder.getRoot());
        createXmlFile(fileToPut.getParentFile(), fileToPut.getName());
        assertTrue(fileToPut.exists());

        final File expectedFile = new File(targetDirectory, fileToPut.getName());
        assertFalse("Expected file exists", expectedFile.exists());

        final Mput payload = new Mput();
        final AttachmentsType attachments = new AttachmentsType();
        payload.setAttachments(attachments);
        final DataSource dataSource1 = new FileDataSource(fileToPut);
        attachments.getFilename().add(new DataHandler(dataSource1));

        final StatusMessage statusError = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_MPUT, MEPPatternConstants.IN_ONLY.value(), payload, MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.ERROR, statusError.getStatus());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_MPUT, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, "(" + fileToPut.getName() + ")", monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        // Assertion about the written file
        assertFalse("Expected file exists", expectedFile.exists());

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        IN_MEMORY_LOG_HANDLER.clear();
        final StatusMessage status = COMPONENT.sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST,
                SU_PROVIDER_NAME, TEST_OP_MPUT, MEPPatternConstants.IN_ONLY.value(), payload, MARSHALLER));

        // Assert the content of the status
        assertEquals(ExchangeStatus.DONE, status.getStatus());

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MPUT,
                monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, "(" + fileToPut.getName() + ")", monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));

        // Assertion about the written file
        assertTrue("Expected file does not exist", expectedFile.exists());
    }

    /**
     * <p>
     * Invoke the operation 'mget' on the provider side to retrieve several files:
     * </p>
     * <ul>
     * <li>files are retrieved individually, without providing a wild card expression.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the files are correctly retrieved,</li>
     * <li>the files are correctly moved in the backup directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mgetWithoutWildCard() throws Exception {

        final String filePrefix = "testFile";
        final File file1 = File.createTempFile(filePrefix, ".xml", this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());

        // Setup assertions
        assertTrue("File #1 to read does not exists in the initial folder", file1.exists());
        assertTrue("File #2 to read does not exists in the initial folder", file2.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final MgetType payload = new MgetType();
        payload.getFilename().add(file1.getName());
        payload.getFilename().add(file2.getName());

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertFalse("A fault is returned", response.isFault());
        assertNotNull(response.getOut());
        assertEquals(2, response.getOutAttachmentNames().size());
        assertNotNull(response.getOutAttachment(file1.getName()));
        assertNotNull(response.getOutAttachment(file2.getName()));

        // Assert the content of the response payload. We must use the JBI attachment unmarshaller to be able to
        // validate that the response contains files optimized with MTOM
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<MgetResponse> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        MgetResponse.class);
                assertNotNull(outPayload.getValue());
                assertEquals(2, outPayload.getValue().getFileContent().size());

                boolean fileFound1 = false;
                boolean fileFound2 = false;
                for (int i = 0; i <= 1; i++) {
                    final DataHandler dh = outPayload.getValue().getFileContent().get(i);
                    assertNotNull(dh);
                    if (dh.getName().equals(file1.getName())) {
                        fileFound1 = true;
                    } else if (dh.getName().equals(file2.getName())) {
                        fileFound2 = true;
                    } else {
                        fail("Unexpected file found: " + dh.getName());
                    }
                }
                assertTrue("File " + file1.getName() + " found", fileFound1);
                assertTrue("File " + file2.getName() + " found", fileFound2);

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assert that files are no more available in initial directory
        assertFalse(file1.exists());
        assertFalse(file2.exists());

        // Assertion about the files
        assertFalse("File #1 to read already exists in the initial folder", file1.exists());
        assertFalse("File #2 to read already exists in the initial folder", file2.exists());
        assertEquals("Files to read not moved in backup directory", 2,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MGET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { file1.getName(), file2.getName() }, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mget' on the provider side to get several files:
     * </p>
     * <ul>
     * <li>an error occurs getting files.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mgetWithFailure() throws Exception {

        final String filePrefix = "testFile";
        final File file1 = File.createTempFile(filePrefix, ".xml", this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());

        assertTrue(file1.exists());
        assertTrue(file2.exists());

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(this.providesFolder.getRoot(), "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final MgetType payload = new MgetType();
        payload.getFilename().add(file1.getName());
        payload.getFilename().add(file2.getName());

        // Before to invoke the service provider, we make the directory not writable to generate an error
        this.providesFolder.getRoot().setReadable(false);

        // Invoke the service provider
        final StatusMessage response = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNull(response.getOut());
        assertNotNull(response.getError());

        // Assert the content of the response error
        assertTrue(response.getError() instanceof ListingDirectoryException);
        assertTrue(response.getError().getMessage().contains(this.providesFolder.getRoot().getName()));
        assertTrue(response.getError().getMessage().contains("can not be listed"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MGET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { file1.getName(), file2.getName() }, monitLogs.get(1));
        assertMonitProviderExtFailureLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderFailureLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mget' on the provider side to retrieve several files:
     * </p>
     * <ul>
     * <li>files are retrieved with wildcard.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the files are correctly retrieved,</li>
     * <li>the files are correctly moved in the backup directory,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mgetWithWildCard() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());
        final File file3 = File.createTempFile(filePrefix, ".log", this.providesFolder.getRoot());
        createXmlFile(file3.getParentFile(), file3.getName());

        // Setup assertions
        assertTrue("File #1 to read does not exists in the initial folder", file1.exists());
        assertTrue("File #2 to read does not exists in the initial folder", file2.exists());
        assertTrue("File #3 to read does not exists in the initial folder", file3.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", this.backupFolder.getRoot()));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final MgetType payload = new MgetType();
        final String filePattern = "*" + fileSuffix;
        payload.getFilename().add(filePattern);
        payload.getFilename().add(file2.getName());

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertFalse("A fault is returned", response.isFault());
        assertNotNull(response.getOut());
        assertEquals(2, response.getOutAttachmentNames().size());
        assertNotNull(response.getOutAttachment(file1.getName()));
        assertNotNull(response.getOutAttachment(file2.getName()));

        // Assert the content of the response payload. We must use the JBI attachment unmarshaller to be able to
        // validate that the response contains files optimized with MTOM
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<MgetResponse> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        MgetResponse.class);
                assertNotNull(outPayload.getValue());
                assertEquals(2, outPayload.getValue().getFileContent().size());

                boolean fileFound1 = false;
                boolean fileFound2 = false;
                for (int i = 0; i <= 1; i++) {
                    final DataHandler dh = outPayload.getValue().getFileContent().get(i);
                    assertNotNull(dh);
                    if (dh.getName().equals(file1.getName())) {
                        fileFound1 = true;
                    } else if (dh.getName().equals(file2.getName())) {
                        fileFound2 = true;
                    } else {
                        fail("Unexpected file found: " + dh.getName());
                    }
                }
                assertTrue("File " + file1.getName() + " found", fileFound1);
                assertTrue("File " + file2.getName() + " found", fileFound2);

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertion about the files
        assertFalse("File #1 to read already exists in the initial folder", file1.exists());
        assertFalse("File #2 to read already exists in the initial folder", file2.exists());
        assertTrue("File #3 to read does not exists in the initial folder", file3.exists());
        assertEquals("Files to read not moved in backup directory", 2,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MGET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { filePattern, file2.getName() }, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mget' on the provider side to retrieve several files without moving them:
     * </p>
     * <ul>
     * <li>files are retrieved with wildcard.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>no error occurs,</li>
     * <li>the files are correctly retrieved,</li>
     * <li>the files are not moved,</li>
     * <li>MONIT traces are as expected.</li>
     * </ul>
     */
    @Test
    public void mgetWithWildCardReadOnly() throws Exception {

        final String filePrefix = "testFile";
        final String fileSuffix = ".xml";
        final File file1 = File.createTempFile(filePrefix, fileSuffix, this.providesFolder.getRoot());
        createXmlFile(file1.getParentFile(), file1.getName());
        final File file2 = File.createTempFile(filePrefix, ".txt", this.providesFolder.getRoot());
        createXmlFile(file2.getParentFile(), file2.getName());
        final File file3 = File.createTempFile(filePrefix, ".log", this.providesFolder.getRoot());
        createXmlFile(file3.getParentFile(), file3.getName());

        // Setup assertions
        assertTrue("File #1 to read does not exists in the initial folder", file1.exists());
        assertTrue("File #2 to read does not exists in the initial folder", file2.exists());
        assertTrue("File #3 to read does not exists in the initial folder", file3.exists());
        assertTrue("Backup directory does not exist", this.backupFolder.getRoot().exists());
        assertEquals("At least one file exists in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME,
                createProvides(this.providesFolder.getRoot(), "toto.xml", true));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final MgetType payload = new MgetType();
        final String filePattern = "*" + fileSuffix;
        payload.getFilename().add(filePattern);
        payload.getFilename().add(file2.getName());

        // Invoke the service provider
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertFalse("A fault is returned", response.isFault());
        assertNotNull(response.getOut());
        assertEquals(2, response.getOutAttachmentNames().size());
        assertNotNull(response.getOutAttachment(file1.getName()));
        assertNotNull(response.getOutAttachment(file2.getName()));

        final OutputStream ebaos1 = new EasyByteArrayOutputStream();
        assertEquals("Invalid size retrieved", file1.length(),
                IOUtils.copy(response.getOutAttachment(file1.getName()).getInputStream(), ebaos1));
        final OutputStream ebaos2 = new EasyByteArrayOutputStream();
        assertEquals("Invalid size retrieved", file2.length(),
                IOUtils.copy(response.getOutAttachment(file2.getName()).getInputStream(), ebaos2));

        // Assert the content of the response payload. We must use the JBI attachment unmarshaller to be able to
        // validate that the response contains files optimized with MTOM
        synchronized (UNMARSHALLER) {
            final AttachmentUnmarshaller attachmentUnmarshallerOld = UNMARSHALLER.getAttachmentUnmarshaller();
            UNMARSHALLER.setAttachmentUnmarshaller(
                    new JBIAttachmentUnmarshaller(response.getMessageExchange().getMessage("OUT")));
            try {
                final JAXBElement<MgetResponse> outPayload = UNMARSHALLER.unmarshal(response.getOut(),
                        MgetResponse.class);
                assertNotNull(outPayload.getValue());
                assertEquals(2, outPayload.getValue().getFileContent().size());

                boolean fileFound1 = false;
                boolean fileFound2 = false;
                for (int i = 0; i <= 1; i++) {
                    final DataHandler dh = outPayload.getValue().getFileContent().get(i);
                    assertNotNull(dh);
                    if (dh.getName().equals(file1.getName())) {
                        fileFound1 = true;
                    } else if (dh.getName().equals(file2.getName())) {
                        fileFound2 = true;
                    } else {
                        fail("Unexpected file found: " + dh.getName());
                    }
                }
                assertTrue("File " + file1.getName() + " found", fileFound1);
                assertTrue("File " + file2.getName() + " found", fileFound2);

            } catch (final JAXBException e) {
                throw new MessagingException(e);
            } finally {
                UNMARSHALLER.setAttachmentUnmarshaller(attachmentUnmarshallerOld);
            }
        }

        // Assertion about the files
        assertTrue("File #1 to read does not exists in the initial folder", file1.exists());
        assertTrue("File #2 to read does not exists in the initial folder", file2.exists());
        assertTrue("File #3 to read does not exists in the initial folder", file3.exists());
        assertEquals("At least on file to read was moved in backup directory", 0,
                FileTransferUtils.listFiles(this.backupFolder.getRoot(), "*").length);

        // Assertions about MONIT traces
        final List<LogRecord> monitLogs = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogs.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MGET,
                monitLogs.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                this.providesFolder.getRoot(), new String[] { filePattern, file2.getName() }, monitLogs.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogs.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogs.get(3));

        COMPONENT_UNDER_TEST.undeployService(SU_PROVIDER_NAME);
        assertFalse(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));
    }

    /**
     * <p>
     * Invoke the operation 'mget' on the provider side to retrieve several files:
     * </p>
     * <ul>
     * <li>the target directory does not exist.</li>
     * </ul>
     * <p>
     * Expected results:
     * </p>
     * <ul>
     * <li>an error occurs, and MONIT traces are as expected,</li>
     * <li>after to have created the directory, and restarted the SU, all work's fine.</li>
     * </ul>
     */
    @Test
    public void mgetTargetDirDoesNotExist() throws Exception {

        assertTrue(COMPONENT_UNDER_TEST.isInstalled());
        assertTrue(COMPONENT_UNDER_TEST.isStarted());

        final String targetFolderName = "sub-folder";
        final File targetDirectory = new File(this.providesFolder.getRoot(), targetFolderName);

        COMPONENT_UNDER_TEST.deployService(SU_PROVIDER_NAME, createProvides(targetDirectory, "toto.xml"));
        assertTrue(COMPONENT_UNDER_TEST.isServiceDeployed(SU_PROVIDER_NAME));

        final MgetType payload = new MgetType();
        payload.getFilename().add("*");

        // Invoke the service provider
        final StatusMessage responseFault = COMPONENT
                .sendAndGetStatus(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("An OUT-payload is returned", responseFault.getOut());
        assertNull("A fault is returned", responseFault.getFault());
        assertNotNull(responseFault.getError());

        // Assert the content of the response error
        assertTrue(responseFault.getError() instanceof UnexistingTargetDirectoryException);
        assertTrue(responseFault.getError().getMessage().contains(targetDirectory.getName()));
        assertTrue(responseFault.getError().getMessage()
                .contains("The target directory where files are read/written does not exist"));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsWithFault = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsWithFault.size());
        final FlowLogData providerFlowLogDataFault = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP,
                TEST_OP_MGET, monitLogsWithFault.get(0));
        final FlowLogData providerExtBeginFlowLogDataFault = assertMonitFileTransferProviderExtBeginLog(
                providerFlowLogDataFault, null, "(*)", monitLogsWithFault.get(1));
        final FlowLogData providerExtFailureFlowLogDataFault = assertMonitProviderExtFailureLog(
                providerExtBeginFlowLogDataFault, monitLogsWithFault.get(2));
        assertTrue(((String) providerExtFailureFlowLogDataFault
                .get(ProvideExtFlowStepFailureLogData.FLOW_STEP_FAILURE_MESSAGE_NAME))
                        .contains(targetDirectory.getAbsolutePath()));
        assertMonitProviderFailureLog(providerFlowLogDataFault, monitLogsWithFault.get(3));

        COMPONENT_UNDER_TEST.stopService(SU_PROVIDER_NAME);
        this.providesFolder.newFolder(targetFolderName);
        COMPONENT_UNDER_TEST.startService(SU_PROVIDER_NAME);

        // Invoke the service provider
        final String fileNameToGet = "a-file.txt";
        createXmlFile(targetDirectory, fileNameToGet);
        IN_MEMORY_LOG_HANDLER.clear();
        final ResponseMessage response = COMPONENT
                .sendAndGetResponse(new RequestToProviderMessage(COMPONENT_UNDER_TEST, SU_PROVIDER_NAME, TEST_OP_MGET,
                        MEPPatternConstants.IN_OUT.value(), new ObjectFactory().createMget(payload), MARSHALLER));

        // Assert the content of the response
        assertNull("A fault is returned", response.getFault());
        assertNotNull(response.getOut());
        assertEquals(1, response.getOutAttachmentNames().size());
        assertNotNull(response.getOutAttachment(fileNameToGet));

        // Assertions about MONIT traces
        final List<LogRecord> monitLogsSucceeded = IN_MEMORY_LOG_HANDLER.getAllRecords(Level.MONIT);
        assertEquals(4, monitLogsSucceeded.size());
        final FlowLogData providerFlowLogData = assertMonitProviderBeginLog(TEST_ITF, TEST_SVC, TEST_EP, TEST_OP_MGET,
                monitLogsSucceeded.get(0));
        final FlowLogData providerExtFlowLogData = assertMonitFileTransferProviderExtBeginLog(providerFlowLogData,
                targetDirectory, "(*)", monitLogsSucceeded.get(1));
        assertMonitProviderExtEndLog(providerExtFlowLogData, monitLogsSucceeded.get(2));
        assertMonitProviderEndLog(providerFlowLogData, monitLogsSucceeded.get(3));
    }
}
