Tuukka Norri avatar Tuukka Norri committed e3e88c7

Added the Log4Cocoa logging framework

Comments (0)

Files changed (127)

Framework/Contrib/Log4Cocoa/AllTests.h

+//
+//  AllTests.h
+//  Log4Cocoa
+//
+//  Created by bob frank on Sun May 04 2003.
+//  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface AllTests : NSObject {
+}
+
++ (TestSuite *)suite;
+
+@end

Framework/Contrib/Log4Cocoa/AllTests.m

+//
+//  AllTests.m
+//  Log4Cocoa
+//
+//  Created by bob frank on Sun May 04 2003.
+//  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
+//
+
+#import "AllTests.h"
+#import "L4LevelTest.h"
+#import "L4PatternLayoutTest.h"
+#import "L4FileAppenderTest.h"
+#import "L4RollingFileAppenderTest.h"
+#import "L4DailyRollingFileAppenderTest.h"
+
+@implementation AllTests
+
++ (TestSuite *) suite
+{
+    TestSuite *suite = [TestSuite suiteWithName: @"My Tests"];
+
+    // Add your tests here ...
+    //
+    [suite addTest: [TestSuite suiteWithClass: [L4LevelTest class]]];
+	[suite addTest: [TestSuite suiteWithClass: [L4PatternLayoutTest class]]];
+	[suite addTest: [TestSuite suiteWithClass: [L4FileAppenderTest class]]];
+	[suite addTest: [TestSuite suiteWithClass: [L4RollingFileAppenderTest class]]];
+	[suite addTest: [TestSuite suiteWithClass: [L4DailyRollingFileAppenderTest class]]];
+
+    return suite;
+}
+
+
+@end

Framework/Contrib/Log4Cocoa/AllTests_Prefix.h

