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