This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch next_stable
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


The following commit(s) were added to refs/heads/next_stable by this push:
     new 22be6885 Restore documented RollingFileAppender configuration 
properties (#146)
22be6885 is described below

commit 22be6885ddfdebaef1b98eca3dba0ca02616d36b
Author: Stephen Webb <[email protected]>
AuthorDate: Tue Nov 1 09:11:03 2022 +1100

    Restore documented RollingFileAppender configuration properties (#146)
    
    * Restore documented RollingFileAppender configuration properties file 
MaxBackupIndex and MaxFileSize options
    
    * Map a property configuration using the obsolete DailyRollingFileAppender 
to a TimeBasedRollingPolicy in RollingFileAppender
    
    * Use the last set policy where RollingFileAppender policies are 
incompatible
    
    Co-authored-by: Stephen Webb <[email protected]>
---
 src/main/cpp/fixedwindowrollingpolicy.cpp          |   8 +-
 src/main/cpp/propertyconfigurator.cpp              |  14 +-
 src/main/cpp/rollingfileappender.cpp               | 133 ++++++++++++++-
 .../include/log4cxx/rolling/rollingfileappender.h  |  42 ++++-
 .../rolling/rollingfileappenderpropertiestest.cpp  | 185 ++++++++++++++++++++-
 .../input/rolling/obsoleteRFA1.properties          |   1 +
 6 files changed, 365 insertions(+), 18 deletions(-)

diff --git a/src/main/cpp/fixedwindowrollingpolicy.cpp 
b/src/main/cpp/fixedwindowrollingpolicy.cpp
index 9e992834..8534c5df 100644
--- a/src/main/cpp/fixedwindowrollingpolicy.cpp
+++ b/src/main/cpp/fixedwindowrollingpolicy.cpp
@@ -14,11 +14,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#if defined(_MSC_VER)
-       #pragma warning ( disable: 4231 4251 4275 4786 )
-#endif
-
-
 #include <log4cxx/logstring.h>
 #include <log4cxx/rolling/fixedwindowrollingpolicy.h>
 #include <log4cxx/helpers/pool.h>
@@ -45,7 +40,8 @@ struct 
FixedWindowRollingPolicy::FixedWindowRollingPolicyPrivate : public Rollin
        FixedWindowRollingPolicyPrivate() :
                RollingPolicyBasePrivate(),
                minIndex(1),
-               maxIndex(7)
+               maxIndex(7),
+               explicitActiveFile(false)
        {}
 
        int minIndex;
diff --git a/src/main/cpp/propertyconfigurator.cpp 
b/src/main/cpp/propertyconfigurator.cpp
index f688d931..4083a78a 100644
--- a/src/main/cpp/propertyconfigurator.cpp
+++ b/src/main/cpp/propertyconfigurator.cpp
@@ -446,7 +446,17 @@ AppenderPtr PropertyConfigurator::parseAppender(
                        props, prefix, Appender::getStaticClass(), 0);
        appender = log4cxx::cast<Appender>( obj );
 
-       if (appender == 0)
+       // Map obsolete DailyRollingFileAppender propertiy configuration
+       if (!appender &&
+               StringHelper::endsWith(OptionConverter::findAndSubst(prefix, 
props), LOG4CXX_STR("DailyRollingFileAppender")))
+       {
+               appender = std::make_shared<RollingFileAppender>();
+               auto datePattern = OptionConverter::findAndSubst(prefix + 
LOG4CXX_STR(".datePattern"), props);
+               if (!datePattern.empty())
+                       props.put(prefix + LOG4CXX_STR(".fileDatePattern"), 
datePattern);
+       }
+
+       if (!appender)
        {
                LogLog::error((LogString) LOG4CXX_STR("Could not instantiate 
appender named \"")
                        + appenderName + LOG4CXX_STR("\"."));
@@ -473,7 +483,6 @@ AppenderPtr PropertyConfigurator::parseAppender(
                                LogLog::debug((LogString) LOG4CXX_STR("Parsing 
layout options for \"")
                                        + appenderName + LOG4CXX_STR("\"."));
 
-                               //configureOptionHandler(layout, layoutPrefix + 
".", props);
                                PropertySetter::setProperties(layout, props, 
layoutPrefix + LOG4CXX_STR("."), p);
                                LogLog::debug((LogString) LOG4CXX_STR("End of 
parsing for \"")
                                        + appenderName +  LOG4CXX_STR("\"."));
@@ -512,7 +521,6 @@ AppenderPtr PropertyConfigurator::parseAppender(
                        }
                }
 
-               //configureOptionHandler((OptionHandler) appender, prefix + 
_T("."), props);
                PropertySetter::setProperties(appender, props, prefix + 
LOG4CXX_STR("."), p);
                LogLog::debug((LogString) LOG4CXX_STR("Parsed \"")
                        + appenderName + LOG4CXX_STR("\" options."));
diff --git a/src/main/cpp/rollingfileappender.cpp 
b/src/main/cpp/rollingfileappender.cpp
index a24a8e49..a9c776a9 100644
--- a/src/main/cpp/rollingfileappender.cpp
+++ b/src/main/cpp/rollingfileappender.cpp
@@ -24,8 +24,11 @@
 #include <log4cxx/rolling/rolloverdescription.h>
 #include <log4cxx/helpers/fileoutputstream.h>
 #include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <log4cxx/helpers/stringhelper.h>
 #include <log4cxx/rolling/fixedwindowrollingpolicy.h>
-#include <log4cxx/rolling/manualtriggeringpolicy.h>
+#include <log4cxx/rolling/timebasedrollingpolicy.h>
+#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
 #include <log4cxx/helpers/transcoder.h>
 #include <log4cxx/private/fileappender_priv.h>
 #include <mutex>
@@ -75,12 +78,132 @@ RollingFileAppender::RollingFileAppender() :
 {
 }
 
+void RollingFileAppender::setOption(const LogString& option, const LogString& 
value)
+{
+       if (StringHelper::equalsIgnoreCase(option,
+                       LOG4CXX_STR("MAXFILESIZE"), LOG4CXX_STR("maxfilesize"))
+               || StringHelper::equalsIgnoreCase(option,
+                       LOG4CXX_STR("MAXIMUMFILESIZE"), 
LOG4CXX_STR("maximumfilesize")))
+       {
+               setMaxFileSize(value);
+       }
+       else if (StringHelper::equalsIgnoreCase(option,
+                       LOG4CXX_STR("MAXBACKUPINDEX"), 
LOG4CXX_STR("maxbackupindex"))
+               || StringHelper::equalsIgnoreCase(option,
+                       LOG4CXX_STR("MAXIMUMBACKUPINDEX"), 
LOG4CXX_STR("maximumbackupindex")))
+       {
+               setMaxBackupIndex(StringHelper::toInt(value));
+       }
+       else if (StringHelper::equalsIgnoreCase(option,
+                       LOG4CXX_STR("FILEDATEPATTERN"), 
LOG4CXX_STR("filedatepattern")))
+       {
+               setDatePattern(value);
+       }
+       else
+       {
+               FileAppender::setOption(option, value);
+       }
+}
+
+int RollingFileAppender::getMaxBackupIndex() const
+{
+       int result = 1;
+       if (auto fwrp = 
log4cxx::cast<FixedWindowRollingPolicy>(_priv->rollingPolicy))
+               result = fwrp->getMaxIndex();
+       return result;
+}
+
+void RollingFileAppender::setMaxBackupIndex(int maxBackups)
+{
+       auto fwrp = 
log4cxx::cast<FixedWindowRollingPolicy>(_priv->rollingPolicy);
+       if (!fwrp)
+       {
+               fwrp = std::make_shared<FixedWindowRollingPolicy>();
+               fwrp->setFileNamePattern(getFile() + LOG4CXX_STR(".%i"));
+               _priv->rollingPolicy = fwrp;
+       }
+       fwrp->setMaxIndex(maxBackups);
+}
+
+size_t RollingFileAppender::getMaximumFileSize() const
+{
+       size_t result = 10 * 1024 * 1024;
+       if (auto sbtp = 
log4cxx::cast<SizeBasedTriggeringPolicy>(_priv->triggeringPolicy))
+               result = sbtp->getMaxFileSize();
+       return result;
+}
+
+void RollingFileAppender::setMaximumFileSize(size_t maxFileSize)
+{
+       auto sbtp = 
log4cxx::cast<SizeBasedTriggeringPolicy>(_priv->triggeringPolicy);
+       if (!sbtp)
+       {
+               sbtp = std::make_shared<SizeBasedTriggeringPolicy>();
+               _priv->triggeringPolicy = sbtp;
+       }
+       sbtp->setMaxFileSize(maxFileSize);
+}
+
+void RollingFileAppender::setMaxFileSize(const LogString& value)
+{
+       setMaximumFileSize(OptionConverter::toFileSize(value, 
long(getMaximumFileSize() + 1)));
+}
+
+LogString RollingFileAppender::makeFileNamePattern(const LogString& 
datePattern)
+{
+       LogString result(getFile());
+       bool inLiteral = false;
+       bool inPattern = false;
+
+       for (size_t i = 0; i < datePattern.length(); i++)
+       {
+               if (datePattern[i] == 0x27 /* '\'' */)
+               {
+                       inLiteral = !inLiteral;
+
+                       if (inLiteral && inPattern)
+                       {
+                               result.append(1, (logchar) 0x7D /* '}' */);
+                               inPattern = false;
+                       }
+               }
+               else
+               {
+                       if (!inLiteral && !inPattern)
+                       {
+                               const logchar dbrace[] = { 0x25, 0x64, 0x7B, 0 
}; // "%d{"
+                               result.append(dbrace);
+                               inPattern = true;
+                       }
+
+                       result.append(1, datePattern[i]);
+               }
+       }
+
+       if (inPattern)
+       {
+               result.append(1, (logchar) 0x7D /* '}' */);
+       }
+       return result;
+}
+
+void RollingFileAppender::setDatePattern(const LogString& newPattern)
+{
+       auto tbrp = log4cxx::cast<TimeBasedRollingPolicy>(_priv->rollingPolicy);
+       if (!tbrp)
+       {
+               tbrp = std::make_shared<TimeBasedRollingPolicy>();
+               _priv->rollingPolicy = tbrp;
+       }
+       tbrp->setFileNamePattern(makeFileNamePattern(newPattern));
+}
+
 /**
  * Prepare instance of use.
  */
 void RollingFileAppender::activateOptions(Pool& p)
 {
-       if (_priv->rollingPolicy == NULL)
+       if (!_priv->rollingPolicy)
        {
                auto fwrp = std::make_shared<FixedWindowRollingPolicy>();
                fwrp->setFileNamePattern(getFile() + LOG4CXX_STR(".%i"));
@@ -90,7 +213,7 @@ void RollingFileAppender::activateOptions(Pool& p)
        //
        //  if no explicit triggering policy and rolling policy is both.
        //
-       if (_priv->triggeringPolicy == NULL)
+       if (!_priv->triggeringPolicy)
        {
                TriggeringPolicyPtr trig = 
log4cxx::cast<TriggeringPolicy>(_priv->rollingPolicy);
 
@@ -100,9 +223,9 @@ void RollingFileAppender::activateOptions(Pool& p)
                }
        }
 
-       if (_priv->triggeringPolicy == NULL)
+       if (!_priv->triggeringPolicy)
        {
-               _priv->triggeringPolicy = 
std::make_shared<ManualTriggeringPolicy>();
+               _priv->triggeringPolicy = 
std::make_shared<SizeBasedTriggeringPolicy>();
        }
 
        {
diff --git a/src/main/include/log4cxx/rolling/rollingfileappender.h 
b/src/main/include/log4cxx/rolling/rollingfileappender.h
index 603dffe4..6d0e9243 100644
--- a/src/main/include/log4cxx/rolling/rollingfileappender.h
+++ b/src/main/include/log4cxx/rolling/rollingfileappender.h
@@ -89,8 +89,48 @@ class LOG4CXX_EXPORT RollingFileAppender : public 
FileAppender
        public:
                RollingFileAppender();
 
-               void activateOptions(log4cxx::helpers::Pool&);
+               /** Returns the value of the <b>MaxBackupIndex</b> option. */
+               int getMaxBackupIndex() const;
 
+               /** Get the maximum size that the output file is allowed to 
reach before being rolled over to backup files. */
+               size_t getMaximumFileSize() const;
+
+
+               /**
+               Set the maximum number of backup files to keep around.
+
+               <p>The <b>MaxBackupIndex</b> option determines how many backup
+                files are kept before the oldest is erased. This option takes
+                a positive integer value. If set to zero, then there will be no
+                backup files and the log file will be truncated when it 
reaches <code>MaxFileSize</code>.
+               */
+               void setMaxBackupIndex( int maxBackupIndex );
+
+               /**
+               Set the maximum size that the output file is allowed to reach 
before being rolled over to backup files.
+
+               <p>In configuration files, the <b>MaxFileSize</b> option takes 
an
+                long integer in the range 0 - 2^63. You can specify the value 
with the suffixes "KB", "MB" or "GB" so that the integer is
+                interpreted being expressed respectively in kilobytes, 
megabytes
+                or gigabytes. For example, the value "10KB" will be 
interpreted as 10240.
+               */
+               void setMaxFileSize( const LogString& value );
+
+               void setMaximumFileSize( size_t value );
+
+               /**
+                  The <b>DatePattern</b> takes a string in the same format as
+                  expected by {@link log4cxx::helpers::SimpleDateFormat 
SimpleDateFormat}. This options determines the
+                  rollover schedule.
+                */
+               void setDatePattern(const LogString& pattern);
+
+               LogString makeFileNamePattern(const LogString& datePattern);
+
+               void setOption( const LogString& option, const LogString& value 
) override;
+
+               /** Prepares RollingFileAppender for use. */
+               void activateOptions( log4cxx::helpers::Pool& pool );
 
                /**
                   Implements the usual roll over behaviour.
diff --git a/src/test/cpp/rolling/rollingfileappenderpropertiestest.cpp 
b/src/test/cpp/rolling/rollingfileappenderpropertiestest.cpp
index 3240f9f7..7ab10204 100644
--- a/src/test/cpp/rolling/rollingfileappenderpropertiestest.cpp
+++ b/src/test/cpp/rolling/rollingfileappenderpropertiestest.cpp
@@ -46,6 +46,11 @@ using namespace log4cxx::rolling;
 LOGUNIT_CLASS(RollingFileAppenderPropertiesTest)
 {
        LOGUNIT_TEST_SUITE(RollingFileAppenderPropertiesTest);
+       LOGUNIT_TEST(testIsOptionHandler);
+       LOGUNIT_TEST(test1);
+       LOGUNIT_TEST(test2);
+       LOGUNIT_TEST(test3);
+       LOGUNIT_TEST(test4);
        LOGUNIT_TEST(testRollingFromProperties);
        LOGUNIT_TEST_SUITE_END();
 
@@ -56,6 +61,162 @@ public:
 
        void tearDown()
        {
+               LogManager::shutdown();
+       }
+
+       /**
+        * Test basic rolling functionality.
+        */
+       void test1()
+       {
+               
PropertyConfigurator::configure(File("input/rolling/obsoleteRFA1.properties"));
+
+               // Make sure that the configured values are what we expect
+               auto appender = 
LogManager::getRootLogger()->getAppender(LOG4CXX_STR("testAppender"));
+               LOGUNIT_ASSERT(appender);
+
+               auto rfa = cast<RollingFileAppender>(appender);
+               LOGUNIT_ASSERT(rfa);
+
+               LOGUNIT_ASSERT_EQUAL(3, rfa->getMaxBackupIndex());
+               LOGUNIT_ASSERT_EQUAL(100, 
static_cast<int>(rfa->getMaximumFileSize()));
+
+               logchar msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', '?', 
0};
+               auto logger = Logger::getLogger("RollingFileAppenderTest");
+
+               // Write exactly 10 bytes with each log
+               for (int i = 0; i < 25; i++)
+               {
+                       apr_sleep(100000);
+
+                       if (i < 10)
+                       {
+                               msg[8] = (logchar) ('0' + i);
+                               LOG4CXX_DEBUG(logger, msg);
+                       }
+                       else if (i < 100)
+                       {
+                               msg[7] = (logchar) ('0' + i / 10);
+                               msg[8] = (logchar) ('0' + i % 10);
+                               LOG4CXX_DEBUG(logger, msg);
+                       }
+               }
+
+               Pool p;
+               LOGUNIT_ASSERT_EQUAL(true, 
File("output/obsoleteRFA-test1.log").exists(p));
+               LOGUNIT_ASSERT_EQUAL(true, 
File("output/obsoleteRFA-test1.log.1").exists(p));
+       }
+
+       /**
+        * Test basic rolling functionality.
+        */
+       void test2()
+       {
+               auto layout = std::make_shared 
<PatternLayout>(LOG4CXX_STR("%m\n"));
+               auto rfa = std::make_shared<RollingFileAppender>();
+               rfa->setName(LOG4CXX_STR("ROLLING"));
+               rfa->setLayout(layout);
+               rfa->setOption(LOG4CXX_STR("append"), LOG4CXX_STR("false"));
+               rfa->setMaximumFileSize(100);
+               rfa->setFile(LOG4CXX_STR("output/obsoleteRFA-test2.log"));
+               Pool p;
+               rfa->activateOptions(p);
+               auto root = Logger::getRootLogger();
+               root->addAppender(rfa);
+
+               logchar msg[] = { 'H', 'e', 'l', 'l', 'o', '-', '-', '-', '?', 
0};
+               auto logger = 
Logger::getLogger("org.apache.logj4.ObsoleteRollingFileAppenderTest");
+
+               // Write exactly 10 bytes with each log
+               for (int i = 0; i < 25; i++)
+               {
+                       apr_sleep(100000);
+
+                       if (i < 10)
+                       {
+                               msg[8] = (logchar) ('0' + i);
+                               LOG4CXX_DEBUG(logger, msg);
+                       }
+                       else if (i < 100)
+                       {
+                               msg[7] = (logchar) ('0' + i / 10);
+                               msg[8] = (logchar) ('0' + i % 10);
+                               LOG4CXX_DEBUG(logger, msg);
+                       }
+               }
+
+               LOGUNIT_ASSERT_EQUAL(true, 
File("output/obsoleteRFA-test2.log").exists(p));
+               LOGUNIT_ASSERT_EQUAL(true, 
File("output/obsoleteRFA-test2.log.1").exists(p));
+       }
+
+       /**
+        * Test propertyfile configured time based rolling functionality.
+        */
+       void test3()
+       {
+               
PropertyConfigurator::configure(File("input/rolling/obsoleteDRFA1.properties"));
+
+               int preCount = getFileCount("output", 
LOG4CXX_STR("obsoleteDRFA-test1.log."));
+               LoggerPtr 
logger(Logger::getLogger("DailyRollingFileAppenderTest"));
+
+               char msg[11];
+               strncpy(msg, "Hello---??", sizeof(msg));
+
+               for (int i = 0; i < 25; i++)
+               {
+                       apr_sleep(100000);
+                       msg[8] = (char) ('0' + (i / 10));
+                       msg[9] = (char) ('0' + (i % 10));
+                       LOG4CXX_DEBUG(logger, msg);
+               }
+
+               int postCount = getFileCount("output", 
LOG4CXX_STR("obsoleteDRFA-test1.log."));
+               LOGUNIT_ASSERT_EQUAL(true, postCount > preCount);
+       }
+
+       /**
+        * Test programatically configured time based rolling functionality.
+        */
+       void test4()
+       {
+               PatternLayoutPtr layout(new PatternLayout(LOG4CXX_STR("%m%n")));
+               auto rfa = std::make_shared<RollingFileAppender>();
+               rfa->setName(LOG4CXX_STR("ROLLING"));
+               rfa->setLayout(layout);
+               rfa->setAppend(false);
+               rfa->setFile(LOG4CXX_STR("output/obsoleteDRFA-test2.log"));
+               rfa->setDatePattern(LOG4CXX_STR("'.'yyyy-MM-dd-HH_mm_ss"));
+               Pool p;
+               rfa->activateOptions(p);
+               LoggerPtr root(Logger::getRootLogger());
+               root->addAppender(rfa);
+               LoggerPtr 
logger(Logger::getLogger("ObsoleteDailyRollingAppenderTest"));
+
+               int preCount = getFileCount("output", 
LOG4CXX_STR("obsoleteDRFA-test2.log."));
+
+               char msg[11];
+               strncpy(msg, "Hello---??", sizeof(msg));
+
+               for (int i = 0; i < 25; i++)
+               {
+                       apr_sleep(100000);
+                       msg[8] = (char) ('0' + i / 10);
+                       msg[9] = (char) ('0' + i % 10);
+                       LOG4CXX_DEBUG(logger, msg);
+               }
+
+               int postCount = getFileCount("output", 
LOG4CXX_STR("obsoleteDRFA-test2.log."));
+               LOGUNIT_ASSERT_EQUAL(true, postCount > preCount);
+       }
+
+       /**
+        *  Tests if class is declared to support the OptionHandler interface.
+        *  See LOGCXX-136.
+        */
+       void testIsOptionHandler()
+       {
+               auto rfa = std::make_shared<RollingFileAppender>();
+               LOGUNIT_ASSERT_EQUAL(true, 
rfa->instanceof(log4cxx::spi::OptionHandler::getStaticClass()));
        }
 
        void testRollingFromProperties(){
@@ -63,22 +224,40 @@ public:
                // what we expect
                
PropertyConfigurator::configure(LOG4CXX_FILE("input/rolling/rollingFileAppenderFromProperties.properties"));
 
-               AppenderPtr appender = 
LogManager::getRootLogger()->getAppender(LOG4CXX_STR("FILE"));
+               auto appender = 
LogManager::getRootLogger()->getAppender(LOG4CXX_STR("FILE"));
                LOGUNIT_ASSERT(appender);
 
-               RollingFileAppenderPtr rfa = 
cast<RollingFileAppender>(appender);
+               auto rfa = cast<RollingFileAppender>(appender);
                LOGUNIT_ASSERT(rfa);
 
                FixedWindowRollingPolicyPtr fixedWindowRolling = 
cast<FixedWindowRollingPolicy>(rfa->getRollingPolicy());
                LOGUNIT_ASSERT(fixedWindowRolling);
 
-               SizeBasedTriggeringPolicyPtr sizeBasedPolicy = 
cast<SizeBasedTriggeringPolicy>(rfa->getTriggeringPolicy());
+               auto sizeBasedPolicy = 
cast<SizeBasedTriggeringPolicy>(rfa->getTriggeringPolicy());
                LOGUNIT_ASSERT(sizeBasedPolicy);
 
                LOGUNIT_ASSERT_EQUAL(3, fixedWindowRolling->getMaxIndex());
                LOGUNIT_ASSERT_EQUAL(100, 
static_cast<int>(sizeBasedPolicy->getMaxFileSize()));
        }
 
+private:
+       static int getFileCount(const char* dir, const LogString & initial)
+       {
+               Pool p;
+               std::vector<LogString> files(File(dir).list(p));
+               int count = 0;
+
+               for (size_t i = 0; i < files.size(); i++)
+               {
+                       if (StringHelper::startsWith(files[i], initial))
+                       {
+                               count++;
+                       }
+               }
+
+               return count;
+       }
+
 };
 
 
diff --git a/src/test/resources/input/rolling/obsoleteRFA1.properties 
b/src/test/resources/input/rolling/obsoleteRFA1.properties
index 1255605c..6fcc8dbe 100644
--- a/src/test/resources/input/rolling/obsoleteRFA1.properties
+++ b/src/test/resources/input/rolling/obsoleteRFA1.properties
@@ -20,6 +20,7 @@ log4j.appender.testAppender.Append=false
 log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
 log4j.appender.testAppender.layout.ConversionPattern=%m\n
 log4j.appender.testAppender.maxFileSize=100
+log4j.appender.testAppender.maxBackupIndex=3
 
 #  Prevent internal log4j DEBUG messages from polluting the output.
 log4j.logger.org.apache.log4j.PropertyConfigurator=INFO

Reply via email to