factory.cpp

00001 
00002 /***************************************************************************
00003  *  factory.cpp - Logger factory
00004  *
00005  *  Created: Mon Jun 04 10:57:21 2007
00006  *  Copyright  2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <utils/logging/factory.h>
00025 #include <utils/logging/console.h>
00026 #include <utils/logging/file.h>
00027 #include <utils/logging/multi.h>
00028 
00029 #include <cstring>
00030 #include <cstdlib>
00031 
00032 namespace fawkes {
00033 
00034 /** @class UnknownLoggerTypeException factory.h <utils/logging/factory.h>
00035  * Unknown logger type exception.
00036  * Thrown if the requested logger has not been recognized
00037  */
00038 
00039 /** Constructor.
00040  * @param msg optional explanation
00041  */
00042 UnknownLoggerTypeException::UnknownLoggerTypeException(const char *msg)
00043   : Exception("Unknown logger type")
00044 {
00045   append(msg);
00046 }
00047 
00048 
00049 /** @class LoggerFactory factory.h <utils/logging/factory.h>
00050  * Logger factory.
00051  * This logging factory provides access to all loggers in a unified way. You just
00052  * supply a logger argument string and depending on the logger type an instance of
00053  * the desired logger is returned or otherwise
00054  * an exception is thrown. See instance() for a list of supported logger types.
00055  *
00056  * @author Tim Niemueller
00057  */
00058 
00059 /** Get logger instance.
00060  * Get an instance of a logger of the given type. The argument string is used for
00061  * logger arguments.
00062  * Supported logger types:
00063  * - console, ConsoleLogger
00064  * - file, FileLogger
00065  * NOT supported:
00066  * - NetworkLogger, needs a FawkesNetworkHub which cannot be passed by parameter
00067  * @param type logger type
00068  * @param as logger argument string
00069  * @return logger instance of requested type
00070  * @exception UnknownLoggerTypeException thrown, if the desired logger could
00071  * not be instantiated. This could be a misspelled logger type.
00072  */
00073 Logger *
00074 LoggerFactory::instance(const char *type, const char *as)
00075 {
00076   Logger *l = NULL;
00077 
00078   if ( strcmp(type, "console") == 0 ) {
00079     // no supported arguments
00080     l = new ConsoleLogger();
00081   } else if ( strcmp(type, "file") == 0 ) {
00082     char *tmp = strdup(as);
00083     char *saveptr;
00084     char *r = strtok_r(tmp, ":", &saveptr);
00085     const char *file_name;
00086     r = strtok_r(tmp, ":", &saveptr);
00087     if ( r == NULL ) {
00088       file_name = "unnamed.log";
00089     } else {
00090       file_name = r;
00091     }
00092     l = new FileLogger(file_name);
00093     free(tmp);
00094   }
00095 
00096   if ( l == NULL )  throw UnknownLoggerTypeException();
00097   return l;
00098 }
00099 
00100 
00101 /** Create MultiLogger instance.
00102  * This creates a multi logger instance based on the supplied argument string.
00103  * The argument string is of the form
00104  * @code
00105  *  ltype:largs[;ltype2:largs2[;...]]
00106  * @endcode
00107  * So it is a list of logger type/argument tuples separated by columns concatenated
00108  * to one list with exclamation marks. The list is not pre-processed, so if you
00109  * mention a logger twice this logger is added twice.
00110  * @param as logger argument string
00111  * @return multi logger instance with requested loggers
00112  * @exception UnknownLoggerTypeException thrown if any of the loggers was unknown.
00113  */
00114 MultiLogger *
00115 LoggerFactory::multilogger_instance(const char *as)
00116 {
00117   MultiLogger *m = new MultiLogger();
00118 
00119   char *logger_string = strdup(as);
00120   char *str = logger_string;
00121   char *saveptr, *r;
00122   const char *type, *args;
00123   char *typeargs_saveptr;
00124   const char *logger_delim = ";";
00125   const char *logger_typeargs_delim = ":";
00126   while ((r = strtok_r(str, logger_delim, &saveptr)) != NULL ) {
00127     type = strtok_r(r, logger_typeargs_delim, &typeargs_saveptr);
00128     args = strtok_r(NULL, logger_typeargs_delim, &typeargs_saveptr);
00129     if ( type == NULL ) {
00130       throw UnknownLoggerTypeException();
00131     }
00132     if ( args == NULL ) {
00133       args = "";
00134     }
00135 
00136     try {
00137       Logger *l = instance(type, args);
00138       m->add_logger(l);
00139     } catch (Exception &e) {
00140       e.append("Could not open logger '%s:%s'", type, args);
00141       free(logger_string);
00142       delete m;
00143       throw;
00144     }
00145     str = NULL;
00146   }
00147 
00148   free(logger_string);
00149 
00150   return m;
00151 }
00152 
00153 
00154 } // end namespace fawkes