merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / DirectoryScanner.cs
1 //
2 // DirectoryScanner.cs: Class used by BuildItem.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 #if NET_2_0
29
30 using System;
31 using System.Collections.Generic;
32 using System.IO;
33
34 namespace Microsoft.Build.BuildEngine {
35         internal class DirectoryScanner {
36                 
37                 DirectoryInfo   baseDirectory;
38                 string          includes;
39                 string          excludes;
40                 string[]        matchedFilenames;
41                 
42                 public DirectoryScanner ()
43                 {
44                 }
45                 
46                 public void Scan ()
47                 {
48                         Dictionary <string, bool> excludedItems;
49                         List <string> includedItems;
50                         string[] splitInclude, splitExclude;
51                         
52                         if (includes == null)
53                                 throw new ArgumentNullException ("Includes");
54                         if (excludes == null)
55                                 throw new ArgumentNullException ("Excludes");
56                         if (baseDirectory == null)
57                                 throw new ArgumentNullException ("BaseDirectory");
58                         
59                         excludedItems = new Dictionary <string, bool> ();
60                         includedItems = new List <string> ();
61                         
62                         splitInclude = includes.Split (';');
63                         splitExclude = excludes.Split (';');
64                         
65                         if (excludes != String.Empty) {
66                                 foreach (string si in splitExclude) {
67                                         ProcessExclude (si, excludedItems);
68                                 }
69                         }
70                         if (includes != String.Empty) {
71                                 foreach (string si in splitInclude) {
72                                         ProcessInclude (si, excludedItems, includedItems);
73                                 }
74                         }
75
76                         matchedFilenames = includedItems.ToArray ();
77                 }
78                 
79                 private void ProcessInclude (string name, Dictionary <string, bool> excludedItems, List <string> includedItems)
80                 {
81                         string[] separatedPath;
82                         FileInfo[] fileInfo;
83
84                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
85                                 if (!excludedItems.ContainsKey (Path.GetFullPath(name)))
86                                         includedItems.Add (name);
87                         } else {
88                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
89                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
90                                 } else {
91                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
92                                 }
93                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
94                                         return;
95                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
96                                 foreach (FileInfo fi in fileInfo)
97                                         if (!excludedItems.ContainsKey (fi.FullName))
98                                                 includedItems.Add (fi.FullName);
99                         }
100                 }
101                 
102                 private void ProcessExclude (string name, Dictionary <string, bool> excludedItems)
103                 {
104                         string[] separatedPath;
105                         FileInfo[] fileInfo;
106                         
107                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
108                                 if (!excludedItems.ContainsKey (Path.GetFullPath (name)))
109                                         excludedItems.Add (Path.GetFullPath (name), true);
110                         } else {
111                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
112                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
113                                 } else {
114                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
115                                 }
116                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
117                                         return;
118                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
119                                 foreach (FileInfo fi in fileInfo)
120                                         if (!excludedItems.ContainsKey (fi.FullName))
121                                                 excludedItems.Add (fi.FullName, true);
122                         }
123                 }
124                 
125                 private FileInfo[] ParseIncludeExclude (string[] input, int ptr, DirectoryInfo directory)
126                 {
127                         if (input.Length > 1 && ptr == 0 && input [0] == String.Empty)
128                                 ptr++;
129                         if (input.Length == ptr + 1) {
130                                 FileInfo[] fi;
131                                 fi = directory.GetFiles (input [ptr]);
132                                 return fi;
133                         } else {
134                                 DirectoryInfo[] di;
135                                 FileInfo[] fi;
136                                 List <FileInfo> fileInfos = new List <FileInfo> ();
137                                 if (input [ptr] == ".") {
138                                         di = new DirectoryInfo [1];
139                                         di [0] = directory;
140                                 } else if (input [ptr] == "..") {
141                                         di = new DirectoryInfo [1];
142                                         di [0] = directory.Parent;
143                                 } else
144                                         di = directory.GetDirectories (input [ptr]);
145                                 foreach (DirectoryInfo info in di) {
146                                         fi = ParseIncludeExclude (input, ptr + 1, info);
147                                         foreach (FileInfo file in fi)
148                                                 fileInfos.Add (file);
149                                 }
150                                 fi = new FileInfo [fileInfos.Count];
151                                 int i = 0;
152                                 foreach (FileInfo file in fileInfos)
153                                         fi [i++] = file;
154                                 return fi;
155                         }
156                 }
157                 
158                 public DirectoryInfo BaseDirectory {
159                         get { return baseDirectory; }
160                         set { baseDirectory = value; }
161                 }
162                 
163                 public string Includes {
164                         get { return includes; }
165                         set { includes = value; }
166                 }
167                 
168                 public string Excludes {
169                         get { return excludes; }
170                         set { excludes = value; }
171                 }
172                 
173                 public string[] MatchedFilenames {
174                         get { return matchedFilenames; }
175                 }
176                 
177         }
178 }
179
180 #endif