I was working on a project porting code from Linux to
AIX. The project uses log4cxx. On Linux log4cxx works
fine. But on AIX it is complaining about
Could not instantiate class
[org.apache.log4j.ConsoleAppender].
Class not found
Could not instantiate appender named "A1".
No appender could be found for logger (DelayedLoop).
Please initialize the log4cxx system properly.
I made some modification to the optionconvert.cpp so
that the static class get initialized. I think I can
share my solution to you. Please see the attachment.
Regards
Katherine Ye
PS: My modification was base on the 2004-11-05 CVS head
__________________________________
Do you Yahoo!?
Yahoo! Small Business - Try our new resources site!
http://smallbusiness.yahoo.com/resources/ /*
* Copyright 2003,2004 The Apache Software Foundation.
*
* 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 <log4cxx/logger.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/basicconfigurator.h>
#include <log4cxx/simplelayout.h>
#include <log4cxx/rollingfileappender.h>
#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/writerappender.h>
#include <log4cxx/ttcclayout.h>
#include <log4cxx/consoleappender.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/helpers/thread.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/appender.h>
#include <log4cxx/layout.h>
#include <log4cxx/level.h>
#include <log4cxx/htmllayout.h>
#include <log4cxx/hierarchy.h>
#include <log4cxx/fileappender.h>
#include <log4cxx/defaultcategoryfactory.h>
#include <log4cxx/dailyrollingfileappender.h>
#include <log4cxx/asyncappender.h>
#include <log4cxx/spi/optionhandler.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/spi/loggerrepository.h>
#include <log4cxx/spi/errorhandler.h>
#include <log4cxx/spi/filter.h>
#include <log4cxx/spi/repositoryselector.h>
#include <log4cxx/spi/triggeringeventevaluator.h>
#include <log4cxx/spi/appenderattachable.h>
#include <log4cxx/spi/defaultrepositoryselector.h>
#include <log4cxx/spi/configurator.h>
#include <log4cxx/varia/denyallfilter.h>
#include <log4cxx/varia/fallbackerrorhandler.h>
#include <log4cxx/varia/levelmatchfilter.h>
#include <log4cxx/varia/levelrangefilter.h>
#include <log4cxx/varia/stringmatchfilter.h>
#include <log4cxx/net/syslogappender.h>
#include <log4cxx/net/socketappender.h>
#include <log4cxx/net/sockethubappender.h>
#include <log4cxx/net/telnetappender.h>
#include <log4cxx/net/socketnode.h>
#include <log4cxx/xml/xmllayout.h>
#include <log4cxx/net/xmlsocketappender.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/helpers/patternconverter.h>
#include <log4cxx/helpers/object.h>
#include <log4cxx/helpers/resourcebundle.h>
#include <log4cxx/helpers/propertyresourcebundle.h>
#include <log4cxx/helpers/onlyonceerrorhandler.h>
#include <log4cxx/helpers/appenderattachableimpl.h>
#include <log4cxx/helpers/timezone.h>
#include <log4cxx/helpers/socketoutputstream.h>
#include <log4cxx/helpers/socketinputstream.h>
#include <log4cxx/helpers/socketimpl.h>
#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/xml.h>
#include <log4cxx/helpers/datagramsocket.h>
#include <log4cxx/helpers/datagrampacket.h>
#include <log4cxx/helpers/boundedfifo.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/optionconverter.h>
#include <algorithm>
#include <ctype.h>
#include <log4cxx/helpers/exception.h>
#include <stdlib.h>
#include <log4cxx/helpers/properties.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/class.h>
#include <log4cxx/helpers/loader.h>
#include <log4cxx/helpers/system.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;
#ifdef LOG4CXX_HAVE_XML
using namespace log4cxx::xml;
#endif
using namespace log4cxx::varia;
using namespace log4cxx::net;
namespace {
// Function object to turn a lower case character into an upper case one
class ToUpper {
public:
void operator()(TCHAR& c){c = toupper(c);}
};
}
namespace log4cxx {
namespace helpers {
class MissingBraceException : public IllegalArgumentException {
public:
MissingBraceException(const String& val, size_t openBrace)
: val(val), openBrace(openBrace) {
}
MissingBraceException(const MissingBraceException& src)
: IllegalArgumentException(src), val(src.val),
openBrace(src.openBrace) {
}
~MissingBraceException() throw() {
}
const char* what() const throw() {
return "Missing brace exception";
}
const String getMessage() const {
StringBuffer oss;
oss << _T("\"") << val
<< _T("\" has no closing brace. Opening brace at position ")
<< openBrace << _T(".");
return oss.str();
}
private:
MissingBraceException& operator=(const MissingBraceException& src);
const String val;
const size_t openBrace;
};
}
}
String OptionConverter::convertSpecialChars(const String& s)
{
TCHAR c;
int len = s.length();
StringBuffer sbuf;
String::const_iterator i = s.begin();
while(i != s.end())
{
c = *i++;
if (c == _T('\\'))
{
c = *i++;
switch (c)
{
case _T('n'):
c = _T('\n');
break;
case _T('r'):
c = _T('\r');
break;
case _T('t'):
c = _T('\t');
break;
case _T('f'):
c = _T('\f');
break;
case _T('\b'):
c = _T('\b');
break;
case _T('\"'):
c = _T('\"');
break;
case _T('\''):
c = _T('\'');
break;
case _T('\\'):
c = _T('\\');
break;
}
}
sbuf.put(c);
}
return sbuf.str();
}
bool OptionConverter::toBoolean(const String& value, bool dEfault)
{
if (value.empty())
{
return dEfault;
}
String trimmedVal =
StringHelper::toLowerCase(StringHelper::trim(value));
if (trimmedVal == _T("true"))
{
return true;
}
if (trimmedVal == _T("false"))
{
return false;
}
return dEfault;
}
int OptionConverter::toInt(const String& value, int dEfault)
{
if (value.empty())
{
return dEfault;
}
return (int)ttol(StringHelper::trim(value).c_str());
}
long OptionConverter::toFileSize(const String& value, long dEfault)
{
if(value.empty())
{
return dEfault;
}
String s = StringHelper::toLowerCase(StringHelper::trim(value));
long multiplier = 1;
int index;
if((index = s.find(_T("kb"))) != -1)
{
multiplier = 1024;
s = s.substr(0, index);
}
else if((index = s.find(_T("mb"))) != -1)
{
multiplier = 1024*1024;
s = s.substr(0, index);
}
else if((index = s.find(_T("gb"))) != -1)
{
multiplier = 1024*1024*1024;
s = s.substr(0, index);
}
if(!s.empty())
{
return ttol(s.c_str()) * multiplier;
}
return dEfault;
}
String OptionConverter::findAndSubst(const String& key, Properties& props)
{
String value = props.getProperty(key);
if(value.empty())
return value;
try
{
return substVars(value, props);
}
catch(IllegalArgumentException& e)
{
LogLog::error(_T("Bad option value [")+value+_T("]."), e);
return value;
}
}
String OptionConverter::substVars(const String& val, Properties& props)
{
StringBuffer sbuf;
static const String delimStart("${");
const TCHAR delimStop = '}';
const int DELIM_START_LEN = 2;
const int DELIM_STOP_LEN = 1;
int i = 0;
int j, k;
while(true)
{
j = val.find(delimStart, i);
if(j == -1)
{
// no more variables
if(i==0)
{ // this is a simple string
return val;
}
else
{ // add the tail string which contails no variables
and return the result.
sbuf << val.substr(i, val.length() - i);
return sbuf.str();
}
}
else
{
sbuf << val.substr(i, j - i);
k = val.find(delimStop, j);
if(k == -1)
{
throw MissingBraceException(val, j);
}
else
{
j += DELIM_START_LEN;
String key = val.substr(j, k - j);
// first try in System properties
String replacement = getSystemProperty(key,
_T(""));
// then try props parameter
if(replacement.empty())
{
replacement = props.getProperty(key);
}
if(!replacement.empty())
{
// Do variable substitution on the
replacement string
// such that we can solve "Hello ${x2}"
as "Hello p1"
// the where the properties are
// x1=p1
// x2=${x1}
String recursiveReplacement =
substVars(replacement, props);
sbuf << (recursiveReplacement);
}
i = k + DELIM_STOP_LEN;
}
}
}
}
String OptionConverter::getSystemProperty(const String& key, const String& def)
{
if (!key.empty())
{
String value = System::getProperty(key);
if (!value.empty())
{
return value;
}
else
{
return def;
}
}
else
{
return def;
}
}
const LevelPtr& OptionConverter::toLevel(const String& value,
const LevelPtr& defaultValue)
{
int hashIndex = value.find(_T("#"));
if (hashIndex == -1)
{
if (value.empty())
{
return defaultValue;
}
else
{
LogLog::debug(
_T("OptionConverter::toLevel: no class name specified,
level=[")
+value+_T("]"));
// no class name specified : use standard Level class
return Level::toLevel(value, defaultValue);
}
}
const LevelPtr& result = defaultValue;
String clazz = value.substr(hashIndex + 1);
String levelName = value.substr(0, hashIndex);
LogLog::debug(_T("OptionConverter::toLevel: class=[") +clazz+_T("],
level=[")+
levelName+_T("]"));
// This is degenerate case but you never know.
if (levelName.empty())
{
return Level::toLevel(value, defaultValue);
}
try
{
Level::LevelClass& levelClass =
(Level::LevelClass&)Loader::loadClass(clazz);
return levelClass.toLevel(levelName);
}
catch (ClassNotFoundException&)
{
LogLog::warn(_T("custom level class [") + clazz + _T("] not
found."));
}
catch(Exception& oops)
{
LogLog::warn(
_T("class [") + clazz + _T("], level [") + levelName +
_T("] conversion) failed."), oops);
}
catch(...)
{
LogLog::warn(
_T("class [") + clazz + _T("], level [") + levelName +
_T("] conversion) failed."));
}
return defaultValue;
}
ObjectPtr OptionConverter::instantiateByKey(Properties& props, const String&
key,
const Class& superClass, const ObjectPtr& defaultValue)
{
// Get the value of the property in string form
String className = findAndSubst(key, props);
if(className.empty())
{
LogLog::error(_T("Could not find value for key ") + key);
return defaultValue;
}
// Trim className to avoid trailing spaces that cause problems.
return OptionConverter::instantiateByClassName(
StringHelper::trim(className), superClass, defaultValue);
}
ObjectPtr OptionConverter::instantiateByClassName(const String& className,
const Class& superClass, const ObjectPtr& defaultValue)
{
if(!className.empty())
{
try
{
const Class& classObj = Loader::loadClass(className);
ObjectPtr newObject = classObj.newInstance();
if (!newObject->instanceof(superClass))
{
return defaultValue;
}
return newObject;
}
catch (Exception& e)
{
LogLog::error(_T("Could not instantiate class [") +
className
+ _T("]."), e);
}
}
return defaultValue;
}
void OptionConverter::selectAndConfigure(const String& configFileName,
const String& _clazz, spi::LoggerRepositoryPtr& hierarchy)
{
static XMLSocketAppender::ClassXMLSocketAppender cxmlsa;
static XMLLayout::ClassXMLLayout cxmll;
static WriterAppender::ClassWriterAppender cwa;
static TTCCLayout::ClassTTCCLayout cttcc;
static Runnable::ClassRunnable cr;
static Thread::ClassThread ct;
static TimeZone::ClassTimeZone ctz;
static TelnetAppender::ClassTelnetAppender cta;
static SyslogAppender::ClassSyslogAppender csad;
static StringMatchFilter::ClassStringMatchFilter csmf;
static SocketOutputStream::ClassSocketOutputStream csos;
static SocketNode::ClassSocketNode csn;
static SocketInputStream::ClassSocketInputStream csis;
static SocketImpl::ClassSocketImpl csi;
static SocketHubAppender::ClassSocketHubAppender csha;
static SocketAppender::ClassSocketAppender csa;
static Socket::ClassSocket cst;
static SimpleLayout::ClassSimpleLayout csl;
static RollingFileAppender::ClassRollingFileAppender crfa;
static ResourceBundle::ClassResourceBundle crb;
static PropertyResourceBundle::ClassPropertyResourceBundle cprb;
static PropertyConfigurator::ClassPropertyConfigurator pc;
static PatternLayout::ClassPatternLayout cpl;
static PatternConverter::ClassPatternConverter cpc;
static OnlyOnceErrorHandler::ClassOnlyOnceErrorHandler cooeh;
static DefaultRepositorySelector::ClassDefaultRepositorySelector cdrs;
static LoggingEvent::ClassLoggingEvent cle;
static Logger::ClassLogger clog;
static Object::ClassObject cobj;
static OptionHandler::ClassOptionHandler coh;
static ErrorHandler::ClassErrorHandler ceh;
static Appender::ClassAppender ca;
static Filter::ClassFilter cf;
static AppenderAttachable::ClassAppenderAttachable caa;
static LoggerFactory::ClassLoggerFactory clf;
static LoggerRepository::ClassLoggerRepository clr;
static DenyAllFilter::ClassDenyAllFilter cdaf;
static RepositorySelector::ClassRepositorySelector crs;
static XMLDOMNode::ClassXMLDOMNode cxmldn;
static XMLDOMDocument::ClassXMLDOMDocument cxmldt;
static XMLDOMElement::ClassXMLDOMElement cxmlde;
static XMLDOMNodeList::ClassXMLDOMNodeList cxmldl;
static TriggeringEventEvaluator::ClassTriggeringEventEvaluator ctee;
static LevelRangeFilter::ClassLevelRangeFilter clrf;
static LevelMatchFilter::ClassLevelMatchFilter clmf;
static Level::LevelClass clvl;
static Layout::ClassLayout clt;
static HTMLLayout::ClassHTMLLayout chtml;
static Hierarchy::ClassHierarchy chy;
//static GnomeXMLDOMNode::ClassGnomeXMLDOMNode cgxmldn;
//static GnomeXMLDOMDocument::ClassGnomeXMLDOMDocument cgxmldt;
//static GnomeXMLDOMElement::ClassGnomeXMLDOMElement cgxmlde;
//static GnomeXMLDOMNodeList::ClassGnomeXMLDOMNodeList cgxmldl;
static FileAppender::ClassFileAppender cfa;
static FallbackErrorHandler::ClassFallbackErrorHandler cfeh;
static DOMConfigurator::ClassDOMConfigurator cdcft;
static DefaultCategoryFactory::ClassDefaultCategoryFactory cdcf;
static DatagramSocket::ClassDatagramSocket cdms;
static DatagramPacket::ClassDatagramPacket cdmp;
static DailyRollingFileAppender::ClassDailyRollingFileAppender cdfa;
static ConsoleAppender::ClassConsoleAppender cca;
static Configurator::ClassConfigurator ccg;
static BoundedFIFO::ClassBoundedFIFO cbfifo;
static AsyncAppender::ClassAsyncAppender caap;
static Dispatcher::ClassDispatcher cds;
static AppenderAttachableImpl::ClassAppenderAttachableImpl cai;
ConfiguratorPtr configurator;
String clazz = _clazz;
#ifdef LOG4CXX_HAVE_XML
if(clazz.empty() && !configFileName.empty()
&& StringHelper::endsWith(configFileName, _T(".xml")))
{
clazz = DOMConfigurator::getStaticClass().toString();
}
#endif
if(!clazz.empty())
{
LogLog::debug(_T("Preferred configurator class: ") + clazz);
configurator = instantiateByClassName(clazz,
Configurator::getStaticClass(),
0);
if(configurator == 0)
{
LogLog::error(_T("Could not instantiate configurator
[")+
clazz+_T("]."));
return;
}
}
else
{
configurator = new PropertyConfigurator();
}
configurator->doConfigure(configFileName, hierarchy);
}