      }
      
      /**
+Index: ports/classes/net/xp_framework/unittest/logging/LogAppenderTest.class.php
+===================================================================
+--- ports/classes/net/xp_framework/unittest/logging/LogAppenderTest.class.php	(revision 0)
++++ ports/classes/net/xp_framework/unittest/logging/LogAppenderTest.class.php	(revision 0)
+@@ -0,0 +1,97 @@
++<?php
++/* This class is part of the XP framework
++ *
++ * $Id$ 
++ */
++
++  uses(
++    'unittest.TestCase',
++    'util.log.LogAppender',
++    'util.log.LogCategory',
++    'util.log.PatternLayout',
++    'util.collections.Vector'
++  );
++
++  /**
++   * TestCase
++   *
++   * @see      reference
++   * @purpose  purpose
++   */
++  class LogAppenderTest extends TestCase {
++    protected $fixture= NULL;
++    protected $events= NULL;
++  
++    /**
++     * Sets up test case
++     *
++     */
++    public function setUp() {
++      $this->events= create('new Vector<String>()');
++      $appender= newinstance('util.log.LogAppender', array($this->events), '{
++        private $events= NULL;
++
++        public function __construct($events) {
++          $this->events= $events;
++        }
++
++        public function append(LoggingEvent $event) {
++          $this->events[]= new String($this->layout->format($event));
++        }
++      }');
++      $this->fixture= create(new LogCategory('default'))
++        ->withAppender($appender->withLayout(new PatternLayout('[%l] %m')))
++      ;
++    }
++    
++    /**
++     * Test
++     *
++     */
++    #[@test]
++    public function info() {
++      $this->fixture->info('Hello');
++      $this->assertEquals(new String('[info] Hello'), $this->events[0]);
++    }
++
++    /**
++     * Test
++     *
++     */
++    #[@test]
++    public function infoWithMultipleArguments() {
++      $this->fixture->info('Hello', 'World');
++      $this->assertEquals(new String('[info] Hello World'), $this->events[0]);
++    }
++
++    /**
++     * Test
++     *
++     */
++    #[@test]
++    public function warn() {
++      $this->fixture->warn('Hello');
++      $this->assertEquals(new String('[warn] Hello'), $this->events[0]);
++    }
++
++    /**
++     * Test
++     *
++     */
++    #[@test]
++    public function debug() {
++      $this->fixture->debug('Hello');
++      $this->assertEquals(new String('[debug] Hello'), $this->events[0]);
++    }
++
++    /**
++     * Test
++     *
++     */
++    #[@test]
++    public function error() {
++      $this->fixture->error('Hello');
++      $this->assertEquals(new String('[error] Hello'), $this->events[0]);
++    }
++  }
++?>
+
+Property changes on: ports/classes/net/xp_framework/unittest/logging/LogAppenderTest.class.php
+___________________________________________________________________
+Added: svn:keywords
+   + Id
+
 Index: ports/unittest/logging.ini
 ===================================================================
 --- ports/unittest/logging.ini	(revision 13884)

+     */
+    public function __destruct() {
+      $this->finalize();
+    }
   }
 ?>

     }
   }
 ?>
Index: skeleton/util/log/DefaultLayout.class.php
===================================================================
--- skeleton/util/log/DefaultLayout.class.php	(revision 0)
+++ skeleton/util/log/DefaultLayout.class.php	(revision 0)
@@ -0,0 +1,43 @@
+<?php
+/* This class is part of the XP framework
+ *
+ * $Id$ 
+ */
+
+  uses('util.log.Layout');
+
+  /**
+   * Default layout
+   *
+   */
+  class DefaultLayout extends utillogLayout {
+  
+    /**
+     * Creates a string representation of the given argument. For any 
+     * string given, the result is the string itself, for any other type,
+     * the result is the xp::stringOf() output.
+     *
+     * @param   var arg
+     * @return  string
+     */
+    protected function stringOf($arg) {
+      return is_string($arg) ? $arg : xp::stringOf($arg);
+    }
+
+    /**
+     * Formats a logging event according to this layout
+     *
+     * @param   util.log.LoggingEvent event
+     * @return  string
+     */
+    public function format(LoggingEvent $event) {
+      return sprintf(
+        '[%s %5d %5s] %s', 
+        date('H:i:s', $event->getTimestamp()),
+        $event->getProcessId(),
+        strtolower(LogLevel::nameOf($event->getLevel())),
+        implode(' ', array_map(array($this, 'stringOf'), $event->getArguments()))
+      );
+    }
+  }
+?>

Property changes on: skeleton/util/log/DefaultLayout.class.php
___________________________________________________________________
Added: svn:keywords
   + Id

