1 //
2 // ReservedNameUtils.cs
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2006 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 using System;
29 using System.Collections;
30 using System.Collections.Specialized;
31 using System.IO;
32 using System.Text;
33 
34 namespace Mono.XBuild.Utilities {
35 
36 	internal static class ReservedNameUtils {
37 
38 		static string[] reservedMetadataNames;
39 		static Hashtable reservedMetadataHash;
40 
ReservedNameUtils()41 		static ReservedNameUtils ()
42 		{
43 			reservedMetadataNames = new string [] {
44 				"FullPath", "RootDir", "Filename", "Extension", "RelativeDir", "Directory",
45 				"RecursiveDir", "Identity", "ModifiedTime", "CreatedTime", "AccessedTime"};
46 			reservedMetadataHash = CollectionsUtil.CreateCaseInsensitiveHashtable (ReservedMetadataNameCount);
47 			foreach (string s in reservedMetadataNames) {
48 				reservedMetadataHash.Add (s, null);
49 			}
50 		}
51 
52 		public static ICollection ReservedMetadataNames {
53 			get {
54 				return (ICollection) reservedMetadataNames.Clone ();
55 			}
56 		}
57 
58 		public static int ReservedMetadataNameCount {
59 			get {
60 				return reservedMetadataNames.Length;
61 			}
62 		}
63 
IsReservedMetadataName(string metadataName)64 		public static bool IsReservedMetadataName (string metadataName)
65 		{
66 			return reservedMetadataHash.Contains (metadataName);
67 		}
68 
GetReservedMetadata(string itemSpec, string metadataName, IDictionary metadata)69 		public static string GetReservedMetadata (string itemSpec,
70 						   string metadataName, IDictionary metadata)
71 		{
72 			if (metadataName == null)
73 				throw new ArgumentNullException ();
74 
75 			if (String.IsNullOrEmpty (itemSpec))
76 				return String.Empty;
77 
78 			switch (metadataName.ToLowerInvariant ()) {
79 			case "fullpath":
80 				var unescapedItemSpec = MSBuildUtils.Unescape (itemSpec);
81 				return MSBuildUtils.Escape (Path.GetFullPath (unescapedItemSpec));
82 			case "rootdir":
83 				if (Path.IsPathRooted (itemSpec))
84 					return Path.GetPathRoot (itemSpec);
85 				else
86 					return Path.GetPathRoot (Environment.CurrentDirectory);
87 			case "filename":
88 				return Path.GetFileNameWithoutExtension (itemSpec);
89 			case "extension":
90 				return Path.GetExtension (itemSpec);
91 			case "relativedir":
92 				return WithTrailingSlash (AbsoluteToRelativePath (Environment.CurrentDirectory, Path.GetDirectoryName (itemSpec)));
93 			case "directory":
94 				string fullpath = Path.GetFullPath (itemSpec);
95 				return WithTrailingSlash (
96 					 Path.GetDirectoryName (fullpath).Substring (Path.GetPathRoot (fullpath).Length));
97 			case "recursivedir":
98 				if (metadata != null && metadata.Contains ("RecursiveDir"))
99 					return (string)metadata ["RecursiveDir"];
100 				else
101 					return String.Empty;
102 			case "identity":
103 				return itemSpec;
104 			case "modifiedtime":
105 				if (File.Exists (itemSpec))
106 					return File.GetLastWriteTime (itemSpec).ToString ();
107 				else if (Directory.Exists (itemSpec))
108 					return Directory.GetLastWriteTime (itemSpec).ToString ();
109 				else
110 					return String.Empty;
111 			case "createdtime":
112 				if (File.Exists (itemSpec))
113 					return File.GetCreationTime (itemSpec).ToString ();
114 				else if (Directory.Exists (itemSpec))
115 					return Directory.GetCreationTime (itemSpec).ToString ();
116 				else
117 					return String.Empty;
118 			case "accessedtime":
119 				if (File.Exists (itemSpec))
120 					return File.GetLastAccessTime (itemSpec).ToString ();
121 				else if (Directory.Exists (itemSpec))
122 					return Directory.GetLastAccessTime (itemSpec).ToString ();
123 				else
124 					return String.Empty;
125 			default:
126 				throw new ArgumentException ("Invalid reserved metadata name");
127 			}
128 		}
129 
WithTrailingSlash(string path)130 		static string WithTrailingSlash (string path)
131 		{
132 			if (String.IsNullOrEmpty (path))
133 				return String.Empty;
134 
135 			if (path.Length > 0)
136 				return path + Path.DirectorySeparatorChar;
137 			else
138 				return path;
139 		}
140 
141 		readonly static char[] separators = { Path.DirectorySeparatorChar, Path.VolumeSeparatorChar, Path.AltDirectorySeparatorChar };
AbsoluteToRelativePath(string baseDirectoryPath, string absPath)142 		static string AbsoluteToRelativePath (string baseDirectoryPath, string absPath)
143 		{
144 			if (!Path.IsPathRooted (absPath))
145 				return absPath;
146 
147 			absPath           = Path.GetFullPath (absPath);
148 			baseDirectoryPath = Path.GetFullPath (baseDirectoryPath.TrimEnd (Path.DirectorySeparatorChar));
149 
150 			string[] bPath = baseDirectoryPath.Split (separators);
151 			string[] aPath = absPath.Split (separators);
152 			int indx = 0;
153 
154 			for (; indx < System.Math.Min (bPath.Length, aPath.Length); indx++) {
155 				if (!bPath[indx].Equals(aPath[indx]))
156 					break;
157 			}
158 
159 			if (indx == 0)
160 				return absPath;
161 
162 			StringBuilder result = new StringBuilder ();
163 
164 			for (int i = indx; i < bPath.Length; i++) {
165 				result.Append ("..");
166 				if (i + 1 < bPath.Length || aPath.Length - indx > 0)
167 					result.Append (Path.DirectorySeparatorChar);
168 			}
169 
170 
171 			result.Append (String.Join(Path.DirectorySeparatorChar.ToString(), aPath, indx, aPath.Length - indx));
172 			if (result.Length == 0)
173 				return ".";
174 			return result.ToString ();
175 		}
176 
RelativeToAbsolutePath(string baseDirectoryPath, string relPath)177 		static string RelativeToAbsolutePath (string baseDirectoryPath, string relPath)
178 		{
179 			return Path.GetFullPath (Path.Combine (baseDirectoryPath, relPath));
180 		}
181 	}
182 }
183