You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-dev@logging.apache.org by ca...@apache.org on 2007/12/11 03:11:37 UTC
svn commit: r603118 - in /logging/log4cxx/trunk: ./ src/dependencies/
src/dependencies/esmtp/ src/main/cpp/ src/main/include/log4cxx/net/
src/main/include/log4cxx/private/ src/main/include/log4cxx/xml/
src/test/cpp/net/ src/test/resources/input/xml/
Author: carnold
Date: Mon Dec 10 18:11:34 2007
New Revision: 603118
URL: http://svn.apache.org/viewvc?rev=603118&view=rev
Log:
LOGCXX-1: Migrate SMTPAppender to libesmtp
Added:
logging/log4cxx/trunk/src/dependencies/
logging/log4cxx/trunk/src/dependencies/esmtp/
logging/log4cxx/trunk/src/dependencies/esmtp/build.xml (with props)
logging/log4cxx/trunk/src/test/resources/input/xml/smtpAppender1.xml
- copied unchanged from r598753, logging/log4j/trunk/tests/input/xml/smtpAppender1.xml
Modified:
logging/log4cxx/trunk/configure.in
logging/log4cxx/trunk/src/main/cpp/class.cpp
logging/log4cxx/trunk/src/main/cpp/domconfigurator.cpp
logging/log4cxx/trunk/src/main/cpp/propertysetter.cpp
logging/log4cxx/trunk/src/main/cpp/smtpappender.cpp
logging/log4cxx/trunk/src/main/include/log4cxx/net/smtpappender.h
logging/log4cxx/trunk/src/main/include/log4cxx/private/log4cxx_private.h.in
logging/log4cxx/trunk/src/main/include/log4cxx/xml/domconfigurator.h
logging/log4cxx/trunk/src/test/cpp/net/smtpappendertestcase.cpp
Modified: logging/log4cxx/trunk/configure.in
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/configure.in?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/configure.in (original)
+++ logging/log4cxx/trunk/configure.in Mon Dec 10 18:11:34 2007
@@ -121,7 +121,7 @@
AC_ARG_ENABLE(cppunit,
AC_HELP_STRING(--enable-cppunit,
- [enable test excution with cppunit (auto)]))
+ [enable test execution with cppunit (auto)]))
enable_tests=yes
@@ -198,12 +198,6 @@
AC_PROG_RANLIB
-# for SocketAppender
-AC_CHECK_FUNCS(gethostbyname,,
- [AC_CHECK_LIB(nsl,gethostbyname,,
- [AC_CHECK_LIB(socket,gethostbyname)])])
-AC_CHECK_FUNCS(setsockopt,,[AC_CHECK_LIB(socket,setsockopt)])
-
#for ODBCAppender
AC_MSG_CHECKING(for ODBC support)
AC_ARG_WITH(ODBC,
@@ -256,43 +250,27 @@
AC_MSG_CHECKING(for SMTP support)
AC_ARG_WITH(SMTP,
AC_HELP_STRING(--with-SMTP, [SMTP support. Accepted arguments :
- libsmtp, CDO, no (default=no)]),
+ libesmtp, no (default=no)]),
[ac_with_smtp=$withval],
[ac_with_smtp=no])
case "$ac_with_smtp" in
- CDO)
- AC_MSG_RESULT(CDO)
- AC_DEFINE(HAVE_CDO_SMTP, 1, SMTP support through Microsoft CDO.)
- AC_DEFINE(HAVE_SMTP, 1, SMTP support)
- ;;
- libsmtp)
- AC_MSG_RESULT(libsmtp)
- AC_CHECK_LIB([smtp_mime], [libsmtp_session_initialize],,
- AC_MSG_ERROR(libsmtp library not found !),
- `glib-config --libs` -lsmtp)
- AC_DEFINE(HAVE_LIBSMTP, 1, SMTP support through libsmtp library.)
- AC_DEFINE(HAVE_SMTP, 1, SMTP support)
- LIBS="`glib-config --libs` -lsmtp $LIBS"
- CPPFLAGS="`glib-config --cflags` $CPPFLAGS"
+ libesmtp)
+ AC_MSG_RESULT(libesmtp)
+ AC_CHECK_LIB([esmtp], [smtp_create_session],,
+ AC_MSG_ERROR(libesmtp library not found !),
+ -lesmtp)
+ AC_SUBST(HAS_LIBESMTP, 1, SMTP support through libesmtp library.)
+ LIBS="-lesmtp $LIBS"
;;
no)
AC_MSG_RESULT(no)
+ AC_SUBST(HAS_LIBESMTP, 0, SMTP support through libesmtp library.)
;;
*)
AC_MSG_RESULT(???)
AC_MSG_ERROR(Unknown option : $ac_with_smtp)
;;
esac
-
-#for _T
-
-case "$host" in
- *apple-darwin*)
- AC_DEFINE(MUST_UNDEF_T, 1, Defined to 1 if macro _T has to be undefined)
- ;;
-esac
-
-CPPFLAGS="-DLOG4CXX $CPPFLAGS"
#for wchar_t
AC_ARG_ENABLE(wchar_t,
Added: logging/log4cxx/trunk/src/dependencies/esmtp/build.xml
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/dependencies/esmtp/build.xml?rev=603118&view=auto
==============================================================================
--- logging/log4cxx/trunk/src/dependencies/esmtp/build.xml (added)
+++ logging/log4cxx/trunk/src/dependencies/esmtp/build.xml Mon Dec 10 18:11:34 2007
@@ -0,0 +1,233 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+
+-->
+
+<!--
+
+This file builds libesmtp using Apache Ant (http://ant.apache.org)
+and the C++ compilation tasks from http://ant-contrib.sourceforge.net.
+
+
+-->
+<project name="esmtp" default="build">
+
+<property name="debug" value="true"/>
+<property name="esmtp.version" value="1.0.4"/>
+<property name="esmtp.dir" location="${ant.file}/../../../../../libesmtp-${esmtp.version}"/>
+<property name="esmtp.include.dir" location="${esmtp.dir}"/>
+<property name="build.dir" location="${user.dir}/target"/>
+<property name="src.dir" location="${esmtp.dir}"/>
+<property name="esmtp.lib.type" value="shared"/>
+<property name="project.dir" location="${build.dir}"/>
+
+<taskdef resource="cpptasks.tasks"/>
+<typedef resource="cpptasks.types"/>
+
+<target name="usage" description="Displays usage notes on build">
+ <echo>
+ </echo>
+</target>
+
+<target name="os-detect">
+ <condition property="is-mac" value="true">
+ <and>
+ <os family="mac"/>
+ <not><isset property="is-windows"/></not>
+ </and>
+ </condition>
+ <condition property="is-unix" value="true">
+ <and>
+ <not>
+ <or>
+ <isset property="is-windows"/>
+ <equals arg1="${os.family}" arg2="windows"/>
+ </or>
+ </not>
+ <or>
+ <os family="unix"/>
+ <equals arg1="${os.family}" arg2="cygwin"/>
+ <equals arg1="${os.family}" arg2="unix"/>
+ </or>
+ </and>
+ </condition>
+ <condition property="is-windows" value="true">
+ <and>
+ <not><isset property="is-unix"/></not>
+ <or>
+ <os family="windows"/>
+ <equals arg1="${os.family}" arg2="windows"/>
+ </or>
+ </and>
+ </condition>
+</target>
+
+
+<target name="win-init" depends="os-detect" if="is-windows">
+ <property name="compiler" value="msvc"/>
+ <property name="arch" value="win32"/>
+ <property name="project.type" value="msvc6"/>
+</target>
+
+<target name="unix-init" depends="os-detect" if="is-unix">
+ <property name="compiler" value="gcc"/>
+ <condition property="is-gcc" value="true">
+ <or>
+ <equals arg1="${compiler}" arg2="gcc"/>
+ <equals arg1="${compiler}" arg2="g++"/>
+ </or>
+ </condition>
+ <property name="arch" value="unix"/>
+ <property name="project.type" value="cbuilderx"/>
+</target>
+
+<target name="init" depends="win-init, unix-init">
+ <property environment="env"/>
+ <condition property="pic-option" value="-fPIC">
+ <and>
+ <isset property="is-gcc"/>
+ <istrue value="${use-pic}"/>
+ </and>
+ </condition>
+
+ <condition property="is-debug" value="true">
+ <istrue value="${debug}"/>
+ </condition>
+
+ <condition property="esmtp.lib.dir" value="${build.dir}/debug/${esmtp.lib.type}">
+ <isset property="is-debug"/>
+ </condition>
+ <property name="esmtp.lib.dir" location="${build.dir}/release/${esmtp.lib.type}"/>
+ <mkdir dir="${esmtp.lib.dir}"/>
+
+ <condition property="lib-suffix" value="d">
+ <isset property="is-debug"/>
+ </condition>
+ <property name="lib-suffix" value=""/>
+
+ <condition property="is-esmtp-shared" value="true">
+ <equals arg1="${esmtp.lib.type}" arg2="shared"/>
+ </condition>
+
+ <condition property="is-bcc" value="true">
+ <equals arg1="${compiler}" arg2="bcc"/>
+ </condition>
+ <condition property="project.if" value="true">
+ <istrue value="${project.if.value}"/>
+ </condition>
+</target>
+
+<target name="clean" description="Removes build product files">
+ <delete dir="${build.dir}"/>
+</target>
+
+
+<target name="configure-check" depends="init">
+ <condition property="esmtp-configure-available" value="true">
+ <available file="${esmtp.include.dir}/libesmtp.h"/>
+ </condition>
+</target>
+
+
+<target name="win-configure" depends="configure-check" if="is-windows" unless="esmtp-configure-available">
+ <copy tofile="${esmtp.include.dir}/libesmtp.h" file="${esmtp.include.dir}/libesmtp.hw"/>
+</target>
+
+<target name="unix-configure" depends="configure-check" if="is-unix" unless="esmtp-configure-available">
+ <!-- shelling to configure allows cygwin to work -->
+ <exec executable="sh" dir="${esmtp.dir}">
+ <arg value="./configure"/>
+ </exec>
+</target>
+
+
+<target name="configure" depends="unix-configure, win-configure"/>
+
+
+<target name="build" depends="configure" description="Build library">
+ <mkdir dir="${esmtp.lib.dir}/esmtp_obj"/>
+ <property name="project.compiler" value="${compiler}"/>
+ <cc name="${project.compiler}"
+ outfile="${esmtp.lib.dir}/esmtp${lib-suffix}"
+ subsystem="console"
+ multithreaded="true"
+ outtype="${esmtp.lib.type}"
+ objdir="${esmtp.lib.dir}/esmtp_obj"
+ outputfileproperty="esmtp.dll"
+ debug="${debug}"
+ projectsOnly="${projectsOnly}">
+ <fileset dir="${src.dir}" includes="*.c" excludes="getaddrinfo.c"/>
+ <includepath path="${esmtp.include.dir}"/>
+ <defineset define="HAVE_CONFIG_H"/>
+ <defineset>
+ <define name="VERSION" value='"${esmtp.version}"'/>
+ </defineset>
+ <compilerarg value="${pic-option}" if="pic-option"/>
+ <libset libs="advapi32 ws2_32 mswsock rpcrt4" if="is-windows"/>
+ <libset libs="ssl crypto" if="is-unix"/>
+ <libset libs="cw32mt" if="is-bcc"/>
+ <project type="${project.type}" outfile="${project.dir}/esmtp" if="project.if"/>
+ </cc>
+</target>
+
+
+<target name="build-projects">
+ <mkdir dir="${project.dir}"/>
+ <antcall target="build">
+ <param name="project.if" value="true"/>
+ <param name="project.type" value="${project.type}"/>
+ <param name="project.compiler" value="${project.compiler}"/>
+ <param name="projects.dir" value="${project.dir}"/>
+ <param name="projectsOnly" value="true"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc6" description="Builds project files for Microsoft Visual C++ 6">
+ <antcall target="build-projects">
+ <param name="project.dir" value="msvc"/>
+ <param name="project.type" value="msvc6"/>
+ <param name="project.compiler" value="msvc"/>
+ </antcall>
+</target>
+
+<target name="build-projects-vc8" description="Builds project files for Microsoft Visual C++ 2005">
+ <antcall target="build-projects">
+ <param name="project.dir" value="msvc"/>
+ <param name="project.type" value="msvc8"/>
+ <param name="project.compiler" value="msvc"/>
+ </antcall>
+</target>
+
+<target name="build-projects-xcode" description="Builds project files for Apple Xcode">
+ <antcall target="build-projects">
+ <param name="project.dir" value="xcode"/>
+ <param name="project.type" value="xcode"/>
+ <param name="project.compiler" value="${compiler}"/>
+ </antcall>
+</target>
+
+<target name="build-projects-cbx" description="Builds project files for Borland CBuilderX">
+ <antcall target="build-projects">
+ <param name="project.dir" value="cbx"/>
+ <param name="project.type" value="cbuilderx"/>
+ <param name="project.compiler" value="${compiler}"/>
+ </antcall>
+</target>
+
+
+
+</project>
Propchange: logging/log4cxx/trunk/src/dependencies/esmtp/build.xml
------------------------------------------------------------------------------
svn:executable = *
Modified: logging/log4cxx/trunk/src/main/cpp/class.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/class.cpp?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/class.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/class.cpp Mon Dec 10 18:11:34 2007
@@ -114,7 +114,7 @@
//
const Class* clazz = getRegistry()[lowerName];
if (clazz == 0) {
- LogString::size_type pos = className.find_last_of(LOG4CXX_STR('.'));
+ LogString::size_type pos = className.find_last_of(LOG4CXX_STR(".$"));
if (pos != LogString::npos) {
LogString terminalName(lowerName, pos + 1, LogString::npos);
clazz = getRegistry()[terminalName];
Modified: logging/log4cxx/trunk/src/main/cpp/domconfigurator.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/domconfigurator.cpp?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/domconfigurator.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/domconfigurator.cpp Mon Dec 10 18:11:34 2007
@@ -46,6 +46,7 @@
#include <apr_xml.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/charsetdecoder.h>
+#include <log4cxx/net/smtpappender.h>
using namespace log4cxx;
using namespace log4cxx::xml;
@@ -224,10 +225,16 @@
}
else if (tagName == TRIGGERING_POLICY_TAG)
{
- TriggeringPolicyPtr triggerPolicy(parseTriggeringPolicy(p, utf8Decoder, currentElement));
+ ObjectPtr policy(parseTriggeringPolicy(p, utf8Decoder, currentElement));
RollingFileAppenderPtr rfa(appender);
if (rfa != NULL) {
- rfa->setTriggeringPolicy(triggerPolicy);
+ rfa->setTriggeringPolicy(policy);
+ } else {
+ log4cxx::net::SMTPAppenderPtr smtpa(appender);
+ if (smtpa != NULL) {
+ log4cxx::spi::TriggeringEventEvaluatorPtr evaluator(policy);
+ smtpa->setEvaluator(evaluator);
+ }
}
}
else if (tagName == APPENDER_REF_TAG)
@@ -521,7 +528,7 @@
/**
Used internally to parse a triggering policy
*/
-TriggeringPolicyPtr DOMConfigurator::parseTriggeringPolicy (
+ObjectPtr DOMConfigurator::parseTriggeringPolicy (
log4cxx::helpers::Pool& p,
log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
apr_xml_elem* layout_element)
@@ -531,8 +538,7 @@
try
{
ObjectPtr instance = Loader::loadClass(className).newInstance();
- TriggeringPolicyPtr layout = instance;
- PropertySetter propSetter(layout);
+ PropertySetter propSetter(instance);
for (apr_xml_elem* currentElement = layout_element->first_child;
currentElement;
@@ -557,7 +563,7 @@
}
propSetter.activate(p);
- return layout;
+ return instance;
}
catch (Exception& oops)
{
Modified: logging/log4cxx/trunk/src/main/cpp/propertysetter.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/propertysetter.cpp?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/propertysetter.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/propertysetter.cpp Mon Dec 10 18:11:34 2007
@@ -69,6 +69,7 @@
LogString value = OptionConverter::findAndSubst(key, properties);
key = key.substr(len);
if (key == LOG4CXX_STR("layout")
+ && obj != 0
&& obj->instanceof(Appender::getStaticClass()))
{
continue;
@@ -86,7 +87,7 @@
if (value.empty())
return;
- if (obj->instanceof(OptionHandler::getStaticClass()))
+ if (obj != 0 && obj->instanceof(OptionHandler::getStaticClass()))
{
LogLog::debug(LOG4CXX_STR("Setting option name=[") +
option + LOG4CXX_STR("], value=[") + value + LOG4CXX_STR("]"));
@@ -96,7 +97,7 @@
void PropertySetter::activate(Pool& p)
{
- if (obj->instanceof(OptionHandler::getStaticClass()))
+ if (obj != 0 && obj->instanceof(OptionHandler::getStaticClass()))
{
OptionHandlerPtr(obj)->activateOptions(p);
}
Modified: logging/log4cxx/trunk/src/main/cpp/smtpappender.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/smtpappender.cpp?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/smtpappender.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/smtpappender.cpp Mon Dec 10 18:11:34 2007
@@ -16,7 +16,6 @@
*/
#include <log4cxx/private/log4cxx_private.h>
-#if LOG4CXX_HAVE_SMTP
#include <log4cxx/net/smtpappender.h>
#include <log4cxx/level.h>
@@ -28,14 +27,280 @@
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/synchronized.h>
-#include <libsmtp.h>
-#include <libsmtp_mime.h>
+
+#include <apr_strings.h>
+#include <vector>
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::net;
using namespace log4cxx::spi;
+#if LOG4CXX_HAVE_LIBESMTP
+#include <auth-client.h>
+#include <libesmtp.h>
+#endif
+
+namespace log4cxx {
+ namespace net {
+ //
+ // The following two classes implement an C++ SMTP wrapper over libesmtp.
+ // The same signatures could be implemented over different SMTP implementations
+ // or libesmtp could be combined with libgmime to enable support for non-ASCII
+ // content.
+
+#if LOG4CXX_HAVE_LIBESMTP
+ /**
+ * SMTP Session.
+ */
+ class SMTPSession {
+ public:
+ /**
+ * Create new instance.
+ */
+ SMTPSession(const LogString& smtpHost,
+ int smtpPort,
+ const LogString& smtpUsername,
+ const LogString& smtpPassword,
+ Pool& p) : session(0), authctx(0),
+ user(toAscii(smtpUsername, p)),
+ pwd(toAscii(smtpPassword, p)) {
+ auth_client_init();
+ session = smtp_create_session();
+ if (session == 0) {
+ throw Exception("Could not initialize session.");
+ }
+ std::string host(toAscii(smtpHost, p));
+ host.append(1, ':');
+ host.append(apr_itoa((apr_pool_t*) p.getAPRPool(), smtpPort));
+ smtp_set_server(session, host.c_str());
+
+ authctx = auth_create_context();
+ auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0);
+ auth_set_interact_cb(authctx, authinteract, (void*) this);
+
+ if (*user || *pwd) {
+ smtp_auth_set_context(session, authctx);
+ }
+ }
+
+ ~SMTPSession() {
+ smtp_destroy_session(session);
+ auth_destroy_context(authctx);
+ }
+
+ void send(Pool& p) {
+ int status = smtp_start_session(session);
+ if (!status) {
+ size_t bufSize = 128;
+ char* buf = (char*) apr_palloc((apr_pool_t*) p.getAPRPool(), bufSize);
+ smtp_strerror(smtp_errno(), buf, bufSize);
+ throw Exception(buf);
+ }
+ }
+
+ operator smtp_session_t() {
+ return session;
+ }
+
+ static char* toAscii(const LogString& str, Pool& p) {
+ char* buf = (char*) apr_palloc((apr_pool_t*) p.getAPRPool(), str.length() + 1);
+ char* current = buf;
+ for(LogString::const_iterator iter = str.begin();
+ iter != str.end();
+ iter++) {
+ unsigned int c = *iter;
+ if (c > 0x7F) {
+ c = '?';
+ }
+ *current++ = c;
+ }
+ *current = 0;
+ return buf;
+ }
+
+ private:
+ SMTPSession(SMTPSession&);
+ SMTPSession& operator=(SMTPSession&);
+ smtp_session_t session;
+ auth_context_t authctx;
+ char* user;
+ char* pwd;
+
+ /**
+ * This method is called if the SMTP server requests authentication.
+ */
+ static int authinteract(auth_client_request_t request, char **result, int fields,
+ void *arg) {
+ SMTPSession* pThis = (SMTPSession*) arg;
+ for (int i = 0; i < fields; i++) {
+ int flag = request[i].flags & 0x07;
+ if (flag == AUTH_USER) {
+ result[i] = pThis->user;
+ } else if(flag == AUTH_PASS) {
+ result[i] = pThis->pwd;
+ }
+ }
+ return 1;
+ }
+
+
+ };
+
+ /**
+ * A message in an SMTP session.
+ */
+ class SMTPMessage {
+ public:
+ SMTPMessage(SMTPSession& session,
+ const LogString& from,
+ const LogString& to,
+ const LogString& cc,
+ const LogString& bcc,
+ const LogString& subject,
+ const LogString msg, Pool& p) {
+ message = smtp_add_message(session);
+ body = current = toMessage(msg, p);
+ smtp_set_reverse_path(message, toAscii(from, p));
+ addRecipients(to, "To", p);
+ addRecipients(cc, "Cc", p);
+ addRecipients(bcc, "Bcc", p);
+ if (!subject.empty()) {
+ smtp_set_header(message, "Subject", toAscii(subject, p));
+ }
+ smtp_set_messagecb(message, messagecb, this);
+ }
+ ~SMTPMessage() {
+ }
+
+ private:
+ SMTPMessage(const SMTPMessage&);
+ SMTPMessage& operator=(const SMTPMessage&);
+ smtp_message_t message;
+ const char* body;
+ const char* current;
+ void addRecipients(const LogString& addresses, const char* field, Pool& p) {
+ if (!addresses.empty()) {
+ char* str = apr_pstrdup((apr_pool_t*) p.getAPRPool(), toAscii(addresses, p));;
+ smtp_set_header(message, field, NULL, str);
+ char* last;
+ for(char* next = apr_strtok(str, ",", &last);
+ next;
+ next = apr_strtok(NULL, ",", &last)) {
+ smtp_add_recipient(message, next);
+ }
+ }
+ }
+ static const char* toAscii(const LogString& str, Pool& p) {
+ return SMTPSession::toAscii(str, p);
+ }
+
+ /**
+ * Message bodies can only contain US-ASCII characters and
+ * CR and LFs can only occur together.
+ */
+ static const char* toMessage(const LogString& str, Pool& p) {
+ //
+ // count the number of carriage returns and line feeds
+ //
+ int feedCount = 0;
+ for(size_t pos = str.find_first_of(LOG4CXX_STR("\n\r"));
+ pos != LogString::npos;
+ pos = str.find_first_of(LOG4CXX_STR("\n\r"), ++pos)) {
+ feedCount++;
+ }
+ //
+ // allocate sufficient space for the modified message
+ char* retval = (char*) apr_palloc((apr_pool_t*) p.getAPRPool(), str.length() + feedCount + 1);
+ char* current = retval;
+ char* startOfLine = current;
+ //
+ // iterator through message
+ //
+ for(LogString::const_iterator iter = str.begin();
+ iter != str.end();
+ iter++) {
+ unsigned int c = *iter;
+ //
+ // replace non-ASCII characters with '?'
+ //
+ if (c > 0x7F) {
+ *current++ = '?';
+ } else if (c == '\n' || c == '\r') {
+ //
+ // replace any stray CR or LF with CRLF
+ // reset start of line
+ *current++ = '\r';
+ *current++ = '\n';
+ startOfLine = current;
+ LogString::const_iterator next = iter + 1;
+ if (next != str.end() && (*next == '\n' || *next == '\r')) {
+ iter++;
+ }
+ } else {
+ //
+ // truncate any lines to 1000 characters (including CRLF)
+ // as required by RFC.
+ if (current < startOfLine + 998) {
+ *current++ = (char) c;
+ }
+ }
+ }
+ *current = 0;
+ return retval;
+ }
+
+ /**
+ * Callback for message.
+ */
+ static const char* messagecb(void** ctx, int* len, void* arg) {
+ *ctx = 0;
+ const char* retval = 0;
+ SMTPMessage* pThis = (SMTPMessage*) arg;
+ // rewind message
+ if (len == NULL) {
+ pThis->current = pThis->body;
+ } else {
+ if (pThis->current) {
+ *len = strlen(pThis->current);
+ }
+ retval = pThis->current;
+ pThis->current = 0;
+ }
+ return retval;
+ }
+
+ };
+#endif
+
+ class LOG4CXX_EXPORT DefaultEvaluator :
+ public virtual spi::TriggeringEventEvaluator,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(DefaultEvaluator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(DefaultEvaluator)
+ LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
+ END_LOG4CXX_CAST_MAP()
+
+ DefaultEvaluator();
+
+ /**
+ Is this <code>event</code> the e-mail triggering event?
+ <p>This method returns <code>true</code>, if the event level
+ has ERROR level or higher. Otherwise it returns
+ <code>false</code>.
+ */
+ virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event);
+ private:
+ DefaultEvaluator(const DefaultEvaluator&);
+ DefaultEvaluator& operator=(const DefaultEvaluator&);
+ }; // class DefaultEvaluator
+
+ }
+}
+
IMPLEMENT_LOG4CXX_OBJECT(DefaultEvaluator)
IMPLEMENT_LOG4CXX_OBJECT(SMTPAppender)
@@ -49,8 +314,7 @@
SMTPAppender::SMTPAppender()
: bufferSize(512), locationInfo(false), cb(bufferSize),
-evaluator(new DefaultEvaluator()), session(0),
-encoding(LOG4CXX_STR("7bit")), charset(LOG4CXX_STR("us-ascii"))
+evaluator(new DefaultEvaluator()), smtpPort(25)
{
}
@@ -59,8 +323,7 @@
TriggeringEventEvaluator for this SMTPAppender. */
SMTPAppender::SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator)
: bufferSize(512), locationInfo(false), cb(bufferSize),
-evaluator(evaluator), session(0),
-encoding(LOG4CXX_STR("7bit")), charset(LOG4CXX_STR("us-ascii"))
+evaluator(evaluator), smtpPort(25)
{
}
@@ -69,6 +332,72 @@
finalize();
}
+bool SMTPAppender::requiresLayout() const {
+ return true;
+}
+
+
+LogString SMTPAppender::getFrom() const {
+ return from;
+}
+
+void SMTPAppender::setFrom(const LogString& newVal) {
+ from = newVal;
+}
+
+
+LogString SMTPAppender::getSubject() const {
+ return subject;
+}
+
+void SMTPAppender::setSubject(const LogString& newVal) {
+ subject = newVal;
+}
+
+LogString SMTPAppender::getSMTPHost() const {
+ return smtpHost;
+}
+
+void SMTPAppender::setSMTPHost(const LogString& newVal) {
+ smtpHost = newVal;
+}
+
+int SMTPAppender::getSMTPPort() const {
+ return smtpPort;
+}
+
+void SMTPAppender::setSMTPPort(int newVal) {
+ smtpPort = newVal;
+}
+
+bool SMTPAppender::getLocationInfo() const {
+ return locationInfo;
+}
+
+void SMTPAppender::setLocationInfo(bool newVal) {
+ locationInfo = newVal;
+}
+
+LogString SMTPAppender::getSMTPUsername() const {
+ return smtpUsername;
+}
+
+void SMTPAppender::setSMTPUsername(const LogString& newVal) {
+ smtpUsername = newVal;
+}
+
+LogString SMTPAppender::getSMTPPassword() const {
+ return smtpPassword;
+}
+
+void SMTPAppender::setSMTPPassword(const LogString& newVal) {
+ smtpPassword = newVal;
+}
+
+
+
+
+
void SMTPAppender::setOption(const LogString& option,
const LogString& value)
{
@@ -88,6 +417,14 @@
{
setSMTPHost(value);
}
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPUSERNAME"), LOG4CXX_STR("smtpusername")))
+ {
+ setSMTPUsername(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPASSWORD"), LOG4CXX_STR("smtppassword")))
+ {
+ setSMTPPassword(value);
+ }
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SUBJECT"), LOG4CXX_STR("subject")))
{
setSubject(value);
@@ -96,13 +433,17 @@
{
setTo(value);
}
- else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CHARSET"), LOG4CXX_STR("charset")))
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CC"), LOG4CXX_STR("cc")))
{
- setCharset(value);
+ setCc(value);
}
- else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("ENCODING"), LOG4CXX_STR("encoding")))
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BCC"), LOG4CXX_STR("bcc")))
{
- setEncoding(value);
+ setBcc(value);
+ }
+ else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPORT"), LOG4CXX_STR("smtpport")))
+ {
+ setSMTPPort(OptionConverter::toInt(value, 25));
}
else
{
@@ -110,126 +451,55 @@
}
}
+
+bool SMTPAppender::asciiCheck(const LogString& value, const logchar* field) {
+ for(LogString::const_iterator iter = value.begin();
+ iter != value.end();
+ iter++) {
+ if (0x7F < (unsigned int) *iter) {
+ LogLog::warn(LogString(field) + LOG4CXX_STR(" contains non-ASCII character"));
+ return false;
+ }
+ }
+ return true;
+}
+
/**
Activate the specified options, such as the smtp host, the
recipient, from, etc. */
void SMTPAppender::activateOptions(Pool& p)
{
- session = ::libsmtp_session_initialize();
- if (session == 0)
- {
- LogLog::error(LOG4CXX_STR("Could not intialize session."));
- return;
- }
-
- LOG4CXX_ENCODE_CHAR(ansiFrom, from);
- LOG4CXX_ENCODE_CHAR(ansiSubject, subject);
- ::libsmtp_set_environment(
- const_cast<char*>(ansiFrom.c_str()),
- const_cast<char*>(ansiSubject.c_str()),
- 0,
- (libsmtp_session_struct *)session);
-
- std::vector<LogString> recipients = parseAddress(to);
- std::vector<LogString>::iterator i;
- for (i = recipients.begin(); i != recipients.end(); i++)
- {
- LOG4CXX_ENCODE_CHAR(ansiTo, *i);
- if (::libsmtp_add_recipient(LIBSMTP_REC_TO,
- const_cast<char*>(ansiTo.c_str()),
- (libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Could not add recipient ")+ *i + LOG4CXX_STR("."));
- return;
- }
- }
-
- // MIMEPART
- if (layout != 0)
- {
- int mimeType = 0;
- LogString contentType(layout->getContentType());
- if (contentType == LOG4CXX_STR("text/plain"))
- {
- mimeType = LIBSMTP_MIME_SUB_PLAIN;
- }
- else if (contentType == LOG4CXX_STR("text/html"))
- {
- mimeType = LIBSMTP_MIME_SUB_HTML;
- }
- else
- {
- LogLog::error(LOG4CXX_STR("invalid layout content type: ")+contentType+LOG4CXX_STR("."));
- return;
- }
-
- int charset = 0;
- if (this->charset == LOG4CXX_STR("us-ascii"))
- {
- charset = LIBSMTP_CHARSET_USASCII;
- }
- else if (this->charset == LOG4CXX_STR("iso8859_1"))
- {
- charset = LIBSMTP_CHARSET_ISO8859_1;
- }
- else if (this->charset == LOG4CXX_STR("iso8859_2"))
- {
- charset = LIBSMTP_CHARSET_ISO8859_2;
- }
- else if (this->charset == LOG4CXX_STR("iso8859_3"))
- {
- charset = LIBSMTP_CHARSET_ISO8859_3;
- }
- else
- {
- LogLog::error(LOG4CXX_STR("invalid charset: ")+this->charset+LOG4CXX_STR("."));
- return;
- }
-
- int encoding = 0;
- if (this->encoding == LOG4CXX_STR("7bit"))
- {
- encoding = LIBSMTP_ENC_7BIT;
- }
- else if (this->encoding == LOG4CXX_STR("8bit"))
- {
- encoding = LIBSMTP_ENC_8BIT;
- }
- else if (this->encoding == LOG4CXX_STR("binary"))
- {
- encoding = LIBSMTP_ENC_BINARY;
- }
- else if (this->encoding == LOG4CXX_STR("base64"))
- {
- encoding = LIBSMTP_ENC_BASE64;
- }
- else if (this->encoding == LOG4CXX_STR("quoted"))
- {
- encoding = LIBSMTP_ENC_QUOTED;
- }
- else
- {
- LogLog::error(LOG4CXX_STR("invalid encoding: ")+this->encoding+LOG4CXX_STR("."));
- return;
- }
-
- libsmtp_part_struct * part = 0;
- part = ::libsmtp_part_new(
- 0,
- LIBSMTP_MIME_TEXT,
- mimeType,
- encoding,
- charset,
- "content",
- (libsmtp_session_struct *)session);
- if (part == 0)
- {
- LogLog::error(LOG4CXX_STR("Error adding part."));
- }
- }
- else
- {
- LogLog::error(LOG4CXX_STR("Layout not set !"));
+ bool activate = true;
+ if (layout == 0) {
+ LogLog::error(LOG4CXX_STR("No layout set for appender named [") +name+ LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(evaluator == 0) {
+ LogLog::error(LOG4CXX_STR("No TriggeringEventEvaluator is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(smtpHost.empty()) {
+ LogLog::error(LOG4CXX_STR("No smtpHost is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ if(to.empty() && cc.empty() && bcc.empty()) {
+ LogLog::error(LOG4CXX_STR("No recipient address is set for appender [")+
+ name+LOG4CXX_STR("]."));
+ activate = false;
+ }
+ activate &= asciiCheck(to, LOG4CXX_STR("to"));
+ activate &= asciiCheck(cc, LOG4CXX_STR("cc"));
+ activate &= asciiCheck(bcc, LOG4CXX_STR("bcc"));
+ activate &= asciiCheck(from, LOG4CXX_STR("from"));
+
+#if !LOG4CXX_HAS_LIBESMTP
+ LogLog::error(LOG4CXX_STR("log4cxx built without SMTP support."));
+ activate = false;
+#endif
+ if (activate) {
+ AppenderSkeleton::activateOptions(p);
}
}
@@ -244,12 +514,11 @@
return;
}
- event->getNDC();
-
-/* if(locationInfo)
- {
- event.getLocationInformation();
- }*/
+ LogString ndc;
+ event->getNDC(ndc);
+ event->getThreadName();
+ // Get a copy of this thread's MDC.
+ event->getMDCCopy();
cb.add(event);
@@ -266,7 +535,8 @@
value <code>false</code> is returned. */
bool SMTPAppender::checkEntryConditions()
{
- if(to.empty() || from.empty() || subject.empty() || smtpHost.empty())
+#if LOG4CXX_HAVE_LIBESMTP
+ if((to.empty() && cc.empty() && bcc.empty()) || from.empty() || smtpHost.empty())
{
errorHandler->error(LOG4CXX_STR("Message not configured."));
return false;
@@ -286,31 +556,39 @@
return false;
}
return true;
+#else
+ return false;
+#endif
}
-void SMTPAppender::close()
-{
- synchronized sync(this);
- if (!this->closed && session != 0)
- {
- ::libsmtp_free((libsmtp_session_struct *)session);
- session = 0;
- }
+
+void SMTPAppender::close() {
this->closed = true;
}
-std::vector<LogString> SMTPAppender::parseAddress(const LogString& addressStr)
-{
- std::vector<LogString> addresses;
+LogString SMTPAppender::getTo() const{
+ return to;
+}
- StringTokenizer st(addressStr, LOG4CXX_STR(","));
- while (st.hasMoreTokens())
- {
- addresses.push_back(st.nextToken());
- }
+void SMTPAppender::setTo(const LogString& addressStr) {
+ to = addressStr;
+}
- return addresses;
+LogString SMTPAppender::getCc() const{
+ return cc;
+}
+
+void SMTPAppender::setCc(const LogString& addressStr) {
+ cc = addressStr;
+}
+
+LogString SMTPAppender::getBcc() const{
+ return bcc;
+}
+
+void SMTPAppender::setBcc(const LogString& addressStr) {
+ bcc = addressStr;
}
/**
@@ -318,6 +596,7 @@
*/
void SMTPAppender::sendBuffer(Pool& p)
{
+#if LOG4CXX_HAS_LIBESMTP
// Note: this code already owns the monitor for this
// appender. This frees us from needing to synchronize on 'cb'.
try
@@ -328,75 +607,25 @@
int len = cb.length();
for(int i = 0; i < len; i++)
{
- //sbuf.append(MimeUtility.encodeText(layout.format(cb.get())));
LoggingEventPtr event = cb.get();
layout->format(sbuf, event, p);
}
layout->appendFooter(sbuf, p);
- LOG4CXX_ENCODE_CHAR(aSmtpHost, smtpHost);
-
- /* This starts the SMTP connection */
- if (::libsmtp_connect(
- const_cast<char*>(aSmtpHost.c_str()),
- 0,
- 0,
- (libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while starting the SMTP connection."));
- return;
- }
-
- /* This will conduct the SMTP dialogue */
- if (::libsmtp_dialogue((libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while conducting the SMTP dialogue."));
- return;
- }
-
- /* Now lets send the headers */
- if (::libsmtp_headers((libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while sending the headers."));
- return;
- }
-
- /* Now lets send the MIME headers */
- if (::libsmtp_mime_headers((libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while sending the MIME headers."));
- return;
- }
-
- LOG4CXX_ENCODE_CHAR(s, sbuf);
- if (::libsmtp_part_send(
- const_cast<char*>(s.c_str()),
- s.length(),
- (libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while sending the message body."));
- }
-
- /* This ends the body part */
- if (::libsmtp_body_end((libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while ending the body part."));
- return;
- }
-
- /* This ends the connection gracefully */
- if (::libsmtp_quit((libsmtp_session_struct *)session) != 0)
- {
- LogLog::error(LOG4CXX_STR("Error occured while ending the connection."));
- return;
- }
+ SMTPSession session(smtpHost, smtpPort, smtpUsername, smtpPassword, p);
+
+ SMTPMessage message(session, from, to, cc,
+ bcc, subject, sbuf, p);
+
+ session.send(p);
}
catch(std::exception& e)
{
LogLog::error(LOG4CXX_STR("Error occured while sending e-mail notification."), e);
}
+#endif
}
/**
@@ -407,6 +636,14 @@
return evaluator == 0 ? LogString() : evaluator->getClass().getName();
}
+log4cxx::spi::TriggeringEventEvaluatorPtr SMTPAppender::getEvaluator() const {
+ return evaluator;
+}
+
+void SMTPAppender::setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger) {
+ evaluator = trigger;
+}
+
/**
The <b>BufferSize</b> option takes a positive integer
representing the maximum number of logging events to collect in a
@@ -432,6 +669,4 @@
evaluator = OptionConverter::instantiateByClassName(value,
TriggeringEventEvaluator::getStaticClass(), evaluator);
}
-
-#endif //LOG4CXX_HAVE_SMTP
Modified: logging/log4cxx/trunk/src/main/include/log4cxx/net/smtpappender.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/net/smtpappender.h?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/net/smtpappender.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/net/smtpappender.h Mon Dec 10 18:11:34 2007
@@ -23,14 +23,10 @@
#include <log4cxx/helpers/cyclicbuffer.h>
#include <log4cxx/spi/triggeringeventevaluator.h>
-
namespace log4cxx
{
namespace net
{
- class SMTPAppender;
- typedef helpers::ObjectPtrT<SMTPAppender> SMTPAppenderPtr;
-
/**
Send an e-mail when a specific logging event occurs, typically on
errors or fatal errors.
@@ -44,18 +40,30 @@
class LOG4CXX_EXPORT SMTPAppender : public AppenderSkeleton
{
private:
+
+ private:
+ SMTPAppender(const SMTPAppender&);
+ SMTPAppender& operator=(const SMTPAppender&);
+ static bool asciiCheck(const LogString&, const logchar*);
+ /**
+ This method determines if there is a sense in attempting to append.
+ <p>It checks whether there is a set output target and also if
+ there is a set layout. If these checks fail, then the boolean
+ value <code>false</code> is returned. */
+ bool checkEntryConditions();
+
LogString to;
+ LogString cc;
+ LogString bcc;
LogString from;
LogString subject;
LogString smtpHost;
+ LogString smtpUsername;
+ LogString smtpPassword;
+ int smtpPort;
int bufferSize; // 512
bool locationInfo;
helpers::CyclicBuffer cb;
- void * session;
- LogString encoding;
- LogString charset;
-
- protected:
spi::TriggeringEventEvaluatorPtr evaluator;
public:
@@ -97,45 +105,35 @@
an e-mail to be sent. */
virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
- /**
- This method determines if there is a sense in attempting to append.
- <p>It checks whether there is a set output target and also if
- there is a set layout. If these checks fail, then the boolean
- value <code>false</code> is returned. */
- bool checkEntryConditions();
virtual void close();
- std::vector<LogString> parseAddress(const LogString& addressStr);
-
/**
Returns value of the <b>To</b> option.
*/
- inline const LogString& getTo() const
- { return to; }
+ LogString getTo() const;
/**
- The <code>SMTPAppender</code> requires a {@link
- Layout layout}. */
- virtual bool requiresLayout() const
- { return true; }
+ Returns value of the <b>cc</b> option.
+ */
+ LogString getCc() const;
/**
- Send the contents of the cyclic buffer as an e-mail message.
+ Returns value of the <b>bcc</b> option.
*/
- void sendBuffer(log4cxx::helpers::Pool& p);
+ LogString getBcc() const;
+
/**
- Returns value of the <b>Charset</b> option.
- */
- inline const LogString& getCharset() const
- { return charset; }
+ The <code>SMTPAppender</code> requires a {@link
+ Layout layout}. */
+ virtual bool requiresLayout() const;
/**
- Returns value of the <b>Encoding</b> option.
+ Send the contents of the cyclic buffer as an e-mail message.
*/
- inline const LogString& getEncoding() const
- { return encoding; }
+ void sendBuffer(log4cxx::helpers::Pool& p);
+
/**
Returns value of the <b>EvaluatorClass</b> option.
@@ -145,44 +143,25 @@
/**
Returns value of the <b>From</b> option.
*/
- inline const LogString& getFrom() const
- { return from; }
+ LogString getFrom() const;
/**
Returns value of the <b>Subject</b> option.
*/
- inline const LogString& getSubject() const
- { return subject; }
+ LogString getSubject() const;
- /**
- The <b>Charset</b> option takes a string value which should be the
- charset of the mail (<code>us-ascii</code>, <code>iso8859_1</code>,
- <code>iso8859_2</code>, <code>iso8859_3</code>).
- */
- inline void setCharset(const LogString& charset)
- { this->charset.assign(charset); }
-
- /**
- The <b>Encoding</b> option takes a string value which should be the
- encoding type of the mail (<code>7bit</code>, <code>8bit</code>,
- <code>base64</code>, <code>binary</code>, <code>quoted</code>).
- */
- inline void setEncoding(const LogString& charset)
- { this->encoding.assign(encoding); }
/**
The <b>From</b> option takes a string value which should be a
e-mail address of the sender.
*/
- inline void setFrom(const LogString& from)
- { this->from.assign(from); }
+ void setFrom(const LogString& from);
/**
The <b>Subject</b> option takes a string value which should be a
the subject of the e-mail message.
*/
- inline void setSubject(const LogString& subject)
- { this->subject.assign(subject); }
+ void setSubject(const LogString& subject);
/**
The <b>BufferSize</b> option takes a positive integer
@@ -197,21 +176,64 @@
The <b>SMTPHost</b> option takes a string value which should be a
the host name of the SMTP server that will send the e-mail message.
*/
- inline void setSMTPHost(const LogString& smtpHost)
- { this->smtpHost.assign(smtpHost); }
+ void setSMTPHost(const LogString& smtpHost);
+
+ /**
+ Returns value of the <b>SMTPHost</b> option.
+ */
+ LogString getSMTPHost() const;
+
+ /**
+ The <b>SMTPPort</b> option takes a string value which should be a
+ the port of the SMTP server that will send the e-mail message.
+ */
+ void setSMTPPort(int port);
/**
Returns value of the <b>SMTPHost</b> option.
*/
- inline const LogString& getSMTPHost() const
- { return smtpHost; }
+ int getSMTPPort() const;
/**
The <b>To</b> option takes a string value which should be a
comma separated list of e-mail address of the recipients.
*/
- inline void setTo(const LogString& to)
- { this->to.assign(to); }
+ void setTo(const LogString& to);
+
+ /**
+ The <b>Cc</b> option takes a string value which should be a
+ comma separated list of e-mail address of the cc'd recipients.
+ */
+ void setCc(const LogString& to);
+
+ /**
+ The <b>Bcc</b> option takes a string value which should be a
+ comma separated list of e-mail address of the bcc'd recipients.
+ */
+ void setBcc(const LogString& to);
+
+
+ /**
+ The <b>SMTPUsername</b> option takes a string value which should be a
+ the user name for the SMTP server.
+ */
+ void setSMTPUsername(const LogString& newVal);
+
+ /**
+ Returns value of the <b>SMTPUsername</b> option.
+ */
+ LogString getSMTPUsername() const;
+
+ /**
+ The <b>SMTPPassword</b> option takes a string value which should be a
+ the password for the SMTP server.
+ */
+ void setSMTPPassword(const LogString& newVal);
+
+ /**
+ Returns value of the <b>SMTPPassword</b> option.
+ */
+ LogString getSMTPPassword() const;
/**
Returns value of the <b>BufferSize</b> option.
@@ -219,6 +241,19 @@
inline int getBufferSize() const
{ return bufferSize; }
+
+ /**
+ * Gets the current triggering evaluator.
+ * @return triggering evaluator.
+ */
+ log4cxx::spi::TriggeringEventEvaluatorPtr getEvaluator() const;
+
+ /**
+ * Sets the triggering evaluator.
+ * @param trigger triggering evaluator.
+ */
+ void setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger);
+
/**
The <b>EvaluatorClass</b> option takes a string value
representing the name of the class implementing the
@@ -227,56 +262,21 @@
for the SMTPAppender.
*/
void setEvaluatorClass(const LogString& value);
-
+
/**
- The <b>LocationInfo</b> option takes a boolean value. By
- default, it is set to false which means there will be no effort
- to extract the location information related to the event. As a
- result, the layout that formats the events as they are sent out
- in an e-mail is likely to place the wrong location information
- (if present in the format).
-
- <p>Location information extraction is comparatively very slow and
- should be avoided unless performance is not a concern.
+ The <b>LocationInfo</b> option is provided for compatibility with log4j
+ and has no effect in log4cxx.
*/
- inline void setLocationInfo(bool locationInfo)
- { this->locationInfo = locationInfo; }
+ void setLocationInfo(bool locationInfo);
/**
Returns value of the <b>LocationInfo</b> option.
*/
- inline bool getLocationInfo() const
- { return locationInfo; }
-
- private:
- SMTPAppender(const SMTPAppender&);
- SMTPAppender& operator=(const SMTPAppender&);
-
+ bool getLocationInfo() const;
}; // class SMTPAppender
+
+ typedef helpers::ObjectPtrT<SMTPAppender> SMTPAppenderPtr;
- class LOG4CXX_EXPORT DefaultEvaluator :
- public virtual spi::TriggeringEventEvaluator,
- public virtual helpers::ObjectImpl
- {
- public:
- DECLARE_LOG4CXX_OBJECT(DefaultEvaluator)
- BEGIN_LOG4CXX_CAST_MAP()
- LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
- END_LOG4CXX_CAST_MAP()
-
- DefaultEvaluator();
-
- /**
- Is this <code>event</code> the e-mail triggering event?
- <p>This method returns <code>true</code>, if the event level
- has ERROR level or higher. Otherwise it returns
- <code>false</code>.
- */
- virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event);
- private:
- DefaultEvaluator(const DefaultEvaluator&);
- DefaultEvaluator& operator=(const DefaultEvaluator&);
- }; // class DefaultEvaluator
} // namespace net
} // namespace log4cxx
Modified: logging/log4cxx/trunk/src/main/include/log4cxx/private/log4cxx_private.h.in
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/private/log4cxx_private.h.in?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/private/log4cxx_private.h.in (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/private/log4cxx_private.h.in Mon Dec 10 18:11:34 2007
@@ -54,7 +54,7 @@
// Capabilities should be checked in client code by
// attempting creation of the corresponding appender.
//
-#define LOG4CXX_HAVE_SMTP 0
+#define LOG4CXX_HAVE_LIBESMTP @HAS_LIBESMTP@
#define LOG4CXX_HAVE_SYSLOG @HAS_SYSLOG@
#endif
Modified: logging/log4cxx/trunk/src/main/include/log4cxx/xml/domconfigurator.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/xml/domconfigurator.h?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/xml/domconfigurator.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/xml/domconfigurator.h Mon Dec 10 18:11:34 2007
@@ -168,7 +168,7 @@
/**
Used internally to parse the logger factory element.
*/
- log4cxx::rolling::TriggeringPolicyPtr parseTriggeringPolicy(
+ log4cxx::helpers::ObjectPtr parseTriggeringPolicy(
log4cxx::helpers::Pool& p,
log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
apr_xml_elem* factoryElement);
Modified: logging/log4cxx/trunk/src/test/cpp/net/smtpappendertestcase.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/test/cpp/net/smtpappendertestcase.cpp?rev=603118&r1=603117&r2=603118&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/test/cpp/net/smtpappendertestcase.cpp (original)
+++ logging/log4cxx/trunk/src/test/cpp/net/smtpappendertestcase.cpp Mon Dec 10 18:11:34 2007
@@ -24,9 +24,45 @@
#include <cppunit/extensions/HelperMacros.h>
#include <log4cxx/net/smtpappender.h>
#include "../appenderskeletontestcase.h"
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/logmanager.h>
+#include <log4cxx/ttcclayout.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
+using namespace log4cxx::net;
+using namespace log4cxx::xml;
+using namespace log4cxx::spi;
+
+namespace log4cxx {
+ namespace net {
+
+ class MockTriggeringEventEvaluator :
+ public virtual spi::TriggeringEventEvaluator,
+ public virtual helpers::ObjectImpl
+ {
+ public:
+ DECLARE_LOG4CXX_OBJECT(MockTriggeringEventEvaluator)
+ BEGIN_LOG4CXX_CAST_MAP()
+ LOG4CXX_CAST_ENTRY(MockTriggeringEventEvaluator)
+ LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
+ END_LOG4CXX_CAST_MAP()
+
+ MockTriggeringEventEvaluator() {
+ }
+
+ virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event) {
+ return true;
+ }
+ private:
+ MockTriggeringEventEvaluator(const MockTriggeringEventEvaluator&);
+ MockTriggeringEventEvaluator& operator=(const MockTriggeringEventEvaluator&);
+ };
+ }
+}
+
+IMPLEMENT_LOG4CXX_OBJECT(MockTriggeringEventEvaluator)
+
/**
Unit tests of log4cxx::SocketAppender
@@ -39,7 +75,8 @@
//
CPPUNIT_TEST(testDefaultThreshold);
CPPUNIT_TEST(testSetOptionThreshold);
-
+ CPPUNIT_TEST(testTrigger);
+ CPPUNIT_TEST(testInvalid);
CPPUNIT_TEST_SUITE_END();
@@ -48,6 +85,38 @@
AppenderSkeleton* createAppenderSkeleton() const {
return new log4cxx::net::SMTPAppender();
}
+
+ void setUp() {
+ }
+
+ void tearDown() {
+ LogManager::resetConfiguration();
+ }
+
+ /**
+ * Tests that triggeringPolicy element will set evaluator.
+ */
+ void testTrigger() {
+ DOMConfigurator::configure("input/xml/smtpAppender1.xml");
+ SMTPAppenderPtr appender(Logger::getRootLogger()->getAppender(LOG4CXX_STR("A1")));
+ TriggeringEventEvaluatorPtr evaluator(appender->getEvaluator());
+ CPPUNIT_ASSERT_EQUAL(true, evaluator->instanceof(MockTriggeringEventEvaluator::getStaticClass()));
+ }
+
+ void testInvalid() {
+ SMTPAppenderPtr appender(new SMTPAppender());
+ appender->setSMTPHost(LOG4CXX_STR("smtp.invalid"));
+ appender->setTo(LOG4CXX_STR("you@example.invalid"));
+ appender->setFrom(LOG4CXX_STR("me@example.invalid"));
+ appender->setLayout(new TTCCLayout());
+ Pool p;
+ appender->activateOptions(p);
+ LoggerPtr root(Logger::getRootLogger());
+ root->addAppender(appender);
+ LOG4CXX_INFO(root, "Hello, World.");
+ LOG4CXX_ERROR(root, "Sending Message");
+ }
+
};
CPPUNIT_TEST_SUITE_REGISTRATION(SMTPAppenderTestCase);