FromXML tweak to validate XML schema

ValidateAndLoadXMLSchemaUpdated
pull/460/merge^2
Buddhika Chathuranga 2020-05-11 00:49:35 +05:30
parent 5e7ddf4480
commit a2740d5eb9
3 changed files with 156 additions and 10 deletions

View File

@ -140,7 +140,28 @@ namespace winsw
public static ServiceDescriptor FromXML(string xml)
{
var dom = new XmlDocument();
dom.LoadXml(xml);
XmlReaderSettings settings = new XmlReaderSettings();
Assembly a = Assembly.GetExecutingAssembly();
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler((object sender, ValidationEventArgs e) => {
if (e.Severity == XmlSeverityType.Error)
{
throw new XmlException("[Error] XML validation - " + e.Message);
}
});
using (Stream schemaStream = a.GetManifestResourceStream("winsw.XMLSchema.xsd"))
{
using (XmlReader schemaReader = XmlReader.Create(schemaStream))
{
settings.Schemas.Add(null, schemaReader);
}
}
var reader = XmlReader.Create(new StringReader(xml), settings);
dom.Load(reader);
return new ServiceDescriptor(dom);
}

View File

@ -3,12 +3,137 @@
<xs:element name="service">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="executable" type="xs:string"/>
</xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="id" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="executable" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="argument" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="arguments" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="logmode" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="workingdirectory" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="logpath" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="delayedAutoStart" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="depend" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="startargument" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="stopexecutable" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="stopargument" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="stoptimeout" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="env" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="interactive" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="onfailure" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="securtityDescriptor" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="priority" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="stopparentprocessfirst" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="errfiledisabled" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="errfilepattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="logname" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="outfiledisabled" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="startmode" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="resetfailure" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="sleeptime" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="waithint" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="outfilepattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<!-- serviceaccount -->
<xs:element name="serviceaccount" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="domain" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="user" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="password" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="allowservicelogon" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
<!-- serviceaccount -->
<!-- log -->
<xs:element name="log" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="sizeThreshold" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="keepFiles" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="autoRollAtTime" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="period" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
<xs:attribute type="xs:string" name="mode"/>
</xs:complexType>
</xs:element>
<!-- log -->
<!-- download -->
<xs:element name="download" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="from"/>
<xs:attribute type="xs:string" name="to"/>
<xs:attribute type="xs:string" name="failOnError"/>
<xs:attribute type="xs:string" name="auth"/>
<xs:attribute type="xs:string" name="user"/>
<xs:attribute type="xs:string" name="password"/>
<xs:attribute type="xs:string" name="unsecureAuth"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!-- download -->
<!-- extensions -->
<xs:element name="extensions">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<!-- extension -->
<xs:element name="extension">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element type="xs:string" name="pidfile"/>
<xs:element type="xs:short" name="stopTimeout"/>
<xs:element type="xs:string" name="stopParentFirst"/>
<xs:element type="xs:string" name="checkWinSWEnvironmentVariable"/>
<!-- mapping -->
<xs:element name="mapping">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="map" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="enabled" use="optional"/>
<xs:attribute type="xs:string" name="label" use="optional"/>
<xs:attribute type="xs:string" name="uncpath" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
<!-- mapping -->
</xs:choice>
<xs:attribute type="xs:string" name="enabled"/>
<xs:attribute type="xs:string" name="true"/>
<xs:attribute type="xs:string" name="className"/>
<xs:attribute type="xs:string" name="id"/>
</xs:complexType>
</xs:element>
<!-- extension -->
</xs:choice>
</xs:complexType>
</xs:element>
<!-- extensions -->
</xs:choice>
</xs:complexType>
</xs:element>

View File

@ -455,13 +455,13 @@ $@"<service>
<executable>jenkins</executable>
</id>";
var dom = new XmlDocument();
XmlDocument dom = new XmlDocument();
dom.LoadXml(seedXml);
var serviceDescriptor = new ServiceDescriptor(dom);
var reader = XmlReader.Create(new StringReader(seedXml));
Assert.That(() => serviceDescriptor.ValidateAndLoadXmlSchema(reader), Throws.TypeOf<XmlException>());
Assert.That(() => serviceDescriptor.ValidateAndLoadXmlSchema(reader), Throws.Exception.TypeOf<XmlException>());
}
}
}