//
// System.Resources.ResourceManager.cs
//
-// Author:
+// Authors:
// Duncan Mak (duncan@ximian.com)
+// Dick Porter (dick@ximian.com)
//
-// 2001 (C) Ximian, Inc. http://www.ximian.com
+// (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
//
using System.Collections;
using System.Reflection;
using System.Globalization;
+using System.IO;
-namespace System.Resources {
- public class ResourceManager {
- public static readonly int HeaderVersionNumber;
- public static readonly int MagicNumber = 0xBEEFCACE;
+namespace System.Resources
+{
+ [Serializable]
+ public class ResourceManager
+ {
+ public static readonly int HeaderVersionNumber = 1;
+ public static readonly int MagicNumber = unchecked((int)0xBEEFCACE);
- protected string BaseNameField;
- protected Assembly MainAssembly;
- protected Hashtable ResourceSets;
+ protected string BaseNameField;
+ protected Assembly MainAssembly;
+ // Maps cultures to ResourceSet objects
+ protected Hashtable ResourceSets;
+
+ private bool ignoreCase;
+ private Type resourceSetType;
+ private String resourceDir;
+
+ /* Recursing through culture parents stops here */
+ private CultureInfo neutral_culture;
+
+ // constructors
+ protected ResourceManager () {
+ ResourceSets=new Hashtable();
+ ignoreCase=false;
+ resourceSetType=typeof(ResourceSet);
+ resourceDir=null;
+ neutral_culture=null;
+ }
+
+ public ResourceManager (Type resourceSource) : this()
+ {
+ if (resourceSource == null)
+ throw new ArgumentNullException ("resourceSource is null.");
+
+ BaseNameField = resourceSource.FullName;
+ MainAssembly = resourceSource.Assembly;
+
+ /* Temporary workaround for bug 43567 */
+ resourceSetType = typeof(ResourceSet);
+ neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
+ }
+
+ public ResourceManager (string baseName, Assembly assembly) : this()
+ {
+ if (baseName == null)
+ throw new ArgumentNullException ("baseName is null.");
+ if(assembly == null)
+ throw new ArgumentNullException ("assembly is null.");
+
+ BaseNameField = baseName;
+ MainAssembly = assembly;
+ neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
+ }
- private bool ignoreCase;
- private Type resourceSetType;
+ private Type CheckResourceSetType(Type usingResourceSet)
+ {
+ if(usingResourceSet==null) {
+ return(typeof(ResourceSet));
+ } else {
+ if (!usingResourceSet.IsSubclassOf (typeof (ResourceSet)))
+ throw new ArgumentException ("Type must be from ResourceSet.");
+
+ return(usingResourceSet);
+ }
+ }
+
+ public ResourceManager (string baseName, Assembly assembly, Type usingResourceSet) : this()
+ {
+ if (baseName == null)
+ throw new ArgumentNullException ("baseName is null.");
+ if(assembly == null)
+ throw new ArgumentNullException ("assembly is null.");
+
+ BaseNameField = baseName;
+ MainAssembly = assembly;
+ resourceSetType = CheckResourceSetType(usingResourceSet);
+ neutral_culture = GetNeutralResourcesLanguage(MainAssembly);
+ }
+
+ /* Private constructor for CreateFileBasedResourceManager */
+ private ResourceManager(String baseName, String resourceDir, Type usingResourceSet) : this()
+ {
+ if(baseName==null) {
+ throw new ArgumentNullException("The base name is null");
+ }
+ if(baseName.EndsWith(".resources")) {
+ throw new ArgumentException("The base name ends in '.resources'");
+ }
+ if(resourceDir==null) {
+ throw new ArgumentNullException("The resourceDir is null");
+ }
- // constructors
- public ResourceManager () {}
+ BaseNameField = baseName;
+ MainAssembly = null;
+ resourceSetType = CheckResourceSetType(usingResourceSet);
+ this.resourceDir = resourceDir;
+ }
+
+ public static ResourceManager CreateFileBasedResourceManager (string baseName,
+ string resourceDir, Type usingResourceSet)
+ {
+ return new ResourceManager(baseName, resourceDir, usingResourceSet);
+ }
- public ResourceManager (Type resourceSource) {
- if (resourceSource == null)
- throw new ArgumentNullException ("resourceSource is null.");
+ public virtual string BaseName
+ {
+ get { return BaseNameField; }
+ }
- BaseNameField = resourceSource.FullName;
- MainAssembly = resourceSource.Assembly;
+ public virtual bool IgnoreCase
+ {
+ get { return ignoreCase; }
+ set { ignoreCase = value; }
+ }
- ignoreCase = false;
- resourceSetType = typeof (resourceSource);
- }
+ public virtual Type ResourceSetType
+ {
+ get { return resourceSetType; }
+ }
- public ResourceManager (string baseName, Assembly assembly) {
- if (baseName == null || assembly == null)
- throw new ArgumentNullException ("The arguments are null.");
+ public virtual object GetObject(string name)
+ {
+ return(GetObject(name, null));
+ }
- BaseNameField = baseName;
- MainAssembly = assembly;
- ignoreCase = false;
- resourceSetType = typeof (ResourceSet);
- }
-
- public ResourceManager (string baseName, Assembly assembly, Type usingResourceSet) {
- if (baseName == null || assembly == null)
- throw new ArgumentNullException ("The arguments are null.");
-
- BaseNameField = baseName;
- Assembly = assembly;
-
- if (usingResourceSet == null) // defaults resourceSet type.
- resourceSetType = typeof (ResourceSet);
- else {
- if (!usingResourceSet.IsSubclassOf (typeof (ResourceSet)))
- throw new ArgumentException ("Type must be from ResourceSet.");
-
- resourceSetType = typeof (usingResourceSet); // must be a subclass of ResourceSet
- }
- }
-
- [MonoTODO]
- public static ResourceManager CreateFileBasedResourceManager (string baseName,
- string resourceDir,
- Type usingResourceSet) {
- return null;
- }
-
- public virtual string BaseName { get { return BaseNameField; }}
-
- public virtual bool IgnoreCase {
- get { return ignoreCase; }
- set { ignoreCase = value; }
- }
-
- public virtual Type ResourceSetType {
- get { return resourceSetType; }
- }
-
- [MonoTODO]
- public virtual ResourceSet GetResourceSet (CultureInfo culture,
- bool createIfNotExists,
- bool tryParents) {
- if (culture == null)
- throw new ArgumentNullException ("CultureInfo is a null reference.");
- return null;
- }
-
- [MonoTODO]
- public virtual string GetString (string name) {
- if (name == null)
- throw new ArgumentNullException ("Name is null.");
- if (ResourceSets.Contains (name)) {
- if (!(ResourceSets[name] is string))
- throw new InvalidOperationException ("The resource is " +
- "not a string.");
- return ResourceSets[name].ToString();
- }
- return null;
- }
-
- [MonoTODO]
- public virtual string GetString (string name, CultureInfo culture) {
- if (name == null)
- throw new ArgumentNullException ("Name is null.");
- return null;
- }
-
- [MonoTODO]
- protected virtual string GetResourceFileName (CultureInfo culture) {
- return culture.Name + ".resources"; // TODO check for correctness.
- }
-
- [MonoTODO]
- protected virtual ResourceSet InternalGetResourceSet (CultureInfo culture,
- bool Createifnotexists,
- bool tryParents) {
- return null;
- }
+ public virtual object GetObject(string name, CultureInfo culture)
+ {
+ if(name==null) {
+ throw new ArgumentNullException("name is null");
+ }
+
+ if(culture==null) {
+ culture=CultureInfo.CurrentUICulture;
+ }
+
+ lock(this) {
+ ResourceSet set=InternalGetResourceSet(culture, true, true);
+ object obj=null;
+
+ if(set != null) {
+ obj=set.GetObject(name, ignoreCase);
+ if(obj != null) {
+ return(obj);
+ }
+ }
+
+ /* Try parent cultures */
+
+ do {
+ culture=culture.Parent;
+
+ set=InternalGetResourceSet(culture, true, true);
+ if(set!=null) {
+ obj=set.GetObject(name, ignoreCase);
+ if(obj != null) {
+ return(obj);
+ }
+ }
+ } while(!culture.Equals(neutral_culture) &&
+ !culture.Equals(CultureInfo.InvariantCulture));
+ }
+
+ return(null);
+ }
+
+
+ public virtual ResourceSet GetResourceSet (CultureInfo culture,
+ bool createIfNotExists, bool tryParents)
+
+ {
+ if (culture == null) {
+ throw new ArgumentNullException ("CultureInfo is a null reference.");
+ }
+
+ lock(this) {
+ return(InternalGetResourceSet(culture, createIfNotExists, tryParents));
+ }
+ }
+
+ public virtual string GetString (string name)
+ {
+ return(GetString(name, null));
+ }
+
+ public virtual string GetString (string name, CultureInfo culture)
+ {
+ if (name == null) {
+ throw new ArgumentNullException ("Name is null.");
+ }
+
+ if(culture==null) {
+ culture=CultureInfo.CurrentUICulture;
+ }
+
+ lock(this) {
+ ResourceSet set=InternalGetResourceSet(culture, true, true);
+ string str=null;
+
+ if(set!=null) {
+ str=set.GetString(name, ignoreCase);
+ if(str!=null) {
+ return(str);
+ }
+ }
+
+ /* Try parent cultures */
+
+ do {
+ culture=culture.Parent;
+
+ set=InternalGetResourceSet(culture, true, true);
+ if(set!=null) {
+ str=set.GetString(name, ignoreCase);
+ if(str!=null) {
+ return(str);
+ }
+ }
+ } while(!culture.Equals(neutral_culture) &&
+ !culture.Equals(CultureInfo.InvariantCulture));
+ }
+
+ return(null);
+ }
+
+ protected virtual string GetResourceFileName (CultureInfo culture)
+ {
+ if(culture.Equals(CultureInfo.InvariantCulture)) {
+ return(BaseNameField + ".resources");
+ } else {
+ return(BaseNameField + "." + culture.Name + ".resources");
+ }
+ }
+
+ protected virtual ResourceSet InternalGetResourceSet (CultureInfo culture, bool Createifnotexists, bool tryParents)
+ {
+ ResourceSet set;
+
+ if (culture == null) {
+ string msg = String.Format ("Could not find any resource appropiate for the " +
+ "specified culture or its parents (assembly:{0})",
+ MainAssembly != null ? MainAssembly.GetName ().Name : "");
+
+ throw new MissingManifestResourceException (msg);
+ }
+ /* if we already have this resource set, return it */
+ set=(ResourceSet)ResourceSets[culture];
+ if(set!=null) {
+ return(set);
+ }
+
+ if(MainAssembly != null) {
+ /* Assembly resources */
+ Stream stream;
+ string filename=GetResourceFileName(culture);
+
+ stream=MainAssembly.GetManifestResourceStream(filename);
+ if(stream==null) {
+ /* Try a satellite assembly */
+ Version sat_version=GetSatelliteContractVersion(MainAssembly);
+ Assembly a = null;
+ try {
+ a = MainAssembly.GetSatelliteAssembly (culture, sat_version);
+ stream=a.GetManifestResourceStream(filename);
+ } catch (Exception) {} // Ignored
+ }
+
+ if(stream!=null && Createifnotexists==true) {
+ object[] args=new Object[1];
+
+ args[0]=stream;
+
+ /* should we catch
+ * MissingMethodException, or
+ * just let someone else deal
+ * with it?
+ */
+ set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
+ } else if (culture == CultureInfo.InvariantCulture) {
+ string msg = "Could not find any resource appropiate for the " +
+ "specified culture or its parents (assembly:{0})";
+
+ msg = String.Format (msg, MainAssembly != null ? MainAssembly.GetName ().Name : "");
+
+ throw new MissingManifestResourceException (msg);
+ }
+ } else if(resourceDir != null) {
+ /* File resources */
+ string filename=Path.Combine(resourceDir, this.GetResourceFileName(culture));
+ if(File.Exists(filename) &&
+ Createifnotexists==true) {
+ object[] args=new Object[1];
+
+ args[0]=filename;
+
+ /* should we catch
+ * MissingMethodException, or
+ * just let someone else deal
+ * with it?
+ */
+ set=(ResourceSet)Activator.CreateInstance(resourceSetType, args);
+ }
+ }
+
+ if(set==null && tryParents==true) {
+ set=this.InternalGetResourceSet(culture.Parent, Createifnotexists, tryParents);
+ }
+
+ if(set!=null) {
+ ResourceSets.Add(culture, set);
+ }
+
+ return(set);
+ }
- public virtual void ReleaseAllResources () {
- foreach (ResourceSet r in ResourceSets)
- r.Close();
- }
-
- [MonoTODO]
- protected static CultureInfo GetNeutralResourcesLanguage (Assembly a) {
- foreach (Attribute attribute in a.GetCustomAttributes (false)) {
- if (attribute is NeutralResourcesLanguageAttribute)
- return new CultureInfo (attribute.CultureName);
- }
- return null;
- }
-
- public static Version GetSatelliteContractVersion (Assembly a) {
- foreach (Attribute attribute in a.GetCustomAttributes (false)) {
- if (attribute is SatelliteContractVersionAttribute)
- return new Version ((attribute as SatelliteContractVersionAttribute).Version);
- }
- return null; // return null if no version was found.
- }
- }
+ public virtual void ReleaseAllResources ()
+ {
+ lock(this)
+ {
+ foreach (ResourceSet r in ResourceSets)
+ r.Close();
+ ResourceSets.Clear();
+ }
+ }
+
+ protected static CultureInfo GetNeutralResourcesLanguage (Assembly a)
+ {
+ object[] attrs;
+
+ attrs=a.GetCustomAttributes(typeof(NeutralResourcesLanguageAttribute), false);
+
+ if(attrs.Length==0) {
+ return(CultureInfo.InvariantCulture);
+ } else {
+ NeutralResourcesLanguageAttribute res_attr=(NeutralResourcesLanguageAttribute)attrs[0];
+
+ return(new CultureInfo(res_attr.CultureName));
+ }
+ }
+
+ protected static Version GetSatelliteContractVersion (Assembly a)
+ {
+ object[] attrs;
+
+ attrs=a.GetCustomAttributes(typeof(SatelliteContractVersionAttribute), false);
+
+ if(attrs.Length==0) {
+ return(null);
+ } else {
+ SatelliteContractVersionAttribute sat_attr=(SatelliteContractVersionAttribute)attrs[0];
+
+ /* Version(string) can throw
+ * ArgumentException if the version is
+ * invalid, but the spec for
+ * GetSatelliteContractVersion says we
+ * can throw the same exception for
+ * the same reason, so dont bother to
+ * catch it.
+ */
+ return(new Version(sat_attr.Version));
+ }
+ }
+ }
}