+/*
+ *  AllTests_Prefix.h
+ *  
+ *
+ *  Created by bob frank on Sun May 04 2003.
+ *  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifdef __OBJC__
+//    #import <Cocoa/Cocoa.h>
+    #import <Foundation/Foundation.h>
+    #import <ObjcUnit/ObjcUnit.h>
+    #import "Log4Cocoa.h"
+#endif
+
Add a comment to this file

Framework/Contrib/Log4Cocoa/English.lproj/InfoPlist.strings

Binary file added.

Framework/Contrib/Log4Cocoa/L4AppenderAttachableImpl.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+// #import "Log4Cocoa.h"
+#import <Foundation/Foundation.h>
+#import "L4LoggingEvent.h"
+#import "L4AppenderProtocols.h"
+
+#define APPENDER_ADDED_EVENT   @"AppenderAddedEvent"
+#define APPENDER_REMOVED_EVENT @"AppenderRemovedEvent"
+
+
+@interface L4AppenderAttachableImpl : NSObject  {
+    NSMutableArray *appenderList;
+}
+
+- (int) appendLoopOnAppenders: (L4LoggingEvent *) event;
+
+@end
+
+@interface L4AppenderAttachableImpl (L4AppenderAttachableMethods) <L4AppenderAttachable>
+
+- (void) addAppender: (id <L4Appender>) newAppender;
+
+- (NSEnumerator *) allAppenders;
+- (NSArray *) allAppendersArray;
+
+- (id <L4Appender>) appenderWithName: (NSString *) aName;
+- (BOOL) isAttached: (id <L4Appender>) appender;
+
+- (void) removeAppenderWithName: (NSString *) aName;
+- (void) removeAppender: (id <L4Appender>) appender;
+- (void) removeAllAppenders;
+
+@end

Framework/Contrib/Log4Cocoa/L4AppenderAttachableImpl.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4AppenderAttachableImpl.h"
+
+
+@implementation L4AppenderAttachableImpl
+
+- (int) appendLoopOnAppenders: (L4LoggingEvent *) event
+{
+    int size = 0;
+
+    if( appenderList != nil )
+    {
+        int i;
+        size = [appenderList count];
+        for( i = 0; i < size; i++ )
+        {
+            [[appenderList objectAtIndex: i] doAppend: event];
+        }
+    }
+    return size;
+}
+
+@end
+
+
+@implementation L4AppenderAttachableImpl (L4AppenderAttachableMethods)
+
+- (void) addAppender: (id <L4Appender>) newAppender
+{
+    if( newAppender == nil )
+    {
+        return; // sanity check
+    }
+
+    if( appenderList == nil )
+    {
+        // only place appenderList array is recreated if its nil.
+        appenderList = [[NSMutableArray alloc] init];
+    }
+
+    if(![appenderList containsObject: newAppender])
+    {
+        [appenderList addObject: newAppender];
+        [[NSNotificationCenter defaultCenter] postNotificationName: APPENDER_ADDED_EVENT
+                                                            object: newAppender];
+    }
+}
+
+- (NSEnumerator *) allAppenders
+{
+    return [appenderList objectEnumerator];
+}
+
+- (NSArray *) allAppendersArray
+{
+    return appenderList;
+}
+
+- (id <L4Appender>) appenderWithName: (NSString *) aName
+{
+    NSEnumerator *enumerator = [appenderList objectEnumerator];
+    id <L4Appender> anAppender;
+
+    while ((anAppender = (id <L4Appender>)[enumerator nextObject]))
+    {
+        if( [[anAppender name] isEqualToString: aName ])
+        {
+            return anAppender;
+        }
+    }
+    return nil;
+}
+
+- (BOOL) isAttached: (id <L4Appender>) appender
+{
+    if((appender == nil) || (appenderList == nil))
+    {
+        return NO; // short circuit the test
+    }
+    return [appenderList containsObject: appender]; 
+}
+
+- (void) removeAppenderWithName: (NSString *) aName
+{
+    [self removeAppender: [self appenderWithName: aName]];
+}
+
+- (void) removeAppender: (id <L4Appender>) appender
+{
+    [appenderList removeObject: appender];
+    [[NSNotificationCenter defaultCenter] postNotificationName: APPENDER_REMOVED_EVENT
+                                                        object: appender];
+}
+
+- (void) removeAllAppenders
+{
+    NSEnumerator *enumerator = [appenderList objectEnumerator];
+    id <L4Appender> anAppender;
+
+    while ((anAppender = (id <L4Appender>)[enumerator nextObject]))
+    {
+        // why only call close in removeAllAppenders & not removeAppender: ????
+        // just doing it like they did it in Log4J ... will figure out later.
+        //
+        [anAppender close];
+        [[NSNotificationCenter defaultCenter] postNotificationName: APPENDER_REMOVED_EVENT
+                                                            object: anAppender];
+    }
+    [appenderList removeAllObjects];
+    [appenderList release];
+    appenderList = nil;
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4AppenderProtocols.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+// #import "L4Logger.h"
+// #import "L4LoggingEvent.h"
+// #import "L4Layout.h"
+// #import "L4Filter.h"
+
+@class L4Logger, L4Filter, L4Layout, L4LoggingEvent;
+
+@protocol L4OptionHandler <NSObject>
+
+- (void) activateOptions;
+
+@end
+
+@protocol L4ErrorHandler <L4OptionHandler>
+
+- (void) activateOptions; // in Java ErrorHandler extends OptionHanlder, but for now I just copied the method
+
+- (void) setLogger: (L4Logger *) aLogger;
+
+- (void) error: (NSString *) message;
+
+- (void) error: (NSString *) message
+     exception: (NSException *) e
+     errorCode: (int) errorCode;
+
+- (void) error: (NSString *) message
+     exception: (NSException *) e
+     errorCode: (int) errorCode
+         event: (L4LoggingEvent *) event;
+
+- (void) setAppender: (id) appender; // can't forward declare protocols, so check to see if the object responds
+- (void) setBackupAppender: (id) appender;
+
+@end
+
+
+@protocol L4Appender <NSObject>
+
+- (void) doAppend: (L4LoggingEvent *) anEvent;   // appender log this event
+
+- (void) addFilter: (L4Filter *) newFilter;      // adds to end of list
+- (L4Filter *) headFilter;   // returns first filter or nil of there are none
+- (void) clearFilters;       // removes all filters from list
+- (void) close;              // it is a programing error to append to a close appender
+
+- (BOOL) requiresLayout;
+
+- (NSString *) name;      // unique name of this appender
+- (void) setName: (NSString *) aName;
+
+- (L4Layout *) layout;
+- (void) setLayout: (L4Layout *) aLayout;
+
+- (id <L4ErrorHandler>) errorHandler;
+- (void) setErrorHandler: (id <L4ErrorHandler>) anErrorHandler;
+
+@end
+
+
+@protocol L4AppenderAttachable <NSObject>
+
+- (void) addAppender: (id <L4Appender>) newAppender;
+
+- (NSEnumerator *) allAppenders;
+- (NSArray *) allAppendersArray;
+
+- (id <L4Appender>) appenderWithName: (NSString *) aName;
+- (BOOL) isAttached: (id <L4Appender>) appender;
+
+- (void) removeAllAppenders;
+- (void) removeAppender: (id <L4Appender>) appender;
+- (void) removeAppenderWithName: (NSString *) aName;
+
+@end

Framework/Contrib/Log4Cocoa/L4AppenderSkeleton.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+#import "L4AppenderProtocols.h"
+#import "L4LoggingEvent.h"
+#import "L4Level.h"
+#import "L4Filter.h"
+#import "L4Layout.h"
+
+@interface L4AppenderSkeleton : NSObject {
+    NSString *name;
+    L4Layout *layout;
+    L4Level *threshold;
+    L4Filter *headFilter;
+    L4Filter *tailFilter;
+    id errorHandler;
+    BOOL closed;
+}
+
+- (void) append: (L4LoggingEvent *) anEvent;
+- (BOOL) isAsSevereAsThreshold: (L4Level *) aLevel;
+
+- (L4Level *) threshold;
+- (void) setThreshold: (L4Level *) aLevel;
+
+@end
+
+
+@interface L4AppenderSkeleton (L4OptionHandlerCategory) <L4OptionHandler>
+
+- (void) activateOptions;
+
+@end
+
+
+@interface L4AppenderSkeleton (L4AppenderCategory) <L4Appender>
+
+- (void) doAppend: (L4LoggingEvent *) anEvent;
+// calls [self append: anEvent] after doing threshold checks
+
+- (void) addFilter: (L4Filter *) aFilter;
+- (L4Filter *) headFilter;
+- (void) clearFilters;
+- (void) close;
+
+- (BOOL) requiresLayout;
+
+- (NSString *) name;
+- (void) setName: (NSString *) aName;
+
+- (L4Layout *) layout;
+- (void) setLayout: (L4Layout *) aLayout;
+
+- (id <L4ErrorHandler>) errorHandler;
+- (void) setErrorHandler: (id <L4ErrorHandler>) anErrorHandler;
+
+@end

Framework/Contrib/Log4Cocoa/L4AppenderSkeleton.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4AppenderSkeleton.h"
+
+
+@implementation L4AppenderSkeleton
+
+- (void) dealloc
+{
+    [name release];
+    [layout release];
+    [threshold release];
+    [headFilter release];
+    [tailFilter release];
+    [super dealloc];
+}
+
+- (void) append: (L4LoggingEvent *) anEvent
+{
+}
+
+- (BOOL) isAsSevereAsThreshold: (L4Level *) aLevel
+{
+    return ((threshold == nil) || ([aLevel isGreaterOrEqual: threshold]));
+}
+
+- (L4Level *) threshold
+{
+    return threshold;
+}
+
+- (void) setThreshold: (L4Level *) aLevel
+{
+    if( threshold != aLevel )
+    {
+        [threshold autorelease];
+        threshold = [aLevel retain];
+    }
+}
+
+@end
+
+
+@implementation L4AppenderSkeleton (L4OptionHandlerCategory)
+
+- (void) activateOptions
+{
+}
+
+@end
+
+
+@implementation L4AppenderSkeleton (L4AppenderCategory)
+
+// calls [self append: anEvent] after doing threshold checks
+- (void) doAppend: (L4LoggingEvent *) anEvent
+{
+    L4Filter *aFilter = [self headFilter];
+    BOOL breakLoop = NO;
+    
+    if( closed )
+    {
+        [L4LogLog error:
+            [@"Attempted to append to closed appender named: " stringByAppendingString: name]];
+        return;
+    }
+
+    if(![self isAsSevereAsThreshold: [anEvent level]])
+    {
+        return;
+    }
+
+    while((aFilter != nil) && !breakLoop)
+    {
+        switch([aFilter decide: anEvent])
+        {
+            case FILTER_DENY:
+                return;
+            case FILTER_ACCEPT:
+                breakLoop = YES;
+                break;
+            case FILTER_NEUTRAL:
+            default:
+                aFilter = [aFilter next];
+                break;
+        }
+    }
+    [self append: anEvent]; // passed all threshold checks, append event.
+}
+
+- (void) addFilter: (L4Filter *) newFilter
+{
+    if( headFilter == nil )
+    {
+        headFilter = [newFilter retain];
+        tailFilter = newFilter; // don't retain at the tail, just the head.
+    }
+    else
+    {
+        [tailFilter setNext: newFilter];
+        tailFilter = newFilter;
+    }
+    
+}
+
+- (L4Filter *) headFilter
+{
+    return headFilter;
+}
+
+- (void) clearFilters
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    
+    id aFilter = [headFilter next];
+    [headFilter autorelease];
+    for( aFilter = headFilter; aFilter != nil; aFilter = [headFilter next] )
+    {
+        [aFilter setNext: nil];
+    }
+    headFilter = nil;
+    tailFilter = nil;
+
+    [pool release];
+}
+
+- (void) close
+{
+}
+
+- (BOOL) requiresLayout
+{
+    return NO;
+}
+
+- (NSString *) name
+{
+    return name;
+}
+
+- (void) setName: (NSString *) aName
+{
+    if( name != aName )
+    {
+        [name autorelease];
+        name = [aName retain];
+    }
+}
+
+- (L4Layout *) layout
+{
+    return layout;
+}
+
+- (void) setLayout: (L4Layout *) aLayout
+{
+    if( layout != aLayout )
+    {
+        [layout autorelease];
+        layout = [aLayout retain];
+    }
+}
+
+- (id <L4ErrorHandler>) errorHandler
+{
+    return errorHandler;
+}
+
+- (void) setErrorHandler: (id <L4ErrorHandler>) anErrorHandler
+{
+    if( anErrorHandler == nil )
+    {
+        [L4LogLog warn: @"You have tried to set a null error-handler."];
+    }
+    else if( errorHandler != (id) anErrorHandler )
+    {
+        [errorHandler autorelease];
+        errorHandler = [anErrorHandler retain];
+    }
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4CLogger.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+#import "L4Logger.h"
+
+/**
+ *  ### TODO -- add pure C cover functions to call into Log4Cocoa.  I plan to convert the __FILE__
+ *              argument into the logger name, but I'll need to parse out the final "." (i.e. file.c)
+ *              probably convert it to a dash "-".  Also need to handle the pure C types being passed in.
+ */
+
+
+/* DEBUG < INFO < WARN < ERROR < FATAL */
+
+// #define cLogError(message) l4CLogError( __LINE__, __FILE__, __PRETTY_FUNCTION__, message)
+
+
+@interface L4CLogger : L4Logger {
+
+}
+
+// (void) l4CLogError( int lineNumber, cString fileName, cString prettyFunction, cString message );
+
+
+@end

