/**
 * Copyright (c) 2010-2012 EBM WebSourcing, 2012-2015 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.log.handler;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

import javax.jbi.messaging.NormalizedMessage;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.junit.Test;
import org.ow2.petals.commons.log.FlowLogData;
import org.ow2.petals.commons.log.Level;
import org.ow2.petals.commons.log.LogData;
import org.ow2.petals.commons.log.PetalsExecutionContext;
import org.ow2.petals.commons.log.TestLogData;
import org.ow2.petals.commons.log.TraceCode;
import org.ow2.petals.jbi.messaging.exchange.MEPPatternConstants;
import org.ow2.petals.jbi.messaging.exchange.MessageExchangeImpl;
import org.ow2.petals.log.LogRecordHelper;
import org.ow2.petals.log.formatter.LogDataFormatter;

import com.ebmwebsourcing.easycommons.lang.UncheckedException;
import com.ebmwebsourcing.easycommons.thread.ExecutionContext;
import com.ebmwebsourcing.easycommons.thread.TestThread;

public class PetalsPayloadDumperFileHandlerTest extends AbstractTestPetalsFileHandler {

    /**
     * Check the loading of the logging configuration against a default standard
     * configuration using only relative paths,except for 'basedir'.
     */
    @Test
    public void testConfigurationWithAllPropertiesCorrectlySetAsRelativePaths() throws Exception {

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("logConf.properties");
            try {
                assertNotNull("Log file configuration not found", is);
                manager.readConfiguration(is);
            } finally {
                is.close();
            }
            final PrintStream standardConsoleError = System.err;

            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("Configuration error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }

    }

    /**
     * Check the loading of the logging configuration against a default standard
     * configuration overridden with a not absolute base dir
     */
    @Test
    public void testConfigurationWithAllPropertiesCorrectlySetWithARelativeBaseDir()
            throws Exception {

        // Generate the log conf file
        final String relativeBaseDir = "relative" + File.separator + "base" + File.separator
                + "dir";
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, relativeBaseDir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertFalse("No configuration error occurs", error.isEmpty());
                assertTrue("Unexpected error message", error.contains(relativeBaseDir));
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(temporaryRootDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                assertEquals(new File(temporaryRootDir, FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }

    }

    /**
     * Check the loading of the logging configuration against a default standard
     * configuration overridden with an absolute flow sub dir
     */
    @Test
    public void testConfigurationWithAllPropertiesCorrectlySetWithAnAbsoluteFlowSubDir()
            throws Exception {

        // Generate the log conf file
        final File absoluteFlowSubDir = this.tempFolder.newFolder("flowsSubDir");
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.FLOW_LOG_SUBDIR_PROPERTY_NAME,
                        absoluteFlowSubDir.getCanonicalPath());
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("Configuration error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(absoluteFlowSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }

    }

    /**
     * Check the use of the default configuration
     * 
     * @throws Exception
     */
    @Test
    public void testDefaultConfiguration() throws Exception {
        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        final PrintStream standardConsoleError = System.err;
        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));

            final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();
            final String error = errBAIS.toString();
            assertTrue("Configuration error occurs", error.isEmpty());
            assertSame(Level.INFO, pfh.getLevel());
            assertEquals(temporaryRootDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
            assertEquals(new File(temporaryRootDir, PetalsFileHandler.DEFAULT_FLOW_LOG_SUBDIR).getCanonicalPath(),
                    pfh.flowsSubdir.getCanonicalPath());
            assertEquals(PetalsFileHandler.DEFAULT_LOGFILENAME, pfh.logfilename);
            assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
        } finally {
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check a configuration with an empty log file name
     */
    @Test
    public void testConstructionWithEmptyLogFilename() throws Exception {
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.LOGFILENAME_PROPERTY_NAME, "");
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("Configuration error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(PetalsFileHandler.DEFAULT_LOGFILENAME, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check a configuration with an log file name containing directory
     */
    @Test
    public void testConstructionWithFileSeparatorInLogFilename() throws Exception {
        final String logFilename = "test" + File.separator + "filename";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.LOGFILENAME_PROPERTY_NAME, logFilename);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertFalse("No error occurs", error.isEmpty());
                assertEquals("Unexpected error",
                        PetalsFileHandler.ERROR_LOGFILENAME_WITH_SEPARATOR, error.trim());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(PetalsFileHandler.DEFAULT_LOGFILENAME, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check a configuration with a loop in property definition of basedir
     */
    @Test
    public void testConstructionWithLoopPropertyInBasedir() throws Exception {

        final String loopPropertyName = "test.loop1";
        final String basedir = "baseDirTest" + File.separator + "${" + loopPropertyName + "}";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, basedir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        System.setProperty(loopPropertyName, "testBaseDir/${" + loopPropertyName + "}");
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertFalse("No error occurs", error.isEmpty());
                assertTrue("Unexpected error", error.contains(loopPropertyName));
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(temporaryRootDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                assertEquals(new File(temporaryRootDir, FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
            System.clearProperty(loopPropertyName);
        }
    }

    /**
     * Check a configuration with a resolvable property in definition of basedir
     */
    @Test
    public void testConstructionWithResolvablePropertyInBasedir() throws Exception {

        final String resolvablePropertyName = "test.resolvable";
        final String resolvablePropertyValue = "testBaseDirValue";
        final String basedir = PetalsFileHandler.DEFAULT_BASEDIR + File.separator + "${"
                + resolvablePropertyName + "}";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, basedir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        System.setProperty(resolvablePropertyName, resolvablePropertyValue);
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, resolvablePropertyValue).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, resolvablePropertyValue),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
            System.clearProperty(resolvablePropertyName);
        }
    }

    /**
     * Check a configuration with a resolvable property in definition of basedir
     */
    @Test
    public void testConstructionWithUnresolvedPropertyInBasedir() throws Exception {

        final String unresolvablePropertyName = "test.unresolvable";
        final String unresolvablePlaceholder = "${" + unresolvablePropertyName + "}";
        final String basedir = PetalsFileHandler.DEFAULT_BASEDIR + File.separator
                + unresolvablePlaceholder;
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, basedir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, unresolvablePlaceholder).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, unresolvablePlaceholder),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check a configuration with a loop in property definition of flows sub dir
     */
    @Test
    public void testConstructionWithLoopPropertyInFlowsSubdir() throws Exception {

        final String loopPropertyName = "test.loop1";
        final String flowsSubdir = "flowsSubDirTest" + File.separator + "${" + loopPropertyName
                + "}";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.FLOW_LOG_SUBDIR_PROPERTY_NAME, flowsSubdir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        System.setProperty(loopPropertyName, "testBaseDir/${" + loopPropertyName + "}");
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertFalse("No error occurs", error.isEmpty());
                assertTrue("Unexpected error", error.contains(loopPropertyName));
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                        PetalsFileHandler.DEFAULT_FLOW_LOG_SUBDIR).getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
            System.clearProperty(loopPropertyName);
        }
    }

    /**
     * Check a configuration with a resolvable property in definition of flows
     * subdir
     */
    @Test
    public void testConstructionWithResolvablePropertyInFlowsSubdir() throws Exception {

        final String resolvablePropertyName = "test.resolvable";
        final String resolvablePropertyValue = "testFlowsSubDir";
        final String flowsSubdir = "${" + resolvablePropertyName + "}";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.FLOW_LOG_SUBDIR_PROPERTY_NAME, flowsSubdir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        System.setProperty(resolvablePropertyName, resolvablePropertyValue);
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(
                        new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE), resolvablePropertyValue)
                                .getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
            System.clearProperty(resolvablePropertyName);
        }
    }

    /**
     * Check a configuration with a resolvable property in definition of the
     * flows subdir
     */
    @Test
    public void testConstructionWithUnresolvedPropertyInFlowsSubdir() throws Exception {

        final String unresolvablePropertyName = "test.unresolvable";
        final String unresolvablePlaceholder = "${" + unresolvablePropertyName + "}";
        final String flowsSubdir = unresolvablePlaceholder;
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.FLOW_LOG_SUBDIR_PROPERTY_NAME, flowsSubdir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(
                        new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE), unresolvablePlaceholder)
                                .getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());
            } finally {
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check the generation of a log trace with an unresolvable property in
     * definition of basedir
     */
    @Test
    public void testPublishWithUnresolvedPropertyInBasedir() throws Exception {

        final String unresolvablePropertyName = "test.unresolvable";
        final String unresolvablePlaceholder = "${" + unresolvablePropertyName + "}";
        final String basedir = PetalsFileHandler.DEFAULT_BASEDIR + File.separator
                + unresolvablePlaceholder;
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, basedir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, unresolvablePlaceholder).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, unresolvablePlaceholder),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                        unresolvablePlaceholder), FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext
                        .getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);

                testPublishRecords(pfh, createTestLogRecords(new String[] { "testMessage1" }),
                        expectedLogFile, createTestLogRecords(new String[] { "testMessage1" }));

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }

    }

    /**
     * Check the generation of a log trace with an unresolvable property in
     * definition of the log filename
     */
    @Test
    public void testPublishWithUnresolvedPropertyInLogFilename() throws Exception {

        final String unresolvablePropertyName = "test.unresolvable";
        final String unresolvablePlaceholder = "${" + unresolvablePropertyName + "}";
        final String logfilename = unresolvablePlaceholder + "-"
                + PetalsFileHandler.DEFAULT_LOGFILENAME;
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.LOGFILENAME_PROPERTY_NAME, logfilename);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.basedir.getCanonicalPath());
                assertEquals(new File(new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                        FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(logfilename, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                        BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE),
                        ExecutionContext.getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        logfilename);

                testPublishRecords(pfh, createTestLogRecords(new String[] { "testMessage1" }),
                        expectedLogFile, createTestLogRecords(new String[] { "testMessage1" }));

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check the generation of a log trace into a log file defined with a loop
     * in property definition of basedir
     */
    @Test
    public void testPublishWithLoopPropertyInBasedir() throws Exception {

        final String loopPropertyName = "test.loop1";
        final String basedir = "baseDirTest" + File.separator + "${" + loopPropertyName + "}";
        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.BASEDIR_PROPERTY_NAME, basedir);
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        System.setProperty(loopPropertyName, "testBaseDir/${" + loopPropertyName + "}");
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

                final String error = errBAIS.toString();
                assertFalse("No error occurs", error.isEmpty());
                assertTrue("Unexpected error", error.contains(loopPropertyName));
                assertSame(Level.FINEST, pfh.getLevel());
                assertEquals(temporaryRootDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                assertEquals(new File(temporaryRootDir, FLOWSUBDIR_DEFAULT_TEST_VALUE).getCanonicalPath(),
                        pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(new File(temporaryRootDir,
                        FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext.getProperties()
                        .getProperty(PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);

                testPublishRecords(pfh, createTestLogRecords(new String[] { "testMessage1" }),
                        expectedLogFile, createTestLogRecords(new String[] { "testMessage1" }));

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
            System.clearProperty(loopPropertyName);
        }
    }

    /**
     * Check the generation of a log traces deleting the log file
     */
    @Test
    public void testPublishCreatesLogFileIfAbsent() throws Exception {

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        final LogManager manager = LogManager.getLogManager();
        final InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("logConf.properties");
        try {
            assertNotNull("Log file configuration not found", is);
            manager.readConfiguration(is);
        } finally {
            is.close();
        }

        final PrintStream standardConsoleError = System.err;
        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));

            final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

            final String error = errBAIS.toString();
            assertTrue("An error occurs", error.isEmpty());
            assertSame(Level.FINEST, pfh.getLevel());
            final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
            final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
            assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
            assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

            PetalsExecutionContext.initFlowInstanceId();
            final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext
                    .getProperties().getProperty(
                            PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                    LOGFILENAME_DEFAULT_TEST_VALUE);

            testPublishRecords(pfh, createTestLogRecords(new String[] { "testMessage1" }),
                    expectedLogFile, createTestLogRecords(new String[] { "testMessage1" }));

            assertTrue(expectedLogFile.delete());

            testPublishRecords(pfh, createTestLogRecords(new String[] { "testMessage2",
                    "testMessage3" }), expectedLogFile, createTestLogRecords(new String[] {
                    "testMessage2", "testMessage3" }));

        } finally {
            PetalsExecutionContext.clear();
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }

    }

    /**
     * Check the appending of a log traces into the log file
     */
    @Test
    public void testPublishAppendsInLogFile() throws Exception {

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        final LogManager manager = LogManager.getLogManager();
        final InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("logConf.properties");
        try {
            assertNotNull("Log file configuration not found", is);
            manager.readConfiguration(is);
        } finally {
            is.close();
        }

        final PrintStream standardConsoleError = System.err;
        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));

            final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

            final String error = errBAIS.toString();
            assertTrue("An error occurs", error.isEmpty());
            assertSame(Level.FINEST, pfh.getLevel());
            final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
            final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
            assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
            assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

            PetalsExecutionContext.initFlowInstanceId();
            final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext
                    .getProperties().getProperty(
                            PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                    LOGFILENAME_DEFAULT_TEST_VALUE);

            testPublishRecords(new PetalsFileHandler(),
                    createTestLogRecords(new String[] { "testMessage1" }), expectedLogFile,
                    createTestLogRecords(new String[] { "testMessage1" }));

            testPublishRecords(new PetalsFileHandler(), createTestLogRecords(new String[] {
                    "testMessage2", "testMessage3" }), expectedLogFile,
                    createTestLogRecords(new String[] { "testMessage1", "testMessage2",
                            "testMessage3" }));

        } finally {
            PetalsExecutionContext.clear();
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check the log trace concurrent generation in different log files
     */
    @Test
    public void testPublishOnSeveralDifferentFilesConcurrently() throws Exception {

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        final LogManager manager = LogManager.getLogManager();
        final InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("logConf.properties");
        try {
            assertNotNull("Log file configuration not found", is);
            manager.readConfiguration(is);
        } finally {
            is.close();
        }

        final PrintStream standardConsoleError = System.err;
        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));

            final PetalsPayloadDumperFileHandler pfh = new PetalsPayloadDumperFileHandler();

            final String error = errBAIS.toString();
            assertTrue("An error occurs", error.isEmpty());
            assertSame(Level.FINEST, pfh.getLevel());
            final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
            final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
            assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
            assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

            final int nbThreads = 100;
            final CyclicBarrier barrier = new CyclicBarrier(nbThreads);
            final TestThread[] testThreads = new TestThread[nbThreads];
            for (int i = 0; i < testThreads.length; ++i) {
                testThreads[i] = new TestThread(new Runnable() {

                    @Override
                    public void run() {
                        final String threadId = String.valueOf(Thread.currentThread().getId());
                        try {
                            barrier.await();
                        } catch (InterruptedException ie) {
                            throw new UncheckedException(ie);
                        } catch (BrokenBarrierException bbe) {
                            throw new UncheckedException(bbe);
                        }
                        ExecutionContext.getProperties().setProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME, threadId);

                        final File expectedLogFile = new File(
                                new File(
                                        new File(new File(temporaryRootDir,
                                                BASEDIR_DEFAULT_TEST_VALUE),
                                                FLOWSUBDIR_DEFAULT_TEST_VALUE),
                                        ExecutionContext
                                                .getProperties()
                                                .getProperty(
                                        PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                                LOGFILENAME_DEFAULT_TEST_VALUE);

                        try {
                            testPublishRecords(pfh, createTestLogRecords(new String[] {
                                    "testMessageA" + threadId, "testMessageB" + threadId,
                                    "testMessageC" + threadId }), expectedLogFile,
                                    createTestLogRecords(new String[] { "testMessageA" + threadId,
                                            "testMessageB" + threadId, "testMessageC" + threadId }));
                        } catch (IOException ioe) {
                            throw new UncheckedException(ioe);
                        }
                    }
                });
                testThreads[i].start();
            }
            for (int i = 0; i < testThreads.length; ++i) {
                testThreads[i].joinExplosively();
            }

        } finally {
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * Check that no error occurs if no message exchange is provided to dump
     */
    @Test
    public void testPublishAndDumpWithoutMessageExchange() throws Exception {

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        final LogManager manager = LogManager.getLogManager();
        final InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("logConf.properties");
        try {
            assertNotNull("Log file configuration not found", is);
            manager.readConfiguration(is);
        } finally {
            is.close();
        }

        final PrintStream standardConsoleError = System.err;
        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));

            final List<String> reportedErrors = new ArrayList<String>();
            final PetalsPayloadDumperFileHandler pfh = createLogHandler(reportedErrors);

            final String error = errBAIS.toString();
            assertTrue("An error occurs", error.isEmpty());
            assertSame(Level.FINEST, pfh.getLevel());
            final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
            final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
            assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
            assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
            assertEquals(SimpleFormatter.class, pfh.getFormatter().getClass());

            PetalsExecutionContext.initFlowInstanceId();
            final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                    BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext
                    .getProperties().getProperty(
                            PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                    LOGFILENAME_DEFAULT_TEST_VALUE);

            testPublishRecords(pfh,
                    createTestLogRecords(new String[] { "testMessage1" }, Level.MONIT),
                    expectedLogFile,
                    createTestLogRecords(new String[] { "testMessage1" }, Level.MONIT));
            assertEquals("An error occurs publishing the log record", 0, reportedErrors.size());

        } finally {
            PetalsExecutionContext.clear();
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }
    
    /**
     * Check that the dump file is referenced as relative path in the log trace
     * when the flow sub dir is defined as relative
     */
    @Test
    public void testPublishAndDumpWithMessageExchange_RelativeFlowSubDir() throws Exception {

        // Generate the log conf file
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + ".formatter", LogDataFormatter.class.getName());
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));
    
                final List<String> reportedErrors = new ArrayList<String>();
                final PetalsPayloadDumperFileHandler pfh = createLogHandler(reportedErrors);
    
                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                        BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(LogDataFormatter.class, pfh.getFormatter().getClass());
    
                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                        BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE), ExecutionContext
                        .getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);
    
                final Source source = new StreamSource(new StringReader("<MySourceContent/>"));
                final MessageExchangeImpl exchange = new MessageExchangeImpl();
                final NormalizedMessage inNm = exchange.createMessage();
                exchange.setPattern(MEPPatternConstants.IN_OUT.value());
                exchange.setMessage(inNm, MessageExchangeImpl.IN_MSG);
                inNm.setContent(source);
    
                final LogRecord lr = LogRecordHelper.newLogRecord(Level.MONIT, "testMessage1", 0);
                final LogData logData = new TestLogData();
                logData.putData(FlowLogData.FLOW_STEP_TRACE_CODE, TraceCode.CONSUME_FLOW_STEP_BEGIN);
                logData.putData(PetalsExecutionContext.FLOW_STEP_ID_PROPERTY_NAME, "my-step-id");
                logData.putData(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME, exchange);
                lr.setParameters(new Object[] { logData });
    
                pfh.publish(lr);
                assertEquals("An error occurs publishing the log record", 0, reportedErrors.size());
    
                assertTrue("log file unexisting", expectedLogFile.exists());
                final InputStream isLogFile = new FileInputStream(expectedLogFile);
                try {
                    final BufferedReader br = new BufferedReader(new InputStreamReader(isLogFile));
                    try {
                        final String strLine = br.readLine();
                        assertNotNull("No log record printed in log file.", strLine);
                        assertTrue(
                                "'"
                                        + PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME
                                        + "' is missing.",
                                strLine.contains(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME));
                        assertTrue("'" + PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME
                                + "' is present.",
                                !strLine.contains(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME));
                        final StringTokenizer tokenizer = new StringTokenizer(strLine, ",", false);
                        while (tokenizer.hasMoreTokens()) {
                            final String token = tokenizer.nextToken();
                            final StringTokenizer tokenTokenizer = new StringTokenizer(token, "=",
                                    false);
                            final String paramKey = tokenTokenizer.nextToken();
                            if (paramKey
                                    .trim()
                                    .equals(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME)) {
                                final String payloadContentDumpFileValue = tokenTokenizer.nextToken();
                                final String payloadContentDumpFileName = payloadContentDumpFileValue
                                        .trim().substring(1, payloadContentDumpFileValue.length() - 2);
                                final File payloadContentDumpFile = new File(payloadContentDumpFileName);
                                assertFalse("payloadContentDumpFile is absolute",
                                        payloadContentDumpFile.isAbsolute());
                                assertTrue("The payload content dump file does not exist", new File(
                                        new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE),
                                        payloadContentDumpFileName).exists());
                            }
                        }
                    } finally {
                        br.close();
                    }
    
                } finally {
                    isLogFile.close();
                }
    
            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check that the dump file is referenced as an absolute path in the log
     * trace when the flow sub dir is defined as absolute.
     * </p>
     * <p>
     * Note: Dump file is generated in the directory 'target' of the current
     * Maven project, and the default log tree is in '/tmp'.
     * </p>
     */
    @Test
    public void testPublishAndDumpWithMessageExchange_AbsoluteFlowSubDir() throws Exception {

        // Generate the log conf file
        final String absoluteFlowsSubdirValue = System.getProperty("absoluteFlowSubDir");
        assertNotNull("Absolute flow sub dir not set", absoluteFlowsSubdirValue);
        assertFalse("Invalid absolute flow sub dir", absoluteFlowsSubdirValue.trim().isEmpty());
        final File absoluteFlowsSubdir = new File(absoluteFlowsSubdirValue);
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + ".formatter", LogDataFormatter.class.getName());
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsFileHandler.FLOW_LOG_SUBDIR_PROPERTY_NAME,
                        absoluteFlowsSubdir.getCanonicalPath());
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final List<String> reportedErrors = new ArrayList<String>();
                final PetalsPayloadDumperFileHandler pfh = createLogHandler(reportedErrors);

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                assertEquals(absoluteFlowsSubdir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(LogDataFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(absoluteFlowsSubdir,
                        ExecutionContext.getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);

                final Source source = new StreamSource(new StringReader("<MySourceContent/>"));
                final MessageExchangeImpl exchange = new MessageExchangeImpl();
                final NormalizedMessage inNm = exchange.createMessage();
                exchange.setPattern(MEPPatternConstants.IN_OUT.value());
                exchange.setMessage(inNm, MessageExchangeImpl.IN_MSG);
                inNm.setContent(source);

                final LogRecord lr = LogRecordHelper.newLogRecord(Level.MONIT, "testMessage1", 0);
                final LogData logData = new TestLogData();
                logData.putData(FlowLogData.FLOW_STEP_TRACE_CODE, TraceCode.CONSUME_FLOW_STEP_BEGIN);
                logData.putData(PetalsExecutionContext.FLOW_STEP_ID_PROPERTY_NAME, "my-step-id");
                logData.putData(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME, exchange);
                lr.setParameters(new Object[] { logData });

                pfh.publish(lr);
                assertEquals("An error occurs publishing the log record", 0, reportedErrors.size());

                assertTrue("log file unexisting", expectedLogFile.exists());
                final InputStream isLogFile = new FileInputStream(expectedLogFile);
                try {
                    final BufferedReader br = new BufferedReader(new InputStreamReader(isLogFile));
                    try {
                        final String strLine = br.readLine();
                        assertNotNull("No log record printed in log file.", strLine);
                        assertTrue(
                                "'"
                                        + PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME
                                        + "' is missing.",
                                strLine.contains(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME));
                        assertTrue(
                                "'" + PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME
                                        + "' is present.",
                                !strLine.contains(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME));
                        final StringTokenizer tokenizer = new StringTokenizer(strLine, ",", false);
                        while (tokenizer.hasMoreTokens()) {
                            final String token = tokenizer.nextToken();
                            final StringTokenizer tokenTokenizer = new StringTokenizer(token, "=",
                                    false);
                            final String paramKey = tokenTokenizer.nextToken();
                            if (paramKey
                                    .trim()
                                    .equals(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME)) {
                                final String payloadContentDumpFileValue = tokenTokenizer
                                        .nextToken();
                                final String payloadContentDumpFileName = payloadContentDumpFileValue
                                        .trim().substring(1,
                                                payloadContentDumpFileValue.length() - 2);
                                final File payloadContentDumpFile = new File(
                                        payloadContentDumpFileName);
                                assertTrue("payloadContentDumpFile is not absolute",
                                        payloadContentDumpFile.isAbsolute());
                                assertTrue("The payload content dump file does not exist",
                                        new File(payloadContentDumpFileName).exists());
                            }
                        }
                    } finally {
                        br.close();
                    }

                } finally {
                    isLogFile.close();
                }

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }
    
    /**
     * Check that the dump file is referenced as relative path in the log trace
     * when the dump base dir is defined as relative to the base dir but using
     * an absolute form.
     */
    @Test
    public void testPublishAndDumpWithMessageExchange_RelativeDumpBaseDir() throws Exception {

        // Generate the log conf file
        final File dumpbaseDir = this.tempFolder.newFolder("dumpBaseDir");
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsPayloadDumperFileHandler.DUMP_BASEDIR_PROPERTY_NAME,
                        dumpbaseDir.getCanonicalPath());
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + ".formatter", LogDataFormatter.class.getName());
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());

        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final List<String> reportedErrors = new ArrayList<String>();
                final PetalsPayloadDumperFileHandler pfh = createLogHandler(reportedErrors);

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                final File expectedFlowsSubDir = new File(new File(temporaryRootDir,
                        BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(LogDataFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(new File(new File(temporaryRootDir,
                        BASEDIR_DEFAULT_TEST_VALUE), FLOWSUBDIR_DEFAULT_TEST_VALUE),
                        ExecutionContext.getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);

                final Source source = new StreamSource(new StringReader("<MySourceContent/>"));
                final MessageExchangeImpl exchange = new MessageExchangeImpl();
                final NormalizedMessage inNm = exchange.createMessage();
                exchange.setPattern(MEPPatternConstants.IN_OUT.value());
                exchange.setMessage(inNm, MessageExchangeImpl.IN_MSG);
                inNm.setContent(source);

                final LogRecord lr = LogRecordHelper.newLogRecord(Level.MONIT, "testMessage1", 0);
                final LogData logData = new TestLogData();
                logData.putData(FlowLogData.FLOW_STEP_TRACE_CODE, TraceCode.CONSUME_FLOW_STEP_BEGIN);
                logData.putData(PetalsExecutionContext.FLOW_STEP_ID_PROPERTY_NAME, "my-step-id");
                logData.putData(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME, exchange);
                lr.setParameters(new Object[] { logData });

                pfh.publish(lr);
                assertEquals("An error occurs publishing the log record", 0, reportedErrors.size());

                assertTrue("log file unexisting", expectedLogFile.exists());
                final InputStream isLogFile = new FileInputStream(expectedLogFile);
                try {
                    final BufferedReader br = new BufferedReader(new InputStreamReader(isLogFile));
                    try {
                        final String strLine = br.readLine();
                        assertNotNull("No log record printed in log file.", strLine);
                        assertTrue(
                                "'"
                                        + PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME
                                        + "' is missing.",
                                strLine.contains(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME));
                        assertTrue(
                                "'" + PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME
                                        + "' is present.",
                                !strLine.contains(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME));
                        final StringTokenizer tokenizer = new StringTokenizer(strLine, ",", false);
                        while (tokenizer.hasMoreTokens()) {
                            final String token = tokenizer.nextToken();
                            final StringTokenizer tokenTokenizer = new StringTokenizer(token, "=",
                                    false);
                            final String paramKey = tokenTokenizer.nextToken();
                            if (paramKey
                                    .trim()
                                    .equals(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME)) {
                                final String payloadContentDumpFileValue = tokenTokenizer
                                        .nextToken();
                                final String payloadContentDumpFileName = payloadContentDumpFileValue
                                        .trim().substring(1,
                                                payloadContentDumpFileValue.length() - 2);
                                final File payloadContentDumpFile = new File(
                                        payloadContentDumpFileName);
                                assertFalse("payloadContentDumpFile is absolute",
                                        payloadContentDumpFile.isAbsolute());
                                assertTrue("The payload content dump file does not exist",
                                        new File(new File(temporaryRootDir,
                                                BASEDIR_DEFAULT_TEST_VALUE),
                                                payloadContentDumpFileName).exists());
                            }
                        }
                    } finally {
                        br.close();
                    }

                } finally {
                    isLogFile.close();
                }

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check that the dump file is referenced as an absolute path in the log
     * trace when the dump base dir is defined as absolute.
     * </p>
     * <p>
     * Note: Dump file is generated in the directory 'target' of the current
     * Maven project, and the default log tree is in '/tmp'.
     * </p>
     */
    @Test
    public void testPublishAndDumpWithMessageExchange_AbsoluteDumpBaseDir() throws Exception {

        // Generate the log conf file
        final String absoluteDumpBaseDirValue = System.getProperty("absoluteDumpBaseDir");
        assertNotNull("Absolute dump base dir not set", absoluteDumpBaseDirValue);
        assertFalse("Invalid dump base sub dir", absoluteDumpBaseDirValue.trim().isEmpty());
        final File absoluteDumpBaseDir = new File(absoluteDumpBaseDirValue);
        final File logConfFile = this.generateLogConfFile(new ConfPropertiesSetter() {

            @Override
            public void customizeProperties(final Properties confProperties) throws Exception {
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + ".formatter", LogDataFormatter.class.getName());
                confProperties.setProperty(PetalsPayloadDumperFileHandler.class.getName()
                        + PetalsPayloadDumperFileHandler.DUMP_BASEDIR_PROPERTY_NAME,
                        absoluteDumpBaseDir.getCanonicalPath());
            }

        });

        final File temporaryRootDir = this.tempFolder.newFolder("root");
        System.setProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME,
                temporaryRootDir.getCanonicalPath());
        try {
            final LogManager manager = LogManager.getLogManager();
            final InputStream is2 = new FileInputStream(logConfFile);
            try {
                manager.readConfiguration(is2);
            } finally {
                is2.close();
            }

            final PrintStream standardConsoleError = System.err;
            try {
                final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
                System.setErr(new PrintStream(errBAIS));

                final List<String> reportedErrors = new ArrayList<String>();
                final PetalsPayloadDumperFileHandler pfh = createLogHandler(reportedErrors);

                final String error = errBAIS.toString();
                assertTrue("An error occurs", error.isEmpty());
                assertSame(Level.FINEST, pfh.getLevel());
                final File expectedBaseDir = new File(temporaryRootDir, BASEDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedBaseDir.getCanonicalPath(), pfh.basedir.getCanonicalPath());
                final File expectedFlowsSubDir = new File(expectedBaseDir,
                        FLOWSUBDIR_DEFAULT_TEST_VALUE);
                assertEquals(expectedFlowsSubDir.getCanonicalPath(), pfh.flowsSubdir.getCanonicalPath());
                assertEquals(LOGFILENAME_DEFAULT_TEST_VALUE, pfh.logfilename);
                assertEquals(LogDataFormatter.class, pfh.getFormatter().getClass());

                PetalsExecutionContext.initFlowInstanceId();
                final File expectedLogFile = new File(new File(expectedFlowsSubDir,
                        ExecutionContext.getProperties().getProperty(
                                PetalsExecutionContext.FLOW_INSTANCE_ID_PROPERTY_NAME)),
                        LOGFILENAME_DEFAULT_TEST_VALUE);

                final Source source = new StreamSource(new StringReader("<MySourceContent/>"));
                final MessageExchangeImpl exchange = new MessageExchangeImpl();
                final NormalizedMessage inNm = exchange.createMessage();
                exchange.setPattern(MEPPatternConstants.IN_OUT.value());
                exchange.setMessage(inNm, MessageExchangeImpl.IN_MSG);
                inNm.setContent(source);

                final LogRecord lr = LogRecordHelper.newLogRecord(Level.MONIT, "testMessage1", 0);
                final LogData logData = new TestLogData();
                logData.putData(FlowLogData.FLOW_STEP_TRACE_CODE, TraceCode.CONSUME_FLOW_STEP_BEGIN);
                logData.putData(PetalsExecutionContext.FLOW_STEP_ID_PROPERTY_NAME, "my-step-id");
                logData.putData(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME, exchange);
                lr.setParameters(new Object[] { logData });

                pfh.publish(lr);
                assertEquals("An error occurs publishing the log record", 0, reportedErrors.size());

                assertTrue("log file unexisting", expectedLogFile.exists());
                final InputStream isLogFile = new FileInputStream(expectedLogFile);
                try {
                    final BufferedReader br = new BufferedReader(new InputStreamReader(isLogFile));
                    try {
                        final String strLine = br.readLine();
                        assertNotNull("No log record printed in log file.", strLine);
                        assertTrue(
                                "'"
                                        + PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME
                                        + "' is missing.",
                                strLine.contains(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME));
                        assertTrue(
                                "'" + PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME
                                        + "' is present.",
                                !strLine.contains(PetalsExecutionContext.FLOW_EXCHANGE_PROPERTY_NAME));
                        final StringTokenizer tokenizer = new StringTokenizer(strLine, ",", false);
                        while (tokenizer.hasMoreTokens()) {
                            final String token = tokenizer.nextToken();
                            final StringTokenizer tokenTokenizer = new StringTokenizer(token, "=",
                                    false);
                            final String paramKey = tokenTokenizer.nextToken();
                            if (paramKey
                                    .trim()
                                    .equals(PetalsPayloadDumperFileHandler.PAYLOAD_CONTENT_DUMP_FILE_LOGDATA_NAME)) {
                                final String payloadContentDumpFileValue = tokenTokenizer
                                        .nextToken();
                                final String payloadContentDumpFileName = payloadContentDumpFileValue
                                        .trim().substring(1,
                                                payloadContentDumpFileValue.length() - 2);
                                final File payloadContentDumpFile = new File(
                                        payloadContentDumpFileName);
                                assertTrue("payloadContentDumpFile is not absolute",
                                        payloadContentDumpFile.isAbsolute());
                                assertTrue("It is not the expected absolute directory",
                                        payloadContentDumpFileName.startsWith(absoluteDumpBaseDir.getCanonicalPath()));
                                assertTrue("The payload content dump file does not exist",
                                        new File(payloadContentDumpFileName).exists());
                            }
                        }
                    } finally {
                        br.close();
                    }

                } finally {
                    isLogFile.close();
                }

            } finally {
                PetalsExecutionContext.clear();
                System.setErr(standardConsoleError);
            }
        } finally {
            System.clearProperty(PetalsFileHandler.PETALS_LOG_DIR_PROPERTY_NAME);
        }
    }
}
