internal UidWriter(UidCollector collector, Stream source, Stream target) { _collector = collector; _sourceReader = new StreamReader(source); UTF8Encoding encoding = new UTF8Encoding(true); _targetWriter = new StreamWriter(target, encoding); _lineBuffer = new LineBuffer(_sourceReader.ReadLine()); }
/// <summary> /// Verify the Uids in the file /// </summary> /// <param name="collector">UidCollector containing all Uid instances</param> /// <param name="logError">true to log errors while verifying</param> /// <returns>true indicates no errors</returns> private bool VerifyUid( UidCollector collector, bool logError ) { bool errorFound = false; for (int i = 0; i < collector.Count; i++) { Uid currentUid = collector[i]; if (currentUid.Status == UidStatus.Absent) { // Uid missing if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.UidMissing, currentUid.ElementName ); } errorFound = true; } else if (currentUid.Status == UidStatus.Duplicate) { // Uid duplicates if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.MultipleUidUse, currentUid.Value, currentUid.ElementName ); } errorFound = true; } } return(!errorFound); }
/// <summary> /// Parse the input file and get all the information of Uids /// </summary> /// <param name="fileName">input file</param> /// <returns>UidCollector containing all the information for the Uids in the file</returns> private UidCollector ParseFile(string fileName) { UidCollector collector = new UidCollector(fileName); using (Stream xamlStream = File.OpenRead(fileName)) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext( null, // nametable nsmgr, // namespace manager null, // xml:Lang scope XmlSpace.Default // XmlSpace ); XmlTextReader reader = new XmlTextReader( xamlStream, // xml stream XmlNodeType.Document, // parsing document context // parser context ); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: { if (collector.RootElementLineNumber < 0) { collector.RootElementLineNumber = reader.LineNumber; collector.RootElementLinePosition = reader.LinePosition; } if (reader.Name.IndexOf('.') >= 0) { // the name has a dot, which suggests it is a property tag. // we will ignore adding uid continue; } Uid currentUid = new Uid( reader.LineNumber, reader.LinePosition + reader.Name.Length, reader.Name, SpaceInsertion.BeforeUid // insert space before the Uid );; if (reader.HasAttributes) { reader.MoveToNextAttribute(); // As a heuristic to better preserve the source file, add uid to the place of the // first attribute currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; currentUid.Space = SpaceInsertion.AfterUid; do { string namespaceUri = nsmgr.LookupNamespace(reader.Prefix); if (reader.LocalName == XamlReaderHelper.DefinitionUid && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Uid attribute, store the actual value and position currentUid.Value = reader.Value; currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefaultNamespaceURI) { // found Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.Prefix == "xmlns") { // found a namespace declaration, store the namespace prefix // so that when we need to add a new namespace declaration later // we won't reuse the namespace prefix. collector.AddNamespacePrefix(reader.LocalName); } }while (reader.MoveToNextAttribute()); } if (currentUid.Value == null) { // there is no x:Uid found on this element, we need to resolve the // namespace prefix in order to add the Uid string prefix = nsmgr.LookupPrefix(XamlReaderHelper.DefinitionNamespaceURI); if (prefix != string.Empty) { currentUid.NamespacePrefix = prefix; } } collector.AddUid(currentUid); break; } } } } return(collector); }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ private bool ManageUids() { int countGoodFiles = 0; // enumerate through each file foreach (ITaskItem inputFile in _markupFiles) { Log.LogMessageFromResources(SRID.CheckingUids, inputFile.ItemSpec); switch (_task) { case UidTask.Check: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool success = VerifyUid( collector, // uid collector true // log error ); if (success) { countGoodFiles++; } break; } case UidTask.Update: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool success = VerifyUid( collector, // uid collector false // log error ); if (!success) { if (SetupBackupDirectory()) { // resolve errors collector.ResolveUidErrors(); // temp file to write to string tempFile = GetTempFileName(inputFile.ItemSpec); // backup file of the source file before it is overwritten. string backupFile = GetBackupFileName(inputFile.ItemSpec); using (Stream uidStream = new FileStream(tempFile, FileMode.Create)) { using (Stream source = File.OpenRead(inputFile.ItemSpec)) { UidWriter writer = new UidWriter(collector, source, uidStream); writer.UpdateUidWrite(); } } // backup source file by renaming it. Expect to be (close to) atomic op. RenameFile(inputFile.ItemSpec, backupFile); // rename the uid output onto the source file. Expect to be (close to) atomic op. RenameFile(tempFile, inputFile.ItemSpec); // remove the temp files RemoveFile(tempFile); RemoveFile(backupFile); countGoodFiles++; } } else { // all uids are good. No-op countGoodFiles++; } break; } case UidTask.Remove: { UidCollector collector = ParseFile(inputFile.ItemSpec); bool hasUid = false; for (int i = 0; i < collector.Count; i++) { if (collector[i].Status != UidStatus.Absent) { hasUid = true; break; } } if (hasUid) { if (SetupBackupDirectory()) { // temp file to write to string tempFile = GetTempFileName(inputFile.ItemSpec); // backup file of the source file before it is overwritten. string backupFile = GetBackupFileName(inputFile.ItemSpec); using (Stream uidStream = new FileStream(tempFile, FileMode.Create)) { using (Stream source = File.OpenRead(inputFile.ItemSpec)) { UidWriter writer = new UidWriter(collector, source, uidStream); writer.RemoveUidWrite(); } } // rename the source file to the backup file name. Expect to be (close to) atomic op. RenameFile(inputFile.ItemSpec, backupFile); // rename the output file over to the source file. Expect to be (close to) atomic op. RenameFile(tempFile, inputFile.ItemSpec); // remove the temp files RemoveFile(tempFile); RemoveFile(backupFile); countGoodFiles++; } } else { // There is no Uid in the file. No need to do remove. countGoodFiles++; } break; } } } // spew out the overral log info for the task switch (_task) { case UidTask.Remove: Log.LogMessageFromResources(SRID.FilesRemovedUid, countGoodFiles); break; case UidTask.Update: Log.LogMessageFromResources(SRID.FilesUpdatedUid, countGoodFiles); break; case UidTask.Check: Log.LogMessageFromResources(SRID.FilesPassedUidCheck, countGoodFiles); if (_markupFiles.Length > countGoodFiles) { Log.LogErrorWithCodeFromResources(SRID.FilesFailedUidCheck, _markupFiles.Length - countGoodFiles); } break; } return(_markupFiles.Length == countGoodFiles); }
internal UidWriter(UidCollector collector, Stream source, Stream target) { _collector = collector; _sourceReader = new StreamReader(source); UTF8Encoding encoding = new UTF8Encoding(true); _targetWriter = new StreamWriter(target, encoding); _lineBuffer = new LineBuffer(_sourceReader.ReadLine()); }
/// <summary> /// Parse the input file and get all the information of Uids /// </summary> /// <param name="fileName">input file</param> /// <returns>UidCollector containing all the information for the Uids in the file</returns> private UidCollector ParseFile(string fileName) { UidCollector collector = new UidCollector(fileName ); using (Stream xamlStream = File.OpenRead(fileName)) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext( null, // nametable nsmgr, // namespace manager null, // xml:Lang scope XmlSpace.Default // XmlSpace ); XmlTextReader reader = new XmlTextReader( xamlStream, // xml stream XmlNodeType.Document, // parsing document context // parser context ); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element : { if (collector.RootElementLineNumber < 0) { collector.RootElementLineNumber = reader.LineNumber; collector.RootElementLinePosition = reader.LinePosition; } if (reader.Name.IndexOf('.') >= 0) { // the name has a dot, which suggests it is a property tag. // we will ignore adding uid continue; } Uid currentUid = new Uid( reader.LineNumber, reader.LinePosition + reader.Name.Length, reader.Name, SpaceInsertion.BeforeUid // insert space before the Uid ); ; if (reader.HasAttributes) { reader.MoveToNextAttribute(); // As a heuristic to better preserve the source file, add uid to the place of the // first attribute currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; currentUid.Space = SpaceInsertion.AfterUid; do { string namespaceUri = nsmgr.LookupNamespace(reader.Prefix); if (reader.LocalName == XamlReaderHelper.DefinitionUid && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Uid attribute, store the actual value and position currentUid.Value = reader.Value; currentUid.LineNumber = reader.LineNumber; currentUid.LinePosition = reader.LinePosition; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefaultNamespaceURI) { // found Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.LocalName == "Name" && namespaceUri == XamlReaderHelper.DefinitionNamespaceURI) { // found x:Name attribute, store the Name value currentUid.FrameworkElementName = reader.Value; } else if (reader.Prefix == "xmlns") { // found a namespace declaration, store the namespace prefix // so that when we need to add a new namespace declaration later // we won't reuse the namespace prefix. collector.AddNamespacePrefix(reader.LocalName); } } while (reader.MoveToNextAttribute()); } if (currentUid.Value == null) { // there is no x:Uid found on this element, we need to resolve the // namespace prefix in order to add the Uid string prefix = nsmgr.LookupPrefix(XamlReaderHelper.DefinitionNamespaceURI); if (prefix != string.Empty) currentUid.NamespacePrefix = prefix; } collector.AddUid(currentUid); break; } } } } return collector; }
/// <summary> /// Verify the Uids in the file /// </summary> /// <param name="collector">UidCollector containing all Uid instances</param> /// <param name="logError">true to log errors while verifying</param> /// <returns>true indicates no errors</returns> private bool VerifyUid( UidCollector collector, bool logError ) { bool errorFound = false; for (int i = 0; i < collector.Count; i++) { Uid currentUid = collector[i]; if (currentUid.Status == UidStatus.Absent) { // Uid missing if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.UidMissing, currentUid.ElementName ); } errorFound = true; } else if (currentUid.Status == UidStatus.Duplicate) { // Uid duplicates if (logError) { Log.LogErrorWithCodeFromResources( null, collector.FileName, currentUid.LineNumber, currentUid.LinePosition, 0, 0, SRID.MultipleUidUse, currentUid.Value, currentUid.ElementName ); } errorFound = true; } } return !errorFound; }