public static IdToGuidDatabase Create(string filename, ILogger owner)
        {
            if (File.Exists(filename))
            {
                //  try
                {
                    XmlReaderSettings settings = new XmlReaderSettings();
                    settings.IgnoreComments   = true;
                    settings.IgnoreWhitespace = true;
                    using (XmlReader rdr = XmlTextReader.Create(filename, settings))
                    {
                        IdToGuidDatabase m = new IdToGuidDatabase(filename, owner);

                        // skip XML declaration
                        do
                        {
                            if (!rdr.Read())
                            {
                                throw new XmlException("Unexpected EOF");
                            }
                        } while (rdr.NodeType != XmlNodeType.Element);

                        if (rdr.Name == "InstallerMetadata")
                        {
                            while (rdr.Read())
                            {
                                if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "File")
                                {
                                    string id   = rdr.GetAttribute("Id");
                                    string guid = rdr.GetAttribute("Guid");
                                    if (id == null || guid == null)
                                    {
                                        throw new XmlException("Unexpected format");
                                    }
                                    m[id] = guid;
                                }
                                else if (rdr.NodeType == XmlNodeType.EndElement)
                                {
                                    break;
                                }
                                else
                                {
                                    throw new XmlException("Unexpected format");
                                }
                            }
                        }

                        return(m);
                    }
                }
//                catch (Exception e)
//                {
//                    // fallthrough
//                    throw e;
//                }
            }

            return(new IdToGuidDatabase(filename, owner));
        }
		public static IdToGuidDatabase Create(string filename, ILogger owner)
		{
			if (File.Exists(filename))
			{
				//  try
				{
					XmlReaderSettings settings = new XmlReaderSettings();
					settings.IgnoreComments = true;
					settings.IgnoreWhitespace = true;
					using (XmlReader rdr = XmlTextReader.Create(filename, settings))
					{
						IdToGuidDatabase m = new IdToGuidDatabase(filename, owner);

						// skip XML declaration
						do
						{
							if (!rdr.Read())
								throw new XmlException("Unexpected EOF");
						} while (rdr.NodeType != XmlNodeType.Element);

						if (rdr.Name == "InstallerMetadata")
						{
							while (rdr.Read())
							{
								if (rdr.NodeType == XmlNodeType.Element && rdr.Name == "File")
								{
									string id = rdr.GetAttribute("Id");
									string guid = rdr.GetAttribute("Guid");
									if (id == null || guid == null)
										throw new XmlException("Unexpected format");
									m[id] = guid;
								}
								else if (rdr.NodeType == XmlNodeType.EndElement)
								{
									break;
								}
								else
								{
									throw new XmlException("Unexpected format");
								}
							}
						}

						return m;
					}
				}
//                catch (Exception e)
//                {
//                    // fallthrough
//                    throw e;
//                }
			}

			return new IdToGuidDatabase(filename, owner);
		}
        private void ProcessDir(XmlElement parent, string dirPath, string outerDirectoryId)
        {
            LogMessage(MessageImportance.Low, "Processing dir {0}", dirPath);

            XmlDocument   doc   = parent.OwnerDocument;
            List <string> files = new List <string>();

            IdToGuidDatabase guidDatabase = IdToGuidDatabase.Create(Path.Combine(dirPath, kFileNameOfGuidDatabase), this);;

            SetupDirectoryPermissions(dirPath, parent, outerDirectoryId, doc, guidDatabase);

            // Build a list of the files in this directory removing any that have been exluded
            foreach (string f in Directory.GetFiles(dirPath))
            {
                if (_fileMatchPattern.IsMatch(f) && !_ignoreFilePattern.IsMatch(f) && !_ignoreFilePattern.IsMatch(Path.GetFileName(f)) && !m_exclude.ContainsKey(f.ToLower()) &&
                    !f.Contains(kFileNameOfGuidDatabase))
                {
                    files.Add(f);
                }
            }

            // Process all files
            bool isFirst = true;

            foreach (string path in files)
            {
                ProcessFile(parent, path, doc, guidDatabase, isFirst, outerDirectoryId);
                isFirst = false;
            }

            // Recursively process any subdirectories
            foreach (string d in Directory.GetDirectories(dirPath))
            {
                string shortName = Path.GetFileName(d);
                if (!m_exclude.ContainsKey(d.ToLower()) && shortName != ".svn" && shortName != "CVS")
                {
                    string id = GetSafeDirectoryId(d, outerDirectoryId);

                    XmlElement elemDir = doc.CreateElement("Directory", XMLNS);
                    elemDir.SetAttribute("Id", id);
                    elemDir.SetAttribute("Name", shortName);
                    parent.AppendChild(elemDir);

                    ProcessDir(elemDir, d, id);

                    if (elemDir.ChildNodes.Count == 0)
                    {
                        parent.RemoveChild(elemDir);
                    }
                }
            }
        }
		private void ProcessFile(XmlElement parent, string path, XmlDocument doc, IdToGuidDatabase guidDatabase, bool isFirst, string directoryId)
		{

			string guid;
			string name = Path.GetFileName(path);
			string id = directoryId+"."+name; //includ the parent directory id so that files with the same name (e.g. "index.html") found twice in the system will get different ids.

			const int kMaxLength = 50; //I have so far not found out what the max really is
			if (id.Length > kMaxLength)
			{
				id = id.Substring(id.Length - kMaxLength, kMaxLength); //get the last chunk of it
			}
			if (!Char.IsLetter(id[0]) && id[0] != '_')//probably not needed now that we're prepending the parent directory id, accept maybe at the root?
				id = '_' + id;
			id = Regex.Replace(id, @"[^\p{Lu}\p{Ll}\p{Nd}._]", "_");

			LogMessage(MessageImportance.Normal, "Adding file {0} with id {1}", path, id);
			string key = id.ToLower();
			if (m_suffixes.ContainsKey(key))
			{
				int suffix = m_suffixes[key] + 1;
				m_suffixes[key] = suffix;
				id += suffix.ToString();
			}
			else
			{
				m_suffixes[key] = 0;
			}

			// Create <Component> and <File> for this file
			XmlElement elemComp = doc.CreateElement("Component", XMLNS);
			elemComp.SetAttribute("Id", id);
			guid = guidDatabase.GetGuid(id,this.CheckOnly);
			if (guid == null)
				m_filesChanged = true;        // this file is new
			else
				elemComp.SetAttribute("Guid", guid.ToUpper());
			parent.AppendChild(elemComp);

			XmlElement elemFile = doc.CreateElement("File", XMLNS);
			elemFile.SetAttribute("Id", id);
			elemFile.SetAttribute("Name", name);
			if (isFirst)
			{
				elemFile.SetAttribute("KeyPath", "yes");
			}
			string relativePath;
			if (String.IsNullOrEmpty(_installerSourceDirectory))
				relativePath = PathUtil.RelativePathTo(Path.GetDirectoryName(_outputFilePath), path);
			else
				relativePath = PathUtil.RelativePathTo(_installerSourceDirectory, path);
			elemFile.SetAttribute("Source", relativePath);

			if (GiveAllPermissions)
			{
				AddPermissionElement(doc, elemFile);
			}


			elemComp.AppendChild(elemFile);
			InsertFileDeletionInstruction(elemComp);
			m_components.Add(id);

			// check whether the file is newer
			if (File.GetLastWriteTime(path) > m_refDate)
				m_filesChanged = true;
		}
		private void SetupDirectoryPermissions(string dirPath, XmlElement parent, string parentDirectoryId, XmlDocument doc, IdToGuidDatabase guidDatabase)
		{
			if (_giveAllPermissions)
			{
				/*	Need to add one of these in order to set the permissions on the directory
					 * <Component Id="biatahCacheDir" Guid="492F2725-9DF9-46B1-9ACE-E84E70AFEE99">
							<CreateFolder Directory="biatahCacheDir">
								<Permission GenericAll="yes" User="******" />
							</CreateFolder>
						</Component>
					 */

				string id = GetSafeDirectoryId(string.Empty, parentDirectoryId);

				XmlElement componentElement = doc.CreateElement("Component", XMLNS);
				componentElement.SetAttribute("Id", id);
				componentElement.SetAttribute("Guid", guidDatabase.GetGuid(id, this.CheckOnly));

				XmlElement createFolderElement = doc.CreateElement("CreateFolder", XMLNS);
				createFolderElement.SetAttribute("Directory", id);
				AddPermissionElement(doc, createFolderElement);

				componentElement.AppendChild(createFolderElement);
				parent.AppendChild(componentElement);

				m_components.Add(id);
			}
		}
        private void ProcessFile(XmlElement parent, string path, XmlDocument doc, IdToGuidDatabase guidDatabase, bool isFirst, string directoryId)
        {
            string guid;
            string name = Path.GetFileName(path);
            string id   = directoryId + "." + name; //includ the parent directory id so that files with the same name (e.g. "index.html") found twice in the system will get different ids.

            const int kMaxLength = 50;              //I have so far not found out what the max really is

            if (id.Length > kMaxLength)
            {
                id = id.Substring(id.Length - kMaxLength, kMaxLength); //get the last chunk of it
            }
            if (!Char.IsLetter(id[0]) && id[0] != '_')                 //probably not needed now that we're prepending the parent directory id, accept maybe at the root?
            {
                id = '_' + id;
            }
            id = Regex.Replace(id, @"[^\p{Lu}\p{Ll}\p{Nd}._]", "_");

            LogMessage(MessageImportance.Normal, "Adding file {0} with id {1}", path, id);
            string key = id.ToLower();

            if (m_suffixes.ContainsKey(key))
            {
                int suffix = m_suffixes[key] + 1;
                m_suffixes[key] = suffix;
                id += suffix.ToString();
            }
            else
            {
                m_suffixes[key] = 0;
            }

            // Create <Component> and <File> for this file
            XmlElement elemComp = doc.CreateElement("Component", XMLNS);

            elemComp.SetAttribute("Id", id);
            guid = guidDatabase.GetGuid(id, this.CheckOnly);
            if (guid == null)
            {
                m_filesChanged = true;                        // this file is new
            }
            else
            {
                elemComp.SetAttribute("Guid", guid.ToUpper());
            }
            parent.AppendChild(elemComp);

            XmlElement elemFile = doc.CreateElement("File", XMLNS);

            elemFile.SetAttribute("Id", id);
            elemFile.SetAttribute("Name", name);
            if (isFirst)
            {
                elemFile.SetAttribute("KeyPath", "yes");
            }
            string relativePath;

            if (String.IsNullOrEmpty(_installerSourceDirectory))
            {
                relativePath = PathUtil.RelativePathTo(Path.GetDirectoryName(_outputFilePath), path);
            }
            else
            {
                relativePath = PathUtil.RelativePathTo(_installerSourceDirectory, path);
            }
            elemFile.SetAttribute("Source", relativePath);

            if (GiveAllPermissions)
            {
                AddPermissionElement(doc, elemFile);
            }


            elemComp.AppendChild(elemFile);
            InsertFileDeletionInstruction(elemComp);
            m_components.Add(id);

            // check whether the file is newer
            if (File.GetLastWriteTime(path) > m_refDate)
            {
                m_filesChanged = true;
            }
        }
        private void SetupDirectoryPermissions(string dirPath, XmlElement parent, string parentDirectoryId, XmlDocument doc, IdToGuidDatabase guidDatabase)
        {
            if (_giveAllPermissions)
            {
                /*	Need to add one of these in order to set the permissions on the directory
                 * <Component Id="biatahCacheDir" Guid="492F2725-9DF9-46B1-9ACE-E84E70AFEE99">
                 *                      <CreateFolder Directory="biatahCacheDir">
                 *                              <Permission GenericAll="yes" User="******" />
                 *                      </CreateFolder>
                 *              </Component>
                 */

                string id = GetSafeDirectoryId(string.Empty, parentDirectoryId);

                XmlElement componentElement = doc.CreateElement("Component", XMLNS);
                componentElement.SetAttribute("Id", id);
                componentElement.SetAttribute("Guid", guidDatabase.GetGuid(id, this.CheckOnly));

                XmlElement createFolderElement = doc.CreateElement("CreateFolder", XMLNS);
                createFolderElement.SetAttribute("Directory", id);
                AddPermissionElement(doc, createFolderElement);

                componentElement.AppendChild(createFolderElement);
                parent.AppendChild(componentElement);

                m_components.Add(id);
            }
        }