minor fix for bug 9520:
[mono.git] / mcs / class / Microsoft.Build.Tasks / Microsoft.Build.Tasks / ResolveAssemblyReference.cs
1 //
2 // ResolveAssemblyReference.cs: Searches for assembly files.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Ankit Jain (jankit@novell.com)
7 // 
8 // (C) 2006 Marek Sieradzki
9 // Copyright 2009 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 #if NET_2_0
31
32 using System;
33 using System.Collections.Generic;
34 using System.Globalization;
35 using System.IO;
36 using System.Linq;
37 using System.Reflection;
38 using System.Security;
39 using Microsoft.Build.Framework;
40 using Microsoft.Build.Utilities;
41
42 namespace Microsoft.Build.Tasks {
43         public class ResolveAssemblyReference : TaskExtension {
44         
45                 bool            autoUnify;
46                 ITaskItem[]     assemblyFiles;
47                 ITaskItem[]     assemblies;
48                 string          appConfigFile;
49                 string[]        allowedAssemblyExtensions;
50                 string[]        allowedRelatedFileExtensions;
51                 string[]        candidateAssemblyFiles;
52                 ITaskItem[]     copyLocalFiles;
53                 ITaskItem[]     filesWritten;
54                 bool            findDependencies;
55                 bool            findRelatedFiles;
56                 bool            findSatellites;
57                 bool            findSerializationAssemblies;
58                 string[]        installedAssemblyTables;
59                 ITaskItem[]     relatedFiles;
60                 ITaskItem[]     resolvedDependencyFiles;
61                 ITaskItem[]     resolvedFiles;
62                 ITaskItem[]     satelliteFiles;
63                 ITaskItem[]     scatterFiles;
64                 string[]        searchPaths;
65                 ITaskItem[]     serializationAssemblyFiles;
66                 bool            silent;
67                 string          stateFile;
68                 ITaskItem[]     suggestedRedirects;
69                 string[]        targetFrameworkDirectories;
70                 string          targetProcessorArchitecture;
71                 static string []        default_assembly_extensions;
72
73                 AssemblyResolver        assembly_resolver;
74                 List<string> dependency_search_paths;
75                 Dictionary<string, ResolvedReference> assemblyNameToResolvedRef;
76                 Dictionary<string, ITaskItem>   tempSatelliteFiles, tempRelatedFiles,
77                         tempResolvedDepFiles, tempCopyLocalFiles;
78                 List<ITaskItem> tempResolvedFiles;
79                 List<PrimaryReference> primaryReferences;
80                 Dictionary<string, string> alreadyScannedAssemblyNames;
81                 Dictionary<string, string> conflictWarningsCache;
82
83                 //FIXME: construct and use a graph of the dependencies, useful across projects
84
85                 static ResolveAssemblyReference ()
86                 {
87                         default_assembly_extensions = new string [] { ".dll", ".exe" };
88                 }
89
90                 public ResolveAssemblyReference ()
91                 {
92                         assembly_resolver = new AssemblyResolver ();
93                 }
94
95                 //FIXME: make this reusable
96                 public override bool Execute ()
97                 {
98                         if (assemblies == null && assemblyFiles == null)
99                                 // nothing to resolve
100                                 return true;
101
102                         LogTaskParameters ();
103
104                         assembly_resolver.Log = Log;
105                         tempResolvedFiles = new List<ITaskItem> ();
106                         tempCopyLocalFiles = new Dictionary<string, ITaskItem> ();
107                         tempSatelliteFiles = new Dictionary<string, ITaskItem> ();
108                         tempRelatedFiles = new Dictionary<string, ITaskItem> ();
109                         tempResolvedDepFiles = new Dictionary<string, ITaskItem> ();
110
111                         primaryReferences = new List<PrimaryReference> ();
112                         assemblyNameToResolvedRef = new Dictionary<string, ResolvedReference> ();
113                         conflictWarningsCache = new Dictionary<string, string> ();
114
115                         ResolveAssemblies ();
116                         ResolveAssemblyFiles ();
117                         resolvedFiles = tempResolvedFiles.ToArray ();
118
119                         alreadyScannedAssemblyNames = new Dictionary<string, string> ();
120
121                         // the first element is place holder for parent assembly's dir
122                         dependency_search_paths = new List<string> () { String.Empty };
123                         dependency_search_paths.AddRange (searchPaths);
124
125                         // resolve dependencies
126                         foreach (PrimaryReference pref in primaryReferences)
127                                 ResolveAssemblyFileDependencies (pref.TaskItem, pref.ParentCopyLocal);
128
129                         copyLocalFiles = tempCopyLocalFiles.Values.ToArray ();
130                         satelliteFiles = tempSatelliteFiles.Values.ToArray ();
131                         relatedFiles = tempRelatedFiles.Values.ToArray ();
132                         resolvedDependencyFiles = tempResolvedDepFiles.Values.ToArray ();
133
134                         tempResolvedFiles.Clear ();
135                         tempCopyLocalFiles.Clear ();
136                         tempSatelliteFiles.Clear ();
137                         tempRelatedFiles.Clear ();
138                         tempResolvedDepFiles.Clear ();
139                         alreadyScannedAssemblyNames.Clear ();
140                         primaryReferences.Clear ();
141                         assemblyNameToResolvedRef.Clear ();
142                         conflictWarningsCache.Clear ();
143                         dependency_search_paths = null;
144
145                         return true;
146                 }
147
148                 void ResolveAssemblies ()
149                 {
150                         if (assemblies == null || assemblies.Length == 0)
151                                 return;
152
153                         foreach (ITaskItem item in assemblies) {
154                                 if (!String.IsNullOrEmpty (item.GetMetadata ("SubType"))) {
155                                         Log.LogWarning ("Reference '{0}' has non-empty SubType. Ignoring.", item.ItemSpec);
156                                         continue;
157                                 }
158
159                                 LogWithPrecedingNewLine (MessageImportance.Low, "Primary Reference {0}", item.ItemSpec);
160                                 ResolvedReference resolved_ref = ResolveReference (item, searchPaths, true);
161                                 if (resolved_ref == null) {
162                                         Log.LogWarning ("Reference '{0}' not resolved", item.ItemSpec);
163                                         assembly_resolver.LogSearchLoggerMessages (MessageImportance.Normal);
164                                 } else {
165                                         if (Environment.GetEnvironmentVariable ("XBUILD_LOG_REFERENCE_RESOLVER") != null)
166                                                 assembly_resolver.LogSearchLoggerMessages (MessageImportance.Low);
167
168                                         Log.LogMessage (MessageImportance.Low,
169                                                         "\tReference {0} resolved to {1}. CopyLocal = {2}",
170                                                         item.ItemSpec, resolved_ref.TaskItem,
171                                                         resolved_ref.TaskItem.GetMetadata ("CopyLocal"));
172
173                                         Log.LogMessage (MessageImportance.Low,
174                                                         "\tReference found at search path {0}",
175                                                         resolved_ref.FoundInSearchPathAsString);
176
177                                         if (TryAddNewReference (tempResolvedFiles, resolved_ref) &&
178                                                 !IsFromGacOrTargetFramework (resolved_ref) &&
179                                                 resolved_ref.FoundInSearchPath != SearchPath.PkgConfig) {
180                                                 primaryReferences.Add (new PrimaryReference (
181                                                                 resolved_ref.TaskItem,
182                                                                 resolved_ref.TaskItem.GetMetadata ("CopyLocal")));
183                                         }
184                                 }
185                         }
186                 }
187
188                 // Use @search_paths to resolve the reference
189                 ResolvedReference ResolveReference (ITaskItem item, IEnumerable<string> search_paths, bool set_copy_local)
190                 {
191                         ResolvedReference resolved = null;
192                         bool specific_version;
193
194                         assembly_resolver.ResetSearchLogger ();
195
196                         if (!TryGetSpecificVersionValue (item, out specific_version))
197                                 return null;
198
199                         foreach (string spath in search_paths) {
200                                 assembly_resolver.LogSearchMessage ("For searchpath {0}", spath);
201
202                                 if (String.Compare (spath, "{HintPathFromItem}") == 0) {
203                                         resolved = assembly_resolver.ResolveHintPathReference (item, specific_version);
204                                 } else if (String.Compare (spath, "{TargetFrameworkDirectory}") == 0) {
205                                         if (targetFrameworkDirectories == null)
206                                                 continue;
207                                         foreach (string fpath in targetFrameworkDirectories) {
208                                                 resolved = assembly_resolver.FindInTargetFramework (item,
209                                                                 fpath, specific_version);
210                                                 if (resolved != null)
211                                                         break;
212                                         }
213                                 } else if (String.Compare (spath, "{GAC}") == 0) {
214                                         resolved = assembly_resolver.ResolveGacReference (item, specific_version);
215                                 } else if (String.Compare (spath, "{RawFileName}") == 0) {
216                                         //FIXME: identify assembly names, as extract the name, and try with that?
217                                         AssemblyName aname;
218                                         if (assembly_resolver.TryGetAssemblyNameFromFile (item.ItemSpec, out aname))
219                                                 resolved = assembly_resolver.GetResolvedReference (item, item.ItemSpec, aname, true,
220                                                                 SearchPath.RawFileName);
221                                 } else if (String.Compare (spath, "{CandidateAssemblyFiles}") == 0) {
222                                         assembly_resolver.LogSearchMessage (
223                                                         "Warning: {{CandidateAssemblyFiles}} not supported currently");
224                                 } else if (String.Compare (spath, "{PkgConfig}") == 0) {
225                                         resolved = assembly_resolver.ResolvePkgConfigReference (item, specific_version);
226                                 } else {
227                                         resolved = assembly_resolver.FindInDirectory (
228                                                         item, spath,
229                                                         allowedAssemblyExtensions ?? default_assembly_extensions,
230                                                         specific_version);
231                                 }
232
233                                 if (resolved != null)
234                                         break;
235                         }
236
237                         if (resolved != null && set_copy_local)
238                                 SetCopyLocal (resolved.TaskItem, resolved.CopyLocal.ToString ());
239
240                         return resolved;
241                 }
242
243                 bool TryGetSpecificVersionValue (ITaskItem item, out bool specific_version)
244                 {
245                         specific_version = true;
246                         string value = item.GetMetadata ("SpecificVersion");
247                         if (String.IsNullOrEmpty (value)) {
248                                 //AssemblyName name = new AssemblyName (item.ItemSpec);
249                                 // If SpecificVersion is not specified, then
250                                 // it is true if the Include is a strong name else false
251                                 //specific_version = assembly_resolver.IsStrongNamed (name);
252
253                                 // msbuild seems to just look for a ',' in the name :/
254                                 specific_version = item.ItemSpec.IndexOf (',') >= 0;
255                                 return true;
256                         }
257
258                         if (Boolean.TryParse (value, out specific_version))
259                                 return true;
260
261                         Log.LogError ("Item '{0}' has attribute SpecificVersion with invalid value '{1}' " +
262                                         "which could not be converted to a boolean.", item.ItemSpec, value);
263                         return false;
264                 }
265
266                 //FIXME: Consider CandidateAssemblyFiles also here
267                 void ResolveAssemblyFiles ()
268                 {
269                         if (assemblyFiles == null)
270                                 return;
271
272                         foreach (ITaskItem item in assemblyFiles) {
273                                 assembly_resolver.ResetSearchLogger ();
274
275                                 if (!File.Exists (item.ItemSpec)) {
276                                         LogWithPrecedingNewLine (MessageImportance.Low,
277                                                         "Primary Reference from AssemblyFiles {0}, file not found. Ignoring",
278                                                         item.ItemSpec);
279                                         continue;
280                                 }
281
282                                 LogWithPrecedingNewLine (MessageImportance.Low, "Primary Reference from AssemblyFiles {0}", item.ItemSpec);
283                                 string copy_local;
284
285                                 AssemblyName aname;
286                                 if (!assembly_resolver.TryGetAssemblyNameFromFile (item.ItemSpec, out aname)) {
287                                         Log.LogWarning ("Reference '{0}' not resolved", item.ItemSpec);
288                                         assembly_resolver.LogSearchLoggerMessages (MessageImportance.Normal);
289                                         continue;
290                                 }
291
292                                 if (Environment.GetEnvironmentVariable ("XBUILD_LOG_REFERENCE_RESOLVER") != null)
293                                         assembly_resolver.LogSearchLoggerMessages (MessageImportance.Low);
294
295                                 ResolvedReference rr = assembly_resolver.GetResolvedReference (item, item.ItemSpec, aname, true,
296                                                 SearchPath.RawFileName);
297                                 copy_local = rr.CopyLocal.ToString ();
298
299                                 if (!TryAddNewReference (tempResolvedFiles, rr))
300                                         // already resolved
301                                         continue;
302
303                                 SetCopyLocal (rr.TaskItem, copy_local);
304
305                                 FindAndAddRelatedFiles (item.ItemSpec, copy_local);
306                                 FindAndAddSatellites (item.ItemSpec, copy_local);
307
308                                 if (FindDependencies && !IsFromGacOrTargetFramework (rr) &&
309                                                 rr.FoundInSearchPath != SearchPath.PkgConfig)
310                                         primaryReferences.Add (new PrimaryReference (item, copy_local));
311                         }
312                 }
313
314                 // Tries to resolve assemblies referenced by @item
315                 // Skips gac references
316                 // @item : filename
317                 void ResolveAssemblyFileDependencies (ITaskItem item, string parent_copy_local)
318                 {
319                         Queue<string> dependencies = new Queue<string> ();
320                         dependencies.Enqueue (item.ItemSpec);
321
322                         while (dependencies.Count > 0) {
323                                 string filename = Path.GetFullPath (dependencies.Dequeue ());
324                                 Assembly asm = Assembly.ReflectionOnlyLoadFrom (filename);
325                                 if (alreadyScannedAssemblyNames.ContainsKey (asm.FullName))
326                                         continue;
327
328                                 // set the 1st search path to this ref's base path
329                                 // Will be used for resolving the dependencies
330                                 dependency_search_paths [0] = Path.GetDirectoryName (filename);
331
332                                 foreach (AssemblyName aname in asm.GetReferencedAssemblies ()) {
333                                         if (alreadyScannedAssemblyNames.ContainsKey (aname.FullName))
334                                                 continue;
335
336                                         ResolvedReference resolved_ref = ResolveDependencyByAssemblyName (
337                                                         aname, asm.FullName, parent_copy_local);
338
339                                         if (resolved_ref != null && !IsFromGacOrTargetFramework (resolved_ref)
340                                                         && resolved_ref.FoundInSearchPath != SearchPath.PkgConfig) {
341                                                 tempResolvedDepFiles[resolved_ref.AssemblyName.FullName] = resolved_ref.TaskItem;
342                                                 dependencies.Enqueue (resolved_ref.TaskItem.ItemSpec);
343                                         }
344                                 }
345                                 alreadyScannedAssemblyNames.Add (asm.FullName, String.Empty);
346                         }
347                 }
348
349                 // Resolves by looking dependency_search_paths
350                 // which is dir of parent reference file, and
351                 // SearchPaths
352                 ResolvedReference ResolveDependencyByAssemblyName (AssemblyName aname, string parent_asm_name,
353                                 string parent_copy_local)
354                 {
355                         // This will check for compatible assembly name/version
356                         ResolvedReference resolved_ref;
357                         if (TryGetResolvedReferenceByAssemblyName (aname, false, out resolved_ref))
358                                 return resolved_ref;
359
360                         LogWithPrecedingNewLine (MessageImportance.Low, "Dependency {0}", aname);
361                         Log.LogMessage (MessageImportance.Low, "\tRequired by {0}", parent_asm_name);
362
363                         ITaskItem item = new TaskItem (aname.FullName);
364                         item.SetMetadata ("SpecificVersion", "false");
365                         resolved_ref = ResolveReference (item, dependency_search_paths, false);
366
367                         if (resolved_ref != null) {
368                                 if (Environment.GetEnvironmentVariable ("XBUILD_LOG_REFERENCE_RESOLVER") != null)
369                                                 assembly_resolver.LogSearchLoggerMessages (MessageImportance.Low);
370
371                                 Log.LogMessage (MessageImportance.Low, "\tReference {0} resolved to {1}.",
372                                         aname, resolved_ref.TaskItem.ItemSpec);
373
374                                 Log.LogMessage (MessageImportance.Low,
375                                                 "\tReference found at search path {0}",
376                                                 resolved_ref.FoundInSearchPathAsString);
377
378                                 if (resolved_ref.FoundInSearchPath == SearchPath.Directory) {
379                                         // override CopyLocal with parent's val
380                                         SetCopyLocal (resolved_ref.TaskItem, parent_copy_local);
381
382                                         Log.LogMessage (MessageImportance.Low,
383                                                         "\tThis is CopyLocal {0} as parent item has this value",
384                                                         parent_copy_local);
385
386                                         if (TryAddNewReference (tempResolvedFiles, resolved_ref)) {
387                                                 FindAndAddRelatedFiles (resolved_ref.TaskItem.ItemSpec, parent_copy_local);
388                                                 FindAndAddSatellites (resolved_ref.TaskItem.ItemSpec, parent_copy_local);
389                                         }
390                                 } else {
391                                         //gac or tgtfmwk
392                                         Log.LogMessage (MessageImportance.Low,
393                                                         "\tThis is CopyLocal false as it is in the gac," +
394                                                         "target framework directory or provided by a package.");
395
396                                         TryAddNewReference (tempResolvedFiles, resolved_ref);
397                                 }
398                         } else {
399                                 Log.LogWarning ("Reference '{0}' not resolved", aname);
400                                 assembly_resolver.LogSearchLoggerMessages (MessageImportance.Normal);
401                         }
402
403                         return resolved_ref;
404                 }
405
406                 void FindAndAddRelatedFiles (string filename, string parent_copy_local)
407                 {
408                         if (!findRelatedFiles || allowedRelatedFileExtensions == null)
409                                 return;
410
411                         foreach (string ext in allowedRelatedFileExtensions) {
412                                 string rfile = filename + ext;
413                                 if (File.Exists (rfile)) {
414                                         ITaskItem item = new TaskItem (rfile);
415                                         SetCopyLocal (item, parent_copy_local);
416
417                                         tempRelatedFiles.AddUniqueFile (item);
418                                 }
419                         }
420                 }
421
422                 void FindAndAddSatellites (string filename, string parent_copy_local)
423                 {
424                         if (!FindSatellites)
425                                 return;
426
427                         string basepath = Path.GetDirectoryName (filename);
428                         string resource = String.Format ("{0}{1}{2}",
429                                         Path.GetFileNameWithoutExtension (filename),
430                                         ".resources",
431                                         Path.GetExtension (filename));
432
433                         string dir_sep = Path.DirectorySeparatorChar.ToString ();
434                         foreach (string dir in Directory.GetDirectories (basepath)) {
435                                 string culture = Path.GetFileName (dir);
436                                 if (!CultureNamesTable.ContainsKey (culture))
437                                         continue;
438
439                                 string res_path = Path.Combine (dir, resource);
440                                 if (File.Exists (res_path)) {
441                                         ITaskItem item = new TaskItem (res_path);
442                                         SetCopyLocal (item, parent_copy_local);
443                                         item.SetMetadata ("DestinationSubdirectory", culture + dir_sep);
444                                         tempSatelliteFiles.AddUniqueFile (item);
445                                 }
446                         }
447                 }
448
449                 // returns true is it was new
450                 bool TryAddNewReference (List<ITaskItem> file_list, ResolvedReference key_ref)
451                 {
452                         ResolvedReference found_ref;
453                         if (!TryGetResolvedReferenceByAssemblyName (key_ref.AssemblyName, key_ref.IsPrimary, out found_ref)) {
454                                 assemblyNameToResolvedRef [key_ref.AssemblyName.Name] = key_ref;
455                                 file_list.Add (key_ref.TaskItem);
456
457                                 return true;
458                         }
459                         return false;
460                 }
461
462                 void SetCopyLocal (ITaskItem item, string copy_local)
463                 {
464                         item.SetMetadata ("CopyLocal", copy_local);
465
466                         // Assumed to be valid value
467                         if (Boolean.Parse (copy_local))
468                                 tempCopyLocalFiles.AddUniqueFile (item);
469                 }
470
471                 bool TryGetResolvedReferenceByAssemblyName (AssemblyName key_aname, bool is_primary, out ResolvedReference found_ref)
472                 {
473                         found_ref = null;
474                         // Match by just name
475                         if (!assemblyNameToResolvedRef.TryGetValue (key_aname.Name, out found_ref))
476                                 // not there
477                                 return false;
478
479                         // match for full name
480                         if (AssemblyResolver.AssemblyNamesCompatible (key_aname, found_ref.AssemblyName, true, false))
481                                 // exact match, so its already there, dont add anything
482                                 return true;
483
484                         // we have a name match, but version mismatch!
485                         assembly_resolver.LogSearchMessage ("A conflict was detected between '{0}' and '{1}'",
486                                         key_aname.FullName, found_ref.AssemblyName.FullName);
487
488                         if (is_primary == found_ref.IsPrimary) {
489                                 assembly_resolver.LogSearchMessage ("Unable to choose between the two. " +
490                                                 "Choosing '{0}' arbitrarily.", found_ref.AssemblyName.FullName);
491                                 return true;
492                         }
493
494                         // since all dependencies are processed after
495                         // all primary refererences, the one in the cache
496                         // has to be a primary
497                         // Prefer a primary reference over a dependency
498
499                         assembly_resolver.LogSearchMessage ("Choosing '{0}' as it is a primary reference.",
500                                         found_ref.AssemblyName.FullName);
501
502                         // If we can successfully use the primary reference, don't log a warning. It's too
503                         // verbose.
504                         //LogConflictWarning (found_ref.AssemblyName.FullName, key_aname.FullName);
505
506                         return true;
507                 }
508
509                 void LogWithPrecedingNewLine (MessageImportance importance, string format, params object [] args)
510                 {
511                         Log.LogMessage (importance, String.Empty);
512                         Log.LogMessage (importance, format, args);
513                 }
514
515                 // conflict b/w @main and @conflicting, picking @main
516                 void LogConflictWarning (string main, string conflicting)
517                 {
518                         string key = main + ":" + conflicting;
519                         if (!conflictWarningsCache.ContainsKey (key)) {
520                                 Log.LogWarning ("Found a conflict between : '{0}' and '{1}'. Using '{0}' reference.",
521                                                 main, conflicting);
522                                 conflictWarningsCache [key] = key;
523                         }
524                 }
525
526                 bool IsFromGacOrTargetFramework (ResolvedReference rr)
527                 {
528                         return rr.FoundInSearchPath == SearchPath.Gac ||
529                                 rr.FoundInSearchPath == SearchPath.TargetFrameworkDirectory;
530                 }
531
532                 void LogTaskParameters ()
533                 {
534                         Log.LogMessage (MessageImportance.Low, "TargetFrameworkDirectories:");
535                         if (TargetFrameworkDirectories != null)
536                                 foreach (string dir in TargetFrameworkDirectories)
537                                         Log.LogMessage (MessageImportance.Low, "\t{0}", dir);
538
539                         Log.LogMessage (MessageImportance.Low, "SearchPaths:");
540                         if (SearchPaths != null)
541                                 foreach (string path in SearchPaths)
542                                         Log.LogMessage (MessageImportance.Low, "\t{0}", path);
543                 }
544
545                 public bool AutoUnify {
546                         get { return autoUnify; }
547                         set { autoUnify = value; }
548                 }
549                 
550                 public ITaskItem[] AssemblyFiles {
551                         get { return assemblyFiles; }
552                         set { assemblyFiles = value; }
553                 }
554                 
555                 public ITaskItem[] Assemblies {
556                         get { return assemblies; }
557                         set { assemblies = value; }
558                 }
559                 
560                 public string AppConfigFile {
561                         get { return appConfigFile; }
562                         set { appConfigFile = value; }
563                 }
564                 
565                 public string[] AllowedAssemblyExtensions {
566                         get { return allowedAssemblyExtensions; }
567                         set { allowedAssemblyExtensions = value; }
568                 }
569
570                 public string[] AllowedRelatedFileExtensions {
571                         get { return allowedRelatedFileExtensions; }
572                         set { allowedRelatedFileExtensions = value; }
573                 }
574                 
575                 public string[] CandidateAssemblyFiles {
576                         get { return candidateAssemblyFiles; }
577                         set { candidateAssemblyFiles = value; }
578                 }
579                 
580                 [Output]
581                 public ITaskItem[] CopyLocalFiles {
582                         get { return copyLocalFiles; }
583                 }
584                 
585                 [Output]
586                 public ITaskItem[] FilesWritten {
587                         get { return filesWritten; }
588                         set { filesWritten = value; }
589                 }
590                 
591                 public bool FindDependencies {
592                         get { return findDependencies; }
593                         set { findDependencies = value; }
594                 }
595                 
596                 public bool FindRelatedFiles {
597                         get { return findRelatedFiles; }
598                         set { findRelatedFiles = value; }
599                 }
600                 
601                 public bool FindSatellites {
602                         get { return findSatellites; }
603                         set { findSatellites = value; }
604                 }
605                 
606                 public bool FindSerializationAssemblies {
607                         get { return findSerializationAssemblies; }
608                         set { findSerializationAssemblies = value; }
609                 }
610                 
611                 public string[] InstalledAssemblyTables {
612                         get { return installedAssemblyTables; }
613                         set { installedAssemblyTables = value; }
614                 }
615                 
616                 [Output]
617                 public ITaskItem[] RelatedFiles {
618                         get { return relatedFiles; }
619                 }
620                 
621                 [Output]
622                 public ITaskItem[] ResolvedDependencyFiles {
623                         get { return resolvedDependencyFiles; }
624                 }
625                 
626                 [Output]
627                 public ITaskItem[] ResolvedFiles {
628                         get { return resolvedFiles; }
629                 }
630                 
631                 [Output]
632                 public ITaskItem[] SatelliteFiles {
633                         get { return satelliteFiles; }
634                 }
635                 
636                 [Output]
637                 public ITaskItem[] ScatterFiles {
638                         get { return scatterFiles; }
639                 }
640                 
641                 [Required]
642                 public string[] SearchPaths {
643                         get { return searchPaths; }
644                         set { searchPaths = value; }
645                 }
646                 
647                 [Output]
648                 public ITaskItem[] SerializationAssemblyFiles {
649                         get { return serializationAssemblyFiles; }
650                 }
651                 
652                 public bool Silent {
653                         get { return silent; }
654                         set { silent = value; }
655                 }
656                 
657                 public string StateFile {
658                         get { return stateFile; }
659                         set { stateFile = value; }
660                 }
661                 
662                 [Output]
663                 public ITaskItem[] SuggestedRedirects {
664                         get { return suggestedRedirects; }
665                 }
666
667 #if NET_4_0
668                 public string TargetFrameworkMoniker { get; set; }
669
670                 public string TargetFrameworkMonikerDisplayName { get; set; }
671 #endif
672
673                 public string TargetFrameworkVersion { get; set; }
674
675                 public string[] TargetFrameworkDirectories {
676                         get { return targetFrameworkDirectories; }
677                         set { targetFrameworkDirectories = value; }
678                 }
679                 
680                 public string TargetProcessorArchitecture {
681                         get { return targetProcessorArchitecture; }
682                         set { targetProcessorArchitecture = value; }
683                 }
684
685
686                 static Dictionary<string, string> cultureNamesTable;
687                 static Dictionary<string, string> CultureNamesTable {
688                         get {
689                                 if (cultureNamesTable == null) {
690                                         cultureNamesTable = new Dictionary<string, string> ();
691                                         foreach (CultureInfo ci in CultureInfo.GetCultures (CultureTypes.AllCultures))
692                                                 cultureNamesTable [ci.Name] = ci.Name;
693                                 }
694
695                                 return cultureNamesTable;
696                         }
697                 }
698         }
699
700         static class ResolveAssemblyReferenceHelper {
701                 public static void AddUniqueFile (this Dictionary<string, ITaskItem> dic, ITaskItem item)
702                 {
703                         if (dic == null)
704                                 throw new ArgumentNullException ("dic");
705                         if (item == null)
706                                 throw new ArgumentNullException ("item");
707
708                         string fullpath = Path.GetFullPath (item.ItemSpec);
709                         if (!dic.ContainsKey (fullpath))
710                                 dic [fullpath] = item;
711                 }
712         }
713
714         struct PrimaryReference {
715                 public ITaskItem TaskItem;
716                 public string ParentCopyLocal;
717
718                 public PrimaryReference (ITaskItem item, string parent_copy_local)
719                 {
720                         TaskItem = item;
721                         ParentCopyLocal = parent_copy_local;
722                 }
723         }
724
725 }
726
727 #endif