From e2853112a2a16be24c8428f1d196da9d38f0d5ee Mon Sep 17 00:00:00 2001 From: Gunnar Wrobel Date: Wed, 22 Dec 2010 15:03:40 +0100 Subject: [PATCH] Add a log decorator and a stop watch decorator. --- .../lib/Horde/Kolab/Storage/Driver.php | 7 + .../Horde/Kolab/Storage/Driver/Decorator/Base.php | 38 +++ .../Horde/Kolab/Storage/Driver/Decorator/Log.php | 39 ++- .../Horde/Kolab/Storage/Driver/Decorator/Timer.php | 316 +++++++++++++++++++++ .../lib/Horde/Kolab/Storage/Driver/Imap.php | 2 +- .../lib/Horde/Kolab/Storage/Factory.php | 51 +++- framework/Kolab_Storage/package.xml | 18 +- .../test/Horde/Kolab/Storage/TestCase.php | 12 + .../Storage/Unit/Driver/Decorator/LogTest.php | 57 ++++ .../Storage/Unit/Driver/Decorator/TimerTest.php | 66 +++++ .../test/Horde/Kolab/Storage/Unit/FactoryTest.php | 30 ++ 11 files changed, 616 insertions(+), 20 deletions(-) create mode 100644 framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Timer.php create mode 100644 framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/LogTest.php create mode 100644 framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/TimerTest.php diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver.php index 585640d1a..f4a98759c 100644 --- a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver.php +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver.php @@ -35,6 +35,13 @@ interface Horde_Kolab_Storage_Driver public function getAuth(); /** + * Retrieves a list of mailboxes from the server. + * + * @return array The list of mailboxes. + */ + public function getMailboxes(); + + /** * Does the given folder exist? * * @param string $folder The folder to check. diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Base.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Base.php index e7aef4e5d..3c9a30a35 100644 --- a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Base.php +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Base.php @@ -29,12 +29,50 @@ class Horde_Kolab_Storage_Driver_Decorator_Base implements Horde_Kolab_Storage_Driver { /** + * The decorated driver. + * + * @var Horde_Kolab_Storage_Driver + */ + private $_driver; + + /** + * Constructor. + * + * @param Horde_Kolab_Storage_Driver $driver The decorated driver. + */ + public function __construct(Horde_Kolab_Storage_Driver $driver) + { + $this->_driver = $driver; + } + + /** + * Return the class name of the decorated driver. + * + * @return string The class name of the decorated driver. + */ + public function getDriverName() + { + return get_class($this->_driver); + } + + /** * Return the id of the user currently authenticated. * * @return string The id of the user that opened the connection. */ public function getAuth() { + return $this->_driver->getAuth(); + } + + /** + * Retrieves a list of mailboxes from the server. + * + * @return array The list of mailboxes. + */ + public function getMailboxes() + { + return $this->_driver->getMailboxes(); } /** diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Log.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Log.php index 1f9c8b938..1e6910cd0 100644 --- a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Log.php +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Log.php @@ -12,7 +12,7 @@ */ /** - * The basic driver decorator definition for accessing Kolab storage. + * A log decorator definition for the Kolab storage drivers. * * Copyright 2010 The Horde Project (http://www.horde.org/) * @@ -29,12 +29,43 @@ class Horde_Kolab_Storage_Driver_Decorator_Log extends Horde_Kolab_Storage_Driver_Decorator_Base { /** - * Return the id of the user currently authenticated. + * A log handler. + * + * @var mixed + */ + private $_logger; + + /** + * Constructor. + * + * @param Horde_Kolab_Storage_Driver $driver The decorated driver. + * @param mixed $logger The log handler. This instance + * must provide the info() method. + */ + public function __construct(Horde_Kolab_Storage_Driver $driver, $logger) + { + $this->_logger = $logger; + parent::__construct($driver); + } + + /** + * Retrieves a list of mailboxes from the server. * - * @return string The id of the user that opened the connection. + * @return array The list of mailboxes. */ - public function getAuth() + public function getMailboxes() { + $this->_logger->info( + sprintf('Driver "%s": Listing folders.', $this->getDriverName()) + ); + $result = parent::getMailboxes(); + $this->_logger->info( + sprintf( + 'Driver "%s": List contained %s folders.', + $this->getDriverName(), + count($result)) + ); + return $result; } /** diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Timer.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Timer.php new file mode 100644 index 000000000..436209879 --- /dev/null +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Decorator/Timer.php @@ -0,0 +1,316 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ + +/** + * A stop watch decorator for outgoing requests from the Kolab storage drivers. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Storage + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ +class Horde_Kolab_Storage_Driver_Decorator_Timer +extends Horde_Kolab_Storage_Driver_Decorator_Base +{ + /** + * A log handler. + * + * @var mixed + */ + private $_logger; + + /** + * A stop watch. + * + * @var Horde_Support_Timer + */ + private $_timer; + + /** + * Constructor. + * + * @param Horde_Kolab_Storage_Driver $driver The decorated driver. + * @param Horde_Support_Timer $timer A stop watch. + * @param mixed $logger The log handler. This instance + * must provide the info() method. + */ + public function __construct( + Horde_Kolab_Storage_Driver $driver, + Horde_Support_Timer $timer, + $logger + ) { + $this->_logger = $logger; + $this->_timer = $timer; + parent::__construct($driver); + } + + /** + * Retrieves a list of mailboxes from the server. + * + * @return array The list of mailboxes. + */ + public function getMailboxes() + { + $this->_timer->push(); + $result = parent::getMailboxes(); + $this->_logger->info( + sprintf( + 'REQUEST OUT IMAP: %s ms [getMailboxes]', + floor($this->_timer->pop() * 1000) + ) + ); + return $result; + } + + /** + * Does the given folder exist? + * + * @param string $folder The folder to check. + * + * @return boolean True in case the folder exists, false otherwise. + */ + public function exists($folder) + { + } + + /** + * Opens the given folder. + * + * @param string $folder The folder to open + * + * @return mixed True in case the folder was opened successfully, a PEAR + * error otherwise. + */ + public function select($folder) + { + } + + /** + * Returns the status of the current folder. + * + * @param string $folder Check the status of this folder. + * + * @return array An array that contains 'uidvalidity' and 'uidnext'. + */ + public function status($folder) + { + } + + /** + * Returns the message ids of the messages in this folder. + * + * @param string $folder Check the status of this folder. + * + * @return array The message ids. + */ + public function getUids($folder) + { + } + + /** + * Create the specified folder. + * + * @param string $folder The folder to create. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + public function create($folder) + { + } + + /** + * Delete the specified folder. + * + * @param string $folder The folder to delete. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + public function delete($folder) + { + } + + /** + * Rename the specified folder. + * + * @param string $old The folder to rename. + * @param string $new The new name of the folder. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + public function rename($old, $new) + { + } + + /** + * Appends a message to the current folder. + * + * @param string $mailbox The mailbox to append the message(s) to. Either + * in UTF7-IMAP or UTF-8. + * @param string $msg The message to append. + * + * @return mixed True or a PEAR error in case of an error. + */ + public function appendMessage($mailbox, $msg) + { + } + + /** + * Deletes messages from the current folder. + * + * @param integer $uids IMAP message ids. + * + * @return mixed True or a PEAR error in case of an error. + */ + public function deleteMessages($mailbox, $uids) + { + } + + /** + * Moves a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + public function moveMessage($old_folder, $uid, $new_folder) + { + } + + /** + * Expunges messages in the current folder. + * + * @param string $mailbox The mailbox to append the message(s) to. Either + * in UTF7-IMAP or UTF-8. + * + * @return mixed True or a PEAR error in case of an error. + */ + public function expunge($mailbox) + { + } + + /** + * Retrieves the message headers for a given message id. + * + * @param string $mailbox The mailbox to append the message(s) to. Either + * in UTF7-IMAP or UTF-8. + * @param int $uid The message id. + * @param boolean $peek_for_body Prefetch the body. + * + * @return mixed The message header or a PEAR error in case of an error. + */ + public function getMessageHeader($mailbox, $uid, $peek_for_body = true) + { + } + + /** + * Retrieves the message body for a given message id. + * + * @param string $mailbox The mailbox to append the message(s) to. Either + * in UTF7-IMAP or UTF-8. + * @param integet $uid The message id. + * + * @return mixed The message body or a PEAR error in case of an error. + */ + public function getMessageBody($mailbox, $uid) + { + } + + /** + * Retrieve the access rights for a folder. + * + * @param Horde_Kolab_Storage_Folder $folder The folder to retrieve the ACL for. + * + * @return An array of rights. + */ + public function getAcl(Horde_Kolab_Storage_Folder $folder) + { + } + + /** + * Set the access rights for a folder. + * + * @param string $folder The folder to act upon. + * @param string $user The user to set the ACL for. + * @param string $acl The ACL. + * + * @return NULL + */ + public function setAcl($folder, $user, $acl) + { + } + + /** + * Delete the access rights for user on a folder. + * + * @param string $folder The folder to act upon. + * @param string $user The user to delete the ACL for + * + * @return NULL + */ + public function deleteAcl($folder, $user) + { + } + + /** + * Fetches the annotation on a folder. + * + * @param string $entry The entry to fetch. + * @param string $folder The name of the folder. + * + * @return string The annotation value. + */ + public function getAnnotation($entry, $folder) + { + } + + /** + * Sets the annotation on a folder. + * + * @param string $entry The entry to set. + * @param array $value The values to set + * @param string $folder The name of the folder. + * + * @return NULL + */ + public function setAnnotation($entry, $value, $folder) + { + } + + /** + * Retrieve the namespace information for this connection. + * + * @return Horde_Kolab_Storage_Driver_Namespace The initialized namespace handler. + */ + public function getNamespace() + { + } + + /** + * Get the group handler for this connection. + * + * @return Horde_Group The group handler. + */ + public function getGroupHandler() + { + } +} \ No newline at end of file diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Imap.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Imap.php index f8f3bbda3..fecfb65b1 100644 --- a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Imap.php +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Driver/Imap.php @@ -62,7 +62,7 @@ extends Horde_Kolab_Storage_Driver_Base } /** - * Retrieves a list of mailboxes on the server. + * Retrieves a list of mailboxes from the server. * * @return array The list of mailboxes. */ diff --git a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Factory.php b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Factory.php index 677f695f7..41506b554 100644 --- a/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Factory.php +++ b/framework/Kolab_Storage/lib/Horde/Kolab/Storage/Factory.php @@ -59,7 +59,7 @@ class Horde_Kolab_Storage_Factory $storage = new Horde_Kolab_Storage_Base( $this->createDriverFromParams($params) ); - if (isset($params['logger'])) { + if (!empty($params['logger'])) { $storage = new Horde_Kolab_Storage_Decorator_Log( $storage, $params['logger'] ); @@ -72,11 +72,11 @@ class Horde_Kolab_Storage_Factory * * @param array $params The parameters for the backend access. See create(). *
-     *  - driver : The type of backend driver. One of "mock", "php", "pear",
-     *             "horde", "horde-socket", and "roundcube".
-     *  - params : Backend specific connection parameters.
-     *
-     *    
+     *  - driver  : The type of backend driver. One of "mock", "php", "pear",
+     *              "horde", "horde-socket", and "roundcube".
+     *  - params  : Backend specific connection parameters.
+     *  - logger  : An optional log handler.
+     *  - timelog : An optional time keeping log handler.
      * 
* * @return Horde_Kolab_Storage_Driver The storage handler. @@ -95,38 +95,47 @@ class Horde_Kolab_Storage_Factory } else { $config = array(); } + if (!empty($params['timelog'])) { + $timer = new Horde_Support_Timer(); + $timer->push(); + } switch ($params['driver']) { case 'mock': $config['data'] = array('user/test' => array()); - return new Horde_Kolab_Storage_Driver_Mock($this, $config); + $driver = new Horde_Kolab_Storage_Driver_Mock($this, $config); + break; case 'horde': $config['hostspec'] = $config['host']; unset($config['host']); - return new Horde_Kolab_Storage_Driver_Imap( + $driver = new Horde_Kolab_Storage_Driver_Imap( new Horde_Imap_Client_Socket( $config ), $this ); + break; case 'horde-php': $config['hostspec'] = $config['host']; unset($config['host']); - return new Horde_Kolab_Storage_Driver_Imap( + $driver = new Horde_Kolab_Storage_Driver_Imap( new Horde_Imap_Client_Cclient( $config ), $this ); + break; case 'php': - return new Horde_Kolab_Storage_Driver_Cclient($this, $config); + $driver = new Horde_Kolab_Storage_Driver_Cclient($this, $config); + break; case 'pear': $client = new Net_IMAP($config['host']); Horde_Kolab_Storage_Exception_Pear::catchError( $client->login($config['username'], $config['password']) ); - return new Horde_Kolab_Storage_Driver_Pear( + $driver = new Horde_Kolab_Storage_Driver_Pear( $client, $this, $config ); + break; case 'roundcube': $client = new rcube_imap_generic(); $client->connect( @@ -139,9 +148,10 @@ class Horde_Kolab_Storage_Factory 'force_caps' => false, ) ); - return new Horde_Kolab_Storage_Driver_Rcube( + $driver = new Horde_Kolab_Storage_Driver_Rcube( $client, $this, $config ); + break; default: throw new Horde_Kolab_Storage_Exception( sprintf( @@ -152,6 +162,23 @@ class Horde_Kolab_Storage_Factory ) ); } + if (!empty($params['logger'])) { + $driver = new Horde_Kolab_Storage_Driver_Decorator_Log( + $driver, $params['logger'] + ); + } + if (!empty($params['timelog'])) { + $params['timelog']->info( + sprintf( + 'REQUEST OUT IMAP: %s ms [construct]', + floor($timer->pop() * 1000) + ) + ); + $driver = new Horde_Kolab_Storage_Driver_Decorator_Timer( + $driver, $timer, $params['timelog'] + ); + } + return $driver; } /** diff --git a/framework/Kolab_Storage/package.xml b/framework/Kolab_Storage/package.xml index a3a74c029..8dc40a2d2 100644 --- a/framework/Kolab_Storage/package.xml +++ b/framework/Kolab_Storage/package.xml @@ -31,8 +31,8 @@ jan@horde.org yes - 2010-12-21 - + 2010-12-22 + 0.4.0 0.1.0 @@ -80,6 +80,7 @@ + @@ -139,6 +140,7 @@ + @@ -429,6 +431,9 @@ + + + @@ -531,6 +536,10 @@ Imap_Client pear.horde.org + + Support + pear.horde.org + imap @@ -542,6 +551,7 @@ + @@ -560,6 +570,7 @@ + @@ -700,6 +711,7 @@ + @@ -774,7 +786,7 @@ alpha alpha - 2010-12-21 + 2010-12-22 LGPL * Added namespace support (Bug #6691). diff --git a/framework/Kolab_Storage/test/Horde/Kolab/Storage/TestCase.php b/framework/Kolab_Storage/test/Horde/Kolab/Storage/TestCase.php index 12ca1f2c2..e60601a8c 100644 --- a/framework/Kolab_Storage/test/Horde/Kolab/Storage/TestCase.php +++ b/framework/Kolab_Storage/test/Horde/Kolab/Storage/TestCase.php @@ -94,4 +94,16 @@ extends PHPUnit_Framework_TestCase } $this->assertTrue($found); } + + protected function assertLogRegExp($regular_expression) + { + $found = false; + foreach ($this->logHandler->events as $event) { + if (preg_match($regular_expression, $event['message'], $matches) !== false) { + $found = true; + break; + } + } + $this->assertTrue($found); + } } diff --git a/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/LogTest.php b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/LogTest.php new file mode 100644 index 000000000..175303593 --- /dev/null +++ b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/LogTest.php @@ -0,0 +1,57 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ + +/** + * Prepare the test setup. + */ +require_once dirname(__FILE__) . '/../../../Autoload.php'; + +/** + * Test the log decorator for the backend drivers. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Storage + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ +class Horde_Kolab_Storage_Unit_Driver_Decorator_LogTest +extends Horde_Kolab_Storage_TestCase +{ + public function testGetMailboxesLogsEntry() + { + $driver = new Horde_Kolab_Storage_Driver_Decorator_Log( + $this->getNullMock(), + $this->getMockLogger() + ); + $driver->getMailboxes(); + $this->assertLogCount(2); + } + + public function testGetMailboxesFolderCount() + { + $driver = new Horde_Kolab_Storage_Driver_Decorator_Log( + $this->getTwoFolderMock(), + $this->getMockLogger() + ); + $driver->getMailboxes(); + $this->assertLogContains('Driver "Horde_Kolab_Storage_Driver_Mock": List contained 2 folders.'); + } +} diff --git a/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/TimerTest.php b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/TimerTest.php new file mode 100644 index 000000000..7724bcadb --- /dev/null +++ b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/Driver/Decorator/TimerTest.php @@ -0,0 +1,66 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ + +/** + * Prepare the test setup. + */ +require_once dirname(__FILE__) . '/../../../Autoload.php'; + +/** + * Test the stop watch decorator for the backend drivers. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Storage + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Storage + */ +class Horde_Kolab_Storage_Unit_Driver_Decorator_TimerTest +extends Horde_Kolab_Storage_TestCase +{ + public function setUp() + { + if (!class_exists('Horde_Support_Timer')) { + $this->markTestSkipped('The "Horde_Support" package seems to be missing!'); + } + } + + public function testGetMailboxesLogsEntry() + { + $driver = new Horde_Kolab_Storage_Driver_Decorator_Timer( + $this->getNullMock(), + new Horde_Support_Timer(), + $this->getMockLogger() + ); + $driver->getMailboxes(); + $this->assertLogCount(1); + } + + public function testGetMailboxesFolderCount() + { + $driver = new Horde_Kolab_Storage_Driver_Decorator_Timer( + $this->getTwoFolderMock(), + new Horde_Support_Timer(), + $this->getMockLogger() + ); + $driver->getMailboxes(); + $this->assertLogRegExp('/REQUEST OUT IMAP:.*getMailboxes.*/'); + } +} diff --git a/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/FactoryTest.php b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/FactoryTest.php index e8098d487..d3cfd70bf 100644 --- a/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/FactoryTest.php +++ b/framework/Kolab_Storage/test/Horde/Kolab/Storage/Unit/FactoryTest.php @@ -122,5 +122,35 @@ extends Horde_Kolab_Storage_TestCase ); } + public function testTimerDecoration() + { + $factory = new Horde_Kolab_Storage_Factory(); + $logger = $this->getMockLogger(); + $this->assertInstanceOf( + 'Horde_Kolab_Storage_Driver_Decorator_Timer', + $factory->createDriverFromParams( + array( + 'driver' => 'mock', + 'logger' => $logger, + 'timelog' => $logger, + ) + ) + ); + } + + public function testTimedDriverConstruction() + { + $factory = new Horde_Kolab_Storage_Factory(); + $logger = $this->getMockLogger(); + $factory->createDriverFromParams( + array( + 'driver' => 'mock', + 'logger' => $logger, + 'timelog' => $logger, + ) + ); + $this->assertLogRegExp('/REQUEST OUT IMAP:.*construct.*/'); + } + } -- 2.11.0