Author: rpopma
Date: Sat Jun 21 16:34:58 2014
New Revision: 1604428

URL: http://svn.apache.org/r1604428
Log:
LOG4J2-581, LOG4J2-675 RollingRandomAccessFile now writes the layout header 
after rollover; RollingFile and RollingRandomAccessFile now write the layout 
footer before rollover.

Added:
    
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java
   (with props)
    
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml
   (with props)
Modified:
    
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
    
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
    
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml

Modified: 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java?rev=1604428&r1=1604427&r2=1604428&view=diff
==============================================================================
--- 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
 (original)
+++ 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/OutputStreamManager.java
 Sat Jun 21 16:34:58 2014
@@ -28,8 +28,7 @@ import org.apache.logging.log4j.core.Lay
 public class OutputStreamManager extends AbstractManager {
 
     private volatile OutputStream os;
-
-    private final Layout<?> layout;
+    protected final Layout<?> layout;
 
     protected OutputStreamManager(final OutputStream os, final String 
streamName, final Layout<?> layout) {
         super(streamName);
@@ -66,11 +65,21 @@ public class OutputStreamManager extends
      */
     @Override
     public void releaseSub() {
+        writeFooter();
+        close();
+    }
+
+    /**
+     * Writes the footer.
+     */
+    protected void writeFooter() {
+        if (layout == null) {
+            return;
+        }
         byte[] footer = layout.getFooter();
         if (footer != null) {
             write(footer);
         }
-        close();
     }
 
     /**

Modified: 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java?rev=1604428&r1=1604427&r2=1604428&view=diff
==============================================================================
--- 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
 (original)
+++ 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
 Sat Jun 21 16:34:58 2014
@@ -167,6 +167,7 @@ public class RollingFileManager extends 
         try {
             final RolloverDescription descriptor = strategy.rollover(this);
             if (descriptor != null) {
+                writeFooter();
                 close();
                 if (descriptor.getSynchronous() != null) {
                     LOGGER.debug("RollingFileManager executing synchronous 
{}", descriptor.getSynchronous());

Modified: 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java?rev=1604428&r1=1604427&r2=1604428&view=diff
==============================================================================
--- 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
 (original)
+++ 
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManager.java
 Sat Jun 21 16:34:58 2014
@@ -55,6 +55,26 @@ public class RollingRandomAccessFileMana
         this.randomAccessFile = raf;
         isEndOfBatch.set(Boolean.FALSE);
         this.buffer = ByteBuffer.allocate(bufferSize);
+        writeHeader();
+    }
+
+    /**
+     * Writes the layout's header to the file if it exists.
+     */
+    private void writeHeader() {
+        if (layout == null) {
+            return;
+        }
+        byte[] header = layout.getHeader();
+        if (header == null) {
+            return;
+        }
+        try {
+            // write to the file, not to the buffer: the buffer may not be 
empty
+            randomAccessFile.write(header, 0, header.length);
+        } catch (final IOException ioe) {
+            LOGGER.error("Unable to write header", ioe);
+        }
     }
 
     public static RollingRandomAccessFileManager 
getRollingRandomAccessFileManager(final String fileName,
@@ -99,6 +119,7 @@ public class RollingRandomAccessFileMana
         if (isAppend()) {
             randomAccessFile.seek(randomAccessFile.length());
         }
+        writeHeader();
     }
 
     @Override

Added: 
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java?rev=1604428&view=auto
==============================================================================
--- 
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java
 (added)
+++ 
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java
 Sat Jun 21 16:34:58 2014
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.rolling;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.layout.HtmlLayout;
+import org.apache.logging.log4j.junit.InitialLoggerContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class RollingRandomAccessFileManagerHeaderFooterTest {
+
+    private static final String DIR = 
"target/RollingRandomAccessFileAppenderHeaderFooterTest/";
+    private static final String LOGFILE = 
"target/RollingRandomAccessFileAppenderHeaderFooterTest.log";
+
+    @Rule
+    public InitialLoggerContext init = new 
InitialLoggerContext("RollingRandomAccessFileAppenderHeaderFooterTest.xml");
+
+    private Logger logger;
+
+    @Before
+    public void setUp() throws Exception {
+        this.logger = 
this.init.getLogger(RollingRandomAccessFileManagerHeaderFooterTest.class.getName());
+        deleteDir();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        deleteDir();
+    }
+
+    @Test
+    public void testAppender() throws Exception {
+        for (int i = 0; i < 8; ++i) {
+            logger.debug("This is test message number " + i);
+        }
+        Thread.sleep(50);
+        final File dir = new File(DIR);
+        assertTrue("Directory not created", dir.exists() && 
dir.listFiles().length > 0);
+        final File[] files = dir.listFiles();
+        assertTrue("No files created", files.length > 0);
+        for (final File file : files) {
+            assertHeader(file);
+            assertFooter(file);
+        }
+        final File logFile = new File(LOGFILE);
+        assertTrue("Expected logfile to exist: " + LOGFILE, logFile.exists());
+        assertHeader(logFile);
+    }
+
+    private void assertHeader(File file) throws Exception {
+        HtmlLayout layout = HtmlLayout.createDefaultLayout();
+        String header = new String(layout.getHeader(), 
Charset.defaultCharset());
+        String withoutTimestamp = header.substring(0, 435);
+        String contents = new String(slurp(file), Charset.defaultCharset());
+        String contentsInitialChunk = contents.substring(0, 435);
+        assertEquals(file.getName(), withoutTimestamp, contentsInitialChunk);
+    }
+
+    private void assertFooter(File file) throws Exception {
+        HtmlLayout layout = HtmlLayout.createDefaultLayout();
+        String footer = new String(layout.getFooter(), 
Charset.defaultCharset());
+        String contents = new String(slurp(file), Charset.defaultCharset());
+        assertTrue(file.getName(), contents.endsWith(footer));
+    }
+
+    private byte[] slurp(File file) throws Exception {
+        FileInputStream in = null;
+        try {
+            in = new FileInputStream(file);
+            byte[] result = new byte[(int) file.length()];
+            int pos = 0;
+            int length = in.read(result);
+            while (length > 0) {
+                pos += length;
+                length = in.read(result, pos, result.length - pos);
+            }
+            return result;
+        } finally {
+            try {
+                in.close();
+            } catch (Exception ignored) {
+            }
+        }
+    }
+
+    private static void deleteDir() {
+        final File dir = new File(DIR);
+        if (dir.exists()) {
+            final File[] files = dir.listFiles();
+            for (final File file : files) {
+                file.delete();
+            }
+            dir.delete();
+        }
+    }
+}

Propchange: 
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingRandomAccessFileManagerHeaderFooterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml?rev=1604428&view=auto
==============================================================================
--- 
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml
 (added)
+++ 
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml
 Sat Jun 21 16:34:58 2014
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="OFF">
+  <Appenders>
+    <RollingRandomAccessFile name="RollingRandomAccessFile" 
fileName="target/RollingRandomAccessFileAppenderHeaderFooterTest.log"
+                 
filePattern="target/RollingRandomAccessFileAppenderHeaderFooterTest/rolled%i.log"
 append="false"
+                 immediateFlush="true">
+      <HTMLLayout></HTMLLayout>
+      <Policies>
+      <!--
+        <TimeBasedTriggeringPolicy />
+      -->
+        <SizeBasedTriggeringPolicy size="1024" />
+      </Policies>
+    </RollingRandomAccessFile>
+  </Appenders>
+  
+  <Loggers>
+    <Root level="trace" includeLocation="false">
+      <AppenderRef ref="RollingRandomAccessFile"/>
+    </Root>
+  </Loggers>
+</Configuration>
\ No newline at end of file

Propchange: 
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/RollingRandomAccessFileAppenderHeaderFooterTest.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1604428&r1=1604427&r2=1604428&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Sat Jun 21 16:34:58 2014
@@ -22,6 +22,12 @@
   </properties>
   <body>
     <release version="2.0-rc2" date="2014-MM-DD" description="Bug fixes and 
enhancements">
+      <action issue="LOG4J2-675" dev="rpopma" type="add">
+        RollingFile and RollingRandomAccessFile now write the layout footer 
before rollover.
+      </action>
+      <action issue="LOG4J2-581" dev="rpopma" type="fix" due-to="Alexander 
Khokhlov">
+        RollingRandomAccessFile now writes the layout header after rollover.
+      </action>
       <action issue="LOG4J2-622" dev="rpopma" type="fix" due-to="Farooq Khan">
         RollingFileManager now correctly honours the bufferedIO configuration 
after rollover.
       </action>


Reply via email to