package com.github.kristofa.test.http.file; import java.io.File; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.kristofa.test.http.HttpRequestResponseLogger; import com.github.kristofa.test.http.HttpRequestResponseLoggerFactory; import com.github.kristofa.test.http.LoggingHttpProxy; /** * Factory that creates {@link HttpRequestResponseFileLogger} instances. * * @see HttpRequestResponseFileLogger * @see LoggingHttpProxy * @author kristof */ public class HttpRequestResponseFileLoggerFactory implements HttpRequestResponseLoggerFactory { private final static Logger LOGGER = LoggerFactory.getLogger(HttpRequestResponseFileLoggerFactory.class); private final AtomicInteger atomicInteger = new AtomicInteger(); private final String directory; private final String fileName; private final HttpRequestFileWriter requestWriter; private final HttpResponseFileWriter responseWriter; private final boolean deleteExistingFiles; private boolean firstRequest = true; /** * Creates a new instance. We will not delete any existing files. * * @param directory Target directory in which to store request/responses. Directory should already exist. Should not be * <code>null</code> or blank. * @param fileName Base file name. Should not contain extension. Will be suffixed with sequence number and .txt * extension. Should not be <code>null</code> or blank. */ public HttpRequestResponseFileLoggerFactory(final String directory, final String fileName) { this(directory, fileName, false); } /** * Creates a new instance. * * @param directory Target directory in which to store request/responses. Directory should already exist. Should not be * <code>null</code> or blank. * @param fileName Base file name. Should not contain extension. Will be suffixed with sequence number and .txt * extension. Should not be <code>null</code> or blank. * @param deleteExistingFiles If value is <code>true</code> we will delete all existing files prior to logging new * requests. This is often helpful because if we have less requests than before otherwise old files keep on * lingering which can cause failing tests. */ public HttpRequestResponseFileLoggerFactory(final String directory, final String fileName, final boolean deleteExistingFiles) { Validate.notBlank(directory); Validate.notBlank(fileName); this.directory = directory; this.fileName = fileName; this.deleteExistingFiles = deleteExistingFiles; requestWriter = new HttpRequestFileWriterImpl(); responseWriter = new HttpResponseFileWriterImpl(); } /** * {@inheritDoc} */ @Override public HttpRequestResponseLogger getHttpRequestResponseLogger() { if (firstRequest && deleteExistingFiles) { synchronized (atomicInteger) { if (firstRequest) { deleteExistingFiles(); firstRequest = false; } } } return new HttpRequestResponseFileLogger(directory, fileName, atomicInteger.incrementAndGet(), requestWriter, responseWriter); } private void deleteExistingFiles() { int seqNr = 1; while (true) { final String requestFileName = FileNameBuilder.REQUEST_FILE_NAME.getFileName(fileName, seqNr); if (FileDeleteStatus.DID_NOT_EXIST.equals(delete(directory, requestFileName))) { return; } final String requestEntityFileName = FileNameBuilder.REQUEST_ENTITY_FILE_NAME.getFileName(fileName, seqNr); delete(directory, requestEntityFileName); final String responseFileName = FileNameBuilder.RESPONSE_FILE_NAME.getFileName(fileName, seqNr); delete(directory, responseFileName); final String responseEntityFileName = FileNameBuilder.RESPONSE_ENTITY_FILE_NAME.getFileName(fileName, seqNr); delete(directory, responseEntityFileName); seqNr++; } } private FileDeleteStatus delete(final String directory, final String fileName) { final File file = new File(directory, fileName); if (file.exists()) { if (!file.delete()) { LOGGER.warn("Unable to delete " + file); return FileDeleteStatus.DELETE_FAILED; } return FileDeleteStatus.DELETE_SUCCES; } return FileDeleteStatus.DID_NOT_EXIST; } private enum FileDeleteStatus { DID_NOT_EXIST, DELETE_SUCCES, DELETE_FAILED }; }