Index: /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/meta.zcml
===================================================================
--- /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/meta.zcml	(revision 11991)
+++ /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/meta.zcml	(revision 11992)
@@ -17,4 +17,10 @@
       />
 
+  <meta:directive
+      namespace="http://namespaces.waeup.org/ikoba"
+      name="paypalconf"
+      schema=".zcml.IPayPalConfig"
+      handler=".zcml.paypal_conf"
+      />
 
 </configure>
Index: /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-datacenter.zcml
===================================================================
--- /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-datacenter.zcml	(revision 11992)
+++ /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-datacenter.zcml	(revision 11992)
@@ -0,0 +1,13 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:ikoba="http://namespaces.waeup.org/ikoba"
+   i18n_domain="waeup.ikoba"
+   package="waeup.ikoba.tests"
+   >
+  <include package="waeup.ikoba" file="meta.zcml" />
+
+  <!-- Sample for the 'datacenter' ZCML directive: -->
+  <ikoba:datacenter
+      path="/some/path" />
+
+</configure>
Index: /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-paypalconf.zcml
===================================================================
--- /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-paypalconf.zcml	(revision 11992)
+++ /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/sample-paypalconf.zcml	(revision 11992)
@@ -0,0 +1,13 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:ikoba="http://namespaces.waeup.org/ikoba"
+   i18n_domain="waeup.ikoba"
+   package="waeup.ikoba.tests"
+   >
+  <include package="waeup.ikoba" file="meta.zcml" />
+
+  <!-- Sample for the 'paypalconf' directive: -->
+  <ikoba:paypalconf
+      path="/path/to/some/paypal.conf" />
+
+</configure>
Index: /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/test_zcml.py
===================================================================
--- /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/test_zcml.py	(revision 11992)
+++ /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/tests/test_zcml.py	(revision 11992)
@@ -0,0 +1,85 @@
+import tempfile
+import shutil
+import unittest
+from waeup.ikoba import tests
+from waeup.ikoba.interfaces import IDataCenterConfig, IPayPalConfig
+from zope.component import getUtility, queryUtility, getGlobalSiteManager
+from zope.configuration.exceptions import ConfigurationError
+from zope.configuration.xmlconfig import file as zcfile
+from zope.configuration.xmlconfig import string as zcstring
+
+
+def get_zcml_conf(xml_code):
+    """Get a working ZCML configuration file with `xml_code` embedded.
+
+    The returned ZCML declares an ikoba namespace for local ZCML
+    extensions and includes the `waeup.ikoba.meta` declarations before
+    embedding `xml_code`.
+
+    The returned string can be 'executed' with `string` or `file` from
+    `zope.configuration.xmlconfig.
+    """
+    config = (
+        '<configure '
+        '   xmlns="http://namespaces.zope.org/zope"'
+        '   xmlns:ikoba="http://namespaces.waeup.org/ikoba"'
+        '   i18n_domain="waeup.ikoba"'
+        '   package="waeup.ikoba.tests"'
+        '>'
+        '<include package="waeup.ikoba" file="meta.zcml" />'
+        ''
+        '%s'
+        ''
+        '</configure>'
+        ) % xml_code
+    return config
+
+
+class ZCMLTests(unittest.TestCase):
+
+    def setUp(self):
+        self.workdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self.workdir)
+        # unregister any remaining utils registered during tests
+        gsm = getGlobalSiteManager()
+        for iface in (IDataCenterConfig, IPayPalConfig):
+            conf = queryUtility(iface)
+            if conf is None:
+                continue
+            gsm.unregisterUtility(conf, iface)
+
+    def test_datacenter_config_directive(self):
+        # the 'datacenter' directive can be used in ZCML
+        assert queryUtility(IDataCenterConfig) is None
+        zcfile("sample.zcml", tests)  # 'execute' the ZCML
+        result = getUtility(IDataCenterConfig)
+        assert result == {'path': u'/some/path'}
+
+    def test_datacenter_config_singleton(self):
+        # we can define only one datacenter config
+        config = get_zcml_conf(
+            '<ikoba:datacenter path="/some/path" />'
+            '<ikoba:datacenter path="/other/path" />'
+            )
+        assert queryUtility(IDataCenterConfig) is None
+        self.assertRaises(
+            ConfigurationError, zcstring, config)
+
+    def test_paypal_config_directive(self):
+        # the 'paypalconf' ZCML directive works
+        assert queryUtility(IPayPalConfig) is None
+        zcfile("sample.zcml", tests)  # 'execute' the ZCML file
+        result = getUtility(IPayPalConfig)
+        assert result == {'path': u'/other/path'}
+
+    def test_paypal_config_singleton(self):
+        # we can define only one paypal config
+        config = get_zcml_conf(
+            '<ikoba:paypalconf path="/some/path" />'
+            '<ikoba:paypalconf path="/other/path" />'
+            )
+        assert queryUtility(IPayPalConfig) is None
+        self.assertRaises(
+            ConfigurationError, zcstring, config)
Index: /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/zcml.py
===================================================================
--- /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/zcml.py	(revision 11991)
+++ /main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/zcml.py	(revision 11992)
@@ -17,5 +17,5 @@
 ##
 from zope.component.zcml import handler
-from waeup.ikoba.interfaces import IDataCenterConfig
+from waeup.ikoba.interfaces import IDataCenterConfig, IPayPalConfig
 
 def data_center_conf(context, path):
@@ -49,2 +49,14 @@
                 {'path':path}, IDataCenterConfig, '')
         )
+
+
+def paypal_conf(context, path):
+    """Handler for ZCML paypalconf directive.
+    """
+    context.action(
+        discriminator = ('utility', IPayPalConfig, ''),
+        callable = handler,
+        args = (
+            'registerUtility',
+            {'path': path}, IPayPalConfig, '')
+        )
