configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py	Thu Mar 11 17:04:37 2010 +0200
@@ -0,0 +1,665 @@
+#
+# 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: 
+#
+'''
+Convert project ConE plugin
+'''
+
+import re
+import os
+import sys
+import logging
+import xml.parsers.expat
+import shutil
+import fnmatch
+
+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.storage import filestorage
+from cone.public import exceptions,plugin,utils,api
+
+class ConvertProjectImpl(plugin.ImplBase):
+    """
+    Class to implements ConE plugin that convert old configuration to
+    configuration project. Some extra functions supported in the top
+    of normal file copying functions. For example creation of layer and
+    configuration root files automatically. 
+    """
+    
+    IMPL_TYPE_ID = "convertprojectml"
+    
+    
+    def __init__(self,ref,configuration):
+        """
+        Overloading the default constructor
+        """
+        plugin.ImplBase.__init__(self,ref,configuration)
+        self.desc = ""
+        self.logger = logging.getLogger('cone.convertprojectml(%s)' % self.ref)
+        self.errors = False
+        
+        #Internal plugin data
+        self.project_data = {}
+        self.layers = []
+
+    def generate(self, context=None):
+        """
+        Generate the given implementation.
+        """
+        
+        #Generating content
+        fullOutputPath = self.output
+        if self.project_data.has_key("path"): 
+            targetPath = utils.resourceref.norm(self.project_data["path"])
+            if targetPath and targetPath != "":
+                fullOutputPath = os.path.join(fullOutputPath, targetPath)             
+        
+        fs = filestorage.FileStorage(fullOutputPath, "w")
+        newProject = api.Project(fs)        
+        for layer in self.layers:
+            layer.generate(newProject, self.configuration.get_storage().get_path())        
+        newProject.close()
+        
+        #Opening project again to validate the content and remove illegal includes.
+        if self.project_data.has_key("validate") and self.project_data["validate"] != "false":            
+            fs = filestorage.FileStorage(fullOutputPath, "w")
+            validateProject = api.Project(fs)
+            for conf in validateProject.list_configurations():
+                validateProject.get_configuration(conf).list_all_configurations()
+            validateProject.close()
+        
+        return 
+    
+    def generate_layers(self,layers):
+        """
+        Generate the given Configuration layers.
+        """
+        self.logger.info('Generating layers %s' % layers)
+        self.generate()
+        
+        return 
+    
+    def has_ref(self,ref):
+        """
+        @returns True if the implementation uses the given ref as input value.
+        Otherwise return False.
+        """
+        
+        return None
+
+#=================================================================
+class ConvertProjectLayer(object):
+    """
+    Object presenting layer in convertprojectml file.
+    """
+    
+    def __init__(self, path):
+        if path != None:
+            self.path = path
+        else:
+            self.path = ""
+        self.folders = []
+        self.files = []        
+
+    def __str__(self):
+        retStr = ""
+        retStr += "\nPath: %s\n" % self.path
+        retStr +="Folders:\n"        
+        for folder in self.folders: 
+            retStr += folder.__str__()
+        retStr +="Files:\n"
+        for file in self.files:
+            retStr += file.__str__()    
+        return retStr
+    
+    def generate(self, project, old_structure_root):
+        """
+        Function to handle generation to one folder.
+        """
+        
+        #Create layer folder.
+        project.get_storage().create_folder(utils.resourceref.norm(self.path))
+        #print "Created Layer:", utils.resourceref.norm(self.path)
+        
+        for folder in self.folders:
+            folder.generate(project, old_structure_root)
+        
+        for f in self.files:
+            f.generate(project, old_structure_root)
+        
+        return
+    
+    def addFolder(self, folder):
+        self.folders.append(folder)
+
+    def addFile(self, file):
+        self.files.append(file)
+
+    def getProjectPath(self):
+        return self.path
+
+                
+class ConvertProjectFolder(object):
+    """
+    Object presenting folder in convertprojectml file.
+    """
+        
+    def __init__(self, path, parent=None):
+        if path != None:
+            self.path = path
+        else:
+            self.path = ""        
+        self.filters = []
+        self.parent = parent
+
+    def __str__(self):
+        retStr = ""
+        retStr += "\tPath: %s\n" % self.path
+        retStr +="\tFilters:\n"
+        for filter in self.filters: 
+            retStr += filter.__str__()
+        return retStr 
+    
+    def generate(self, project, old_structure_root):
+        
+        #Adding new folder to project.
+        project.get_storage().create_folder(utils.resourceref.norm(self.getProjectPath()))
+        #print "Created folder:", utils.resourceref.norm(self.getProjectPath())
+        
+        for filter in self.filters:
+            filter.generate(project, old_structure_root, "folder")
+        return
+    
+    def addFilter(self, filter):
+        self.filters.append(filter)
+
+    def getProjectPath(self):
+        return os.path.join(self.parent.getProjectPath(), self.path)
+    
+class ConvertProjectFile(object):
+    """
+    Object presenting file in convertprojectml file.
+    """
+        
+    def __init__(self, path, type, parent=None):
+        if path != None:
+            self.path = path
+        else:
+            self.path = ""
+        if type != None:
+            self.type = type
+        else:
+            self.type = ""        
+            
+        self.filters = []
+        self.parent = parent
+        self.meta = []
+        self.desc = ""
+        
+    def __str__(self):
+        retStr = ""
+        retStr += "\tPath: %s\n" % self.path
+        retStr += "\tType: %s\n" % self.type
+        retStr +="\tFilters:\n"
+        for filter in self.filters:
+            retStr += filter.__str__()
+        return retStr             
+
+    def generate(self, project, old_structure_root):
+        for filter in self.filters:            
+            filter.generate(project, old_structure_root, self.type)                        
+
+        if self.type == "configuration_root":
+            #Adding metadata                
+            config = project.get_configuration(utils.resourceref.norm(self.path))
+            if self.meta:                
+                if not config.meta:
+                    config.meta = []
+                for meta in self.meta:
+                    config.meta.add(meta[0], meta[1], meta[2], meta[3])                        
+            if self.desc:
+                config.desc = self.desc
+                
+            config.save()                    
+        return
+
+    def addFilter(self, filter):
+        self.filters.append(filter)
+
+    def addMeta(self, meta):
+        self.meta = meta
+
+    def addDescription(self, desc):
+        self.desc = desc
+
+    def getProjectPath(self):
+        return os.path.join(self.parent.getProjectPath(), self.path)
+
+class ConvertProjectFilter(object):
+    """
+    Object presenting filter in convertprojectml file.
+    """
+        
+    def __init__(self, action, data, parent=None, remove_includes = "false", recursive = "false"):
+        self.action = action
+        self.data = data
+        self.parent = parent
+        if remove_includes:
+            self.remove_includes = remove_includes
+        else:
+            self.remove_includes = "false"
+        if recursive:
+            self.recursive = recursive
+        else:
+             self.recursive = "false"
+
+    def __str__(self):
+        retStr = ""
+        retStr += "\t\tAction: %s\n" % self.action
+        retStr += "\t\tData: %s\n" % self.data
+        return retStr    
+        
+    def generate(self, project, old_structure_root, type="none"):
+        """
+        @param project: New configuration project
+        @type project:
+        @param old_structure_root: Path to old projects root.
+        @type old_structure_root:
+        
+        """
+               
+        if type == "" or type == "folder":
+            self.handleAddRemove(project, old_structure_root)
+        elif type == "layer_root":
+            self.handleLayerRoot(project)
+        elif type == "configuration_root":
+            self.handleConfigurationRoot(project)
+        else:
+            #raise exceptions.NotSupportedException("Type: %s not supported as file type" % repr(type))
+            pass            
+        return
+
+    def handleAddRemove(self, project, old_structure_root):
+        """
+        """
+        
+        pathPart, wildCardPart = self.separatePathAndWildcard(self.data)
+        filesToProcess = []
+        if wildCardPart == "":
+            #No wildcards found.
+            if self.recursive == "false":
+                source = os.path.join(old_structure_root, pathPart)
+                targetDir = self.resolveTargetDir(project, source)                
+                filesToProcess.append({"source": source, "targetDir": targetDir})                
+            else:
+            #recursive search for directory entries.               
+                directoryPath = os.path.join(old_structure_root, pathPart)
+                if os.path.isdir(directoryPath):
+                    for root, dirs, files in os.walk(directoryPath):
+                        for f in files:
+                            #Handling files.
+                            source = os.path.join(root, f)
+                            targetDir = self.resolveTargetDir(project, source)                
+                            filesToProcess.append({"source": source, "targetDir": targetDir})
+                        
+                        for d in dirs:
+                            #Handling directories to get empty folders included also.
+                            source = os.path.join(root, d)
+                            targetDir = self.resolveTargetDir(project, source)
+                            filesToProcess.append({"source": source, "targetDir": targetDir})                            
+                            
+        else:
+            #Need to handle wildcard part
+            filesToProcess = self.getFilesByWildcard(os.path.join(old_structure_root, pathPart)\
+                                                     ,wildCardPart, project)
+                        
+        for f in filesToProcess:
+            source = f["source"]
+            targetDir = f["targetDir"]
+                      
+            if source.lower().find(".svn") != -1:
+            #Ignoring svn files
+                continue
+            
+            if os.path.isfile(source):
+                #targetDir = self.resolveTargetDir(project, f)                    
+                if self.action == "add":
+                    if not os.path.exists(targetDir):
+                        os.makedirs(targetDir)
+                    shutil.copy2(source, targetDir)                    
+                elif self.action == "remove":
+                    targetFile = os.path.join(targetDir, os.path.split(source)[1])
+                    os.remove(targetFile)
+            elif os.path.isdir(source):
+                folderToCreate = os.path.join(targetDir, os.path.split(source)[1])
+                if not os.path.isdir(folderToCreate):
+                    os.makedirs(folderToCreate)
+
+    def resolveTargetDir(self, project, filepath):
+        """
+        """
+        if self.recursive == "false":
+            return os.path.join(project.get_storage().get_path(), self.getProjectPath())
+        else:            
+            retPath = os.path.join(project.get_storage().get_path(), self.getProjectPath())            
+            startFound = 0
+            
+            for item in os.path.normpath(filepath).split("\\"):
+                if self.data.find(item) != -1:
+                    startFound = 1
+                if startFound and self.data.find(item) == -1:
+                    retPath = os.path.join(retPath, item)                
+            return os.path.split(retPath)[0]
+                        
+
+    def handleLayerRoot(self, project):
+        """
+        """
+        
+        pathPart, wildCardPart = self.separatePathAndWildcard(self.data) 
+        filesToProcess = []
+        
+        if wildCardPart == "":
+            #No wildcards found. Checking still if path has folder and file elements
+            
+            folderPath, filePart = os.path.split(pathPart)
+            if folderPath == "":
+                #filename only
+                pathPart = ""
+            else:
+                #file and folder
+                pathPart = folderPath
+            
+            source = os.path.join(project.get_storage().get_path(), self.getProjectPath(), pathPart, filePart)    
+            filesToProcess.append({"source": source, "targetDir": None})
+            
+        else:
+            #Need to handle wildcard part
+            fullSearchPath = os.path.join(project.get_storage().get_path(), self.getProjectPath(), pathPart)
+            filesToProcess = self.getFilesByWildcard(fullSearchPath, wildCardPart, project)
+        
+        #Creating rootfile.        
+        rootFilePath = os.path.join(self.getProjectPath(), self.parent.path)        
+        config = project.create_configuration(utils.resourceref.norm(rootFilePath))
+        
+        #Adding defined includes.
+        for f in filesToProcess:
+            source = f["source"]
+            #Getting path in configuration project and adding it as include.
+            filePath = utils.resourceref.norm(os.path.join(pathPart, os.path.split(source)[1]))
+            config.include_configuration(filePath)
+            if self.remove_includes == "true":
+                self.removeIncludes(config.get_configuration(filePath))                        
+        config.save()
+    
+    def removeIncludes(self, config):
+        """
+        @param config: Configuration object that is processed
+        
+        @return: None
+        """
+
+        #Getting all configurations from included configuration.
+        configList = config.list_configurations()
+        for item in configList:
+            config.remove_configuration(utils.resourceref.norm(item))            
+        
+        config.save()
+        
+
+    def handleConfigurationRoot(self, project):
+        """
+        """        
+        #Always in the root of the project
+        configname = utils.resourceref.norm(self.parent.path)
+        if configname in project.list_configurations():
+            config = project.get_configuration(configname)
+        else:
+            config = project.create_configuration(utils.resourceref.norm(self.parent.path))
+        config.include_configuration(utils.resourceref.norm(self.data))                
+        config.save()
+
+
+    def getProjectPath(self):
+        if isinstance(self.parent, ConvertProjectFile):
+            #print "FILE", self.parent.parent.getProjectPath()
+            return self.parent.parent.getProjectPath() 
+        else:
+            #print "other"
+            return self.parent.getProjectPath()
+        
+
+    def getFilesByWildcard(self, folder, wildcard, project):
+        """
+        @param folder: folder where matching is made
+        @type folder: string
+        @param wildcard: wildcard pattern
+        @type wildcard: string   
+        """
+                
+        #Array of files and folders matching with the wildcard.        
+        retArray = []
+        if os.path.isdir(folder):     
+            for root, dirs, files in os.walk(folder):
+                if self.recursive == "false" and os.path.normpath(root) != os.path.normpath(folder):
+                #No recursive search used and therefore only topmost directory is handled.
+                    continue
+                else:
+                    for f in files:
+                        if fnmatch.fnmatch(os.path.join(root, f), wildcard):
+                            source = os.path.join(root, f)
+                            targetDir = self.resolveTargetDir(project, source)                
+                            retArray.append({"source": source, "targetDir": targetDir})
+
+                    for d in dirs:
+                        if fnmatch.fnmatch(os.path.join(root, d), wildcard):
+                            source = os.path.join(root, d)
+                            targetDir = self.resolveTargetDir(project, source)                
+                            retArray.append({"source": source, "targetDir": targetDir})                            
+                            
+        return retArray
+
+    def separatePathAndWildcard(self, data):
+        """        
+        @param data: data from XML that may contain path and wildcard parts
+        @type data: string
+        
+        @return: Path and wildcard parts separately. 
+        """
+        pathPart = ""
+        wildCardPart = ""
+
+        if data.find("*") == -1:
+        #Only supported wildcard is currently *
+            pathPart = data
+            wildCardPart =""
+        else:
+        #Some wildcards found. Wildcards are supported only in the last segment.
+            pathPart, wildCardPart = os.path.split(data)
+
+        return pathPart, wildCardPart
+
+
+#=================================================================
+    
+class ConvertProjectReader(plugin.ReaderBase):
+    """
+    Parses a single convertprojectml  file
+    """ 
+    
+    NAMESPACE = 'http://www.s60.com/xml/convertprojectml/1'
+    FILE_EXTENSIONS = ['convertprojectml']
+    
+    def __init__(self):
+        self.desc = None
+        self.output_dir = None
+        self.input_dir = None
+        self.namespaces = [self.NAMESPACE]
+        self.project_data = {}
+        self.layers = []
+    
+    @classmethod
+    def read_impl(cls, resource_ref, configuration, etree):
+        reader = ConvertProjectReader()
+        reader.from_etree(etree, configuration.get_storage().get_path())
+        
+        impl = ConvertProjectImpl(resource_ref, configuration)
+        impl.project_data   = reader.project_data
+        impl.layers         = reader.layers
+        return impl
+    
+    def from_etree(self, etree, old_structure_root = ""):
+        self.project_data = self.parse_attributes(etree, "targetProject")        
+        self.layers = self.parse_layers(etree) 
+        for fe in self.parse_foreach(etree, old_structure_root):
+            self.layers.append(fe)
+        
+        #for l in self.layers:
+            #print l
+        return    
+    
+    def parse_foreach(self, etree, old_structure_root):
+        layersTmp = []
+        for fe in etree.findall("{%s}foreach" % self.namespaces[0]):
+            variable = fe.get("variable")
+            data = fe.get("data")
+            folders = [] 
+            for item in os.listdir(os.path.join(old_structure_root, data)):
+                if os.path.isdir(os.path.join(old_structure_root, data, item)) and item != '.svn':
+                    folders.append(item)
+            
+            for folder in folders:
+                mapping_data = {variable: folder}                                             
+                for layer in fe.findall("{%s}layer" % self.namespaces[0]):            
+                    layersTmp.append(self.parse_layer(layer, mapping_data))
+                                
+        return layersTmp
+    
+    def parse_layers(self,etree):
+        layersTmp = []
+        for layer in etree.findall("{%s}layer" % self.namespaces[0]):            
+            layersTmp.append(self.parse_layer(layer))
+            
+        return layersTmp
+    
+    def parse_layer(self, etree, mapping_data=None):        
+        path = self.handleMapping(etree.get("path"), mapping_data)
+        
+        layerObject = ConvertProjectLayer(path)        
+        for folder in etree.findall("{%s}folder" % self.namespaces[0]):
+            layerObject.addFolder(self.parse_folder(folder, layerObject, mapping_data))
+
+        for f in etree.findall("{%s}file" % self.namespaces[0]):
+            layerObject.addFile(self.parse_file(f, layerObject, mapping_data))
+        
+        return layerObject
+    
+    def parse_folder(self, etree, parent, mapping_data=None):        
+        path = self.handleMapping(etree.get("path"), mapping_data)
+        
+        folderObject = ConvertProjectFolder(path, parent)
+        for filter in etree.findall("{%s}filter" % self.namespaces[0]):                        
+            #Remove includes supported only for files.
+            folderObject.addFilter(self.parse_filter(filter, folderObject, mapping_data))                
+        return folderObject
+
+    def parse_file(self, etree, parent, mapping_data=None):
+        path = self.handleMapping(etree.get("path"), mapping_data)
+        type = self.handleMapping(etree.get("type"), mapping_data)
+        
+        fileObject = ConvertProjectFile(path, type, parent)        
+        for filter in etree.findall("{%s}filter" % self.namespaces[0]):
+            fileObject.addFilter(self.parse_filter(filter, fileObject, mapping_data))
+        
+        metaElement = etree.find("{%s}meta" % self.namespaces[0])
+        namespacePattern = re.compile("\{(.*)\}(.*)")
+        metaArray = [] #tag, value, ns, attrs
+        if metaElement:
+            for item in metaElement.getiterator():
+                mo = namespacePattern.search(item.tag)
+                if mo:        
+                    if mo.group(2) != "meta":
+                        tmpArray = []                        
+                        tmpArray.append(mo.group(2))    #Tag name
+                        tmpArray.append(item.text)      #value
+                        tmpArray.append(mo.group(1))    #Namespace
+                        tmpDict = {}
+                        for attribute in item.keys():
+                            tmpDict[attribute] = item.get(attribute)
+                        tmpArray.append(tmpDict)
+                        metaArray.append(tmpArray)
+        
+        descElement = etree.find("{%s}desc" % self.namespaces[0])
+        description = ""
+        if descElement != None:
+            description = descElement.text                
+                         
+        fileObject.addMeta(metaArray)
+        fileObject.addDescription(description)                
+        return fileObject
+
+    def parse_filter(self, etree, parent, mapping_data=None):
+        """
+        """
+        data = self.handleMapping(etree.get("data"), mapping_data)
+        action = self.handleMapping(etree.get("action"), mapping_data)
+        remove_includes = self.handleMapping(etree.get("remove_includes"), mapping_data)
+        recursive = self.handleMapping(etree.get("recursive"), mapping_data)
+        
+        return ConvertProjectFilter(action, data, parent, remove_includes, recursive)
+    
+
+    def parse_rule(self, etree, parent):
+        return {"name": etree.get("name"), "type": etree.get("type"), "data": etree.get("data")}
+
+    def parse_attributes(self, etree, tagName):
+        tmpDict = {}        
+        tmpElement = etree.find("{%s}%s" % (self.namespaces[0], tagName))
+        for attribute in tmpElement.keys():
+            tmpDict[attribute] = tmpElement.get(attribute)
+        return tmpDict
+    
+    def handleMapping(self, data, mapping):
+        """
+        """
+        
+        retStr = data
+        
+        if mapping != None and data != None:                        
+            for key in mapping.keys():
+                retStr = retStr.replace(key, mapping[key])
+        return retStr
+        
+        
+        
+        
+        
+        
+
+
+    
+    
+    
\ No newline at end of file