protected Object ProcessInputStream(Stream template, string identifier, ProvisioningTemplate result) { if (template == null) { throw new ArgumentNullException(nameof(template)); } // Crate a copy of the source stream MemoryStream sourceStream = new MemoryStream(); template.CopyTo(sourceStream); sourceStream.Position = 0; // Check the provided template against the XML schema if (!this.IsValid(sourceStream)) { // TODO: Use resource file throw new ApplicationException("The provided template is not valid!"); } sourceStream.Position = 0; XDocument xml = XDocument.Load(sourceStream); XNamespace pnp = this.NamespaceUri; // Prepare a variable to hold the single source formatted template TSchemaTemplate source = default(TSchemaTemplate); // Determine if we're working on a wrapped ProvisioningTemplate or not if (xml.Root.Name == pnp + "Provisioning") { // Deserialize the whole wrapper Object wrapper = null; var wrapperType = Type.GetType($"{PnPSerializationScope.Current?.BaseSchemaNamespace}.Provisioning, {PnPSerializationScope.Current?.BaseSchemaAssemblyName}", true); XmlSerializer xmlSerializer = new XmlSerializer(wrapperType); using (var reader = xml.Root.CreateReader()) { wrapper = xmlSerializer.Deserialize(reader); } // Handle the Parameters of the schema wrapper, if any var tps = new TemplateParametersSerializer(); tps.Deserialize(wrapper, result); // Handle the Localizations of the schema wrapper, if any var ls = new LocalizationsSerializer(); ls.Deserialize(wrapper, result); // Handle the Tenant-wide settings of the schema wrapper, if any var ts = new TenantSerializer(); ts.Deserialize(wrapper, result); // Get the list of templates, if any, wrapped by the wrapper var wrapperTemplates = wrapperType.GetProperty("Templates", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(wrapper); if (wrapperTemplates != null) { // Search for the requested Provisioning Template foreach (var templates in (IEnumerable)wrapperTemplates) { // Let's see if we have an in-place template with the provided ID or if we don't have a provided ID at all var provisioningTemplates = templates.GetType() .GetProperty("ProvisioningTemplate", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(templates); if (provisioningTemplates != null) { foreach (var t in (IEnumerable)provisioningTemplates) { var templateId = (String)t.GetType().GetProperty("ID", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(t); if ((templateId != null && templateId == identifier) || String.IsNullOrEmpty(identifier)) { source = (TSchemaTemplate)t; } } if (source == null) { var provisioningTemplateFiles = templates.GetType() .GetProperty("ProvisioningTemplateFile", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(templates); // If we don't have a template, but there are external file references if (source == null && provisioningTemplateFiles != null) { foreach (var f in (IEnumerable)provisioningTemplateFiles) { var templateId = (String)f.GetType().GetProperty("ID", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(f); if ((templateId != null && templateId == identifier) || String.IsNullOrEmpty(identifier)) { // Let's see if we have an external file for the template var externalFile = (String)f.GetType().GetProperty("File", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase).GetValue(f); Stream externalFileStream = this.Provider.Connector.GetFileStream(externalFile); xml = XDocument.Load(externalFileStream); if (xml.Root.Name != pnp + "ProvisioningTemplate") { throw new ApplicationException("Invalid external file format. Expected a ProvisioningTemplate file!"); } else { source = XMLSerializer.Deserialize <TSchemaTemplate>(xml); } } } } } } if (source != null) { break; } } } } else if (xml.Root.Name == pnp + "ProvisioningTemplate") { var IdAttribute = xml.Root.Attribute("ID"); // If there is a provided ID, and if it doesn't equal the current ID if (!String.IsNullOrEmpty(identifier) && IdAttribute != null && IdAttribute.Value != identifier) { // TODO: Use resource file throw new ApplicationException("The provided template identifier is not available!"); } else { source = XMLSerializer.Deserialize <TSchemaTemplate>(xml); } } return(source); }
public ProvisioningHierarchy ToProvisioningHierarchy(Stream hierarchy) { // Create a copy of the source stream MemoryStream sourceStream = new MemoryStream(); hierarchy.Position = 0; hierarchy.CopyTo(sourceStream); sourceStream.Position = 0; // Check the provided template against the XML schema if (!this.IsValid(sourceStream)) { // TODO: Use resource file throw new ApplicationException("The provided provisioning file is not valid!"); } // Prepare the output variable ProvisioningHierarchy resultHierarchy = new ProvisioningHierarchy(); // Determine if the file is a provisioning hierarchy sourceStream.Position = 0; XDocument xml = XDocument.Load(sourceStream); if (xml.Root.Name.LocalName != "Provisioning") { throw new ApplicationException("The provided provisioning file is not a Hierarchy!"); } // Determine the specific formatter needed for the current provisioning file var innerFormatter = XMLPnPSchemaFormatter.GetSpecificFormatter( xml.Root.Name.NamespaceName); // Process all the provisioning templates included in the hierarchy, if any XmlNamespaceManager nsManager = new XmlNamespaceManager(new System.Xml.NameTable()); nsManager.AddNamespace("pnp", xml.Root.Name.NamespaceName); // Start with templates embedded in the provisioning file var templates = xml.XPathSelectElements("/pnp:Provisioning/pnp:Templates/pnp:ProvisioningTemplate", nsManager).ToList(); foreach (var template in templates) { // Save the single template into a MemoryStream MemoryStream templateStream = new MemoryStream(); template.Save(templateStream); templateStream.Position = 0; // Process the single template with the classic technique var provisioningTemplate = innerFormatter.ToProvisioningTemplate(templateStream); // Add the generated template to the resulting hierarchy resultHierarchy.Templates.Add(provisioningTemplate); } // Then process any external file reference var templateFiles = xml.XPathSelectElements("/pnp:Provisioning/pnp:Templates/pnp:ProvisioningTemplateFile", nsManager).ToList(); foreach (var template in templateFiles) { var templateID = template.Attribute("ID")?.Value; var templateFile = template.Attribute("File")?.Value; if (!String.IsNullOrEmpty(templateFile) && !String.IsNullOrEmpty(templateID)) { // Process the single template file with the classic technique var provisioningTemplate = this._provider.GetTemplate(templateFile); provisioningTemplate.Id = templateID; // Add the generated template to the resulting hierarchy resultHierarchy.Templates.Add(provisioningTemplate); } } // And now process the top level children elements // using schema specific serializers using (var scope = new PnPSerializationScope(typeof(TSchemaTemplate))) { // We prepare a dummy template to leverage the existing serialization infrastructure var dummyTemplate = new ProvisioningTemplate(); dummyTemplate.Id = $"DUMMY-{Guid.NewGuid()}"; resultHierarchy.Templates.Add(dummyTemplate); // Deserialize the whole wrapper Object wrapper = null; var wrapperType = Type.GetType($"{PnPSerializationScope.Current?.BaseSchemaNamespace}.Provisioning, {PnPSerializationScope.Current?.BaseSchemaAssemblyName}", true); XmlSerializer xmlSerializer = new XmlSerializer(wrapperType); using (var reader = xml.Root.CreateReader()) { wrapper = xmlSerializer.Deserialize(reader); } // Handle the Parameters of the schema wrapper, if any var tps = new TemplateParametersSerializer(); tps.Deserialize(wrapper, dummyTemplate); // Handle the Localizations of the schema wrapper, if any var ls = new LocalizationsSerializer(); ls.Deserialize(wrapper, dummyTemplate); // Handle the Tenant-wide settings of the schema wrapper, if any var ts = new TenantSerializer(); ts.Deserialize(wrapper, dummyTemplate); // Handle the Sequences var ss = new SequenceSerializer(); ss.Deserialize(wrapper, dummyTemplate); // Handle the Provisioning Hierarchy properties var phs = new ProvisioningHierarchySerializer(); phs.Deserialize(wrapper, dummyTemplate); // Remove the dummy template from the hierarchy resultHierarchy.Templates.Remove(dummyTemplate); } return(resultHierarchy); }