/// <summary> /// Adds a set of object definitions to the schema. The format of the schema /// is a sequence of lines where objects are separated by empty lines. /// Each line of an object definition is a pair of an attribute display name and an /// attribute value, separated by ':'. Takes care of "bootstrapping" the contents of /// the schema, resolving cyclic dependencies between attribute definitions and objects. /// </summary> /// <param name="schema">The schema, represented as explained above.</param> /// <param name="valueSubstitution">A substitution of strings which should be applied to each value in the /// schema. For example, may map '<rootdomaindn>' as used in schemas to represent the root name of the /// current DC to an actual value</param> /// <param name="serverVersion">Specify the OS version of the server</param> /// <returns>Result of the Load Schema method.</returns> public ModelResult LoadSchema(IEnumerable<string> schema, Map<string, string> valueSubstitution, OSVersion serverVersion) { SequenceContainer<ModelObject> newObjects = new SequenceContainer<ModelObject>(); UnresolvedSyntax unresolvedSyntax = new UnresolvedSyntax(); #region Pass 1: read in objects resolving only builtin attributes // We need this phase for bootstrapping, as we don't have the // attributes available which are used in the objects. Thus // in this phase, we just parse attribute values of a certain set // of builting attributes which are required to get attribute syntax // definitions. InitializeBuiltinAttributes(); ModelObject tempobj = null; ModelObject obj = null; foreach (string rawLine in schema) { string line = (rawLine == null)?null:rawLine.Trim(); if (String.IsNullOrEmpty(line)) { // Object ends here if (obj != null) { if (obj[StandardNames.attributeID] == null && obj[StandardNames.governsId] == null) { if (obj.attributes.Count == 1) { // If the server is Windows 2000 if (serverVersion == OSVersion.WinSvr2000) { string attr = obj.attributes.Keys.ElementAt(0); if (tempobj.attributes.Keys.Contains(attr)) { tempobj.attributes.Keys.Remove(attr); tempobj.attributes.Add(obj.attributes.ElementAt(0)); } else { tempobj.attributes.Add(obj.attributes.ElementAt(0)); } newObjects.RemoveAt(newObjects.Count - 1); newObjects.Add(tempobj); } } else { Checks.Fail("attributeId/governsId is mandatory for each object {0}.", obj[StandardNames.cn]); } } else if (obj[StandardNames.attributeID] != null) { AddAttribute(obj); newObjects.Add(obj); } else if (obj[StandardNames.governsId] != null) { // This is a class definition. Fill in class map. AddClass(obj); newObjects.Add(obj); } tempobj = obj; obj = null; } } else { if (obj == null) { obj = new ModelObject(); } obj.dc = this; string attr, valueString; string[] splits = line.Split(new char[] { ':' }, 2); if (splits == null || splits.Length != 2) { Checks.Fail("invalid schema line '{0}'", line); continue; } attr = splits[0].Trim().ToLower(); valueString = Substitute(valueSubstitution, splits[1].Trim()); AttributeContext parsingContext; if (!builtinAttributeSyntax.TryGetValue(attr, out parsingContext)) { parsingContext = new AttributeContext(this, attr, unresolvedSyntax); } obj[attr] = parsingContext.Parse(valueString); } } #endregion #region Pass 2: resolve syntax of all new objects // As we have now attribute definitions which map to the syntax, we can parse // All values in the new objects. foreach (ModelObject newObj in newObjects) { foreach (string attr in newObj.attributes.Keys) { AttributeContext parsingContext = GetAttributeContext(attr); Value value = newObj[attr]; if (value.Syntax is UnresolvedSyntax) { newObj[attr] = parsingContext.Parse((string)value); } else { Checks.IsTrue( parsingContext.syntax == value.Syntax, "bultin syntax assignment of '{0}' must match syntax declared in schema", attr); } } } #endregion #region Pass 3: add objects // Now all definitions are complete. Add them to schema replica root. foreach (ModelObject newObj in newObjects) { AddChild(schemaReplica.root, newObj); } #endregion #region Pass 4: check consistency // The tree is finally setup. Now check for consistency Consistency.Check(newObjects.ToSequence()); #endregion if (Checks.HasDiagnostics) { return new ModelResult(ResultCode.ConstraintViolation, Checks.GetAndClearLog(), Checks.GetAndClearDiagnostics()); } else { //return Result.Success; ModelResult tempRes = new ModelResult(ResultCode.Success); tempRes.logMessage = Checks.GetAndClearLog(); return tempRes; } }
public static void ClassInitialize(TestContext testContext) { TestClassBase.Initialize(testContext); // Initializing the ITestSite object if (null == DataSchemaSite) { DataSchemaSite = TestClassBase.BaseTestSite; } adAdapter = new ADDataSchemaAdapter(); adAdapter.Initialize(DataSchemaSite); //Model for AD/DS dcModel = new ModelDomainController(adAdapter.rootDomainDN, null); //Protocol Short Name. DataSchemaSite.DefaultProtocolDocShortName = "MS-ADTS-Schema"; //Specifying the windows version ServerVersion serverVersion = (ServerVersion)adAdapter.PDCOSVersion; if (serverVersion == ServerVersion.Win2003) { serverOS = OSVersion.WinSvr2003; } else if (serverVersion == ServerVersion.Win2008) { serverOS = OSVersion.WinSvr2008; } else if (serverVersion == ServerVersion.Win2008R2) { serverOS = OSVersion.WinSvr2008R2; } else if (serverVersion == ServerVersion.Win2012) { serverOS = OSVersion.WinSvr2012; } else if (serverVersion == ServerVersion.Win2012R2) { serverOS = OSVersion.WinSvr2012R2; } else if (serverVersion == ServerVersion.Win2016) { serverOS = OSVersion.Win2016; } else if (serverVersion == ServerVersion.Winv1803) { serverOS = OSVersion.Winv1803; } else { serverOS = OSVersion.OtherOS; } //Storing the XML paths. string[] tdSources; if (serverVersion <= ServerVersion.Win2012R2) { tdSources = adAdapter.TDXmlPath.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); } else { tdSources = adAdapter.OpenXmlPath.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); } Map <string, string> rootDomainDNSubs = new Map <string, string>().Add("<RootDomainDN>", adAdapter.rootDomainDN); DSSchemaLoadResult = dcModel.LoadSchema( SchemaReader.ReadSchema( tdSources, null, true, serverOS), rootDomainDNSubs, serverOS); if (adAdapter.RunLDSTestCases) { string[] ldsTdSource; if (serverVersion <= ServerVersion.Win2012R2) { ldsTdSource = adAdapter.LdsTDXmlPath.Split(','); } else { ldsTdSource = adAdapter.LdsOpenXmlPath.Split(','); } //Model for AD/LDS adamModel = new ModelDomainController(adAdapter.LDSRootObjectName, null); Map <string, string> adamRootDomainDNSubs = new Map <string, string>().Add("<RootDomainDN>", adAdapter.LDSRootObjectName); LDSSchemaLoadResult = adamModel.LoadSchema( SchemaReader.ReadSchema( ldsTdSource, null, true, serverOS), adamRootDomainDNSubs, serverOS); } }