private static void RaiseValidationError(object sender, ValidationEventArgs args) { XmlSchemaException ex = args.Exception; MTurkLog.Error("XML validation error at line {1} position {2}: '{0}'", ex.Message, ex.LineNumber, ex.LinePosition); throw ex; }
public PropertyInfo GetProperty(string propName, bool throwOnError) { PropertyInfo ret = null; try { if (htPropertyCache.ContainsKey(propName)) { ret = htPropertyCache[propName]; } else { lock (syncToken) { if (htPropertyCache.ContainsKey(propName)) { ret = htPropertyCache[propName]; } else { // check only if the property is not yet on the exclude list if (!excludeList.Contains(propName)) { // look for public property; ret = _type.GetProperty(propName); if (ret == null) { ret = _type.GetProperty(propName, BindingFlags.Instance | BindingFlags.NonPublic); if (ret == null) { if (throwOnError) { throw new ArgumentException("No such property for type " + _type.FullName, "propName"); } else { // add to exclude list excludeList.Add(propName); } } } else { htPropertyCache[propName] = ret; } } } } } } catch (ArgumentException ex) { MTurkLog.Warn("Cannot find property {0} for type {1}: {2}", propName, _type.FullName, ex.Message); } return(ret); }
/// <summary> /// Instantiates the client configuration by reading the application configuration file (app.config). /// </summary> /// <remarks> /// The following values are read from the application configuration file: /// <list type="bullet"> /// <item> /// <term>MechanicalTurk.ServiceEndpoint</term> /// <description> /// The service endpoint receiving and processing mturk requests. Defaults to the sandbox endpoint at /// <c>https://mechanicalturk.sandbox.amazonaws.com?Service=AWSMechanicalTurkRequester</c> /// </description> /// </item> /// <item> /// <term>MechanicalTurk.AccessKeyId</term> /// <description>Required: The access key ID for the Amazon Web Services account</description> /// </item> /// <item> /// <term>MechanicalTurk.SecretAccessKey</term> /// <description>Required: The secret access key for the Amazon Web Services account</description> /// </item> /// <item> /// <term>MechanicalTurk.Log.Level</term> /// <description>The log level for SDK log messages (<see cref="ILog"/> for details). Defaults to 2 (Info)</description> /// </item> /// <item> /// <term>MechanicalTurk.Proxy.Url</term> /// <description> /// Proxy URL (only necessary when used through a web proxy that requires authentication) /// </description> /// </item> /// <item> /// <term>MechanicalTurk.Proxy.User</term> /// <description> /// User name for proxy credentials (only necessary when used through a web proxy that /// requires authentication) /// </description> /// </item> /// <item> /// <term>MechanicalTurk.Proxy.Password</term> /// <description> /// Password for proxy credentials (only necessary when used through a web proxy /// that requires authentication) /// </description> /// </item> /// <item> /// <term>MechanicalTurk.Proxy.Domain</term> /// <description> /// User domain for proxy credentials (only necessary when used through a web proxy /// that requires authentication) /// </description> /// </item> /// <item> /// <term>MechanicalTurk.MiscOptions.EnsureQuestionsAreXmlWrapped</term> /// <description> /// If set to true (default), ensures that questions are wrapped as XML when sent to /// Mechanical Turk. /// </description> /// </item> /// <item> /// <term>MechanicalTurk.MiscOptions.EnsureQuestionValidity</term> /// <description> /// If set to true (default is false), ensures that questions are validated before /// they are sent to Mechanical Turk /// </description> /// </item> /// </list> /// </remarks> public MTurkConfig() { string configFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; MTurkLog.Info("Loading config from " + configFile); if (!File.Exists(configFile)) { throw new IOException(string.Format("Cannot find Mechanical turk configuration file at '{0}'", configFile)); } Init(); }
/// <summary> /// Constructs a Question XML String that contains a multiple freetext questions /// </summary> /// <param name="questions">The question phrase to ask</param> /// <returns>Question in XML format</returns> public static string ConvertMultipleFreeTextQuestionToXML(string[] questions) { if (questions == null || questions.Length == 0) { throw new ArgumentNullException("questions", "Empty or null question cannot be converted to XML"); } System.Text.StringBuilder sb = new System.Text.StringBuilder(); for (int i = 0; i < questions.Length; i++) { if (questions[i] != null && questions[i].Length > 0) { sb.Append(string.Format(TPL_FREE_TEXT_QUESTION_SINGLE, i + 1, XmlUtil.XmlEncode(questions[i]))); } else { MTurkLog.Warn("Ignoring empty question at position {0}", i); } } return(string.Format(TPL_FREE_TEXT_QUESTION_FORM, sb.ToString())); }
private void Init() { // log level string logLevel = GetConfig("MechanicalTurk.Log.Level", "2"); byte level = 2; if (!byte.TryParse(logLevel, out level)) { MTurkLog.Warn("Invalid log level specified in configuration file ({0}). Defaulting to 'INFO'", logLevel); } MTurkLog.Level = level; // AWS settings string s = GetConfig("MechanicalTurk.ServiceEndpoint", null); if (string.IsNullOrEmpty(s)) { this.ServiceEndpoint = "https://mechanicalturk.sandbox.amazonaws.com?Service=AWSMechanicalTurkRequester"; } else { this.ServiceEndpoint = s; } AccessKeyId = GetConfig("MechanicalTurk.AccessKeyId", null); SecretAccessKey = GetConfig("MechanicalTurk.SecretAccessKey", null); // Proxy settings when connecting through a proxy that requires authentication string proxyURL = GetConfig("MechanicalTurk.Proxy.Url", null); if (!string.IsNullOrEmpty(proxyURL)) { Proxy = new WebProxy(proxyURL); } // set default credentials Proxy.Credentials = CredentialCache.DefaultNetworkCredentials; string proxyUser = GetConfig("MechanicalTurk.Proxy.User", null); string proxyPassword = GetConfig("MechanicalTurk.Proxy.Password", null); string proxyDomain = GetConfig("MechanicalTurk.Proxy.Domain", null); if (!string.IsNullOrEmpty(proxyUser) && !string.IsNullOrEmpty(proxyPassword)) { // override default credentials Proxy.Credentials = new NetworkCredential(proxyUser, proxyPassword, proxyDomain); } // worker website string url = GetConfig("MechanicalTurk.Url", null); if (url != null) { this.WebsiteURL = url; } else { if (this.ServiceEndpoint.ToLower().IndexOf("sandbox") != -1) { this.WebsiteURL = "http://workersandbox.mturk.com"; } else { this.WebsiteURL = "http://www.mturk.com"; } } // question settings: Implicitly wrap questions string wrap = GetConfig("MechanicalTurk.MiscOptions.EnsureQuestionsAreXmlWrapped", null); if (wrap != null) { this.EnsureQuestionsAreXmlWrappedBeforeSending = wrap.ToLower().Equals("true"); } // question settings: Implicitly validate string validate = GetConfig("MechanicalTurk.MiscOptions.EnsureQuestionValidity", null); if (validate != null) { this.ValidateQuestionBeforeSending = validate.ToLower().Equals("true"); } // retry delay for sandbox throttling MaxRetryDelay = int.Parse(GetConfig("MechanicalTurk.MaxRetryDelay", "8000")); MTurkLog.Info("Initialized configuration for '{0}'", this.ServiceEndpoint); }
/// <summary> /// Evaluates whether any optional properties in a request item have been set. If this /// is the case, then the correlating "Specified" property will be set to, otherwise /// the property does not get serialized in the soap request. /// /// See e.g. http://blogs.msdn.com/eugeneos/archive/2007/02/05/solving-the-disappearing-data-issue-when-using-add-web-reference-or-wsdl-exe-with-wcf-services.aspx /// for more details (using WCF is out of question for the API) /// </summary> /// <param name="request">Array of request items passed in an MTurk request /// (such as CreateItemRequest[])</param> public static void PreProcessOptionalRequestProperties(object request) { if (request != null) { Type requestType = request.GetType(); if (requestType.IsArray) { // caches the optional property to its "Specified" member (e.g. "PageSize->PageSizeSpecified") Dictionary <PropertyInfo, PropertyInfo> htOptionalProps = null; object[] requestItems = request as object[]; Type itemType = null; object curRequestItem = null; for (int i = 0; i < requestItems.Length; i++) { curRequestItem = requestItems[i]; itemType = curRequestItem.GetType(); htOptionalProps = GetCachedOptionalProperties(itemType); // evaluate optional properties and set the "Specified" property to true, // if the reference property was modified. From a client perspective, this // alleviates the pain of setting the "Specified" properties to true explicitly if (htOptionalProps.Count > 0) { PropertyInfo piSpecified = null; object valRef = null; bool valSpecified = false; Type propTypeRef = null; // flag indicating, whether the "xxxSpecified" property needs to be set bool requiresSpecSet = false; foreach (PropertyInfo piRef in htOptionalProps.Keys) { // check first, if it was explicitly set to true valSpecified = false; piSpecified = htOptionalProps[piRef]; valSpecified = (bool)piSpecified.GetValue(curRequestItem, null); if (!valSpecified) { valRef = piRef.GetValue(curRequestItem, null); if (valRef != null) { // Generally, value types require to be explicitly set, // otherwise they can'typeOfTargetObject be set back to their default // values easily (e.g. setting a value back from "true" to "false") // The following code will set the "Specified" property to true // if the reference value is different from the default value // for the reference value type requiresSpecSet = false; propTypeRef = valRef.GetType(); if (propTypeRef.IsValueType) { if (valRef is bool) { requiresSpecSet = (bool)valRef; } else if (valRef is DateTime) { requiresSpecSet = !DateTime.MinValue.Equals(valRef); } else if (propTypeRef.IsEnum) { requiresSpecSet = !(valRef.Equals(Enum.GetValues(propTypeRef).GetValue(0))); } else { requiresSpecSet = !(Decimal.Parse(valRef.ToString(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat).Equals(Decimal.Zero)); } } else if (propTypeRef.IsArray) { requiresSpecSet = ((object[])valRef).Length > 0; } else if (propTypeRef.IsClass) { requiresSpecSet = true; } else { MTurkLog.Warn("Cannot preprocess optional property {0} for type {1} (No handler for property type {2}).", piRef.Name, itemType.FullName, propTypeRef.FullName); } // set the "xxSpecified" property, so the referenced member gets soap serialized if (requiresSpecSet) { piSpecified.SetValue(curRequestItem, true, null); } } } } } } } } }
/// <summary> /// Sets the property path value. If one of the properties in the path is null, a new instance for its type is created. /// </summary> /// <param name="objRoot">The root object for the path. Needs to be of the cached type</param> /// <param name="propertyPath">The property path (e.g. "LocaleValue.Country")</param> /// <param name="newValueForProperty">New value for the last property in the path</param> public void SetPropertyPathValue(object objRoot, string propertyPath, object newValueForProperty) { Type curType = null; PropertyInfo pi = null; PropertyInfo[] resolvedPath = GetPropertyPath(propertyPath); object curParent = objRoot; object cur = objRoot; for (int i = 0; i < resolvedPath.Length - 1; i++) { curParent = cur; pi = resolvedPath[i]; curType = pi.PropertyType; cur = pi.GetValue(cur, null); if (cur == null) { if (curType.IsClass || curType.IsValueType) { // Create a new instance (requires default constructor) ConstructorInfo ctor = curType.GetConstructor(EMPTY_PARAMS); if (ctor == null) { throw new InvalidOperationException(string.Format("Cannot execute property resolvedPath '{0}'. No default constructor found for type '{1}'", propertyPath, curType.FullName)); } else { // create a new instance and set it on the curParent cur = ctor.Invoke(null); ReflectionUtil.SetPropertyValue(pi.Name, curParent, cur); } } else { throw new InvalidOperationException(string.Format("Cannot execute property resolvedPath '{0}'. Property '{1}' is neither class nor value type", propertyPath, pi.Name)); } } } // now set the value for the last element of the resolvedPath pi = resolvedPath[resolvedPath.Length - 1]; curType = pi.PropertyType; if (newValueForProperty != null) { if (!curType.Equals(newValueForProperty.GetType())) { // check if it is nullable and use underlying typ if (curType.IsGenericType && curType.GetGenericTypeDefinition() == typeof(Nullable <>)) { curType = Nullable.GetUnderlyingType(curType); } if (curType.IsEnum) { newValueForProperty = Enum.Parse(curType, newValueForProperty.ToString(), true); } else { TypeConverter tc = TypeDescriptor.GetConverter(newValueForProperty.GetType()); if (tc.CanConvertTo(curType)) { newValueForProperty = tc.ConvertTo(newValueForProperty, curType); } else { // no builtin converter found: let's look if we have a static Parse method for this type) MethodInfo mi = curType.GetMethod("Parse", new Type[] { newValueForProperty.GetType() }); if (mi != null) { object[] param = { newValueForProperty }; newValueForProperty = mi.Invoke(null, param); } else { MTurkLog.Warn("No type conversion/parser found for {0}. Defaulting to {1} ({2})", pi.Name, newValueForProperty, newValueForProperty.GetType().Name); } } } } } pi.SetValue(cur, newValueForProperty, null); }