// Module: Log4CPLUS // File: log4judpappender.cxx // Created: 7/2012 // Author: Siva Chandran P // // // Copyright 2012-2013 Siva Chandran P // // Licensed 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 #include #include #include #include #include #include #include #include #include #if defined (UNICODE) #include #else #include #endif namespace log4cplus { namespace { static inline bool is_control (tchar ch) { #if defined (UNICODE) return !! std::iswcntrl (std::char_traits::to_int_type (ch)); #else return !! std::iscntrl (std::char_traits::to_int_type (ch)); #endif } //! Outputs str with reserved XML characters escaped. static void output_xml_escaped (tostream & os, tstring const & str) { for (tstring::const_iterator it = str.begin (); it != str.end (); ++it) { tchar const & ch = *it; switch (ch) { case LOG4CPLUS_TEXT ('<'): os << LOG4CPLUS_TEXT ("<"); break; case LOG4CPLUS_TEXT ('>'): os << LOG4CPLUS_TEXT (">"); break; case LOG4CPLUS_TEXT ('&'): os << LOG4CPLUS_TEXT ("&"); break; case LOG4CPLUS_TEXT ('\''): os << LOG4CPLUS_TEXT ("'"); break; case LOG4CPLUS_TEXT ('"'): os << LOG4CPLUS_TEXT ("""); break; default: if (is_control (ch)) { tchar const prev_fill = os.fill (); std::ios_base::fmtflags const prev_flags = os.flags (); os.flags (std::ios_base::hex | std::ios_base::right); os.fill (LOG4CPLUS_TEXT ('0')); os << std::setw (0) << LOG4CPLUS_TEXT ("&#x") << std::setw (2) << std::char_traits::to_int_type (ch) << std::setw (0) << LOG4CPLUS_TEXT (";"); os.fill (prev_fill); os.flags (prev_flags); } else os.put (ch); } } } //! Helper manipulator like class for escaped XML output. struct outputXMLEscaped { outputXMLEscaped (tstring const & s) : str (s) { } tstring const & str; }; //! Overload stream insertion for outputXMLEscaped. static tostream & operator << (tostream & os, outputXMLEscaped const & x) { output_xml_escaped (os, x.str); return os; } } // namespace ////////////////////////////////////////////////////////////////////////////// // Log4jUdpAppender ctors and dtor ////////////////////////////////////////////////////////////////////////////// Log4jUdpAppender::Log4jUdpAppender(const tstring& host_, int port_) : host(host_) , port(port_) { layout.reset (new PatternLayout (LOG4CPLUS_TEXT ("%m"))); openSocket(); } Log4jUdpAppender::Log4jUdpAppender(const helpers::Properties & properties) : Appender(properties) , port(5000) { host = properties.getProperty( LOG4CPLUS_TEXT("host"), LOG4CPLUS_TEXT ("localhost") ); properties.getInt (port, LOG4CPLUS_TEXT ("port")); openSocket(); } Log4jUdpAppender::~Log4jUdpAppender() { destructorImpl(); } ////////////////////////////////////////////////////////////////////////////// // Log4jUdpAppender public methods ////////////////////////////////////////////////////////////////////////////// void Log4jUdpAppender::close() { helpers::getLogLog().debug( LOG4CPLUS_TEXT("Entering Log4jUdpAppender::close()...")); socket.close(); closed = true; } ////////////////////////////////////////////////////////////////////////////// // Log4jUdpAppender protected methods ////////////////////////////////////////////////////////////////////////////// void Log4jUdpAppender::openSocket() { if(!socket.isOpen()) { socket = helpers::Socket(host, port, true); } } void Log4jUdpAppender::append(const spi::InternalLoggingEvent& event) { if(!socket.isOpen()) { openSocket(); if(!socket.isOpen()) { helpers::getLogLog().error( LOG4CPLUS_TEXT("Log4jUdpAppender::append()- Cannot connect to server")); return; } } tstring & str = formatEvent (event); internal::appender_sratch_pad & appender_sp = internal::get_appender_sp (); tostringstream & buffer = appender_sp.oss; detail::clear_tostringstream (buffer); buffer << LOG4CPLUS_TEXT("") << LOG4CPLUS_TEXT("") // TODO: Some escaping of special characters is needed here. << outputXMLEscaped (str) << LOG4CPLUS_TEXT("") << LOG4CPLUS_TEXT("") // TODO: Some escaping of special characters is needed here. << outputXMLEscaped (event.getNDC()) << LOG4CPLUS_TEXT("") << LOG4CPLUS_TEXT("") << LOG4CPLUS_TEXT(""); LOG4CPLUS_TSTRING_TO_STRING (buffer.str ()).swap (appender_sp.chstr); bool ret = socket.write(appender_sp.chstr); if (!ret) { helpers::getLogLog().error( LOG4CPLUS_TEXT( "Log4jUdpAppender::append()- Cannot write to server")); } } } // namespace log4cplus