Framework/Contrib/Log4Cocoa/L4CLogger.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4CLogger.h"
+
+
+@implementation L4CLogger
+
+@end

Framework/Contrib/Log4Cocoa/L4Configurator.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+
+#define LINE_BREAK_SEPERATOR_KEY @"LINE_BREAK_SEPERATOR_KEY"
+
+@interface L4Configurator : NSObject {
+
+}
+
++ (void) initialize;
+
++ (void) basicConfiguration;
++ (id) propertyForKey: (NSString *) aKey;
+
++ (void) resetLineBreakChar;
++ (NSData *) lineBreakChar;
+
+@end

Framework/Contrib/Log4Cocoa/L4Configurator.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4Configurator.h"
+#import "L4Logger.h"
+#import "L4Level.h"
+#import "L4ConsoleAppender.h"
+#import "L4Layout.h"
+
+static NSData *lineBreakChar;
+
+@implementation L4Configurator
+
++ (void) initialize
+{
+    // Making sure that we capture the startup time of
+    // this application.  This sanity check is also in
+    // +[L4Logger initialize] too.
+    //
+    [L4LoggingEvent startTime];
+}
+
++ (void) basicConfiguration
+{
+    [[L4Logger rootLogger] setLevel: [L4Level debug]];
+    [[L4Logger rootLogger] addAppender:
+        [[L4ConsoleAppender alloc] initStandardOutWithLayout: [L4Layout simpleLayout]]];
+}
+
++ (void) autoConfigure
+{
+    // [[NSFileManager defaultManager] currentDirectoryPath];
+}
+
++ (id) propertyForKey: (NSString *) aKey
+{
+    return nil;
+}
+
++ (void) resetLineBreakChar
+{
+    [lineBreakChar autorelease];
+    lineBreakChar = nil;
+}
+
++ (NSData *) lineBreakChar
+{
+    if( lineBreakChar == nil )
+    {
+        id breakChar = [self propertyForKey: LINE_BREAK_SEPERATOR_KEY];
+        if( breakChar != nil )
+        {
+            lineBreakChar = [[breakChar dataUsingEncoding: NSASCIIStringEncoding
+                                     allowLossyConversion: YES] retain];
+        }
+        else
+        {
+            // DEFAULT VALUE
+            lineBreakChar = [[@"\n" dataUsingEncoding: NSASCIIStringEncoding
+                                 allowLossyConversion: YES] retain];
+        }
+    }
+
+    return lineBreakChar;
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4ConsoleAppender.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+// #import "Log4Cocoa.h"
+#import <Foundation/Foundation.h>
+#import "L4Layout.h"
+#import "L4WriterAppender.h"
+
+@interface L4ConsoleAppender : L4WriterAppender {
+    BOOL isStandardOut;
+}
+
++ (L4ConsoleAppender *) standardOutWithLayout: (L4Layout *) aLayout;
++ (L4ConsoleAppender *) standardErrWithLayout: (L4Layout *) aLayout;
+
+- (id) init;
+
+- (id) initTarget: (BOOL) standardOut
+       withLayout: (L4Layout *) aLayout;
+
+- (id) initStandardOutWithLayout: (L4Layout *) aLayout;
+- (id) initStandardErrWithLayout: (L4Layout *) aLayout;
+
+- (void) setStandardOut;
+- (void) setStandardErr;
+
+- (NSFileHandle *) target;
+- (BOOL) isStandardOut;
+
+@end

Framework/Contrib/Log4Cocoa/L4ConsoleAppender.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4ConsoleAppender.h"
+
+
+@implementation L4ConsoleAppender
+
++ (L4ConsoleAppender *) standardOutWithLayout: (L4Layout *) aLayout
+{
+    return (L4ConsoleAppender *) [[[L4ConsoleAppender alloc] initTarget: YES
+                                                             withLayout: aLayout] autorelease];
+}
+
++ (L4ConsoleAppender *) standardErrWithLayout: (L4Layout *) aLayout
+{
+    return (L4ConsoleAppender *) [[[L4ConsoleAppender alloc] initTarget: NO
+                                                             withLayout: aLayout] autorelease];
+}
+
+- (id) init
+{
+    self = [super init];
+    return self;
+}
+
+- (id) initTarget: (BOOL) standardOut
+       withLayout: (L4Layout *) aLayout
+{
+    self = [super init];
+    if( self != nil )
+    {
+        if( standardOut )
+        {
+            [self setStandardOut];
+        }
+        else
+        {
+            [self setStandardErr];
+        }
+        [self setLayout: aLayout];
+    }
+    return self;
+}
+
+- (id) initStandardOutWithLayout: (L4Layout *) aLayout
+{
+    return [self initTarget: YES
+                 withLayout: aLayout];
+}
+
+- (id) initStandardErrWithLayout: (L4Layout *) aLayout
+{
+    return [self initTarget: NO
+                 withLayout: aLayout];
+}
+
+- (void) setStandardOut
+{
+    if(!isStandardOut || (fileHandle == nil))
+    {
+        isStandardOut = YES;
+        [fileHandle autorelease];
+        fileHandle = [[NSFileHandle fileHandleWithStandardOutput] retain];
+    }
+}
+
+- (void) setStandardErr
+{
+    if(isStandardOut || (fileHandle == nil))
+    {
+        isStandardOut = NO;
+        [fileHandle autorelease];
+        fileHandle = [[NSFileHandle fileHandleWithStandardError] retain];
+    }
+}
+
+- (NSFileHandle *) target
+{
+    return fileHandle;
+}
+
+- (BOOL) isStandardOut
+{
+    return isStandardOut;
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4DailyRollingFileAppender.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+
+//
+//  L4DailyRollingFileAppender.h
+//  Log4Cocoa
+//
+//  Created by Michael James on Thu Apr 29 2004.
+//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+/*!
+	@header L4DailyRollingFileAppender
+	@updated 2004-04-29
+*/
+
+#import <Foundation/Foundation.h>
+#import "L4FileAppender.h"
+
+/*!
+	@typedef L4RollingFrequency
+	@abstract The accepted constants for L4DailyRollingFileAppenderFrequency's <code>setFrequency:</code> method.
+	@constant never Never roll the file over (this is a default setting)
+	@constant monthly Roll the file over every month
+	@constant weekly Roll the file over every week
+	@constant daily Roll the file over every day
+	@constant half_daily Roll the file over every half day (once at midnight, once at noon)
+	@constant hourly Roll the file over every hour
+	@constant minutely Roll the file over every minute
+*/
+typedef enum L4RollingFrequency
+{
+	never,
+	monthly,
+	weekly,
+	daily,
+	half_daily,
+	hourly,
+	minutely
+} L4RollingFrequency;
+
+/*!
+	@class L4DailyRollingFileAppender
+	@discussion L4DailyRollingFileAppender extends L4FileAppender so that the underlying file is rolled over at a user-chosen frequency.
+
+		For example, if the fileName is set to /foo/bar.log and the frequency is set to daily, on 2001-02-16 at midnight, the logging file /foo/bar.log will be copied to /foo/bar.log.2001-02-16 and logging for 2001-02-17 will continue in /foo/bar.log until it rolls over the next day.
+
+		It is possible to specify monthly, weekly, half-daily, daily, hourly, or minutely rollover schedules.  
+*/
+@interface L4DailyRollingFileAppender : L4FileAppender
+{
+	L4RollingFrequency	_rollingFrequency;
+	NSCalendarDate*		_lastRolloverDate;
+}
+
+/*!
+	@method init
+	@abstract This initializer calls the <code>initWithLayout:fileName:rollingFrequency:</code> method with the respective values: nil, nil, never
+	@result An initialized instance of this class
+*/
+- (id)init;
+
+/*!
+	@method initWithLayout:fileName:rollingFrequency:
+	@abstract Initializes an instance of this class with the specified layout, file name, and rolling frequency.
+	@param aLayout The layout object for this appender
+	@param aName The file path to the file in which you want logging output recorded
+	@param rollingFrequency The frequency at which you want the log file rolled over
+	@result An initialized instance of this class
+*/
+- (id)initWithLayout: (L4Layout*)aLayout fileName: (NSString*)aName rollingFrequency: (L4RollingFrequency)rollingFrequency;
+
+/*!
+	@method rollingFrequency
+	@abstract Returns this object's rolling frequency.
+	@result This object's rolling frequency
+*/
+- (L4RollingFrequency)rollingFrequency;
+
+/*!
+	@method setRollingFrequency:
+	@abstract Sets the object's rolling frequency
+	@param rollingFrequency The desired rolling frequency for this object
+*/
+- (void)setRollingFrequency: (L4RollingFrequency)rollingFrequency;
+
+@end
+
+/*!
+	@category L4DailyRollingFileAppender (__ProtectedMethods)
+	@discussion These methods are "protected" methods and should not be called except by subclasses.
+*/
+@interface L4DailyRollingFileAppender (__ProtectedMethods)
+
+/*!
+	@method subAppend:
+	@discussion This method overrides the implementation in L4WriterAppender.  It checks if the rolling frequency has been exceeded.  If so, it rolls the file over.
+	@param event An L4LoggingEvent that contains logging specific information
+*/
+- (void)subAppend: (L4LoggingEvent*)event;
+
+@end

Framework/Contrib/Log4Cocoa/L4DailyRollingFileAppender.m

+//
+//  L4DailyRollingFileAppender.m
+//  Log4Cocoa
+//
+//  Created by Michael James on Thu Apr 29 2004.
+//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+#import "L4DailyRollingFileAppender.h"
+#import "L4Layout.h"
+#import <math.h>
+
+@implementation L4DailyRollingFileAppender
+
+- (id)init
+{
+	return [self initWithLayout: nil fileName: nil rollingFrequency: never];
+}
+
+- (id)initWithLayout: (L4Layout*)aLayout fileName: (NSString*)aName rollingFrequency: (L4RollingFrequency)rollingFrequency
+{
+	self = [super initWithLayout: aLayout fileName: aName append: YES bufferIO: NO bufferSize: 0];
+	
+	if (self != nil)
+	{
+		[self setRollingFrequency: rollingFrequency];
+	}
+	
+	return self;
+}
+
+- (void)dealloc
+{
+	[_lastRolloverDate release];
+	_lastRolloverDate = nil;
+	
+	[super dealloc];
+}
+
+- (L4RollingFrequency)rollingFrequency
+{
+	return _rollingFrequency;
+}
+
+- (void)setRollingFrequency: (L4RollingFrequency)rollingFrequency
+{	
+	_rollingFrequency = rollingFrequency;
+	[self _setLastRolloverDate: [NSCalendarDate calendarDate]];
+}
+
+@end
+
+@implementation L4DailyRollingFileAppender (__ProtectedMethods)
+
+- (void)subAppend: (L4LoggingEvent*)event
+{
+	// check if it's time to rollover, and if so, rollover
+	[self _rollOver];	
+	
+	// call superclass's subAppend:
+	[super subAppend: event];
+}
+
+@end
+
+@interface L4DailyRollingFileAppender (__PrivateMethods)
+
+- (NSCalendarDate*)_lastRolloverDate;
+- (void)_setLastRolloverDate: (NSDate*)date;
+- (void)_rollOver;
+
+@end
+
+@implementation L4DailyRollingFileAppender (__PrivateMethods)
+
+- (NSCalendarDate*)_lastRolloverDate
+{
+	return _lastRolloverDate;
+}
+
+- (void)_setLastRolloverDate: (NSDate*)date
+{
+	if ((NSDate*)_lastRolloverDate != date)
+	{
+		[_lastRolloverDate release];
+		_lastRolloverDate = nil;
+		_lastRolloverDate = [date retain];
+	}
+}
+
+- (void)_rollOver
+{
+	NSCalendarDate*	now = nil;
+	NSString*		pathExtension = nil;
+	NSCalendarDate*	tempLastRolloverDate = nil;
+	NSCalendarDate*	tempCalendarDate = nil, *tempCalendarDate2 = nil;
+	NSString*		newFileName = nil;
+	NSFileManager*	fm = nil;
+	BOOL			rolloverTime = NO;
+
+	fm = [NSFileManager defaultManager];
+
+	// get the current date and time
+	now = [NSCalendarDate calendarDate];
+
+	// if the rolling frequency is never, return
+	if (_rollingFrequency == never)
+	{
+		return;
+	}
+
+	// save a reference to the last rollover date, before we possible change it
+	tempLastRolloverDate = [[self _lastRolloverDate] retain];
+
+	// determine if we need to rollover now
+	switch (_rollingFrequency)
+	{
+		case monthly:
+		{
+			// if the last rollover date and now are not in the same month of the same year, time to rollover
+			if ([_lastRolloverDate monthOfYear] != [now monthOfYear] || [_lastRolloverDate yearOfCommonEra] != [now yearOfCommonEra])
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		case weekly:
+		{
+			// first find the first days of the week for the last rollover date and now
+			tempCalendarDate = [_lastRolloverDate dateByAddingYears: 0 months: 0 days: (0 - [_lastRolloverDate dayOfWeek]) hours: 0 minutes: 0 seconds: 0];
+			tempCalendarDate2 = [now dateByAddingYears: 0 months: 0 days: (0 - [now dayOfWeek]) hours: 0 minutes: 0 seconds: 0];
+
+			// if the last rollover date and now are not in the same week of the same year, time to rollover
+			if ([tempCalendarDate dayOfYear] != [tempCalendarDate2 dayOfYear] || [tempCalendarDate yearOfCommonEra] != [tempCalendarDate2 yearOfCommonEra])
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		case daily:
+		{
+			// if the last rollover date and now are not in the same day of the same year, time to rollover
+			if ([_lastRolloverDate dayOfYear] != [now dayOfYear] || [_lastRolloverDate yearOfCommonEra] != [now yearOfCommonEra])
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		case half_daily:
+		{
+			// if the last rollover date is between noon and midnight and now is between midnight and noon, time to rollover
+			if ([_lastRolloverDate hourOfDay] >= 12 && [now hourOfDay] < 12)
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+			// else if the last rollover date is between midnight and noon and now is between noon and midnight, time to rollover
+			else if ([_lastRolloverDate hourOfDay] < 12 && [now hourOfDay] >= 12)
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		case hourly:
+		{
+			// if the last rollover date is not the same hour of the same day of the same year as now, it is time to rollover
+			if ([_lastRolloverDate hourOfDay] != [now hourOfDay]  || [_lastRolloverDate dayOfYear] != [now dayOfYear] || [_lastRolloverDate yearOfCommonEra] != [now yearOfCommonEra])
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		case minutely:
+		{
+			// if the last rollover date is not the same minute of the same hour of the same day of the same year, it is time to rollover
+			if ([_lastRolloverDate minuteOfHour] != [now minuteOfHour] || [_lastRolloverDate hourOfDay] != [now hourOfDay] || [_lastRolloverDate dayOfYear] != [now dayOfYear] || [_lastRolloverDate yearOfCommonEra] != [now yearOfCommonEra])
+			{
+				rolloverTime = YES;
+
+				// update the last rollover date to now
+				[self _setLastRolloverDate: now];
+			}
+		}
+			break;
+
+		default:
+		{
+			rolloverTime = NO;
+		}
+			break;
+	}
+
+	// if we have passed the rollover date
+	if (rolloverTime)
+	{
+		// if rolling frequency is not never, calculate the path extension
+		if (_rollingFrequency != never)
+		{
+			switch (_rollingFrequency)
+			{
+				case monthly:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: @"%Y-%m" timeZone: nil locale: nil];
+				}
+				break;
+
+				case weekly:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: [@"%Y-%m-" stringByAppendingString: [NSString stringWithFormat: @"%d", floor([tempCalendarDate dayOfYear] / 7)]] timeZone: nil locale: nil];
+				}
+				break;
+
+				case daily:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: @"%Y-%m-%d" timeZone: nil locale: nil];
+				}
+				break;
+
+				case half_daily:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: @"%Y-%m-%d-%p" timeZone: nil locale: nil];
+				}
+				break;
+
+				case hourly:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: @"%Y-%m-%d-%H" timeZone: nil locale: nil];
+				}
+				break;
+
+				case minutely:
+				{
+					pathExtension = [tempLastRolloverDate descriptionWithCalendarFormat: @"%Y-%m-%d-%H-%M" timeZone: nil locale: nil];
+				}
+				break;
+				
+				default:
+				{
+					// ignore other values, if we are here, we got an illegal value so reset the rolling frequency to never
+					[self setRollingFrequency: never];
+				}
+				break;
+			}
+		}
+
+		[tempLastRolloverDate release];
+		tempLastRolloverDate = nil;
+
+		// generate the new rollover log file name
+		newFileName = [[self fileName] stringByAppendingPathExtension: pathExtension];
+
+		// close the current log file
+		[self closeFile];
+
+		// rename the current log file to the new rollover log file name
+		if (![fm movePath: [self fileName] toPath: newFileName handler: nil])
+		{
+			// if we can't rename the file, raise an exception
+			[NSException raise: @"CantMoveFileException" format: @"Unable to move file from %@ to %@", [self fileName], newFileName];
+		}
+
+		// re-activate this appender (this will open a new log file named [self fileName])
+		[self activateOptions];
+	}
+
+	[tempLastRolloverDate release];
+	tempLastRolloverDate = nil;
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4DailyRollingFileAppenderTest.h