Index: ports/classes/net/xp_framework/unittest/logging/LoggingEventTest.class.php
===================================================================
--- ports/classes/net/xp_framework/unittest/logging/LoggingEventTest.class.php	(revision 0)
+++ ports/classes/net/xp_framework/unittest/logging/LoggingEventTest.class.php	(revision 0)
@@ -0,0 +1,79 @@
+<?php
+/* This class is part of the XP framework
+ *
+ * $Id$ 
+ */
+
+  uses(
+    'unittest.TestCase',
+    'util.log.LoggingEvent'
+  );
+
+  /**
+   * TestCase
+   *
+   * @see      xp://util.log.LoggingEvent
+   */
+  class LoggingEventTest extends TestCase {
+    protected $fixture= NULL;
+  
+    /**
+     * Creates fixture
+     *
+     */
+    public function setUp() {
+      $this->fixture= new LoggingEvent(
+        new LogCategory('default', NULL, NULL, 0), 
+        1258733284, 
+        1, 
+        LogLevel::INFO, 
+        array('Hello')
+      );
+    }
+  
+    /**
+     * Test getCategory() method
+     *
+     */
+    #[@test]
+    public function getCategory() {
+      $this->assertEquals(new LogCategory('default', NULL, NULL, 0), $this->fixture->getCategory());
+    }
+ 
+    /**
+     * Test getTimestamp() method
+     *
+     */
+    #[@test]
+    public function getTimestamp() {
+      $this->assertEquals(1258733284, $this->fixture->getTimestamp());
+    }
+
+    /**
+     * Test getProcessId() method
+     *
+     */
+    #[@test]
+    public function getProcessId() {
+      $this->assertEquals(1, $this->fixture->getProcessId());
+    }
+
+    /**
+     * Test getLevel() method
+     *
+     */
+    #[@test]
+    public function getLevel() {
+      $this->assertEquals(LogLevel::INFO, $this->fixture->getLevel());
+    }
+
+    /**
+     * Test getArguments() method
+     *
+     */
+    #[@test]
+    public function getArguments() {
+      $this->assertEquals(array('Hello'), $this->fixture->getArguments());
+    }
+  }
+?>

Property changes on: ports/classes/net/xp_framework/unittest/logging/LoggingEventTest.class.php
___________________________________________________________________
Added: svn:keywords
   + Id

Index: ports/classes/net/xp_framework/unittest/logging/PatternLayoutTest.class.php
===================================================================
--- ports/classes/net/xp_framework/unittest/logging/PatternLayoutTest.class.php	(revision 0)
+++ ports/classes/net/xp_framework/unittest/logging/PatternLayoutTest.class.php	(revision 0)
@@ -0,0 +1,92 @@
+<?php
+/* This class is part of the XP framework
+ *
+ * $Id$ 
+ */
+
+  uses(
+    'unittest.TestCase',
+    'util.log.PatternLayout'
+  );
+
+  /**
+   * TestCase
+   *
+   * @see      xp://util.log.PatternLayout
+   */
+  class PatternLayoutTest extends TestCase {
+
+    /**
+     * Test illegal format token %Q
+     * 
+     */
+    #[@test, @expect('lang.IllegalArgumentException')]
+    public function illegalFormatToken() {
+      new PatternLayout('%Q');
+    }
+ 
+    /**
+     * Test unterminated format token
+     * 
+     */
+    #[@test, @expect('lang.IllegalArgumentException')]
+    public function unterminatedFormatToken() {
+      new PatternLayout('%');
+    }
+    
+    /**
+     * Creates a new logging event
+     *
+     * @return  util.log.LoggingEvent
+     */
+    protected function newLoggingEvent() {
+      return new LoggingEvent(
+        new LogCategory('default'), 
+        1258733284, 
+        1214, 
+        LogLevel::WARN, 
+        array('Hello')
+      );   
+    }
+
+    /**
+     * Test literal percent
+     * 
+     */
+    #[@test]
+    public function literalPercent() {
+      $this->assertEquals(
+        '100%',
+        create(new PatternLayout('100%%'))->format($this->newLoggingEvent())
+      );
+    }
+
+    /**
+     * Test simple format:
+     * <pre>
+     *   INFO [default] Hello
+     * </pre>
+     */
+    #[@test]
+    public function simpleFormat() {
+      $this->assertEquals(
+        'WARN [default] Hello',
+        create(new PatternLayout('%L [%c] %m'))->format($this->newLoggingEvent())
+      );
+    }
+
+    /**
+     * Test default format:
+     * <pre>
+     *   [16:08:04 1214 warn] Hello
+     * </pre>
+     */
+    #[@test]
+    public function defaultFormat() {
+      $this->assertEquals(
+        '[16:08:04 1214 warn] Hello',
+        create(new PatternLayout('[%t %p %l] %m'))->format($this->newLoggingEvent())
+      );
+    }
+  }
+?>

Property changes on: ports/classes/net/xp_framework/unittest/logging/PatternLayoutTest.class.php
___________________________________________________________________
Added: svn:keywords
   + Id

Index: ports/classes/net/xp_framework/unittest/logging/LogCategoryTest.class.php
===================================================================
--- ports/classes/net/xp_framework/unittest/logging/LogCategoryTest.class.php	(revision 13884)
