public void buildManifest(File pAdditionalPropertiesFile, PrintWriter pDestination) 
  throws ExManifestBuilder, ExParser {
    
    //Assert the config file exists    
    Collection<File> lConfigFileList = FileUtils.listFiles(
      mBaseDirectory
    , new RegexFileFilter(BUILDER_CONFIG_FILENAME_PREFIX + ".*" + BUILDER_CONFIG_FILENAME_SUFFIX)
    , new NameFileFilter(ScriptRunner.SCRIPTRUNNER_DIRECTORY_NAME)
    );
    
    File lConfigFile;
    if(lConfigFileList.size() != 1){
      throw new ExManifestBuilder("Exactly one builder[*].cfg file should be specified but found " + lConfigFileList.size());
    }
    else {      
      lConfigFile = lConfigFileList.iterator().next();
      Logger.logDebug("Found builder config file called " + lConfigFile.getName());
    }    
    
    //Attempt to locate the manifest override 
    Collection<File> lManifestOverrideFileList = FileUtils.listFiles(
      mBaseDirectory
    , new RegexFileFilter(OVERRIDE_FILENAME_PREFIX + ".*" + OVERRIDE_FILENAME_SUFFIX)
    , new NameFileFilter(ScriptRunner.SCRIPTRUNNER_DIRECTORY_NAME)
    );
    
    if(lManifestOverrideFileList.size() > 1){
      throw new ExManifestBuilder("Only one manifest override can be specified, found " + lManifestOverrideFileList.size());
    }
    
    //Parse the manifest override if it exists
    ManifestParser lOverrideParser = null;
    if(lManifestOverrideFileList.size() == 1){      
      lOverrideParser = parseManifestOverride(lManifestOverrideFileList.iterator().next());
    }
    
    //Parse additional properties if specified
    if(pAdditionalPropertiesFile != null){
      parseAdditionalPropertiesFile(pAdditionalPropertiesFile);
    }
    
    //Parse the config file
    ConfigFileParser lConfigParser = new ConfigFileParser(this);
    lConfigParser.parse(lConfigFile);
    
    
    //For each Config Entry, generate all the associated manifest entries
    lConfigParser.generateAllManifestEntries();
    
    //Verify all files implicated in override rules were selected by a config file entry
    validateOverrideFiles();
    
    //Coalesce the processed manifest entries into a final list 
    composeFinalManifestEntryList(lConfigParser);
    
    //Generate the promotion properties map
    generatePromotionProperties(lOverrideParser);
    
    //Serialise the manifest
    ManifestSerialiser lManifestSerialiser = new ManifestSerialiser(this);
    lManifestSerialiser.serialise(pDestination);
  }