+//
+//  L4DailyRollingFileAppenderTest.h
+//  Log4Cocoa
+//
+//  Created by Michael James on Thu Apr 29 2004.
+//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <ObjcUnit/ObjcUnit.h>
+
+@class L4DailyRollingFileAppender;
+
+@interface L4DailyRollingFileAppenderTest : TestCase
+{
+	L4DailyRollingFileAppender*	_drfa;
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4DailyRollingFileAppenderTest.m

+//
+//  L4DailyRollingFileAppenderTest.m
+//  Log4Cocoa
+//
+//  Created by Michael James on Thu Apr 29 2004.
+//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
+//
+
+#import "L4DailyRollingFileAppenderTest.h"
+#import "L4DailyRollingFileAppender.h"
+#import "L4Layout.h"
+
+#define TEST_DRFA_OUTPUTDIR [@"~/Desktop/DRFATest" stringByExpandingTildeInPath]
+#define TEST_DRFA_LOG_OUTPUTFILE [@"~/Desktop/DRFATest/testDailyRollingFileAppender" stringByExpandingTildeInPath]
+
+@implementation L4DailyRollingFileAppenderTest
+
+- (void)setUp
+{
+	_drfa = [[L4DailyRollingFileAppender alloc] init];
+}
+
+- (void)tearDown
+{
+	[[self l4Logger] removeAppender: _drfa];
+	
+	[_drfa release];
+	_drfa = nil;
+}
+
+- (void)testCreation
+{
+	[self assertNotNil: _drfa message: @"_drfa is nil!"];
+	[self assertTrue: ([_drfa rollingFrequency] == never) message: @"_drfa's rolling frequency is not never!"];
+}
+
+- (void)testSetRollingFrequency
+{
+	[_drfa setRollingFrequency: minutely];
+	[self assertTrue: ([_drfa rollingFrequency] == minutely) message: @"_drfa's rolling frequency is not minuntely!"];
+}
+
+- (void)testLogging
+{
+	NSDate*				now = nil;
+	NSDate*				aMinuteFromNow = nil;
+	L4PatternLayout*	pl = nil;
+	NSFileManager*		fm = [NSFileManager defaultManager];
+	
+	pl = [[[L4PatternLayout alloc] initWithConversionPattern: @"%m"] autorelease];
+	[_drfa setLayout: pl];
+	
+	[fm createDirectoryAtPath: TEST_DRFA_OUTPUTDIR attributes: nil];
+		
+	now = [NSDate date];
+	aMinuteFromNow = [NSDate dateWithTimeIntervalSinceNow: 61];
+
+	[_drfa setFileName: TEST_DRFA_LOG_OUTPUTFILE];
+	[_drfa setRollingFrequency: minutely];
+	[_drfa activateOptions];	
+	
+	[[self l4Logger] addAppender: _drfa];
+	log4Debug(@"This is the first test logging statement!", nil);
+	
+	[NSThread sleepUntilDate: aMinuteFromNow];
+	log4Debug(@"This is the second test logging statement!", nil);
+	
+	[self assertTrue: ([[fm directoryContentsAtPath: TEST_DRFA_OUTPUTDIR] count] >= 2) message: @"There are not 2 files in the TEST_DRFA_OUTPUTDIR!"];
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4DefaultRenderer.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+#import "L4LoggerProtocols.h"
+
+@interface L4DefaultRenderer : NSObject <L4ObjectRenderer> {
+
+}
+
+- (NSString *) render: (id) object;
+
+@end

Framework/Contrib/Log4Cocoa/L4DefaultRenderer.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import "L4DefaultRenderer.h"
+
+
+@implementation L4DefaultRenderer
+
+- (NSString *) render: (id) object
+{
+    return [object description];
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4ErrorHandler.h

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+*  - Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*  - Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+*  - Neither the name of Log4Cocoa nor the names of its contributors or owners
+*    may be used to endorse or promote products derived from this software
+*    without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+****************************/
+
+#import <Foundation/Foundation.h>
+
+
+@interface L4ErrorHandler : NSObject {
+
+}
+
+@end

Framework/Contrib/Log4Cocoa/L4ErrorHandler.m

+/****************************
+*
+* Copyright (c) 2002, 2003, Bob Frank
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions