From 9152d2f4973f272f6c78a5cdd834a24fc469e4f8 Mon Sep 17 00:00:00 2001
From: Nicolas Delaby <nicolas@nexedi.com>
Date: Thu, 27 Oct 2011 12:41:43 +0200
Subject: [PATCH] Allows to install custom font, from http location

Configuration sample:
<parameter id="cloudooo-json">{"font_url_list": ["http://example.com/my_font.ttf"]}</parameter>
---
 setup.py                                      |  2 +
 slapos/recipe/fontconfig/__init__.py          | 85 +++++++++++++++++++
 .../template/fontconfig-snippet.cfg.in        |  1 +
 .../fontconfig/template/fontconfig.cfg.in     |  5 ++
 .../template/onetimedownload_run.in           |  4 +
 slapos/recipe/generate_cloudooo.py            | 59 +++++++++++++
 .../generic_cloudooo/template/cloudooo.cfg.in |  1 +
 software/erp5/instance-cloudooo.cfg           | 11 +++
 software/erp5/instance-erp5-development.cfg   |  2 +
 software/erp5/instance-erp5-production.cfg    |  2 +
 software/erp5/instance.cfg                    |  7 +-
 software/erp5/snippet-fontconfig.cfg          |  2 +
 software/erp5/software.cfg                    | 15 +++-
 stack/erp5.cfg                                |  1 +
 14 files changed, 192 insertions(+), 5 deletions(-)
 create mode 100644 slapos/recipe/fontconfig/__init__.py
 create mode 100644 slapos/recipe/fontconfig/template/fontconfig-snippet.cfg.in
 create mode 100644 slapos/recipe/fontconfig/template/fontconfig.cfg.in
 create mode 100644 slapos/recipe/fontconfig/template/onetimedownload_run.in
 create mode 100644 slapos/recipe/generate_cloudooo.py
 create mode 100644 software/erp5/snippet-fontconfig.cfg

