AppenderPtr DOMConfigurator::parseAppender()

in src/main/cpp/domconfigurator.cpp [210:337]


AppenderPtr DOMConfigurator::parseAppender(Pool& p,
	LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* appenderElement,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{

	LogString className(subst(getAttribute(utf8Decoder, appenderElement, CLASS_ATTR)));
	if (LogLog::isDebugEnabled())
	{
		LogLog::debug(LOG4CXX_STR("Class name: [") + className + LOG4CXX_STR("]"));
	}

	try
	{
		ObjectPtr instance = ObjectPtr(Loader::loadClass(className).newInstance());
		AppenderPtr appender = LOG4CXX_NS::cast<Appender>(instance);
		if(!appender){
			LogLog::error(LOG4CXX_STR("Could not cast class of type [") + className + LOG4CXX_STR("] to appender"));
			return AppenderPtr();
		}
		PropertySetter propSetter(appender);

		appender->setName(subst(getAttribute(utf8Decoder, appenderElement, NAME_ATTR)));

		for (apr_xml_elem* currentElement = appenderElement->first_child;
			currentElement;
			currentElement = currentElement->next)
		{

			std::string tagName(currentElement->name);

			// Parse appender parameters
			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
			// Set appender layout
			else if (tagName == LAYOUT_TAG)
			{
				appender->setLayout(parseLayout(p, utf8Decoder, currentElement));
			}
			// Add filters
			else if (tagName == FILTER_TAG)
			{
				std::vector<LOG4CXX_NS::spi::FilterPtr> filters;
				parseFilters(p, utf8Decoder, currentElement, filters);

				for (auto& item : filters)
				{
					appender->addFilter(item);
				}
			}
			else if (tagName == ERROR_HANDLER_TAG)
			{
				parseErrorHandler(p, utf8Decoder, currentElement, appender, doc, appenders);
			}
			else if (tagName == ROLLING_POLICY_TAG)
			{
				RollingPolicyPtr rollPolicy(parseRollingPolicy(p, utf8Decoder, currentElement));
				RollingFileAppenderPtr rfa = LOG4CXX_NS::cast<RollingFileAppender>(appender);

				if (rfa != NULL)
				{
					rfa->setRollingPolicy(rollPolicy);
				}
			}
			else if (tagName == TRIGGERING_POLICY_TAG)
			{
				ObjectPtr policy(parseTriggeringPolicy(p, utf8Decoder, currentElement));
				RollingFileAppenderPtr rfa = LOG4CXX_NS::cast<RollingFileAppender>(appender);
				TriggeringPolicyPtr policyPtr = LOG4CXX_NS::cast<TriggeringPolicy>(policy);

				if (rfa != NULL)
				{
					rfa->setTriggeringPolicy(policyPtr);
				}
				else
				{
					auto smtpa = LOG4CXX_NS::cast<LOG4CXX_NS::net::SMTPAppender>(appender);

					if (smtpa != NULL)
					{
						auto evaluator = LOG4CXX_NS::cast<TriggeringEventEvaluator>(policy);
						smtpa->setEvaluator(evaluator);
					}
				}
			}
			else if (tagName == APPENDER_REF_TAG)
			{
				LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));

				if (!refName.empty() && appender->instanceof(AppenderAttachable::getStaticClass()))
				{
					AppenderAttachablePtr aa = LOG4CXX_NS::cast<AppenderAttachable>(appender);
					if (LogLog::isDebugEnabled())
					{
						LogLog::debug(LOG4CXX_STR("Attaching appender named [") +
							refName + LOG4CXX_STR("] to appender named [") +
							appender->getName() + LOG4CXX_STR("]."));
					}
					aa->addAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
				}
				else if (refName.empty())
				{
					LogLog::error(LOG4CXX_STR("Can't add appender with empty ref attribute"));
				}
				else
				{
					LogLog::error(LOG4CXX_STR("Requesting attachment of appender named [") +
						refName + LOG4CXX_STR("] to appender named [") + appender->getName() +
						LOG4CXX_STR("] which does not implement AppenderAttachable."));
				}
			}
		}

		propSetter.activate(p);
		return appender;
	}
	/* Yes, it's ugly.  But all of these exceptions point to the same
	    problem: we can't create an Appender */
	catch (Exception& oops)
	{
		LogLog::error(LOG4CXX_STR("Could not create an Appender. Reported error follows."),
			oops);
		return 0;
	}
}