configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/generators.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeImagePlugin/imageplugin/generators.py	Thu Mar 11 17:04:37 2010 +0200
@@ -0,0 +1,587 @@
+#
+# 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: 
+#
+'''
+Generator classes
+'''
+
+
+import re
+import os
+import sys
+import logging
+import subprocess
+import shutil
+
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+from cone.public import utils, exceptions
+
+class InvalidInputFileException(RuntimeError):
+    """
+    Exception thrown in case of an invalid input file list.
+    """
+    pass
+
+class OutputGenerator(object):
+    def __init__(self,outputpath,**kwargs):
+        self._configuration = None
+        self._subpath = ''
+        self._contentpath = ''
+        self._command = ''
+        self._inputs = []
+        for arg in kwargs.keys():
+            setattr(self, arg, kwargs[arg])
+        self._outputpath = outputpath
+
+    def __str__(self):
+        return "Generator for output %s: %s"  % (self.path,self.get_command())
+
+    def generate(self, context=None):
+        command = self.get_command()
+        if command:
+            return command.execute()
+        else:
+            return 0
+
+    def get_outputpath(self):
+        """
+        Get the confml ref value from configuration if the outputpath is actually a ref
+        """
+        if self._outputpath and ConfmlRefs.is_confml_ref(self._outputpath):
+             oref = ConfmlRefs.get_confml_ref(self._outputpath)
+             opath = self.configuration.get_default_view().get_feature(oref).get_value()
+             if opath == None: 
+                 logging.getLogger('cone.imageml').warning('Output path not set.')
+                 return self._outputpath 
+                 #raise exceptions.NotBound("Output path reference has no value %s" % oref)
+             (drive,opath) = os.path.splitdrive(opath)
+             opath = utils.resourceref.norm(opath)
+             opath = utils.resourceref.remove_begin_slash(opath)
+             return opath
+        else:
+             return self._outputpath
+
+    def set_outputpath(self, value): 
+        self._outputpath = value
+
+    def del_outputpath(self): 
+        self._outputpath = None
+
+    def get_subpath(self):
+        return self._subpath
+
+    def set_subpath(self, value): 
+        self._subpath = value
+
+    def del_subpath(self): 
+        self._subpath = None
+
+    def get_inputs(self): 
+        return self._inputs
+
+    def set_inputs(self, value): 
+        self._inputs = value
+
+    def del_inputs(self): 
+        self._inputs = []
+
+    def get_configuration(self): 
+        return self._configuration
+
+    def set_configuration(self, value): 
+        self._configuration= value
+        for input in self.inputs:
+            input.configuration = self.configuration
+
+    def del_configuration(self): 
+        self._configuration= None
+
+    @property
+    def path(self):
+        return utils.resourceref.join_refs([self.subpath, self.outputpath])
+
+    def get_command(self):
+        (_,ext) = os.path.splitext(self.path)
+        if ext == '.mbm':
+            return BmconvCommand(self)
+        elif ext == '.mif':
+            return MifconvCommand(self)
+        elif ext == '.gif':
+            return CopyCommand(self)
+        else:
+            return None
+    
+    def get_refs(self):
+        refs = []
+        for input in self.inputs:
+            refs.extend(input.get_refs())
+        return refs
+
+    configuration = property(get_configuration, set_configuration, del_configuration)
+    inputs = property(get_inputs, set_inputs, del_inputs)
+    outputpath = property(get_outputpath, set_outputpath, del_outputpath)
+    subpath = property(get_subpath, set_subpath, del_subpath)
+
+class Command(object):
+    def __init__(self,generator):
+        self._generator = generator
+        self._workdir = 'conversion_workdir'
+
+    def execute(self):
+        """ Execute this command """
+        pass
+
+    def get_command(self, input_files):
+        """ return the command as an array """
+        return []
+
+    def create_workdir(self, input_files):
+        """
+        Extract the necessary input files from storage to a working directory
+        @param input_files: The input files (a list of InputFile objects) 
+        """
+        if not os.path.exists(self._workdir):
+            os.makedirs(self._workdir)
+        
+        for file in input_files:
+            self.import_to_work(file.filename)
+
+    def clean_workdir(self):
+        """
+        Clean up working directory 
+        """
+        if os.path.exists(self._workdir):
+            shutil.rmtree(self._workdir)
+
+    def import_to_work(self,storage_filename):
+        """
+        Convert a storage filename to a work filename
+        """
+        workfile = self.workfilename(storage_filename)
+        res = self._generator.configuration.get_resource(storage_filename,"rb")
+        workfile = open(workfile,"wb")
+        workfile.write(res.read())
+        res.close()
+        workfile.close()
+
+    def workfilename(self,filename):
+        """
+        Convert a storage filename to a work filename
+        """
+        (_,workname) = os.path.split(filename)
+        return os.path.join(self.workdir,workname)
+
+    def quote_needed(self,str):
+        """
+        Add quotes around str if it has spaces
+        """
+        if str.split(' ',1) > 1:
+            return '"%s"' % str
+        else:
+            return str
+        
+    @property
+    def tool(self):
+        return ''
+
+    @property
+    def generator(self):
+        return self._generator
+
+    @property
+    def workdir(self):
+        return self._workdir
+    
+    def _get_filtered_input_files(self):
+        """
+        Get the list of InputFile objects and with ignored
+        (optional empty or invalid files) entries filtered out.
+        
+        Raise InvalidInputFileException if the input file list is invalid.
+        """
+        # Get all input files
+        input_files = []
+        for input in self.generator.inputs:
+            input_files.extend(input.files)
+        
+        # Check if all are empty
+        all_empty = True
+        for file in input_files:
+            if not file.is_empty():
+                all_empty = False
+                break
+        if all_empty:
+            return []
+        
+        # Create the filtered list
+        result = []
+        for file in input_files:
+            if file.is_empty():
+                if file.is_optional():
+                    # Optional file is empty: no error
+                    pass
+                else:
+                    raise InvalidInputFileException("Input file empty but not optional")
+            else:
+                if not file.is_valid():
+                    raise InvalidInputFileException("Invalid input file: '%s'" % file.path)
+                else:
+                    result.append(file)
+        return result 
+
+class BmconvCommand(Command):
+    def __init__(self,generator):
+        super(BmconvCommand, self).__init__(generator)
+
+    def execute(self):
+        """
+        Execute the command in the current working directory
+        """
+        input_files = self._get_filtered_input_files()
+        if len(input_files) == 0: return 0
+        self.create_workdir(input_files)
+        
+        if not os.path.exists(os.path.dirname(self.generator.path)):
+            os.makedirs(os.path.dirname(self.generator.path))
+        
+        command = self.get_command(input_files)
+        p = subprocess.Popen(command,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+        
+        # Wait for the process to return
+        out, err = [ e.splitlines() for e in p.communicate() ]
+        for outl in out:
+            if outl not in err:
+                logging.getLogger('cone.bmconv').info(outl)
+        for outl in err:
+            logging.getLogger('cone.bmconv').error(outl)
+        if p.returncode != 0:
+            logging.getLogger('cone.bmconv').error("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
+        else:
+            logging.getLogger('cone.bmconv').info("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
+        if p.returncode == 0:
+        	self.clean_workdir()
+        return p.returncode 
+
+    def get_command(self, input_files):
+        command = [self.tool]
+        """ Add palette file """
+        if hasattr(self._generator,'palette'):
+            command.append('/p%s' % os.path.abspath(self.generator.palette))
+
+        """ Add output file """
+        """ Add output file as compressed if needed """
+        if self.rom:
+            if self.compress:
+                command.append('/s')
+            else:
+                command.append('/r')
+        else:
+            pass
+        command.append(os.path.normpath(self.generator.path))
+        
+        
+        for inputfile in input_files:
+            depth = ''
+            if inputfile.depth:
+                depth = '/%s' % inputfile.depth
+            command.append('%s%s' % (depth,self.workfilename(inputfile.filename)))
+        return command
+
+    @property
+    def tool(self):
+        if hasattr(self._generator,'tool'):
+            return os.path.abspath(self._generator.tool)
+        elif hasattr(self._generator, 'tooldir'):
+            return os.path.abspath(os.path.join(self._generator.tooldir, 'bmconv'))
+        else:
+            return 'bmconv'
+
+    @property
+    def rom(self):
+        if hasattr(self._generator,'rom') and self._generator.rom.lower() == 'true':
+            return True
+        else:
+            return False
+
+    @property
+    def compress(self):
+        if hasattr(self._generator,'compress') and self._generator.compress.lower() == 'true':
+            return True
+        else:
+            return False
+
+class MifconvCommand(Command):
+    def __init__(self,generator):
+        super(MifconvCommand, self).__init__(generator)
+
+    def execute(self):
+        """
+        Execute the command in the current working directory
+        """
+        input_files = self._get_filtered_input_files()
+        if len(input_files) == 0: return 0
+        self.create_workdir(input_files)
+        
+        runenv = None
+        runshell = True
+        if os.path.dirname(self.tool):
+            runenv = {}
+            runenv['path'] = os.path.dirname(self.tool)
+            runshell = True
+        if not os.path.exists(os.path.dirname(self.generator.path)):
+            os.makedirs(os.path.dirname(self.generator.path))
+        
+        command = self.get_command(input_files)
+        p = subprocess.Popen(command,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             env=runenv,
+                             shell=runshell)
+        
+        # Wait for the process to return
+        out, err = [ e.splitlines() for e in p.communicate() ]
+        for outl in out:
+            if outl not in err:
+                logging.getLogger('cone.mifconv').info(outl)
+        for outl in err:
+            logging.getLogger('cone.mifconv').error(outl)
+        if p.returncode != 0:
+            logging.getLogger('cone.mifconv').error("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
+        else:
+            logging.getLogger('cone.mifconv').info("Command returned with returncode %s: %s" % (p.returncode, ' '.join(command)))
+        if p.returncode == 0:
+	        self.clean_workdir()
+        return p.returncode 
+
+    def get_command(self, input_files):
+        command = [self.tool]
+        
+        """ Add output file """
+        command.append(os.path.normpath(self.generator.path))
+        
+        """ Add temp_path """
+        command.append("/t%s" % self.temppath)
+        
+        # Add tool directory if given
+        if hasattr(self._generator,'tooldir'):
+            command.append('/S%s' % os.path.abspath(self.generator.tooldir))
+        
+        """ Get input files """
+        for inputfile in input_files:
+            depth = 'c8'
+            if inputfile.depth:
+                depth = inputfile.depth
+            command.append('/%s' % depth)
+            command.append( '%s' % self.workfilename(inputfile.filename))
+        return command
+
+    @property
+    def tool(self):
+        if hasattr(self._generator,'tool'):
+            return os.path.abspath(self._generator.tool)
+        elif hasattr(self._generator, 'tooldir'):
+            return os.path.abspath(os.path.join(self._generator.tooldir, 'mifconv'))
+        else:
+            return 'mifconv'
+
+    @property
+    def temppath(self):
+        if hasattr(self._generator,'temp'):
+            return os.path.abspath(self._generator.temp)
+        else:
+            return self.workdir
+
+class CopyCommand(object):
+    def __init__(self,generator):
+        self._generator = generator
+
+    def execute(self):
+        pass
+
+    @property
+    def tool(self):
+        return 'copy'
+
+class InputFile(object):
+    def __init__(self,path,**kwargs):
+        self.configuration = None
+        self._depth = None
+        for arg in kwargs.keys():
+            if arg == 'depth':
+                # Special handling for depth ('depth' is a property that
+                # expands refs using '_depth' as the base)
+                self._depth = kwargs[arg]
+            else:
+                setattr(self, arg, kwargs[arg])
+        self._path= path
+
+    def get_input(self): 
+        """ 
+        Get the confml ref value from configuration if the outputpath is actually a ref 
+        """
+        if self._path and self.configuration is not None:
+            dview = self.configuration.get_default_view()
+            def expand(ref, index):
+                value = dview.get_feature(ref).get_original_value()
+                if value is None:   return ''
+                else:               return value
+            return utils.expand_delimited_tokens(self._path, expand)
+        else:
+            return self._path
+
+    def set_input(self, value): self._path = value
+
+    def del_input(self): self._path = None
+
+    @property 
+    def type(self):
+        return 'file'
+    
+    @property
+    def depth(self):
+        if self._depth and self.configuration:
+            dview = self.configuration.get_default_view()
+            return utils.expand_refs_by_default_view(self._depth, dview)
+        else:
+            return self._depth or ''
+
+    @property 
+    def files(self):
+        """ 
+        Return a list of file names 
+        """
+        return [self]
+        
+    @property 
+    def filename(self):
+        """ 
+        Return a the path to the layer specific filename
+        """ 
+        if self.configuration and self.path:
+            content = self.configuration.layered_content().flatten()
+            inputpath = self.path
+            return content.get(inputpath)
+        else:
+            return self.path
+
+    path = property(get_input, set_input, del_input, "The input 'path'.")
+    
+    def is_valid(self):
+        """
+        Return whether the input file is valid (not empty
+        and exists in project content).
+        """
+        return not self.is_empty() and self.filename
+    
+    def is_empty(self):
+        """
+        Return whether the input file is empty.
+        """
+        return self.path in ('', None)
+    
+    def is_optional(self):
+        """
+        Return whether the input file is optional.
+        """
+        return hasattr(self, 'optional') \
+            and self.optional.lower() in ('1', 't', 'true', 'yes', 'y')
+    
+    def get_refs(self):
+        return utils.extract_delimited_tokens(self._path)
+    
+    def __repr__(self):
+        return "InputFile(path=%r, optional=%r)" % (self._path, self.is_optional())
+
+class InputDir(InputFile):
+    def __init__(self,path,**kwargs):
+        super(InputDir,self).__init__(path,**kwargs)
+        self._files = []
+        self._include = None
+        self._exclude = None
+
+    def get_include(self): 
+        return self._include.get('pattern',[])
+
+    def set_include(self, value): 
+        self._include = value
+
+    def del_include(self): 
+        self._include = None
+
+    def get_exclude(self):
+        return self._exclude.get('pattern',[])
+
+    def set_exclude(self, value): 
+        self._exclude = value
+
+    def del_exclude(self): 
+        self._exclude = None
+
+    @property 
+    def type(self): 
+        return 'dir'
+
+    @property 
+    def files(self):
+        """ 
+        Return a list of file names under this directory definition
+        """ 
+        if self.configuration:
+            inputlist = []
+            content = self.configuration.layered_content().flatten()
+            contentfiles = content.keys()
+            
+            folderfiles = utils.resourceref.filter_resources(contentfiles, "^%s" % self.path)
+            for inputfilter in self.include:
+                folderfiles = utils.resourceref.filter_resources(folderfiles, inputfilter)
+            for excludefilter in self.exclude:
+                folderfiles = utils.resourceref.neg_filter_resources(folderfiles, excludefilter)
+            folderfiles.sort()
+            for filename in folderfiles:
+                inputlist.append(InputFile(filename, **self.__dict__))
+            return inputlist
+        else:
+            return []
+
+    include = property(get_include, set_include, del_include)
+    exclude = property(get_exclude, set_exclude, del_exclude)
+
+
+
+class ConfmlRefs(object):
+    
+    ref_pattern = re.compile('^\$\{(.*)\}$')
+
+    @classmethod
+    def is_confml_ref(cls, variableref):
+        """
+        
+        Returns true if the given variable ref is a confml reference
+        """
+        return cls.ref_pattern.match(variableref) != None
+
+    @classmethod
+    def get_confml_ref(cls, variableref):
+        """
+        
+        Returns true if the given variable ref is a confml reference
+        """
+        matchref = cls.ref_pattern.match(variableref)
+        if matchref:
+            return matchref.group(1)
+        else:
+            return None