text: ## @file
  # Install distribution package.
  #
  # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
  #
  # This program and the accompanying materials are licensed and made available 
  # under the terms and conditions of the BSD License which accompanies this 
  # distribution. The full text of the license may be found at 
  # http://opensource.org/licenses/bsd-license.php
  #
  # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  #
  
  '''
  MkPkg
  '''
  
  ##
  # Import Modules
  #
  from os import remove
  from os import getcwd
  from os import chdir
  import os.path
  from sys import stdin
  from sys import platform
  from traceback import format_exc
  from platform import python_version
  import md5
  from time import strftime
  from time import localtime
  from uuid import uuid4
  
  from Logger import StringTable as ST
  from Logger.ToolError import OPTION_UNKNOWN_ERROR
  from Logger.ToolError import OPTION_VALUE_INVALID
  from Logger.ToolError import ABORT_ERROR
  from Logger.ToolError import UPT_REPKG_ERROR
  from Logger.ToolError import CODE_ERROR
  from Logger.ToolError import FatalError
  from Logger.ToolError import FILE_NOT_FOUND
  import Logger.Log as Logger
  
  from Xml.XmlParser import DistributionPackageXml
  from Xml.IniToXml import IniToXml
  
  from Library import GlobalData
  from Library.ParserValidate import IsValidPath
  
  from Core.DistributionPackageClass import DistributionPackageClass
  from Core.PackageFile import PackageFile
  
  ## CheckForExistingDp
  #
  # Check if there is a same name DP file existing
  # @param Path: The path to be checked 
  #
  def CheckForExistingDp(Path):
      if os.path.exists(Path):
          Logger.Info(ST.MSG_DISTRIBUTION_PACKAGE_FILE_EXISTS % Path)
          Input = stdin.readline()
          Input = Input.replace('\r', '').replace('\n', '')
          if Input.upper() != "Y":
              Logger.Error("\nMkPkg", ABORT_ERROR, ST.ERR_USER_ABORT, RaiseError=True)
  
  ## Tool entrance method
  #
  # This method mainly dispatch specific methods per the command line options.
  # If no error found, return zero value so the caller of this tool can know
  # if it's executed successfully or not.
  #
  #
  def Main(Options = None):
      if Options == None:
          Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND)
      try:
          DataBase = GlobalData.gDB        
          ContentFileClosed = True
          WorkspaceDir = GlobalData.gWORKSPACE
  
          #
          # Init PackFileToCreate
          #
          if not Options.PackFileToCreate:
              Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND)
          
          #
          # Handle if the distribution package file already exists
          #
          CheckForExistingDp(Options.PackFileToCreate)
  
          #
          # Check package file existing and valid
          #
          CheckFileList('.DEC', Options.PackageFileList, ST.ERR_INVALID_PACKAGE_NAME, ST.ERR_INVALID_PACKAGE_PATH)
          #            
          # Check module file existing and valid
          #
          CheckFileList('.INF', Options.ModuleFileList, ST.ERR_INVALID_MODULE_NAME, ST.ERR_INVALID_MODULE_PATH)
  
          #
          # Get list of files that installed with RePackage attribute available
          #
          RePkgDict = DataBase.GetRePkgDict()
                
          ContentFile = PackageFile(GlobalData.gCONTENT_FILE, "w")       
          ContentFileClosed = False
          
          #
          # Add temp distribution header
          #
          if Options.PackageInformationDataFile:
              XmlFile = IniToXml(Options.PackageInformationDataFile)
              DistPkg = DistributionPackageXml().FromXml(XmlFile)
              remove(XmlFile)
  
              #
              # add distribution level tool/misc files
              # before pack, current dir should be workspace dir, else the full 
              # path will be in the pack file
              #
              Cwd = getcwd()
              chdir(WorkspaceDir)
              ToolObject = DistPkg.Tools
              MiscObject = DistPkg.MiscellaneousFiles
              FileList = []
              if ToolObject:
                  FileList += ToolObject.GetFileList()
              if MiscObject:
                  FileList += MiscObject.GetFileList()
              for FileObject in FileList:
                  #
                  # If you have unicode file names, please convert them to byte 
                  # strings in your desired encoding before passing them to 
                  # write().
                  #
                  FromFile = os.path.normpath(FileObject.GetURI()).encode('utf_8')
                  FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, FromFile))
                  if FileFullPath in RePkgDict:
                      (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath]
                      if not Repackage:
                          Logger.Error("\nMkPkg",
                                       UPT_REPKG_ERROR,
                                       ST.ERR_UPT_REPKG_ERROR,
                                       ExtraData=ST.MSG_REPKG_CONFLICT %\
                                       (FileFullPath, DpGuid, DpVersion, DpName)
                                       )
                      else:
                          DistPkg.Header.RePackage = True
                  ContentFile.PackFile(FromFile)
              chdir(Cwd)
          
          #    
          # Add init dp information
          #
          else:
              DistPkg = DistributionPackageClass()
              DistPkg.Header.Name = 'Distribution Package'
              DistPkg.Header.Guid = str(uuid4())
              DistPkg.Header.Version = '1.0'
              
          DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, \
                                         Options.ModuleFileList)
          FileList, MetaDataFileList = DistPkg.GetDistributionFileList()
          for File in FileList + MetaDataFileList:
              FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, File))
              #
              # check whether file was included in a distribution that can not 
              # be repackaged
              #
              if FileFullPath in RePkgDict:
                  (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath]
                  if not Repackage:
                      Logger.Error("\nMkPkg",
                                   UPT_REPKG_ERROR,
                                   ST.ERR_UPT_REPKG_ERROR,
                                   ExtraData = \
                                   ST.MSG_REPKG_CONFLICT %(FileFullPath, DpName, \
                                                           DpGuid, DpVersion)
                                   )
                  else:
                      DistPkg.Header.RePackage = True
            
          Cwd = getcwd()
          chdir(WorkspaceDir)        
          ContentFile.PackFiles(FileList)
          chdir(Cwd)
          
          Logger.Verbose(ST.MSG_COMPRESS_DISTRIBUTION_PKG) 
          
          ContentFile.Close()
          ContentFileClosed = True
          
          #
          # Add Md5Sigature
          #
          DistPkg.Header.Signature = md5.new(open(str(ContentFile), 'rb').read()).hexdigest()
          #
          # Add current Date
          #
          DistPkg.Header.Date = str(strftime("%Y-%m-%dT%H:%M:%S", localtime()))
          
          #
          # Finish final dp file
          #
          DistPkgFile = PackageFile(Options.PackFileToCreate, "w")
          DistPkgFile.PackFile(str(ContentFile))
          DistPkgXml = DistributionPackageXml()
          DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), GlobalData.gDESC_FILE)
          DistPkgFile.Close()
          Logger.Quiet(ST.MSG_FINISH)
          ReturnCode = 0
  
      except FatalError, XExcept:
          ReturnCode = XExcept.args[0]        
          if Logger.GetLevel() <= Logger.DEBUG_9:
              Logger.Quiet(ST.MSG_PYTHON_ON % \
                           (python_version(), platform) + format_exc())
      except KeyboardInterrupt:
          ReturnCode = ABORT_ERROR
          if Logger.GetLevel() <= Logger.DEBUG_9:
              Logger.Quiet(ST.MSG_PYTHON_ON % \
                           (python_version(), platform) + format_exc())
      except OSError:
          pass
      except:
          Logger.Error(
                      "\nMkPkg",
                      CODE_ERROR,
                      ST.ERR_UNKNOWN_FATAL_CREATING_ERR % \
                      Options.PackFileToCreate,
                      ExtraData=ST.MSG_SEARCH_FOR_HELP,
                      RaiseError=False
                      )
          Logger.Quiet(ST.MSG_PYTHON_ON % \
                       (python_version(), platform) + format_exc())
          ReturnCode = CODE_ERROR
      finally:
          if os.path.exists(GlobalData.gCONTENT_FILE):
              if not ContentFileClosed:
                  ContentFile.Close()
              os.remove(GlobalData.gCONTENT_FILE)
  
      return ReturnCode
  
  
  ## CheckFileList
  # 
  # @param QualifiedExt:             QualifiedExt
  # @param FileList:                 FileList
  # @param ErrorStringExt:           ErrorStringExt
  # @param ErrorStringFullPath:      ErrorStringFullPath
  #
  def CheckFileList(QualifiedExt, FileList, ErrorStringExt, ErrorStringFullPath):
      if not FileList:
          return
      WorkspaceDir = GlobalData.gWORKSPACE
      WorkspaceDir = os.path.normpath(WorkspaceDir)
      for Item in FileList:
          Ext = os.path.splitext(Item)[1]
          if Ext.upper() != QualifiedExt.upper():
              Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
                           ErrorStringExt % Item)
          
          Item = os.path.normpath(Item)
          Path = os.path.normpath(os.path.join(WorkspaceDir, Item))
          if not os.path.exists(Path):
              Logger.Error("\nMkPkg", FILE_NOT_FOUND, ST.ERR_NOT_FOUND % Item)
          elif Item == Path:
              Logger.Error("\nMkPkg", OPTION_VALUE_INVALID,
                           ErrorStringFullPath % Item)
          elif not IsValidPath(Item, WorkspaceDir):
              Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
                           ErrorStringExt % Item)
          
          if not os.path.split(Item)[0]:
              Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
                           ST.ERR_INVALID_METAFILE_PATH % Item)
  