3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** Class: FileBasedResourceGroveler
10 ** <OWNER>[....]</OWNER>
13 ** Purpose: Searches for resources on disk, used for file-
14 ** based resource lookup.
17 ===========================================================*/
18 namespace System.Resources {
20 using System.Collections;
21 using System.Collections.Generic;
23 using System.Globalization;
24 using System.Runtime.CompilerServices;
25 using System.Runtime.Versioning;
27 using System.Threading;
28 using System.Diagnostics.Contracts;
30 internal class FileBasedResourceGroveler : IResourceGroveler
32 private ResourceManager.ResourceManagerMediator _mediator;
34 public FileBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator)
36 Contract.Assert(mediator != null, "mediator shouldn't be null; check caller");
40 // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out
41 // serialization compat story for moving ResourceManager members to either file-based or
42 // manifest-based classes. Want to continue tightening the design to get rid of unused params.
43 [System.Security.SecuritySafeCritical] // auto-generated
44 public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark)
46 Contract.Assert(culture != null, "culture shouldn't be null; check caller");
48 String fileName = null;
49 ResourceSet rs = null;
51 // Don't use Assembly manifest, but grovel on disk for a file.
55 new System.Security.Permissions.FileIOPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
58 // Create new ResourceSet, if a file exists on disk for it.
59 String tempFileName = _mediator.GetResourceFileName(culture);
60 fileName = FindResourceFile(culture, tempFileName);
65 // If we've hit top of the Culture tree, return.
66 if (culture.HasInvariantCultureName)
68 // We really don't think this should happen - we always
69 // expect the neutral locale's resources to be present.
70 throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoNeutralDisk") + Environment.NewLine + "baseName: " + _mediator.BaseNameField + " locationInfo: " + (_mediator.LocationInfo == null ? "<null>" : _mediator.LocationInfo.FullName) + " fileName: " + _mediator.GetResourceFileName(culture));
76 rs = CreateResourceSet(fileName);
83 System.Security.CodeAccessPermission.RevertAssert();
88 #if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr
89 public bool HasNeutralResources(CultureInfo culture, String defaultResName)
91 // Detect missing neutral locale resources.
92 String defaultResPath = FindResourceFile(culture, defaultResName);
93 if (defaultResPath == null || !File.Exists(defaultResPath))
95 String dir = _mediator.ModuleDir;
96 if (defaultResPath != null)
98 dir = Path.GetDirectoryName(defaultResPath);
106 // Given a CultureInfo, it generates the path &; file name for
107 // the .resources file for that CultureInfo. This method will grovel
108 // the disk looking for the correct file name & path. Uses CultureInfo's
109 // Name property. If the module directory was set in the ResourceManager
110 // constructor, we'll look there first. If it couldn't be found in the module
111 // diretory or the module dir wasn't provided, look in the current
114 [ResourceExposure(ResourceScope.Machine)]
115 [ResourceConsumption(ResourceScope.Machine)]
116 private String FindResourceFile(CultureInfo culture, String fileName)
118 Contract.Assert(culture != null, "culture shouldn't be null; check caller");
119 Contract.Assert(fileName != null, "fileName shouldn't be null; check caller");
121 // If we have a moduleDir, check there first. Get module fully
122 // qualified name, append path to that.
123 if (_mediator.ModuleDir != null)
126 if (ResourceManager.DEBUG >= 3)
127 BCLDebug.Log("FindResourceFile: checking module dir: \""+_mediator.ModuleDir+'\"');
130 String path = Path.Combine(_mediator.ModuleDir, fileName);
131 if (File.Exists(path))
134 if (ResourceManager.DEBUG >= 3)
135 BCLDebug.Log("Found resource file in module dir! "+path);
142 if (ResourceManager.DEBUG >= 3)
143 BCLDebug.Log("Couldn't find resource file in module dir, checking .\\"+fileName);
147 if (File.Exists(fileName))
150 return null; // give up.
153 // Constructs a new ResourceSet for a given file name. The logic in
154 // here avoids a ReflectionPermission check for our RuntimeResourceSet
155 // for perf and working set reasons.
156 [System.Security.SecurityCritical]
157 [ResourceExposure(ResourceScope.Machine)]
158 [ResourceConsumption(ResourceScope.Machine)]
159 private ResourceSet CreateResourceSet(String file)
161 Contract.Assert(file != null, "file shouldn't be null; check caller");
163 if (_mediator.UserResourceSet == null)
165 // Explicitly avoid CreateInstance if possible, because it
166 // requires ReflectionPermission to call private & protected
168 return new RuntimeResourceSet(file);
172 Object[] args = new Object[1];
176 return (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
178 catch (MissingMethodException e)
180 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResMgrBadResSet_Type", _mediator.UserResourceSet.AssemblyQualifiedName), e);