--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeGenconfmlPlugin/genconfmlplugin/genconfmlplugin.py Thu Mar 11 17:04:37 2010 +0200
@@ -0,0 +1,401 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+'''
+GenConfml plugin for ConE
+'''
+
+import re
+import os
+import sys
+import logging
+import xml.parsers.expat
+import confflattener
+import xslttransformer
+import codecs
+import tempfile
+import tempfile
+
+try:
+ from cElementTree import ElementTree
+except ImportError:
+ try:
+ from elementtree import ElementTree
+ except ImportError:
+ try:
+ from xml.etree import cElementTree as ElementTree
+ except ImportError:
+ from xml.etree import ElementTree
+
+import __init__
+
+from cone.public import exceptions,plugin,utils,api
+from cone.confml import persistentconfml
+
+class GenconfmlImpl(plugin.ImplBase):
+ """
+ GenConfml plugin implementation
+ """
+
+ IMPL_TYPE_ID = "gcfml"
+
+
+ def __init__(self,ref,configuration, output='output', linesep=os.linesep, reader=None):
+ """
+ Overloading the default constructor
+ """
+ plugin.ImplBase.__init__(self,ref,configuration)
+ self.logger = logging.getLogger('cone.gcfml(%s)' % self.ref)
+ self.errors = False
+ self.xstl_etree = None
+ self.xslt_temp_file_name = os.path.join(tempfile.gettempdir(), "genconfml_temp_%i.xslt" % os.getpid())
+ self.set_output_root(output)
+ self.linesep = linesep
+ self._flatconfig = None
+ self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
+ self.reader = reader
+
+ def generate(self, context=None):
+ """
+ Generate the given implementation.
+ """
+ self.create_output()
+ return
+
+ def get_refs(self):
+ result = []
+ for ref in self.reader.settings:
+ # Process the reference, so that it will work with has_ref().
+ # E.g. 'MyFeature/MySetting' -> 'MyFeature.MySetting'
+ # 'MyFeature/* -> 'MyFeature'
+ ref = ref.replace('/', '.')
+ if ref.endswith('.*'):
+ ref = ref[:-2]
+ result.append(ref)
+ return result
+
+ def list_output_files(self):
+ """ Return a list of output files as an array. """
+ return [self.get_output_filename()]
+
+ def get_output_filename(self):
+ """ Return a output file name. """
+
+ name = self.reader.name
+ if name == None: name = ""
+ target = self.reader.target
+ if target == None: target = ""
+ output = self.output
+ if self.output == None: output = ""
+
+ # Make sure that target file is generated under output
+ target = utils.resourceref.remove_begin_slash(utils.resourceref.norm(target))
+ subdir = self.reader.subdir
+ if subdir == None:
+ self.output_subdir = subdir
+ output_file = os.path.normpath(os.path.join(output, target, name))
+
+ return output_file
+
+ def create_output(self, layers=None):
+ """ Generate all output """
+ resource = self.configuration.get_resource(self.ref)
+ write_element_enc(self.reader.stylesheet_elem, self.xslt_temp_file_name, self.reader.stylesheet_output_enc)
+ gen = Generator()
+
+ target = self.reader.target
+ if target == None: target = ""
+
+ output_file = self.get_output_filename()
+ # Don't create the dirs here, since the output file may be filtered out
+ # if it is empty
+ #if not os.path.exists(os.path.dirname(output_file)):
+ # os.makedirs(os.path.dirname(output_file))
+
+ self.logger.info('Generating %s' % output_file)
+
+ flatted_conf_as_element = persistentconfml.ConfmlWriter().dumps(self.flatconfig)
+ postprocessed_element = self.post_process_flattening(flatted_conf_as_element)
+ write_element_enc(postprocessed_element, self.temp_confml_file, self.reader.stylesheet_output_enc)
+ gen.generate(self.configuration, resource, output_file, self.xslt_temp_file_name, self.reader.settings, self.reader.stylesheet_output_enc)
+
+ def post_process_flattening(self, element):
+ """
+ Pick just data element and build document out of it
+ """
+
+ data_element = element.find("data")
+ if data_element == None:
+ self.logger.warning('No data to generate!!')
+ new_doc = "<?xml version=\"1.0\"?><configuration>" + "</configuration>"
+ else:
+ new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>"
+ return ElementTree.fromstring(new_doc)
+
+ @property
+ def flatconfig(self):
+ """
+ Create a flat configuration from the current configuration with the given setting refs.
+ Take the last configuration element, which will contain the data elements
+ """
+ if not self._flatconfig:
+ try:
+ cf = confflattener.ConfigurationFlattener()
+ self._flatconfig = api.Configuration()
+ cf.flat(self.configuration, self.reader.settings, self._flatconfig)
+ except (exceptions.ConeException, TypeError, Exception), e:
+ utils.log_exception(self.logger, 'Failed to flat configuration with settings %s. Exception: %s' % (self.reader.settings, e))
+ raise exceptions.ConeException('Failed to flat configuration. Exception: %s' % e)
+ return self._flatconfig
+
+
+def write_element(element, output, linesep=os.linesep):
+ """
+ """
+ if element != None and ElementTree.iselement(element):
+ enc = None
+
+
+ try:
+ out_file = open(output, 'w')
+ out_string = ElementTree.tostring(element)
+ out_string = out_string.replace('\r\n', linesep)
+ out_string = out_string.replace('\n', linesep)
+ out_file.write(out_string)
+ out_file.close()
+ except Exception, e:
+ raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ else:
+ raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.')
+
+def remove_namespace(doc, namespace):
+ """Remove namespace in the passed document in place."""
+ ns = u'{%s}' % namespace
+ nsl = len(ns)
+ for elem in doc.getiterator():
+ if elem.tag.startswith(ns):
+ elem.tag = elem.tag[nsl:]
+
+def write_element_enc(element, output, enc, linesep=os.linesep):
+ """
+ Writes element to file
+ """
+ if element != None and ElementTree.iselement(element):
+ enc = None
+
+
+ try:
+ remove_namespace(element, 'http://www.s60.com/xml/genconfml/1')
+
+
+ out_file = codecs.open(output, 'w', enc)
+ output_string = ElementTree.tostring(element)
+ output_string = output_string.replace('\r\n', linesep)
+ output_string = output_string.replace('\n', linesep)
+ out_file.write(output_string)
+ out_file.close()
+ except Exception, e:
+ raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ else:
+ raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.')
+
+
+def write_element_tempfile(element, tempfile):
+ """
+ Writes element to temp file
+ """
+ if element != None and ElementTree.iselement(element):
+
+ try:
+ tempfile.write(ElementTree.tostring(element))
+ except Exception, e:
+ raise exceptions.ConeException('Cannot write Element to file (%s). Exception: %s' % (output, e))
+ else:
+ raise exceptions.ConeException('Cannot write element to file, because None element passed or not Element passed.')
+
+class GenconfmlImplReader(plugin.ReaderBase):
+ """
+ Parses a single gcfml file
+ """
+ NAMESPACE = 'http://www.s60.com/xml/genconfml/1'
+ IGNORED_NAMESPACES = ['http://www.w3.org/1999/XSL/Transform',
+ 'http://www.w3.org/2001/xinclude']
+ FILE_EXTENSIONS = ['gcfml']
+
+ def __init__(self):
+ self.stylesheet = None
+ self.namespaces = self.IGNORED_NAMESPACES + [self.NAMESPACE]
+ self.settings = None
+ self.name = None
+ self.subdir = None
+ self.target = None
+ self.stylesheet_elem = None
+ self.stylesheet_output_enc = None
+ self.nss = None
+
+ @classmethod
+ def read_impl(cls, resource_ref, configuration, etree):
+
+ reader = GenconfmlImplReader()
+ reader.from_etree(etree)
+ return GenconfmlImpl(resource_ref, configuration, reader=reader)
+
+ def from_etree(self, etree):
+ self.stylesheet = self.parse_stylesheet(etree)
+ self.settings = self.parse_settings(etree)
+ self.name = self.parse_name(etree)
+ self.subdir = self.parse_subdir(etree)
+ self.target = self.parse_target(etree)
+ self.stylesheet_elem = self.parse_stylesheet_elem(etree)
+ self.stylesheet_output_enc = self.parse_stylesheet_output_enc(etree)
+ self.nss = self.parse_stylesheet_nss(etree)
+
+ return
+
+ def parse_target(self, etree):
+ """
+ Parses target from etree
+ """
+
+ target = ""
+ for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
+ if elem != None:
+ target = elem.get('target')
+
+ return target
+
+ def parse_name(self, etree):
+ """
+ Parses name from etree
+ """
+
+ name = ""
+ for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
+ if elem != None:
+ name = elem.get('name')
+
+ return name
+
+ def parse_subdir(self, etree):
+ """
+ Parses subdir from etree
+ """
+
+ subdir = ""
+ for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
+ if elem != None:
+ subdir = elem.get('subdir')
+ if subdir == None:
+ subdir = ""
+
+ return subdir
+
+
+ def parse_stylesheet(self,etree):
+ """
+ Parses stylesheet from getree
+ """
+
+ stylesheet = ""
+ stylesheet_elem = etree.find("{%s}stylesheet" % self.namespaces[0])
+ if stylesheet_elem != None:
+ stylesheet = ElementTree.tostring(stylesheet_elem)
+ return stylesheet
+
+ def parse_stylesheet_output_enc(self, etree):
+ enc = ""
+ ss_elem = etree.find("{%s}stylesheet" % self.namespaces[0])
+ if ss_elem != None:
+ children = ss_elem.getchildren()
+ for child in children:
+ if child.tag == '{%s}output' % self.namespaces[0]:
+ enc = child.attrib.get('encoding')
+ return enc
+
+ def parse_stylesheet_nss(self, etree):
+ nss = None
+
+ for elem in etree.getiterator():
+ name = elem.tag
+ if name[0] == "{":
+ uri, tag = name[1:].split("}")
+ if tag == "stylesheet":
+ nss = uri
+ return nss
+
+ def parse_stylesheet_elem(self,etree):
+ """
+ Parses stylesheet element from getree
+ """
+
+ return etree.find("{%s}stylesheet" % self.namespaces[0])
+
+ def parse_settings(self,etree):
+ """
+ Parses settings from etree
+ """
+
+ settings = []
+
+ for elem in etree.getiterator("{%s}file" % self.namespaces[2]):
+ if elem != None:
+ setting_elems = elem.findall("{%s}setting" % self.namespaces[2])
+ for setting_elem in setting_elems:
+ if setting_elem != None:
+ settings.append(setting_elem.get('ref'))
+
+ return settings
+
+class Generator(object):
+ """
+ Genconfml generator
+ """
+ def __init__(self):
+ self.temp_confml_file = os.path.join(tempfile.gettempdir(),'temp_flatted_%i.confml' % os.getpid())
+ pass
+
+ def post_process_flattening(self, element):
+ """
+ Pick just data element and build document out of it
+ """
+
+ data_element = element.find("data")
+ if data_element == None:
+ self.logger.warning('No data to generate!!')
+ new_doc = "<?xml version=\"1.0\"?><configuration>" + "</configuration>"
+ else:
+ new_doc = "<?xml version=\"1.0\"?><configuration>" + ElementTree.tostring(data_element) + "</configuration>"
+ return ElementTree.fromstring(new_doc)
+
+
+ def generate(self, configuration, input, output, xslt, settings, enc=sys.getdefaultencoding()):
+ """
+ Generates output
+ """
+ self.logger = logging.getLogger('cone.gcfml{%s}' % input.path)
+
+
+ try:
+ tf = xslttransformer.XsltTransformer()
+ tf.transform_lxml(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
+ #tf.transform_4s(os.path.abspath(self.temp_confml_file), os.path.abspath(xslt), output, enc)
+ except (exceptions.ConeException, TypeError, Exception), e:
+ logging.getLogger('cone.gcfml').warning('Failed to do XSLT tranformation. Exception: %s' % e)
+ raise exceptions.ConeException('Failed to do XSLT tranformation. Exception: %s' % e)
+
+ """ Removes template files """
+ if not logging.getLogger('cone').getEffectiveLevel() != 10:
+ os.remove(os.path.abspath(self.temp_confml_file))
+ os.remove(os.path.abspath(xslt))