diff -r 000000000000 -r 2e8eeb919028 configurationengine/source/plugins/symbian/ConeProjectConverterPlugin/projectconvertplugin/convertproject.py --- /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