// Paolo Molaro lupus@ximian.com
// Peter Bartok pbartok@novell.com
// Gert Driesen drieseng@users.sourceforge.net
-//
+// Olivier Dufour olivier.duff@gmail.com
+// Gary Barnett gary.barnett.mono@gmail.com
using System;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using System.Reflection;
+using System.Drawing;
+using System.Runtime.Serialization;
namespace System.Resources
{
- public class ResXResourceReader : IResourceReader, IDisposable
+#if INSIDE_SYSTEM_WEB
+ internal
+#else
+ public
+#endif
+ class ResXResourceReader : IResourceReader, IDisposable
{
#region Local Variables
private string fileName;
private Hashtable hasht;
private ITypeResolutionService typeresolver;
private XmlTextReader xmlReader;
-
-
-#if NET_2_0
private string basepath;
private bool useResXDataNodes;
private AssemblyName [] assemblyNames;
private Hashtable hashtm;
-#endif
#endregion // Local Variables
#region Constructors & Destructor
public ResXResourceReader (Stream stream)
{
if (stream == null)
- throw new ArgumentNullException ("Value cannot be null.");
+ throw new ArgumentNullException ("stream");
if (!stream.CanRead)
throw new ArgumentException ("Stream was not readable.");
this.stream = stream;
-#if NET_2_0
- this.useResXDataNodes = false;
-#endif
- }
+ }
- public ResXResourceReader (Stream stream, ITypeResolutionService typeresolver)
+ public ResXResourceReader (Stream stream, ITypeResolutionService typeResolver)
: this (stream)
{
- this.typeresolver = typeresolver;
+ this.typeresolver = typeResolver;
}
public ResXResourceReader (string fileName)
{
this.fileName = fileName;
-#if NET_2_0
- this.useResXDataNodes = false;
-#endif
- }
+ }
- public ResXResourceReader (string fileName, ITypeResolutionService typeresolver)
+ public ResXResourceReader (string fileName, ITypeResolutionService typeResolver)
: this (fileName)
{
- this.typeresolver = typeresolver;
+ this.typeresolver = typeResolver;
}
public ResXResourceReader (TextReader reader)
{
this.reader = reader;
-#if NET_2_0
- this.useResXDataNodes = false;
-#endif
}
- public ResXResourceReader (TextReader reader, ITypeResolutionService typeresolver)
+ public ResXResourceReader (TextReader reader, ITypeResolutionService typeResolver)
: this (reader)
{
- this.typeresolver = typeresolver;
+ this.typeresolver = typeResolver;
}
-#if NET_2_0
-
public ResXResourceReader (Stream stream, AssemblyName [] assemblyNames)
: this (stream)
{
this.assemblyNames = assemblyNames;
}
-
-#endif
~ResXResourceReader ()
{
Dispose (false);
}
#endregion // Constructors & Destructor
-#if NET_2_0
public string BasePath {
get { return basepath; }
set { basepath = value; }
}
+
public bool UseResXDataNodes {
get { return useResXDataNodes; }
set {
useResXDataNodes = value;
}
}
-#endif
#region Private Methods
private void LoadData ()
{
hasht = new Hashtable ();
-#if NET_2_0
hashtm = new Hashtable ();
-#endif
if (fileName != null) {
stream = File.OpenRead (fileName);
}
case "data":
ParseDataNode (false);
break;
-#if NET_2_0
case "metadata":
ParseDataNode (true);
break;
-#endif
}
}
-#if NET_2_0
} catch (XmlException ex) {
throw new ArgumentException ("Invalid ResX input.", ex);
+ } catch (SerializationException ex) {
+ throw ex;
+ } catch (TargetInvocationException ex) {
+ throw ex;
} catch (Exception ex) {
XmlException xex = new XmlException (ex.Message, ex,
xmlReader.LineNumber, xmlReader.LinePosition);
throw new ArgumentException ("Invalid ResX input.", xex);
}
-#else
- } catch (Exception ex) {
- throw new ArgumentException ("Invalid ResX input.", ex);
- }
-#endif
-
header.Verify ();
} finally {
if (fileName != null) {
return null;
}
- private string GetDataValue (bool meta)
+ private string GetDataValue (bool meta, out string comment)
{
string value = null;
-#if NET_2_0
+ comment = null;
while (xmlReader.Read ()) {
if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.LocalName == (meta ? "metadata" : "data"))
break;
value = xmlReader.ReadString ();
xmlReader.WhitespaceHandling = WhitespaceHandling.None;
} else if (xmlReader.Name.Equals ("comment")) {
- xmlReader.Skip ();
+ xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
+ comment = xmlReader.ReadString ();
+ xmlReader.WhitespaceHandling = WhitespaceHandling.None;
if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.LocalName == (meta ? "metadata" : "data"))
break;
}
else
value = xmlReader.Value.Trim ();
}
-#else
- xmlReader.Read ();
- if (xmlReader.NodeType == XmlNodeType.Element) {
- value = xmlReader.ReadElementString ();
- } else {
- value = xmlReader.Value.Trim ();
- }
-
- if (value == null)
- value = string.Empty;
-#endif
return value;
}
private void ParseDataNode (bool meta)
{
+ Hashtable hashtable = ((meta && ! useResXDataNodes) ? hashtm : hasht);
+ Point pos = new Point (xmlReader.LineNumber, xmlReader.LinePosition);
string name = GetAttribute ("name");
string type_name = GetAttribute ("type");
string mime_type = GetAttribute ("mimetype");
-#if NET_2_0
- Hashtable hashtable = (meta ? hashtm : hasht);
-#else
- Hashtable hashtable = hasht;
-#endif
- Type type = type_name == null ? null : ResolveType (type_name);
- if (type_name != null && type == null)
- throw new ArgumentException (String.Format (
- "The type '{0}' of the element '{1}' could not be resolved.", type_name, name));
-
- if (type == typeof (ResXNullRef)) {
-
-#if NET_2_0
- if (useResXDataNodes)
- hashtable [name] = new ResXDataNode(name, null);
- else
-#endif
- hashtable [name] = null;
- return;
- }
+ string comment = null;
+ string value = GetDataValue (meta, out comment);
- string value = GetDataValue (meta);
- object obj = null;
+ ResXDataNode node = new ResXDataNode (name, mime_type, type_name, value, comment, pos, BasePath);
- if (mime_type != null && mime_type.Length > 0) {
- if (mime_type == ResXResourceWriter.BinSerializedObjectMimeType) {
- byte [] data = Convert.FromBase64String (value);
- BinaryFormatter f = new BinaryFormatter ();
- using (MemoryStream s = new MemoryStream (data)) {
- obj = f.Deserialize (s);
- }
- } else if (mime_type == ResXResourceWriter.ByteArraySerializedObjectMimeType) {
- if (type != null) {
- TypeConverter c = TypeDescriptor.GetConverter (type);
- if (c.CanConvertFrom (typeof (byte [])))
- obj = c.ConvertFrom (Convert.FromBase64String (value));
- }
- }
- } else if (type != null) {
- if (type == typeof (byte [])) {
- obj = Convert.FromBase64String (value);
- } else {
- TypeConverter c = TypeDescriptor.GetConverter (type);
- if (c.CanConvertFrom (typeof (string))) {
-#if NET_2_0
- if (BasePath != null && type == typeof (ResXFileRef)) {
- string [] parts = ResXFileRef.Parse (value);
- parts [0] = Path.Combine (BasePath, parts [0]);
- obj = c.ConvertFromInvariantString (string.Join (";", parts));
- } else {
- obj = c.ConvertFromInvariantString (value);
- }
-#else
- obj = c.ConvertFromInvariantString (value);
-#endif
- }
- }
- } else {
- obj = value;
+ if (useResXDataNodes) {
+ hashtable [name] = node;
+ return;
}
-#if ONLY_1_1
- if (obj == null)
- obj = value;
-#endif
-
if (name == null)
throw new ArgumentException (string.Format (CultureInfo.CurrentCulture,
- "Could not find a name for a resource. The resource value "
- + "was '{0}'.", obj));
-#if NET_2_0
- if (useResXDataNodes)
- hashtable [name] = new ResXDataNode(name, obj);
- else
-#endif
- hashtable [name] = obj;
- }
+ "Could not find a name for a resource. The resource value was '{0}'.",
+ node.GetValue ((AssemblyName []) null).ToString()));
- private Type ResolveType (string type)
- {
- if (typeresolver != null) {
- return typeresolver.GetType (type);
- }
-#if NET_2_0
- if (assemblyNames != null) {
- Type result;
- foreach (AssemblyName assem in assemblyNames) {
- Assembly myAssembly = Assembly.Load (assem);
- result = myAssembly.GetType (type, false);
- if (result != null)
- return result;
- //else loop
+ // useResXDataNodes is false, add to dictionary of values
+ if (assemblyNames != null) {
+ try {
+ hashtable [name] = node.GetValue (assemblyNames);
+ } catch (TypeLoadException ex) {
+ // different error messages depending on type of resource, hacky solution
+ if (node.handler is TypeConverterFromResXHandler)
+ hashtable [name] = null;
+ else
+ throw ex;
+ }
+ } else { // there is a typeresolver or its null
+ try {
+ hashtable [name] = node.GetValue (typeresolver);
+ } catch (TypeLoadException ex) {
+ if (node.handler is TypeConverterFromResXHandler)
+ hashtable [name] = null;
+ else
+ throw ex;
}
- //if type not found on assembly list we return null or we get from current assembly?
- //=> unit test needed
}
-#endif
- return Type.GetType (type);
}
+
#endregion // Private Methods
#region Public Methods
{
return new ResXResourceReader (new StringReader (fileContents), typeResolver);
}
-#if NET_2_0
+
public static ResXResourceReader FromFileContents (string fileContents, AssemblyName [] assemblyNames)
{
return new ResXResourceReader (new StringReader (fileContents), assemblyNames);
LoadData ();
return hashtm.GetEnumerator ();
}
-#endif
+
#endregion // Public Methods
#region Internal Classes