Mark tests as not working under TARGET_JVM
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AppCodeCompiler.cs
1 //
2 // System.Web.Compilation.AppCodeCompiler: A compiler for the App_Code folder
3 //
4 // Authors:
5 //   Marek Habersack (grendello@gmail.com)
6 //
7 // (C) 2006 Marek Habersack
8 //
9
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 using System;
32 using System.CodeDom;
33 using System.CodeDom.Compiler;
34 using System.Configuration;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Globalization;
38 using System.IO;
39 using System.Reflection;
40 using System.Web;
41 using System.Web.Configuration;
42 using System.Web.Profile;
43 using System.Web.Util;
44
45 namespace System.Web.Compilation
46 {
47         internal class AppCodeAssembly
48         {
49                 private List<string> files;
50                 private List<CodeCompileUnit> units;
51                 
52                 private string name;
53                 private string path;
54                 private bool validAssembly;
55                 private string outputAssemblyName;
56
57                 public string OutputAssemblyName
58                 {
59                         get {
60                                 return outputAssemblyName;
61                         }
62                 }
63                 
64                 public bool IsValid
65                 {
66                         get { return validAssembly; }
67                 }
68
69                 public string SourcePath
70                 {
71                         get { return path; }
72                 }
73
74 // temporary
75                 public string Name
76                 {
77                         get { return name; }
78                 }
79                 
80                 public List<string> Files
81                 {
82                         get { return files; }
83                 }
84 // temporary
85                 
86                 public AppCodeAssembly (string name, string path)
87                 {
88                         this.files = new List<string> ();
89                         this.units = new List<CodeCompileUnit> ();
90                         this.validAssembly = true;
91                         this.name = name;
92                         this.path = path;
93                 }
94
95                 public void AddFile (string path)
96                 {
97                         files.Add (path);
98                 }
99
100                 public void AddUnit (CodeCompileUnit unit)
101                 {
102                         units.Add (unit);
103                 }
104                 
105                 object OnCreateTemporaryAssemblyFile (string path)
106                 {
107                         FileStream f = new FileStream (path, FileMode.CreateNew);
108                         f.Close ();
109                         return path;
110                 }
111                 
112                 // Build and add the assembly to the BuildManager's
113                 // CodeAssemblies collection
114                 public void Build (string[] binAssemblies)
115                 {
116                         Type compilerProvider = null;
117                         CompilerInfo compilerInfo = null, cit;
118                         string extension, language, cpfile = null;
119                         List<string> knownfiles = new List<string>();
120                         List<string> unknownfiles = new List<string>();
121                         
122                         // First make sure all the files are in the same
123                         // language
124                         bool known;
125                         foreach (string f in files) {
126                                 known = true;
127                                 language = null;
128                                 
129                                 extension = Path.GetExtension (f);
130                                 if (!CodeDomProvider.IsDefinedExtension (extension))
131                                         known = false;
132                                 if (known) {
133                                         language = CodeDomProvider.GetLanguageFromExtension(extension);
134                                         if (!CodeDomProvider.IsDefinedLanguage (language))
135                                                 known = false;
136                                 }
137                                 if (!known || language == null) {
138                                         unknownfiles.Add (f);
139                                         continue;
140                                 }
141                                 
142                                 cit = CodeDomProvider.GetCompilerInfo (language);
143                                 if (cit == null || !cit.IsCodeDomProviderTypeValid)
144                                         continue;
145                                 if (compilerProvider == null) {
146                                         cpfile = f;
147                                         compilerProvider = cit.CodeDomProviderType;
148                                         compilerInfo = cit;
149                                 } else if (compilerProvider != cit.CodeDomProviderType)
150                                         throw new HttpException (
151                                                 String.Format (
152                                                         "Files {0} and {1} are in different languages - they cannot be compiled into the same assembly",
153                                                         Path.GetFileName (cpfile),
154                                                         Path.GetFileName (f)));
155                                 knownfiles.Add (f);
156                         }
157
158                         CodeDomProvider provider = null;
159                         CompilationSection compilationSection = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
160                         if (compilerInfo == null) {
161                                 if (!CodeDomProvider.IsDefinedLanguage (compilationSection.DefaultLanguage))
162                                         throw new HttpException ("Failed to retrieve default source language");
163                                 compilerInfo = CodeDomProvider.GetCompilerInfo (compilationSection.DefaultLanguage);
164                                 if (compilerInfo == null || !compilerInfo.IsCodeDomProviderTypeValid)
165                                         throw new HttpException ("Internal error while initializing application");
166                                 provider = compilerInfo.CreateProvider ();
167                                 if (provider == null)
168                                         throw new HttpException ("A code provider error occurred while initializing application.");
169                         }
170
171                         provider = compilerInfo.CreateProvider ();
172                         if (provider == null)
173                                 throw new HttpException ("A code provider error occurred while initializing application.");
174
175                         AssemblyBuilder abuilder = new AssemblyBuilder (provider);
176                         foreach (string file in knownfiles)
177                                 abuilder.AddCodeFile (file);
178                         foreach (CodeCompileUnit unit in units)
179                                 abuilder.AddCodeCompileUnit (unit);
180                         
181                         BuildProvider bprovider;
182                         CompilerParameters parameters = compilerInfo.CreateDefaultCompilerParameters ();
183                         parameters.IncludeDebugInformation = compilationSection.Debug;
184                         
185                         if (binAssemblies != null && binAssemblies.Length > 0)
186                                 parameters.ReferencedAssemblies.AddRange (binAssemblies);
187                         
188                         if (compilationSection != null) {
189                                 AssemblyName asmName;
190                                 foreach (AssemblyInfo ai in compilationSection.Assemblies)
191                                         if (ai.Assembly != "*") {
192                                                 try {
193                                                         asmName = new AssemblyName (ai.Assembly);
194                                                         parameters.ReferencedAssemblies.Add (asmName.Name);
195                                                 } catch (Exception ex) {
196                                                         throw new HttpException (
197                                                                 String.Format ("Could not find assembly {0}.", ai.Assembly),
198                                                                 ex);
199                                                 }
200                                         }
201                                 
202                                 BuildProviderCollection buildProviders = compilationSection.BuildProviders;
203                                 
204                                 foreach (string file in unknownfiles) {
205                                         bprovider = GetBuildProviderFor (file, buildProviders);
206                                         if (bprovider == null)
207                                                 continue;
208                                         bprovider.GenerateCode (abuilder);
209                                 }
210                         }
211                         
212                         outputAssemblyName = (string)FileUtils.CreateTemporaryFile (
213                                 AppDomain.CurrentDomain.SetupInformation.DynamicBase,
214                                 name, "dll", OnCreateTemporaryAssemblyFile);
215                         parameters.OutputAssembly = outputAssemblyName;
216                         foreach (Assembly a in BuildManager.TopLevelAssemblies)
217                                 parameters.ReferencedAssemblies.Add (a.Location);
218                         CompilerResults results = abuilder.BuildAssembly (parameters);
219                         if (results.Errors.Count == 0) {
220                                 BuildManager.CodeAssemblies.Add (results.CompiledAssembly);
221                                 BuildManager.TopLevelAssemblies.Add (results.CompiledAssembly);
222                                 HttpRuntime.WritePreservationFile (results.CompiledAssembly, name);
223                         } else {
224                                 if (HttpContext.Current.IsCustomErrorEnabled)
225                                         throw new HttpException ("An error occurred while initializing application.");
226                                 throw new CompilationException (null, results.Errors, null);
227                         }
228                 }
229
230                 private BuildProvider GetBuildProviderFor (string file, BuildProviderCollection buildProviders)
231                 {
232                         if (file == null || file.Length == 0 || buildProviders == null || buildProviders.Count == 0)
233                                 return null;
234
235                         BuildProvider ret = buildProviders.GetProviderForExtension (Path.GetExtension (file));
236                         if (ret != null && IsCorrectBuilderType (ret)) {
237                                 ret.SetVirtualPath (VirtualPathUtility.ToAppRelative (file));
238                                 return ret;
239                         }
240                                 
241                         return null;
242                 }
243
244                 private bool IsCorrectBuilderType (BuildProvider bp)
245                 {
246                         if (bp == null)
247                                 return false;
248                         Type type;
249                         object[] attrs;
250
251                         type = bp.GetType ();
252                         attrs = type.GetCustomAttributes (true);
253                         if (attrs == null)
254                                 return false;
255                         
256                         BuildProviderAppliesToAttribute bpAppliesTo;
257                         bool attributeFound = false;
258                         foreach (object attr in attrs) {
259                                 bpAppliesTo = attr as BuildProviderAppliesToAttribute;
260                                 if (bpAppliesTo == null)
261                                         continue;
262                                 attributeFound = true;
263                                 if ((bpAppliesTo.AppliesTo & BuildProviderAppliesTo.All) == BuildProviderAppliesTo.All ||
264                                     (bpAppliesTo.AppliesTo & BuildProviderAppliesTo.Code) == BuildProviderAppliesTo.Code)
265                                         return true;
266                         }
267
268                         if (attributeFound)
269                                 return false;
270                         return true;
271                 }
272                 
273         }
274         
275         internal class AppCodeCompiler
276         {
277                 static private bool _alreadyCompiled;
278                 internal static string DefaultAppCodeAssemblyName;
279                 
280                 // A dictionary that contains an entry per an assembly that will
281                 // be produced by compiling App_Code. There's one main assembly
282                 // and an optional number of assemblies as defined by the
283                 // codeSubDirectories sub-element of the compilation element in
284                 // the system.web section of the app's config file.
285                 // Each entry's value is an AppCodeAssembly instance.
286                 //
287                 // Assemblies are named as follows:
288                 //
289                 //  1. main assembly: App_Code.{HASH}
290                 //  2. subdir assemblies: App_SubCode_{DirName}.{HASH}
291                 //
292                 // If any of the assemblies contains files that would be
293                 // compiled with different compilers, a System.Web.HttpException
294                 // is thrown.
295                 //
296                 // Files for which there is no explicit builder are ignored
297                 // silently
298                 //
299                 // Files for which exist BuildProviders but which have no
300                 // unambiguous language assigned to them (e.g. .wsdl files), are
301                 // built using the default website compiler.
302                 private List<AppCodeAssembly> assemblies;
303                 string _bindir;
304                 
305                 public AppCodeCompiler ()
306                 {
307                         assemblies = new List<AppCodeAssembly>();
308                 }
309
310                 bool ProcessAppCodeDir (string appCode, AppCodeAssembly defasm)
311                 {
312                         // First process the codeSubDirectories
313                         CompilationSection cs = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
314                         
315                         if (cs != null) {
316                                 string aname;
317                                 for (int i = 0; i < cs.CodeSubDirectories.Count; i++) {
318                                         aname = String.Format ("App_SubCode_{0}", cs.CodeSubDirectories[i].DirectoryName);
319                                         assemblies.Add (new AppCodeAssembly (
320                                                                 aname,
321                                                                 Path.Combine (appCode, cs.CodeSubDirectories[i].DirectoryName)));
322                                 }
323                         }
324                         
325                         return CollectFiles (appCode, defasm);
326                 }
327
328                 CodeTypeReference GetProfilePropertyType (string type)
329                 {
330                         if (String.IsNullOrEmpty (type))
331                                 throw new ArgumentException ("String size cannot be 0", "type");
332                         return new CodeTypeReference (type);
333                 }
334
335                 Type GetTypeFromBin (string typeName)
336                 {
337                         string bindir = BinDir;
338                         if (!Directory.Exists (bindir))
339                                 return null;
340                         
341                         string [] binDlls = Directory.GetFiles (bindir, "*.dll");
342                         Type ret = null;
343                         foreach (string dll in binDlls) {
344                                 try {
345                                         Assembly asm = Assembly.LoadFrom (dll);
346                                         ret = asm.GetType (typeName, false);
347                                         if (ret != null)
348                                                 break;
349                                 } catch (Exception) {
350                                         continue;
351                                 }
352                         }
353
354                         return ret;
355                 }
356
357                 string FindProviderTypeName (ProfileSection ps, string providerName)
358                 {
359                         if (ps.Providers == null || ps.Providers.Count == 0)
360                                 return null;
361                         
362                         ProviderSettings pset = ps.Providers [providerName];
363                         if (pset == null)
364                                 return null;
365                         return pset.Type;
366                 }
367                 
368                 void GetProfileProviderAttribute (ProfileSection ps, CodeAttributeDeclarationCollection collection,
369                                                   string providerName)
370                 {
371                         string providerTypeName;
372
373                         if (String.IsNullOrEmpty (providerName))
374                                 providerTypeName = FindProviderTypeName (ps, ps.DefaultProvider);
375                         else
376                                 providerTypeName = FindProviderTypeName (ps, providerName);
377                         if (providerTypeName == null)
378                                 throw new HttpException (String.Format ("Profile provider type not found: {0}",
379                                                                         providerTypeName));
380                         
381                         Type type = Type.GetType (providerTypeName, false);
382                         if (type == null) {
383                                 type = GetTypeFromBin (providerTypeName);
384                                 if (type == null)
385                                         throw new HttpException (String.Format ("Profile provider type not found: {0}",
386                                                                                 providerTypeName));
387                         }
388                         
389                         collection.Add (
390                                 new CodeAttributeDeclaration (
391                                         "ProfileProvider",
392                                         new CodeAttributeArgument (
393                                                 new CodePrimitiveExpression (providerTypeName)
394                                         )
395                                 )
396                         );
397                 }
398
399                 void GetProfileSettingsSerializeAsAttribute (ProfileSection ps, CodeAttributeDeclarationCollection collection,
400                                                              SerializationMode mode)
401                 {
402                         string parameter = String.Format ("SettingsSerializeAs.{0}", mode.ToString ());
403                         collection.Add (
404                                 new CodeAttributeDeclaration (
405                                         "SettingsSerializeAs",
406                                         new CodeAttributeArgument (
407                                                 new CodeSnippetExpression (parameter)
408                                         )
409                                 )
410                         );
411                                         
412                 }
413
414                 void AddProfileClassGetProfileMethod (CodeTypeDeclaration profileClass)
415                 {
416                         CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression (
417                                 new CodeTypeReferenceExpression (typeof (System.Web.Profile.ProfileBase)),
418                                 "Create");
419                         CodeMethodInvokeExpression minvoke = new CodeMethodInvokeExpression (
420                                 mref,
421                                 new CodeExpression[] { new CodeVariableReferenceExpression ("username") }
422                         );
423                         CodeCastExpression cast = new CodeCastExpression ();
424                         cast.TargetType = new CodeTypeReference ("ProfileCommon");
425                         cast.Expression = minvoke;
426                         
427                         CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
428                         ret.Expression = cast;
429                         
430                         CodeMemberMethod method = new CodeMemberMethod ();
431                         method.Name = "GetProfile";
432                         method.ReturnType = new CodeTypeReference ("ProfileCommon");
433                         method.Parameters.Add (new CodeParameterDeclarationExpression("System.String", "username"));
434                         method.Statements.Add (ret);
435                         method.Attributes = MemberAttributes.Public;
436                         
437                         profileClass.Members.Add (method);
438                 }
439                 
440                 void AddProfileClassProperty (ProfileSection ps, CodeTypeDeclaration profileClass, ProfilePropertySettings pset)
441                 {
442                         string name = pset.Name;
443                         if (String.IsNullOrEmpty (name))
444                                 throw new HttpException ("Profile property 'Name' attribute cannot be null.");
445                         CodeMemberProperty property = new CodeMemberProperty ();
446                         string typeName = pset.Type;
447                         if (typeName == "string")
448                                 typeName = "System.String";
449                         property.Name = name;
450                         property.Type = GetProfilePropertyType (typeName);
451                         property.Attributes = MemberAttributes.Public;
452                         
453                         CodeAttributeDeclarationCollection collection = new CodeAttributeDeclarationCollection();
454                         GetProfileProviderAttribute (ps, collection, pset.Provider);
455                         GetProfileSettingsSerializeAsAttribute (ps, collection, pset.SerializeAs);
456
457                         property.CustomAttributes = collection;
458                         CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
459                         CodeCastExpression cast = new CodeCastExpression ();
460                         ret.Expression = cast;
461
462                         CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression (
463                                 new CodeThisReferenceExpression (),
464                                 "GetPropertyValue");
465                         CodeMethodInvokeExpression minvoke = new CodeMethodInvokeExpression (
466                                 mref,
467                                 new CodeExpression[] { new CodePrimitiveExpression (name) }
468                         );
469                         cast.TargetType = new CodeTypeReference (typeName);
470                         cast.Expression = minvoke;
471                         property.GetStatements.Add (ret);
472
473                         if (!pset.ReadOnly) {
474                                 mref = new CodeMethodReferenceExpression (
475                                         new CodeThisReferenceExpression (),
476                                         "SetPropertyValue");
477                                 minvoke = new CodeMethodInvokeExpression (
478                                         mref,
479                                         new CodeExpression[] { new CodePrimitiveExpression (name), new CodeSnippetExpression ("value") }
480                                 );
481                                 property.SetStatements.Add (minvoke);
482                         }
483                         
484                         
485                         profileClass.Members.Add (property);
486                 }
487
488                 void AddProfileClassGroupProperty (string groupName, string memberName, CodeTypeDeclaration profileClass)
489                 {                       
490                         CodeMemberProperty property = new CodeMemberProperty ();
491                         property.Name = memberName;
492                         property.Type = new CodeTypeReference (groupName);
493                         property.Attributes = MemberAttributes.Public;
494
495                         CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
496                         CodeCastExpression cast = new CodeCastExpression ();
497                         ret.Expression = cast;
498
499                         CodeMethodReferenceExpression mref = new CodeMethodReferenceExpression (
500                                 new CodeThisReferenceExpression (),
501                                 "GetProfileGroup");
502                         CodeMethodInvokeExpression minvoke = new CodeMethodInvokeExpression (
503                                 mref,
504                                 new CodeExpression[] { new CodePrimitiveExpression (memberName) }
505                         );
506                         cast.TargetType = new CodeTypeReference (groupName);
507                         cast.Expression = minvoke;
508                         property.GetStatements.Add (ret);
509                         
510                         profileClass.Members.Add (property);
511                 }
512                 
513                 void BuildProfileClass (ProfileSection ps, string className, ProfilePropertySettingsCollection psc,
514                                         CodeNamespace ns, string baseClass, bool baseIsGlobal,
515                                         SortedList <string, string> groupProperties)
516                 {
517                         CodeTypeDeclaration profileClass = new CodeTypeDeclaration (className);
518                         CodeTypeReference cref = new CodeTypeReference (baseClass);
519                         if (baseIsGlobal)
520                                 cref.Options |= CodeTypeReferenceOptions.GlobalReference;
521                         profileClass.BaseTypes.Add (cref);
522                         profileClass.TypeAttributes = TypeAttributes.Public;
523                         ns.Types.Add (profileClass);
524                         
525                         foreach (ProfilePropertySettings pset in psc)
526                                 AddProfileClassProperty (ps, profileClass, pset);
527                         if (groupProperties != null && groupProperties.Count > 0)
528                                 foreach (KeyValuePair <string, string> group in groupProperties)
529                                         AddProfileClassGroupProperty (group.Key, group.Value, profileClass);
530                         AddProfileClassGetProfileMethod (profileClass);
531                 }
532
533                 string MakeGroupName (string name)
534                 {
535                         return String.Format ("ProfileGroup{0}", name);
536                 }
537                 
538                 // FIXME: there should be some validation of syntactic correctness of the member/class name
539                 // for the groups/properties. For now it's left to the compiler to report errors.
540                 //
541                 // CodeGenerator.IsValidLanguageIndependentIdentifier (id) - use that
542                 //
543                 bool ProcessCustomProfile (ProfileSection ps, AppCodeAssembly defasm)
544                 {
545                         CodeCompileUnit unit = new CodeCompileUnit ();
546                         CodeNamespace ns = new CodeNamespace (null);
547                         unit.Namespaces.Add (ns);
548                         defasm.AddUnit (unit);
549                         
550                         ns.Imports.Add (new CodeNamespaceImport ("System"));
551                         ns.Imports.Add (new CodeNamespaceImport ("System.Configuration"));
552                         ns.Imports.Add (new CodeNamespaceImport ("System.Web"));
553                         ns.Imports.Add (new CodeNamespaceImport ("System.Web.Profile"));
554                         
555                         RootProfilePropertySettingsCollection props = ps.PropertySettings;
556                         if (props == null || props.Count == 0)
557                                 return true;
558
559                         SortedList<string, string> groupProperties = new SortedList<string, string> ();
560                         string groupName;
561                         foreach (ProfileGroupSettings pgs in props.GroupSettings) {
562                                 groupName = MakeGroupName (pgs.Name);
563                                 groupProperties.Add (groupName, pgs.Name);
564                                 BuildProfileClass (ps, groupName, pgs.PropertySettings, ns,
565                                                    "System.Web.Profile.ProfileGroupBase", true, null);
566                         }
567                         
568                         string baseType = ps.Inherits;
569                         bool baseIsGlobal = false;
570                         if (String.IsNullOrEmpty (baseType)) {
571                                 baseType = "System.Web.Profile.ProfileBase";
572                                 baseIsGlobal = true;
573                         }
574                         
575                         BuildProfileClass (ps, "ProfileCommon", props, ns, baseType, baseIsGlobal, groupProperties);
576                         return true;
577                 }
578
579 //              void PutCustomProfileInContext (HttpContext context, string assemblyName)
580 //              {
581 //                      Type type = Type.GetType (String.Format ("ProfileCommon, {0}",
582 //                                                               Path.GetFileNameWithoutExtension (assemblyName)));
583 //                      ProfileBase pb = Activator.CreateInstance (type) as ProfileBase;
584 //                      if (pb != null)
585 //                              context.Profile = pb;
586 //              }
587                 
588                 public void Compile ()
589                 {
590                         if (_alreadyCompiled)
591                                 return;
592                         _alreadyCompiled = false;
593                         
594                         string appCode = Path.Combine (HttpRuntime.AppDomainAppPath, "App_Code");
595                         ProfileSection ps = WebConfigurationManager.GetSection ("system.web/profile") as ProfileSection;
596                         bool haveAppCodeDir = Directory.Exists (appCode);
597                         bool haveCustomProfile = ps != null ? ps.PropertySettings.Count > 0 : false;
598                         
599                         if (!haveAppCodeDir && !haveCustomProfile)
600                                 return;
601
602                         AppCodeAssembly defasm = new AppCodeAssembly ("App_Code", appCode);
603                         assemblies.Add (defasm);
604
605                         bool haveCode = false;
606                         if (haveAppCodeDir)
607                                 haveCode = ProcessAppCodeDir (appCode, defasm);
608                         if (haveCustomProfile)
609                                 if (ProcessCustomProfile (ps, defasm))
610                                         haveCode = true;
611
612                         if (!haveCode)
613                                 return;
614
615                         HttpRuntime.EnableAssemblyMapping (true);
616                         string bindir = BinDir;
617                         string[] binAssemblies = null;
618                         if (Directory.Exists (bindir))
619                                 binAssemblies = Directory.GetFiles (bindir, "*.dll");
620                         foreach (AppCodeAssembly aca in assemblies)
621                                 aca.Build (binAssemblies);
622                         DefaultAppCodeAssemblyName = Path.GetFileNameWithoutExtension (defasm.OutputAssemblyName);
623                 }
624
625                 private bool CollectFiles (string dir, AppCodeAssembly aca)
626                 {
627                         bool haveFiles = false;
628                         
629                         AppCodeAssembly curaca = aca;
630                         foreach (string f in Directory.GetFiles (dir)) {
631                                 aca.AddFile (f);
632                                 haveFiles = true;
633                         }
634                         
635                         foreach (string d in Directory.GetDirectories (dir)) {
636                                 foreach (AppCodeAssembly a in assemblies)
637                                         if (a.SourcePath == d) {
638                                                 curaca = a;
639                                                 break;
640                                         }
641                                 if (CollectFiles (d, curaca))
642                                         haveFiles = true;
643                                 curaca = aca;
644                         }
645                         return haveFiles;
646                 }
647
648                 private string BinDir {
649                         get {
650                                 if (_bindir != null)
651                                         return _bindir;
652                                 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
653                                 _bindir = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath);
654                                 return _bindir;
655                         }
656                 }
657         }
658 }
659 #endif