diff --git a/setup.py b/setup.py
index 6e46d3546..1a3a66e2a 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ setup(name=name,
           'erp5testnode = slapos.recipe.erp5testnode:Recipe',
           'helloworld = slapos.recipe.helloworld:Recipe',
           'generic.cloudooo = slapos.recipe.generic_cloudooo:Recipe',
+          'fontconfig = slapos.recipe.fontconfig:Recipe',
           'java = slapos.recipe.java:Recipe',
           'kumofs = slapos.recipe.kumofs:Recipe',
           'generic.kumofs = slapos.recipe.generic_kumofs:Recipe',
@@ -89,6 +90,7 @@ setup(name=name,
           'generic.zope = slapos.recipe.generic_zope:Recipe',
           'generic.zope.zeo.client = slapos.recipe.generic_zope_zeo_client:Recipe',
           'generate.erp5.tidstorage = slapos.recipe.generate_erp5_tidstorage:Recipe',
+          'generate.cloudooo = slapos.recipe.generate_cloudooo:Recipe',
           'zeo = slapos.recipe.zeo:Recipe',
           'tidstorage = slapos.recipe.tidstorage:Recipe',
           'erp5.update = slapos.recipe.erp5_update:Recipe',
diff --git a/slapos/recipe/fontconfig/__init__.py b/slapos/recipe/fontconfig/__init__.py
new file mode 100644
index 000000000..c60e42b5a
--- /dev/null
+++ b/slapos/recipe/fontconfig/__init__.py
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+from slapos.recipe.librecipe import GenericBaseRecipe
+import pkg_resources
+import os
+import zc.buildout
+
+class Recipe(GenericBaseRecipe):
+  """
+  fontconfig instance configuration.
+
+  conf-path -- location of the configuration file
+
+  font-system-folder -- fonts installed by software release
+
+  font-folder -- location where to download fonts
+
+  url-list -- From where to download fonts
+  """
+
+  def install(self):
+    created_file_list = []
+    font_folder = self.options['font-folder']
+    service_folder = self.options['service-folder']
+    snippet_filename = self.getTemplateFilename(
+                                    'fontconfig-snippet.cfg.in')
+    font_snippet_list = [self.substituteTemplate(snippet_filename,
+                    dict(font_folder_path=self.options['font-system-folder']))]
+    font_snippet_list.append(self.substituteTemplate(snippet_filename,
+                                           dict(font_folder_path=font_folder)))
+
+    config = dict(
+        font_folder_path_snippet=''.join(font_snippet_list),
+        )
+    template_filename = self.getTemplateFilename('fontconfig.cfg.in')
+    configuration_path = self.createFile(
+        self.options['conf-path'],
+        self.substituteTemplate(template_filename, config))
+
+    created_file_list.append(configuration_path)
+    # Instanciate onetimedownloads, one for each url
+    wrapper_template_location = pkg_resources.resource_filename(
+                                        __name__, os.path.join(
+                                        'template', 'onetimedownload_run.in'))
+
+    onetimedownload_config = {}
+    onetimedownload_config.update(self.options)
+    for index, url in enumerate(self.options['url-list'].split()):
+      if not url.strip():
+        continue
+      bin_path = os.path.join(service_folder, 'onetimedownload%s' % index)
+      file_path = os.path.join(font_folder, '%s' % index)
+      onetimedownload_config['url'] = url
+      onetimedownload_config['file_path'] = file_path
+      onetimedownload_runner_path = self.createExecutable(bin_path,
+          self.substituteTemplate(wrapper_template_location, 
+                                  onetimedownload_config))
+
+      created_file_list.append(onetimedownload_runner_path)
+
+    return created_file_list
diff --git a/slapos/recipe/fontconfig/template/fontconfig-snippet.cfg.in b/slapos/recipe/fontconfig/template/fontconfig-snippet.cfg.in
new file mode 100644
index 000000000..adfb6a2a4
--- /dev/null
+++ b/slapos/recipe/fontconfig/template/fontconfig-snippet.cfg.in
@@ -0,0 +1 @@
+<dir>%(font_folder_path)s</dir>
diff --git a/slapos/recipe/fontconfig/template/fontconfig.cfg.in b/slapos/recipe/fontconfig/template/fontconfig.cfg.in
new file mode 100644
index 000000000..c6799d21d
--- /dev/null
+++ b/slapos/recipe/fontconfig/template/fontconfig.cfg.in
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+%(font_folder_path_snippet)s
+</fontconfig>
\ No newline at end of file
diff --git a/slapos/recipe/fontconfig/template/onetimedownload_run.in b/slapos/recipe/fontconfig/template/onetimedownload_run.in
new file mode 100644
index 000000000..0060b06c0
--- /dev/null
+++ b/slapos/recipe/fontconfig/template/onetimedownload_run.in
@@ -0,0 +1,4 @@
+#!/bin/sh
+# BEWARE: This file is operated by slapgrid
+# BEWARE: It will be overwritten automatically
+exec %(onetimedownload_path)s "%(url)s" "%(file_path)s"
diff --git a/slapos/recipe/generate_cloudooo.py b/slapos/recipe/generate_cloudooo.py
new file mode 100644
index 000000000..6c7881446
--- /dev/null
+++ b/slapos/recipe/generate_cloudooo.py
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+from slapos.recipe.librecipe import GenericSlapRecipe
+import os
+import json
+import traceback
+
+
+class Recipe(GenericSlapRecipe):
+  def _options(self, options):
+    self.dirname = os.path.join(self.buildout['buildout']['parts-directory'],
+                                self.name)
+    options['output'] = os.path.join(self.dirname, self.name + '.cfg')
+
+  def _generateRealTemplate(self):
+    # TODO check json against schema
+    json_data = json.loads(self.parameter_dict['cloudooo-json'])
+    # dymanic fonts
+    font_url_list = json_data.get('font_url_list', [])
+    fontconfig_template = open(self.options['template']).read()
+    fontconfig = open(self.options['snippet-fontconfig']).read()
+    fontconfig_extension = fontconfig % dict(font_url_list=' '.join(font_url_list))
+    with open(self.options['output'], 'w') as f:
+      f.write(fontconfig_template + fontconfig_extension)
+
+  def _install(self):
+    if not os.path.exists(self.dirname):
+      os.mkdir(self.dirname)
+    if "cloudooo-json" in self.parameter_dict:
+      try:
+        self._generateRealTemplate()
+      except Exception:
+        print 'Ignored issue during template generation:\n%s' % \
+          traceback.format_exc()
+    return [self.dirname]
diff --git a/slapos/recipe/generic_cloudooo/template/cloudooo.cfg.in b/slapos/recipe/generic_cloudooo/template/cloudooo.cfg.in
index 17ead81aa..156f7e4ae 100644
--- a/slapos/recipe/generic_cloudooo/template/cloudooo.cfg.in
+++ b/slapos/recipe/generic_cloudooo/template/cloudooo.cfg.in
@@ -34,6 +34,7 @@ application_hostname = %(ip)s
 openoffice_port = %(openoffice_port)s
 # LD_LIBRARY_PATH passed to OpenOffice
 env-LD_LIBRARY_PATH = %(LD_LIBRARY_PATH)s
+env-FONTCONFIG_FILE = %(FONTCONFIG_FILE)s
 
 #
 # Mimetype Registry
diff --git a/software/erp5/instance-cloudooo.cfg b/software/erp5/instance-cloudooo.cfg
index 480863541..894530fed 100644
--- a/software/erp5/instance-cloudooo.cfg
+++ b/software/erp5/instance-cloudooo.cfg
@@ -28,6 +28,7 @@ data-directory = $${directory:cloudooo-data}
 
 environment =
   LD_LIBRARY_PATH = ${file:location}/lib:${fontconfig:location}/lib:${freetype:location}/lib:${libICE:location}/lib:${libSM:location}/lib:${libX11:location}/lib:${libXau:location}/lib:${libXdmcp:location}/lib:${libXext:location}/lib:${libXinerama:location}/lib:${libxcb:location}/lib:${zlib:location}/lib
+  FONTCONFIG_FILE = $${fontconfig-instance:conf-path}
 
 # Binary information
 # cloudooo specific configuration
@@ -35,6 +36,15 @@ ooo-binary-path = ${libreoffice-bin:location}/program
 ooo-paster = ${buildout:bin-directory}/cloudooo_paster
 ooo-uno-path = ${libreoffice-bin:location}/basis-link/program
 
+[fontconfig-instance]
+recipe = slapos.cookbook:fontconfig
+conf-path = $${rootdirectory:etc}/font.conf
+font-system-folder = ${fonts:location}
+font-folder = $${directory:font}
+url-list = $${dynamic-fontconfig-instance:url-list}
+service-folder = $${basedirectory:services}
+onetimedownload_path = ${buildout:bin-directory}/onetimedownload
+
 # rest of parts are candidates for some generic stuff
 [basedirectory]
 recipe = slapos.cookbook:mkdirectory
@@ -43,6 +53,7 @@ services = $${rootdirectory:etc}/run
 [directory]
 recipe = slapos.cookbook:mkdirectory
 cloudooo-data = $${rootdirectory:srv}/cloudooo
+font = $${rootdirectory:srv}/font
 
 [rootdirectory]
 recipe = slapos.cookbook:mkdirectory
diff --git a/software/erp5/instance-erp5-development.cfg b/software/erp5/instance-erp5-development.cfg
index 949f60b29..8e39ad782 100644
--- a/software/erp5/instance-erp5-development.cfg
+++ b/software/erp5/instance-erp5-development.cfg
@@ -99,6 +99,8 @@ software-type = mariadb
 [request-cloudooo]
 <=request-common
 name = Cloudooo
+config = cloudooo-json
+config-cloudooo-json = $${slap-parameter:cloudooo-json}
 software-type = cloudooo
 
 [request-memcached]
diff --git a/software/erp5/instance-erp5-production.cfg b/software/erp5/instance-erp5-production.cfg
index 5f28751b2..eeffa9b4e 100644
--- a/software/erp5/instance-erp5-production.cfg
+++ b/software/erp5/instance-erp5-production.cfg
@@ -43,6 +43,8 @@ software-type = mariadb
 [request-cloudooo]
 <=request-common
 name = Cloudooo
+config = cloudooo-json
+config-cloudooo-json = $${slap-parameter:cloudooo-json}
 software-type = cloudooo
 
 [request-memcached]
diff --git a/software/erp5/instance.cfg b/software/erp5/instance.cfg
index 0f081a502..8abb090d5 100644
--- a/software/erp5/instance.cfg
+++ b/software/erp5/instance.cfg
@@ -17,13 +17,18 @@ snippet-zope = ${template-snippet-zope:output}
 snippet-master = ${template-snippet-master:output}
 snippet-backend = ${template-snippet-backend:output}
 
+[dynamic-template-cloudooo]
+recipe = slapos.cookbook:generate.cloudooo
+template = ${template-cloudooo:output}
+snippet-fontconfig = ${template-snippet-fontconfig:output}
+
 [switch-softwaretype]
 recipe = slapos.cookbook:softwaretype
 default = ${template-erp5-development:output}
 production = ${template-erp5-production:output}
 kumofs = ${template-kumofs:output}
 memcached = ${template-memcached:output}
-cloudooo = ${template-cloudooo:output}
+cloudooo = $${dynamic-template-cloudooo:output}
 zope = ${template-zope:output}
 mariadb = ${template-mariadb:output}
 sphinx = ${template-sphinx:output}
diff --git a/software/erp5/snippet-fontconfig.cfg b/software/erp5/snippet-fontconfig.cfg
new file mode 100644
index 000000000..7d99ce0c7
--- /dev/null
+++ b/software/erp5/snippet-fontconfig.cfg
@@ -0,0 +1,2 @@
+[dynamic-fontconfig-instance]
+url-list = %(font_url_list)s
diff --git a/software/erp5/software.cfg b/software/erp5/software.cfg
index d926f73a6..1bed9c7e1 100644
--- a/software/erp5/software.cfg
+++ b/software/erp5/software.cfg
@@ -66,10 +66,17 @@ mode = 0644
 [template-cloudooo]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance-cloudooo.cfg
-md5sum = 55fb694f0fb6193156b7d26ff40882a9
+md5sum = 8ea2839e951f26af2bc74b9a8c0fa5c2
 output = ${buildout:directory}/template-cloudooo.cfg
 mode = 0644
 
+[template-snippet-fontconfig]
+recipe = slapos.recipe.template
+url = ${:_profile_base_location_}/snippet-fontconfig.cfg
+md5sum = 76c5d4cd1c8d48648684d9873f1ffed3
+output = ${buildout:directory}/template-snippet-fontconfig.cfg
+mode = 0644
+
 [template-kumofs]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance-kumofs.cfg
@@ -80,7 +87,7 @@ mode = 0644
 [template]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance.cfg
-md5sum = 877b508ff60f74d3915b638c6ea4f241
+md5sum = 961d404f5726fce7c4d8b34d7e120077
 output = ${buildout:directory}/template.cfg
 mode = 0644
 
@@ -94,14 +101,14 @@ mode = 0644
 [template-erp5-development]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance-erp5-development.cfg
-md5sum = 79216b0c413b373b0dbe00220a0fbaf9
+md5sum = 1b62acfe42d7992df81cef8d7999349a
 output = ${buildout:directory}/template-erp5-development.cfg
 mode = 0644
 
 [template-erp5-production]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/instance-erp5-production.cfg
-md5sum = 09d278f233e8a8a9ad84c46f8ce7faf9
+md5sum = 452bad01b27bf2a97739920a41aac7f3
 output = ${buildout:directory}/template-erp5-production.cfg
 mode = 0644
 
diff --git a/stack/erp5.cfg b/stack/erp5.cfg
index 9e9348028..49f0bb6cb 100644
--- a/stack/erp5.cfg
+++ b/stack/erp5.cfg
@@ -395,6 +395,7 @@ eggs =
 
 scripts =
   killpidfromfile = slapos.systool:killpidfromfile
+  onetimedownload = slapos.toolbox:onetimedownload
 
 [cloudooo]
 recipe = zc.recipe.egg
-- 
2.30.9