2 // License compiler for mono
5 // Carlo Kok (ck@remobjects.com)
7 // (C) 2009 RemObjects Software
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
32 using System
.Collections
;
33 using System
.Collections
.Generic
;
37 using System
.ComponentModel
.Design
;
39 using System
.Reflection
;
40 using System
.Globalization
;
41 using System
.ComponentModel
;
42 using System
.Runtime
.Serialization
.Formatters
.Binary
;
46 public class LCLicenseContext
: DesigntimeLicenseContext
48 public string OutputFilename { get; set; }
49 public string LicxFilename { get; set; }
54 static List
<String
> privatePaths
= new List
<string>();
56 static int Main(string[] args
)
60 string complist
= null;
61 string targetdir
= ".";
62 List
<string> references
= new List
<string>();
66 OptionSet p
= new OptionSet() {
67 {"v|verbose", "Verbose output", v => verbose = v!= null }
,
68 {"t|target=", "Target assembly name", v => target = v }
,
69 {"c|complist=","licx file to compile", v => complist = v }
,
70 {"i|load=", "Reference to load", v=> {if (v != null) references.Add(v);}}
,
71 {"o|outdir=", "Output directory for the .licenses file", v=> targetdir = v }
,
72 {"nologo", "Do not display logo", v=> nologo = null != v }
,
73 {"h|?|help", "Show help", v=>help = v != null }
78 extra
= p
.Parse(args
);
80 catch(OptionException e
)
82 Console
.WriteLine("lc: " + e
.Message
);
83 Console
.WriteLine("try lc --help for more information");
87 Console
.WriteLine("Mono License Compiler");
88 Console
.WriteLine("Copyright (c) 2009 by RemObjects Software");
92 Console
.WriteLine("lc -c filename -t targetassembly [-i references] [-v] [-o] [-nologo]");
94 Console
.WriteLine("Options:");
95 p
.WriteOptionDescriptions(Console
.Out
);
98 if (extra
.Count
> 0) {
99 Console
.WriteLine("Unexpected arguments passed on cmd line");
102 if (target
== null || complist
== null){
103 Console
.WriteLine("No target/complist passed");
107 if (!File
.Exists(complist
)) {
108 Console
.WriteLine("Could not find file: "+complist
);
112 LCLicenseContext ctx
= new LCLicenseContext();
113 ctx
.LicxFilename
= complist
;
114 if (verbose
) Console
.WriteLine("Input file: "+complist
);
115 ctx
.OutputFilename
= Path
.Combine(targetdir
??".", target
)+".licenses";
116 if (verbose
) Console
.WriteLine("Output filename: "+ctx
.OutputFilename
);
117 AppDomain
.CurrentDomain
.AssemblyResolve
+= new ResolveEventHandler(CurrentDomain_AssemblyResolve
);
118 privatePaths
.Add(".");
119 Dictionary
<string, Assembly
> loaded
= new Dictionary
<string, Assembly
>();
120 foreach (string reference
in references
) {
121 string path
= Path
.GetDirectoryName(reference
);
122 if (!privatePaths
.Contains(path
))
124 if (verbose
) Console
.WriteLine("Adding " + Path
.GetDirectoryName(reference
) + " to private paths");
125 privatePaths
.Add(path
);
127 Assembly asm
= Assembly
.LoadFrom(reference
);
128 loaded
.Add(asm
.GetName().Name
, asm
);
129 if (verbose
) Console
.WriteLine("Loaded assembly: "+asm
.GetName().ToString());
133 using (StreamReader sr
= new StreamReader(complist
))
137 while (sr
.Peek() != -1)
141 line
= sr
.ReadLine();
142 if (line
== null || line
== "" || line
[0] == '#' ) continue;
143 if (verbose
) Console
.WriteLine("Generating license for: "+line
);
145 string[] sLine
= line
.Split(new char[] { ',' }
, 2);
147 if (sLine
.Length
== 1)
149 stype
= Type
.GetType(line
, false, true);
152 foreach (KeyValuePair
<string, Assembly
> et
in loaded
)
154 stype
= et
.Value
.GetType(sLine
[0], false, true);
156 if (verbose
) Console
.WriteLine("Found type in "+et
.Key
);
164 if (sLine
[1].IndexOf(',') >= 0)
166 stype
= Type
.GetType(line
, false, true);
170 string s
= sLine
[1].Trim();
171 foreach (KeyValuePair
<string, Assembly
> et
in loaded
)
173 if (String
.Compare(et
.Key
, s
, true, CultureInfo
.InvariantCulture
) == 0)
175 stype
= et
.Value
.GetType(sLine
[0], false, true);
177 if (verbose
) Console
.WriteLine("Found type in "+et
.Key
);
184 foreach (KeyValuePair
<string, Assembly
> et
in loaded
)
186 stype
= et
.Value
.GetType(sLine
[0], false, true);
188 if (verbose
) Console
.WriteLine("Found type in "+et
.Key
);
196 throw new Exception("Unable to find type: " + line
);
197 LicenseManager
.CreateWithContext(stype
, ctx
);
201 Console
.WriteLine("Exception during compiling " + complist
+ ": " + lineno
);
202 Console
.WriteLine(e
.ToString());
207 using (FileStream fs
= new FileStream(ctx
.OutputFilename
, FileMode
.Create
)) {
209 DesigntimeLicenseContextSerializer
.Serialize(fs
, target
.ToUpper(CultureInfo
.InvariantCulture
), ctx
);
211 if (fs
.Length
== 0) // older mono does not support this, but when it does, we should use the proper version.
212 IntSerialize(fs
, target
.ToUpper(CultureInfo
.InvariantCulture
), ctx
);
215 Console
.WriteLine("Saved to: "+ Path
.GetFullPath(ctx
.OutputFilename
));
217 } catch(Exception e
){
218 Console
.WriteLine("Exception: "+e
.ToString());
225 private static void IntSerialize(Stream o
,
227 DesigntimeLicenseContext context
)
229 Object
[] lData
= new Object
[2];
230 lData
[0] = cryptoKey
;
231 Hashtable lNewTable
= new Hashtable();
233 typeof(DesigntimeLicenseContext
).GetField("savedLicenseKeys", BindingFlags
.NonPublic
| BindingFlags
.Instance
) ??
234 typeof(DesigntimeLicenseContext
).GetField("keys", BindingFlags
.NonPublic
| BindingFlags
.Instance
)
236 Hashtable lOrgTable
= (Hashtable
)fi
.GetValue(context
);
237 foreach (DictionaryEntry et
in lOrgTable
)
239 if (et
.Key
is string)
240 lNewTable
.Add(et
.Key
, et
.Value
);
242 lNewTable
.Add(((Type
)et
.Key
).AssemblyQualifiedName
, et
.Value
);
244 lData
[1] = lNewTable
;
246 BinaryFormatter lFormatter
= new BinaryFormatter();
247 lFormatter
.Serialize(o
, lData
);
250 static Dictionary
<string, Assembly
> loadedAssemblies
= new Dictionary
<string, Assembly
>();
252 static bool CompareAssemblyName(string s1
, string s2
)
254 s1
= s1
.ToLowerInvariant().Replace(" ", "");
255 s2
= s2
.ToLowerInvariant().Replace(" ", "");
259 static System
.Reflection
.Assembly
CurrentDomain_AssemblyResolve(object sender
, ResolveEventArgs args
)
261 string[] lArgs
= args
.Name
.Split(',');
262 string lName
= lArgs
[0].Trim();
263 if (loadedAssemblies
.ContainsKey(args
.Name
))
265 return loadedAssemblies
[args
.Name
];
267 for (int i
= 0; i
< privatePaths
.Count
; i
++)
269 string sPath
= Path
.Combine(privatePaths
[i
].ToString(), lName
);
270 if (File
.Exists(sPath
+ ".dll"))
272 else if (File
.Exists(sPath
+ ".DLL"))
274 else if (File
.Exists(sPath
+ ".exe"))
276 else if (File
.Exists(sPath
+ ".EXE"))
280 AssemblyName an2
= AssemblyName
.GetAssemblyName(sPath
);
281 if (CompareAssemblyName(an2
.ToString(), args
.Name
) || (lArgs
.Length
== 1 && CompareAssemblyName(an2
.Name
, lName
)))
286 asm
= Assembly
.LoadFrom(sPath
);
290 asm
= Assembly
.LoadFile(sPath
);
294 loadedAssemblies
.Add(args
.Name
, asm
);
299 throw new Exception("Unable to find assembly "+args
.Name
);