/// <summary> /// Parses a contentsOfVariableName specification in composition XML in its short-hand form. /// </summary> public static object ParseWindowsRegistry(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string keyPath = null; string valueName = null; foreach (var attribute in attributes) { switch (attribute.Name) { case "windowsRegistryKeyPath": keyPath = attribute.Value; break; case "windowsRegistryValueName": valueName = attribute.Value; break; default: context.ReportError( string.Format("Attribute name {0} is not supported for windowsRegistry value elements.", attribute.Name)); return(null); } } if (keyPath == null) { context.ReportError("Attribute 'windowsRegistryKeyPath' is required."); return(null); } return(ParseWindowsRegistry(keyPath, valueName, context)); }
/// <summary> /// Used for parsing short-hand form of specifying an object in the parent element /// </summary> public static object ParseObject(XmlAttribute[] attributes, XmlElement[] childElements, XmlProcessingContext context) { string typeName = null; var initializePlugs = false; foreach (var attribute in attributes) { switch (attribute.Name) { case "objectType": typeName = attribute.Value; break; case "objectInitializePlugs": initializePlugs = Boolean.Parse(attribute.Value); break; default: context.ReportError( string.Format("Attribute name {0} is not supported for object value elements.", attribute.Name)); return(null); } } if (typeName == null) { context.ReportError("Attribute 'objectType' is required."); return(null); } return(ParseObject(typeName, initializePlugs, childElements, context)); }
private static void ParseDictionaryItem(IDictionary result, XmlElement childElement, XmlProcessingContext xmlProcessingContext) { if (childElement.GetElementsByTagName("Key").Count != 1) { xmlProcessingContext.ReportError( "Each 'Item' in a 'Dictionary' should contain exactly one 'Key' element as a nested tag."); return; } if (childElement.GetElementsByTagName("Value").Count != 1) { xmlProcessingContext.ReportError( "Each 'Item' in a 'Dictionary' should contain exactly one 'Value' element as a nested tag."); return; } xmlProcessingContext.EnterRunningLocation("Key"); var keyValue = XmlValueParser.ParseValue((XmlElement)childElement.GetElementsByTagName("Key")[0], xmlProcessingContext, null); xmlProcessingContext.LeaveRunningLocation(); xmlProcessingContext.EnterRunningLocation("Value"); var valueValue = XmlValueParser.ParseValue((XmlElement)childElement.GetElementsByTagName("Value")[0], xmlProcessingContext, null); xmlProcessingContext.LeaveRunningLocation(); result.Add(keyValue, valueValue); }
/// <summary> /// Parses a contentsOfVariableName specification in composition XML in its short-hand form. /// </summary> public static object ParseContentsOfVariable(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string variableName = null; foreach (var attribute in attributes) { if (attribute.Name == "contentsOfVariableName") { variableName = attribute.Value; } else { context.ReportError( string.Format("Attribute name {0} is not supported for contentsOfVariable value elements.", attribute.Name)); return(null); } } if (variableName == null) { context.ReportError("Attribute 'contentsOfVariableName' is required."); return(null); } return(ParseContentsOfVariable(variableName, context)); }
/// <summary> /// Parses a ContentsOfVariable element in the composition XML. /// </summary> public static object ParseWindowsRegistry(XmlElement element, XmlProcessingContext context) { if (element.ChildNodes.Count > 0) { context.ReportError("'WindowsRegistry' elements should not contain any child elements."); return(null); } string keyPath = null; string valueName = null; if (element.Attributes["keyPath"] != null) { keyPath = element.Attributes["keyPath"].Value; } if (element.Attributes["valueName"] != null) { valueName = element.Attributes["valueName"].Value; } if (keyPath == null) { context.ReportError("'WindowsRegistry' elements require a 'keyPath' attribute."); return(null); } return(ParseWindowsRegistry(keyPath, valueName, context)); }
private static void ParseObjectProperty(object result, XmlElement childElement, XmlProcessingContext xmlProcessingContext) { if (childElement.Attributes["name"] == null) { xmlProcessingContext.ReportError("'Property' element in the composition XML should have a 'name' attribute."); return; } var propertyName = childElement.Attributes["name"].Value; xmlProcessingContext.EnterRunningLocation(string.Format("Property({0})", propertyName)); var propertyInfo = result.GetType().GetProperty(propertyName); if (propertyInfo == null) { xmlProcessingContext.ReportError( string.Format("Object type '{0}' does not contain a property definition named '{1}", result.GetType().FullName, propertyName)); xmlProcessingContext.LeaveRunningLocation(); return; } var propertyValue = XmlValueParser.ParseValue(childElement, xmlProcessingContext, ObjectPropertyExcludedAttributes); propertyInfo.SetValue(result, propertyValue, null); xmlProcessingContext.LeaveRunningLocation(); }
/// <summary> /// Used for parsing short-hand array specification in composition XML. /// </summary> public static Array ParseArray(IEnumerable <XmlAttribute> attributes, XmlElement[] childElements, XmlProcessingContext context) { string elementType = null; foreach (var attribute in attributes) { if (attribute.Name == "arrayElementType") { elementType = attribute.Value; } else { context.ReportError(string.Format("Attribute name {0} is not supported for array value elements.", attribute.Name)); return(null); } } if (elementType == null) { context.ReportError("Attribute 'arrayElementType' is required."); return(null); } return(ParseArray(elementType, childElements, context)); }
/// <summary> /// Parses an Assembly element in the composition XML. /// </summary> public static Assembly ParseAssembly(XmlElement element, XmlProcessingContext context) { if (element.ChildNodes.Count > 0) { context.ReportError("Type elements should not contain any child elements."); return(null); } string assemblyName = null; if (element.Attributes["name"] != null) { assemblyName = element.Attributes["name"].Value; } var result = ParseAssembly(assemblyName, context); if (result == null) { context.EnterRunningLocation(string.Format("Assembly({0})", assemblyName)); context.ReportError("Could not load assembly '" + assemblyName + "'."); context.LeaveRunningLocation(); return(null); } return(result); }
/// <summary> /// Parses a Ref specification in the short-hand form from a /// composition XML. /// </summary> public static object ParseRef(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string refType = null; string refName = null; foreach (var attribute in attributes) { switch (attribute.Name) { case "refType": refType = attribute.Value; break; case "refName": refName = attribute.Value; break; default: context.ReportError( string.Format("Attribute name {0} is not supported for ref value elements.", attribute.Name)); return(null); } } if (refType == null) { context.ReportError("Attribute 'refType' is required."); return(null); } return(ParseRef(refType, refName, context)); }
private static void ParseObjectField(object result, XmlElement childElement, XmlProcessingContext xmlProcessingContext) { if (childElement.Attributes["name"] == null) { xmlProcessingContext.ReportError("'Field' element in the composition XML should have a 'name' attribute."); return; } var fieldName = childElement.Attributes["name"].Value; xmlProcessingContext.EnterRunningLocation(string.Format("Field({0})", fieldName)); var fieldInfo = result.GetType().GetField(fieldName); if (fieldInfo == null) { xmlProcessingContext.ReportError( string.Format("Object type '{0}' does not contain a field definition named '{1}", result.GetType().FullName, fieldName)); xmlProcessingContext.LeaveRunningLocation(); return; } var fieldValue = XmlValueParser.ParseValue(childElement, xmlProcessingContext, objectFieldExcludedAttributes); fieldInfo.SetValue(result, fieldValue); xmlProcessingContext.LeaveRunningLocation(); }
/// <summary> /// Actually parses an Enum specification in the composition XML, and /// is used in both element form, and short-hand forms. /// </summary> public static object ParseEnum(string enumTypeName, string enumValue, XmlProcessingContext context) { if (enumTypeName == null) { throw new ArgumentNullException("enumTypeName"); } if (enumValue == null) { throw new ArgumentNullException("enumValue"); } context.EnterRunningLocation(string.Format("enum({0}, {1})", enumTypeName, enumValue)); var enumType = ParseType(enumTypeName, context); if (enumType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", enumTypeName)); return(null); } if (!enumType.IsValueType) { context.ReportError( string.Format("Type '{0}' is not an enumeration type, and can not be used in <EnumValue> tag.", enumType)); return(null); } var result = Enum.Parse(enumType, enumValue); context.LeaveRunningLocation(); return(result); }
/// <summary> /// Parses an enum value in its short-hand form in composition XML. /// </summary> public static object ParseEnum(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string enumType = null; string enumValue = null; foreach (var attribute in attributes) { switch (attribute.Name) { case "enumType": enumType = attribute.Value; break; case "enumValue": enumValue = attribute.Value; break; default: context.ReportError( string.Format("Attribute name {0} is not supported for enum value elements.", attribute.Name)); return(null); } } if ((enumValue == null) || (enumType == null)) { context.ReportError("Both 'enumType' and 'enumValue' attributes are required."); return(null); } return(ParseEnum(enumType, enumValue, context)); }
public static byte[] ParseByteArray(string value, XmlProcessingContext context) { var filteredString = ""; // remove all none A-F, 0-9, characters for (var i = 0; i < value.Length; i++) { var c = value[i]; if ((char.IsWhiteSpace(c)) || (c == '-') || (c == '_')) { continue; } if (!char.IsLetterOrDigit(c)) { context.ReportError("Character is not allowed in a hex string: '" + c + "', ignoring."); continue; } c = char.ToUpper(c); if ((char.IsLetter(c)) && ((c > 'F') || (c < 'A'))) { context.ReportError("Character is not allowed in a hex string: '" + c + "', ignoring."); continue; } filteredString += c; } // if odd number of characters, add a zero to the beginning if (filteredString.Length % 2 != 0) { filteredString = "0" + filteredString; } var byteLength = filteredString.Length / 2; var result = new byte[byteLength]; for (var i = 0; i < result.Length; i++) { result[i] = byte.Parse(filteredString.Substring(i << 1, 2), NumberStyles.HexNumber); } return(result); }
/// <summary> /// Used for parsing short-hand specification of dictionaries in /// the composition XML. /// </summary> public static IDictionary ParseDictionary(IEnumerable <XmlAttribute> attributes, XmlElement[] childElements, XmlProcessingContext context) { string keyType = null; string valueType = null; foreach (var attribute in attributes) { switch (attribute.Name) { case "dictionaryKeyType": keyType = attribute.Value; break; case "dictionaryValueType": valueType = attribute.Value; break; default: context.ReportError(string.Format("Attribute name {0} is not supported for array value elements.", attribute.Name)); return(null); } } return(ParseDictionary(keyType, valueType, childElements, context)); }
/// <summary> /// Actually parses an array, and is used in both short-hand and separate /// element formats of array specification. /// </summary> public static Array ParseArray(string elementTypeName, XmlElement[] childElements, XmlProcessingContext context) { context.EnterRunningLocation(string.Format("Array({0})", elementTypeName ?? "object")); var elementType = typeof(object); if (elementTypeName != null) { elementType = SimpleTypeParserUtil.ParseType(elementTypeName, context); if (elementType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", elementTypeName)); return(null); } } var arrayElements = GetCollectionElements(childElements, elementType, context); var result = Array.CreateInstance(elementType, arrayElements.Count); for (var i = 0; i < result.Length; i++) { result.SetValue(arrayElements[i], i); } context.LeaveRunningLocation(); return(result); }
/// <summary> /// Used for parsing an Object element in the composition XML. /// </summary> public static object ParseObject(XmlElement element, XmlProcessingContext context) { string typeName = null; var initializePlugs = false; if (element.Attributes["type"] != null) { typeName = element.Attributes["type"].Value; } if (element.Attributes["initializePlugs"] != null) { initializePlugs = Boolean.Parse(element.Attributes["initializePlugs"].Value); } if (typeName == null) { context.ReportError("'Object' element in the composition XML should have a 'type' attribute."); return(null); } var childElements = new List <XmlElement>(); foreach (XmlNode childNode in element.ChildNodes) { if (childNode is XmlElement) { childElements.Add((XmlElement)childNode); } } return(ParseObject(typeName, initializePlugs, childElements.ToArray(), context)); }
/// <summary> /// Actually parses the contents of lists from composition XMLs, and is /// used in both short-hand form and complete form of list specification. /// </summary> public static IList ParseList(string elementTypeName, XmlElement[] childElements, XmlProcessingContext context) { context.EnterRunningLocation(string.Format("List({0})", elementTypeName ?? "object")); var elementType = typeof(object); if (elementTypeName != null) { elementType = SimpleTypeParserUtil.ParseType(elementTypeName, context); if (elementType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", elementTypeName)); context.LeaveRunningLocation(); return(null); } } var listElements = GetCollectionElements(childElements, elementType, context); var listType = Type.GetType(string.Format("System.Collections.Generic.List`1[[{0}]]", elementType.AssemblyQualifiedName)); var result = (IList)Activator.CreateInstance(listType); foreach (var o in listElements) { result.Add(o); } context.LeaveRunningLocation(); return(result); }
internal static void ProcessCompositionXml(Stream configurationStream, XmlProcessingContext xmlProcessingContext) { if (configurationStream == null) { throw new ArgumentNullException(nameof(configurationStream)); } var xsdStream = typeof(AssemblyPointer).Assembly.GetManifestResourceStream( "ComposerCore.CompositionXml.Schema.compositionXml.1.0.xsd"); if (xsdStream == null) { throw new NullReferenceException("Could not load XSD resource from DLL."); } var schema = XmlSchema.Read( xsdStream, (sender, e) => throw new CompositionXmlValidationException( "Could not load XSD for Composition XML. Message: " + e.Message + "; Sender: " + sender, e.Exception)); var schemaSet = new XmlSchemaSet(); schemaSet.Add(schema); var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, Schemas = schemaSet }; settings.ValidationEventHandler += delegate(object sender, ValidationEventArgs e) { var errorMessage = "Composition XML Schema Validation error: "; if (e.Exception is XmlSchemaValidationException validationException) { errorMessage += "Line: " + validationException.LineNumber + ", Position: " + validationException.LinePosition + "; " + validationException.Message; } else { errorMessage += "Message: " + e.Message + "; Sender: " + sender + "; Inner exception: " + e.Exception.Message; } xmlProcessingContext.ReportError(errorMessage); }; var serializer = new XmlSerializer(typeof(CompositionInfo)); var reader = XmlReader.Create(configurationStream, settings); var info = (CompositionInfo)serializer.Deserialize(reader); info.Validate(); CompositionInfoApplicator.ApplyCompositionInfo(info, xmlProcessingContext); }
/// <summary> /// Parses a contentsOfVariableName specification in composition XML in its short-hand form. /// </summary> public static object ParseTimeSpan(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { // Declare variables for possible input values string timeSpanString = null; int? days = null; int? hours = null; int? minutes = null; int? seconds = null; int? milliseconds = null; long? ticks = null; // Extract input values from the attributes (can be in any order) foreach (var attribute in attributes) { switch (attribute.Name) { case "timeSpan": timeSpanString = attribute.Value; break; case "timeSpanDays": days = Int32.Parse(attribute.Value); break; case "timeSpanHours": hours = Int32.Parse(attribute.Value); break; case "timeSpanMinutes": minutes = Int32.Parse(attribute.Value); break; case "timeSpanSeconds": seconds = Int32.Parse(attribute.Value); break; case "timeSpanMilliseconds": milliseconds = Int32.Parse(attribute.Value); break; case "timeSpanTicks": ticks = Int64.Parse(attribute.Value); break; default: context.ReportError( string.Format("Attribute name {0} is not supported for timeSpan value elements.", attribute.Name)); return(null); } } // Validate and parse the extracted values return(ParseTimeSpan(timeSpanString, days, hours, minutes, seconds, milliseconds, ticks, context)); }
private static List <object> GetCollectionElements(XmlElement[] xmlElements, Type elementType, XmlProcessingContext xmlProcessingContext) { var arrayElements = new List <object>(); for (var i = 0; i < xmlElements.Length; i++) { xmlProcessingContext.EnterRunningLocation(string.Format("Item({0})", i)); var childElement = xmlElements[i]; if (childElement.Name == "Item") { var arrayElement = XmlValueParser.ParseValue(childElement, xmlProcessingContext, null); if ((arrayElement != null) && (!elementType.IsInstanceOfType(arrayElement))) { xmlProcessingContext.ReportError( string.Format("Array of the element type {0} can not contain items with type {1}.", elementType.FullName, arrayElement.GetType().FullName)); xmlProcessingContext.LeaveRunningLocation(); return(null); } arrayElements.Add(arrayElement); } else { xmlProcessingContext.ReportError( string.Format("Xml element '{0}' is not allowed in 'Array' element - type: {1}[]", childElement.Name, elementType.FullName)); xmlProcessingContext.LeaveRunningLocation(); return(null); } xmlProcessingContext.LeaveRunningLocation(); } return(arrayElements); }
private static object[] ParseConstructorArgs(XmlElement element, XmlProcessingContext xmlProcessingContext) { if (element.Name != "ConstructorArgs") { throw new ArgumentException("Calling this method is only valid for 'ConstructorArgs' element."); } if (element.HasAttributes) { xmlProcessingContext.ReportError("'ConstructorArgs' element should not have any attributes."); } xmlProcessingContext.EnterRunningLocation("ConstructorArgs"); var result = new List <object>(); foreach (XmlNode childNode in element.ChildNodes) { var childElement = childNode as XmlElement; if (childElement == null) { continue; } if (childElement.Name == "Arg") { result.Add(XmlValueParser.ParseValue(childElement, xmlProcessingContext, null)); } else { xmlProcessingContext.ReportError( string.Format("Element '{0}' is not allowed in the 'ConstructorArgs' element.", childElement.Name)); } } xmlProcessingContext.LeaveRunningLocation(); return(result.ToArray()); }
internal static void ProcessCompositionXmlFromResource(Assembly assembly, string configurationResourceName, XmlProcessingContext xmlProcessingContext) { var stream = assembly.GetManifestResourceStream(configurationResourceName); if (stream == null) { xmlProcessingContext.ReportError($"Resource name '{configurationResourceName}' could not be loaded from assembly '{assembly.FullName}'."); return; } ProcessCompositionXml(stream, xmlProcessingContext); }
/// <summary> /// Parses a ContentsOfVariable element in the composition XML. /// </summary> public static object ParseContentsOfVariable(XmlElement element, XmlProcessingContext context) { if (element.ChildNodes.Count > 0) { context.ReportError("'ContentsOfVariable' elements should not contain any child elements."); return(null); } string variableName = null; if (element.Attributes["name"] != null) { variableName = element.Attributes["name"].Value; } if (variableName == null) { context.ReportError("'ContentsOfVariable' elements require a 'name' attribute."); return(null); } return(ParseContentsOfVariable(variableName, context)); }
/// <summary> /// Parses an assembly specification in composition XML in its short-hand form. /// </summary> public static Assembly ParseAssembly(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string assemblyName = null; foreach (var attribute in attributes) { if (attribute.Name == "assemblyName") { assemblyName = attribute.Value; } else { context.ReportError( string.Format("Attribute name {0} is not supported for assembly value elements.", attribute.Name)); return(null); } } if (assemblyName == null) { context.ReportError("Attribute 'assemblyName' is required."); return(null); } var result = ParseAssembly(assemblyName, context); if (result == null) { context.EnterRunningLocation(string.Format("Assembly({0})", assemblyName)); context.ReportError("Could not load assembly '" + assemblyName + "'."); context.LeaveRunningLocation(); return(null); } return(result); }
/// <summary> /// Parses a type specification in composition XML in its short-hand form. /// </summary> public static Type ParseType(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context) { string typeName = null; foreach (var attribute in attributes) { if (attribute.Name == "typeName") { typeName = attribute.Value; } else { context.ReportError(string.Format("Attribute name {0} is not supported for type value elements.", attribute.Name)); return(null); } } if (typeName == null) { context.ReportError("Attribute 'typeName' is required."); return(null); } var result = ParseType(typeName, context); if (result == null) { context.EnterRunningLocation(string.Format("Type({0})", typeName)); context.ReportError("Could not load type '" + typeName + "'."); context.LeaveRunningLocation(); return(null); } return(result); }
internal static void ProcessCompositionXml(string configurationPath, XmlProcessingContext xmlProcessingContext) { if (configurationPath == null) { throw new ArgumentNullException(nameof(configurationPath)); } if (!File.Exists(configurationPath)) { xmlProcessingContext.ReportError($"Specified configuration file '{configurationPath}' does not exist."); return; } using (Stream configurationStream = File.Open(configurationPath, FileMode.Open, FileAccess.Read)) { ProcessCompositionXml(configurationStream, xmlProcessingContext); } }
/// <summary> /// Parses a Ref element in the composition XML. /// </summary> public static object ParseRef(XmlElement element, XmlProcessingContext context) { if (element.ChildNodes.Count > 0) { context.ReportError("Ref elements should not contain any child elements."); return(null); } string refType = null; string refName = null; if (element.Attributes["type"] != null) { refType = element.Attributes["type"].Value; } if (element.Attributes["name"] != null) { refName = element.Attributes["name"].Value; } return(ParseRef(refType, refName, context)); }
/// <summary> /// Actually parses the contents on Ref specification in composition XML. /// Looks up the referenced component in the component context, and returns the result. /// Is used both in short-hand form and element form on Ref specification. /// </summary> public static object ParseRef(string refTypeName, string refName, XmlProcessingContext context) { if (refTypeName == null) { throw new ArgumentNullException("refTypeName"); } context.EnterRunningLocation(string.Format("Ref({0})", refTypeName)); var refType = ParseType(refTypeName, context); if (refType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", refTypeName)); return(null); } var result = context.ComponentContext.GetComponent(refType, refName); context.LeaveRunningLocation(); return(result); }
/// <summary> /// Parses an Enum element in a composition XML. /// </summary> public static object ParseEnum(XmlElement element, XmlProcessingContext context) { if (element.ChildNodes.Count > 0) { context.ReportError("Enum elements should not contain any child elements."); return(null); } string enumTypeName = null; string enumValue = null; if (element.Attributes["type"] != null) { enumTypeName = element.Attributes["type"].Value; } if (element.Attributes["value"] != null) { enumValue = element.Attributes["value"].Value; } return(ParseEnum(enumTypeName, enumValue, context)); }
/// <summary> /// Actually parses the object and returns the result. Used both in short-hand /// form and in direct Object element parsing. /// </summary> public static object ParseObject(string typeName, bool initializePlugs, XmlElement[] childElements, XmlProcessingContext context) { context.EnterRunningLocation(string.Format("Object({0})", typeName)); // Look for constructor arguments. // Set default to null, so that Activator calls default constructor // in case the the "ConstructorArgs" element is not specified. object[] constructorArguments = null; foreach (var childElement in childElements) { if (childElement.Name != "ConstructorArgs") { continue; } // Check if this is the second "ConstructorArgs" element. // If so, report an error and return. if (constructorArguments != null) { context.ReportError("The 'ConstructorArgs' element can be specified maximum once in an 'Object' element."); context.LeaveRunningLocation(); return(null); } constructorArguments = ParseConstructorArgs(childElement, context); context.ThrowIfErrors(); } // Resolve the "Type" for the object to be instantiated var objectType = SimpleTypeParserUtil.ParseType(typeName, context); if (objectType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", typeName)); context.LeaveRunningLocation(); return(null); } // Use Activator class to instantiate the object var result = Activator.CreateInstance(objectType, constructorArguments); if (initializePlugs) { context.ComponentContext.InitializePlugs(result, objectType); } foreach (var childElement in childElements) { switch (childElement.Name) { case "ConstructorArgs": break; case "Property": ParseObjectProperty(result, childElement, context); break; case "Field": ParseObjectField(result, childElement, context); break; default: // Also: case "ConstructorArgs" context.ReportError( string.Format("Xml element '{0}' is not allowed in 'Object' element - type: {1}", childElement.Name, typeName)); context.LeaveRunningLocation(); return(null); } } context.LeaveRunningLocation(); return(result); }