public void parse()
  throws FileNotFoundException, IOException, ExParser, ExManifest {    
    
    BufferedReader lReader = null;
    try {
      lReader = new BufferedReader(new FileReader(mManifestFile));
      String lLine;
      int lHighestSequencePosition = 0;
      
      Map<String, Integer> lFileIndexes = new HashMap<String, Integer>();
      
      LINE_LOOP:
      while((lLine = lReader.readLine())!= null){
        
        //Trim whitespace
        lLine = lLine.trim();
        
        //Skip empty lines
        if("".equals(lLine)){
          continue LINE_LOOP;
        }
        
        //Skip comment lines
        if(lLine.charAt(0) == '#'){
          continue LINE_LOOP;
        }
        
        //Attempt to parse the line as a property line (this will return null if it is not)
        Map<String, String> lPromotionPropertyMap = parsePromotionPropertiesLine(lLine);
        if(lPromotionPropertyMap != null){
          Logger.logDebug("Parsed promotion property line");
          if(mPromotionPropertyMap != null){
            //Only one definition allowed per manifest
            throw new ExParser("Duplicate PROMOTION definition line found");
          }
          mPromotionPropertyMap = lPromotionPropertyMap;
          continue LINE_LOOP;
        }
        
        //Assume any other line is a manifest entry (this will error if it is not)
        ManifestEntry lManifestEntry = parseManifestEntryLine(lLine, lHighestSequencePosition);
        
        lHighestSequencePosition = lManifestEntry.getSequencePosition();
        mManifestEntryList.add(lManifestEntry);
        if(!lManifestEntry.isForcedDuplicate()){
          mFinalProcessedFilePathSet.add(lManifestEntry.getFilePath());
        }
        
        //Record the index of the file
        Integer lFileIndex = lFileIndexes.get(lManifestEntry.getFilePath());
        if(lFileIndex  == null){
          lFileIndex = 1;
        }
        else {
          lFileIndex++;
        }
        lManifestEntry.setFileIndex(lFileIndex);
        lFileIndexes.put(lManifestEntry.getFilePath(), lFileIndex);        
        
        //Construct a new loader if necessary
        createLoaderIfUndefined(lManifestEntry.getLoaderName());        
        
        Logger.logDebug("Parsed manifest entry for " + lManifestEntry.getFilePath());        
      }
    } 
    finally {
      //Close the reader to release the lock on the file
      if(lReader != null){
        lReader.close();
      }
    }
    
  }