} // proc IncludeConfigTree private void MergeConfigTree(ParseContext context, XProcessingInstruction xPI) { var xDoc = context.LoadFile(xPI, xPI.Data); // parse the loaded document var fileToken = new XFileAnnotation(); var newFrame = context.PushFrame(xPI); if (xDoc.Root.Name != DEConfigurationConstants.xnFragment) { throw context.CreateConfigException(xDoc.Root, "<fragment> expected."); } ParseConfiguration(context, xDoc.Root, fileToken); context.PopFrame(newFrame); // merge the parsed nodes MergeConfigTree(xPI.Document.Root, xDoc.Root, fileToken); } // proc MergeConfigTree
} // proc MergeConfigTree private void MergeConfigTree(XElement xRoot, XElement xMerge, XFileAnnotation currentFileToken) { // merge attributes var attributeMerge = xMerge.FirstAttribute; while (attributeMerge != null) { var attributeRoot = xRoot.Attribute(attributeMerge.Name); if (attributeRoot == null) // attribute does not exists --> insert { xRoot.SetAttributeValue(attributeMerge.Name, attributeMerge.Value); } else // attribute exists --> override or combine lists { var attributeDefinition = GetAttribute(attributeMerge); if (attributeDefinition != null) { if (attributeDefinition.IsList) // list detected { attributeRoot.Value = attributeRoot.Value + " " + attributeMerge.Value; } else { var a = attributeRoot.Annotation <XFileAnnotation>(); if (a != null && a != currentFileToken) // check for annotation, that marks the base file content { attributeRoot.Value = attributeMerge.Value; } } } } attributeMerge = attributeMerge.NextAttribute; } // merge elements var xCurNodeMerge = xMerge.FirstNode; while (xCurNodeMerge != null) { var xCurMerge = xCurNodeMerge as XElement; var xNextNode = xCurNodeMerge.NextNode; if (xCurMerge != null) { var xCurRoot = FindConfigTreeElement(xRoot, xCurMerge); if (xCurRoot == null) // node is not present -> include { Procs.XCopyAnnotations(xCurMerge, xCurMerge); xCurMerge.Remove(); xRoot.Add(xCurMerge); } else // merge node { MergeConfigTree(xCurRoot, xCurMerge, currentFileToken); } } xCurNodeMerge = xNextNode; } } // proc MergeConfigTree
} // proc ValidationEvent private void ParseConfiguration(ParseContext context, XContainer x, XFileAnnotation fileToken) { var c = x.FirstNode; while (c != null) { var deleteMe = (XNode)null; var value = (string)null; if (c is XComment) { deleteMe = c; } else if (c is XProcessingInstruction) { ParseConfigurationPI(context, (XProcessingInstruction)c); deleteMe = c; } else { if (context.CurrentFrame.IsDeleteNodes) { deleteMe = c; } else if (c is XElement) { var xCur = (XElement)c; // Replace values in attributes foreach (var attr in xCur.Attributes()) { if (ChangeConfigurationValue(context, attr, attr.Value, out value)) { attr.Value = value; } // mark the attribute with the current frame if (attr.Annotation <XFileAnnotation>() == null) { attr.AddAnnotation(fileToken); } } // Parse the current element var newFrame = context.PushFrame(xCur); ParseConfiguration(context, xCur, fileToken); context.PopFrame(newFrame); // Load assemblies -> they preprocessor needs them if (xCur.Name == xnServer) { foreach (var cur in xCur.Elements()) { if (cur.Name == xnServerResolve) // resolve paths { if (ChangeConfigurationValue(context, cur, cur.Value, out value)) { cur.Value = value; } switch (cur.GetAttribute("type", "net")) { case "net": resolver?.AddPath(cur.Value); break; case "platform": resolver?.AddPath(cur.Value); if (IntPtr.Size == 4) // 32bit { DEServer.AddToProcessEnvironment(Path.Combine(cur.Value, "x86")); } else { DEServer.AddToProcessEnvironment(Path.Combine(cur.Value, "x64")); } break; case "envonly": DEServer.AddToProcessEnvironment(cur.Value); break; default: throw context.CreateConfigException(cur, "resolve @type has an invalid attribute value."); } } else if (cur.Name == xnServerLoad) { if (ChangeConfigurationValue(context, cur, cur.Value, out value)) { cur.Value = value; } try { UpdateSchema(Assembly.Load(cur.Value)); } catch (Exception e) { throw context.CreateConfigException(cur, String.Format("Failed to load assembly ({0}).", cur.Value), e); } } } } } else if (c is XText) { XText xText = (XText)c; if (ChangeConfigurationValue(context, xText, xText.Value, out value)) { xText.Value = value; } } } // Nächster Knoten c = c.NextNode; // Lösche den Knoten, sonst würde Next nicht funktionieren if (deleteMe != null) { deleteMe.Remove(); } } } // proc ParseConfiguration