| /* | |
| * 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. | |
| */ | |
| #include <log4cxx/spi/loggingevent.h> | |
| #include <log4cxx/appenderskeleton.h> | |
| #include <log4cxx/helpers/loglog.h> | |
| #include <log4cxx/helpers/onlyonceerrorhandler.h> | |
| #include <log4cxx/level.h> | |
| #include <log4cxx/helpers/stringhelper.h> | |
| #include <log4cxx/private/appenderskeleton_priv.h> | |
| #include <mutex> | |
| using namespace LOG4CXX_NS; | |
| using namespace LOG4CXX_NS::spi; | |
| using namespace LOG4CXX_NS::helpers; | |
| IMPLEMENT_LOG4CXX_OBJECT(AppenderSkeleton) | |
| AppenderSkeleton::AppenderSkeleton( std::unique_ptr<AppenderSkeletonPrivate> priv ) | |
| : m_priv(std::move(priv)) | |
| { | |
| } | |
| AppenderSkeleton::AppenderSkeleton() | |
| : m_priv(std::make_unique<AppenderSkeletonPrivate>()) | |
| { | |
| } | |
| AppenderSkeleton::AppenderSkeleton(const LayoutPtr& layout) | |
| : m_priv(std::make_unique<AppenderSkeletonPrivate>(layout)) | |
| { | |
| } | |
| AppenderSkeleton::~AppenderSkeleton() {} | |
| void AppenderSkeleton::activateOptions( ) | |
| { | |
| } | |
| void AppenderSkeleton::addFilter(const spi::FilterPtr& newFilter) | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(m_priv->mutex); | |
| if (m_priv->headFilter == nullptr) | |
| { | |
| m_priv->headFilter = m_priv->tailFilter = newFilter; | |
| } | |
| else | |
| { | |
| m_priv->tailFilter->setNext(newFilter); | |
| m_priv->tailFilter = newFilter; | |
| } | |
| } | |
| void AppenderSkeleton::clearFilters() | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(m_priv->mutex); | |
| m_priv->headFilter = m_priv->tailFilter = nullptr; | |
| } | |
| bool AppenderSkeleton::isAsSevereAsThreshold(const LevelPtr& level) const | |
| { | |
| return ((level == 0) || level->isGreaterOrEqual(m_priv->threshold)); | |
| } | |
| void AppenderSkeleton::doAppend( const spi::LoggingEventPtr& event ) | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(m_priv->mutex); | |
| doAppendImpl( event ); | |
| } | |
| void AppenderSkeleton::doAppendImpl( const spi::LoggingEventPtr& event ) | |
| { | |
| if (m_priv->closed) | |
| { | |
| LogLog::warn(LOG4CXX_STR("Attempted to append to closed appender named [") | |
| + m_priv->name + LOG4CXX_STR("].")); | |
| } | |
| else if (isAsSevereAsThreshold(event->getLevel()) && isAccepted(event)) | |
| { | |
| append( event ); | |
| } | |
| } | |
| bool AppenderSkeleton::isAccepted(const spi::LoggingEventPtr& event) const | |
| { | |
| FilterPtr f = m_priv->headFilter; | |
| while (f != 0) | |
| { | |
| switch (f->decide(event)) | |
| { | |
| case Filter::DENY: | |
| return false; | |
| case Filter::ACCEPT: | |
| f = nullptr; | |
| break; | |
| default: | |
| case Filter::NEUTRAL: | |
| f = f->getNext(); | |
| } | |
| } | |
| return true; | |
| } | |
| bool AppenderSkeleton::AppenderSkeletonPrivate::checkNotClosed() | |
| { | |
| if (this->closed) | |
| { | |
| if (!this->warnedClosed) | |
| { | |
| LogLog::warn(LOG4CXX_STR("Not allowed to write to a closed appender.")); | |
| this->warnedClosed = true; | |
| } | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool AppenderSkeleton::AppenderSkeletonPrivate::setClosed() | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(this->mutex); | |
| bool wasOpen = !this->closed; | |
| this->closed = true; | |
| return wasOpen; | |
| } | |
| bool AppenderSkeleton::AppenderSkeletonPrivate::checkLayout() | |
| { | |
| if (!this->layout) | |
| { | |
| if (!this->warnedNoLayout) | |
| { | |
| this->errorHandler->error | |
| ( LogString(LOG4CXX_STR("No layout set for the appender named [")) | |
| + this->name + LOG4CXX_STR("].") | |
| ); | |
| this->warnedNoLayout = true; | |
| } | |
| return false; | |
| } | |
| return true; | |
| } | |
| void AppenderSkeleton::setErrorHandler(const spi::ErrorHandlerPtr& errorHandler1) | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(m_priv->mutex); | |
| if (errorHandler1 == nullptr) | |
| { | |
| // We do not throw exception here since the cause is probably a | |
| // bad config file. | |
| LogLog::warn(LOG4CXX_STR("You have tried to set a null error-handler.")); | |
| } | |
| else | |
| { | |
| m_priv->errorHandler = errorHandler1; | |
| } | |
| } | |
| void AppenderSkeleton::setThreshold(const LevelPtr& threshold1) | |
| { | |
| std::lock_guard<std::recursive_mutex> lock(m_priv->mutex); | |
| m_priv->threshold = threshold1; | |
| } | |
| void AppenderSkeleton::setOption(const LogString& option, | |
| const LogString& value) | |
| { | |
| if (StringHelper::equalsIgnoreCase(option, | |
| LOG4CXX_STR("THRESHOLD"), LOG4CXX_STR("threshold"))) | |
| { | |
| setThreshold(Level::toLevelLS(value)); | |
| } | |
| else if (StringHelper::equalsIgnoreCase(option, | |
| LOG4CXX_STR("NAME"), LOG4CXX_STR("name"))) | |
| { | |
| setName(value); | |
| } | |
| #if ENABLE_FAILING_APPENDER_SIMULATION_TESTING | |
| else if (StringHelper::equalsIgnoreCase(option, | |
| LOG4CXX_STR("FAILONMESSAGE"), LOG4CXX_STR("failonmessage"))) | |
| { | |
| m_priv->exceptionTriggeringMessage = value; | |
| } | |
| #endif | |
| else | |
| Appender::setOption(option, value); | |
| } | |
| const spi::ErrorHandlerPtr AppenderSkeleton::getErrorHandler() const | |
| { | |
| return m_priv->errorHandler; | |
| } | |
| spi::FilterPtr AppenderSkeleton::getFilter() const | |
| { | |
| return m_priv->headFilter; | |
| } | |
| const spi::FilterPtr AppenderSkeleton::getFirstFilter() const | |
| { | |
| return m_priv->headFilter; | |
| } | |
| LayoutPtr AppenderSkeleton::getLayout() const | |
| { | |
| return m_priv->layout; | |
| } | |
| LogString AppenderSkeleton::getName() const | |
| { | |
| return m_priv->name; | |
| } | |
| const LevelPtr AppenderSkeleton::getThreshold() const | |
| { | |
| return m_priv->threshold; | |
| } | |
| void AppenderSkeleton::setLayout(const LayoutPtr& layout1) | |
| { | |
| m_priv->layout = layout1; | |
| } | |
| void AppenderSkeleton::setName(const LogString& name1) | |
| { | |
| m_priv->name.assign(name1); | |
| } |