2 // License compiler for mono
\r
5 // Carlo Kok (ck@remobjects.com)
\r
7 // (C) 2009 RemObjects Software
\r
11 // Permission is hereby granted, free of charge, to any person obtaining
\r
12 // a copy of this software and associated documentation files (the
\r
13 // "Software"), to deal in the Software without restriction, including
\r
14 // without limitation the rights to use, copy, modify, merge, publish,
\r
15 // distribute, sublicense, and/or sell copies of the Software, and to
\r
16 // permit persons to whom the Software is furnished to do so, subject to
\r
17 // the following conditions:
\r
19 // The above copyright notice and this permission notice shall be
\r
20 // included in all copies or substantial portions of the Software.
\r
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
32 using System.Collections;
\r
33 using System.Collections.Generic;
\r
37 using System.ComponentModel.Design;
\r
39 using System.Reflection;
\r
40 using System.Globalization;
\r
41 using System.ComponentModel;
\r
42 using System.Runtime.Serialization.Formatters.Binary;
\r
46 public class LCLicenseContext : DesigntimeLicenseContext
\r
48 public string OutputFilename { get; set; }
\r
49 public string LicxFilename { get; set; }
\r
54 static List<String> privatePaths = new List<string>();
\r
56 static int Main(string[] args)
\r
58 bool verbose = false;
\r
59 string target = null;
\r
60 string complist = null;
\r
61 string targetdir = ".";
\r
62 List<string> references = new List<string>();
\r
64 bool nologo = false;
\r
66 OptionSet p = new OptionSet() {
\r
67 {"v|verbose", "Verbose output", v => verbose = v!= null },
\r
68 {"t|target=", "Target assembly name", v => target = v },
\r
69 {"c|complist=","licx file to compile", v => complist = v },
\r
70 {"i|load=", "Reference to load", v=> {if (v != null) references.Add(v);}},
\r
71 {"o|outdir=", "Output directory for the .licenses file", v=> targetdir = v },
\r
72 {"nologo", "Do not display logo", v=> nologo = null != v },
\r
73 {"h|?|help", "Show help", v=>help = v != null }
\r
78 extra = p.Parse(args);
\r
80 catch(OptionException e)
\r
82 Console.WriteLine("lc: " + e.Message);
\r
83 Console.WriteLine("try lc --help for more information");
\r
87 Console.WriteLine("Mono License Compiler");
\r
88 Console.WriteLine("Copyright (c) 2009 by RemObjects Software");
\r
91 Console.WriteLine();
\r
92 Console.WriteLine("lc -c filename -t targetassembly [-i references] [-v] [-o] [-nologo]");
\r
93 Console.WriteLine();
\r
94 Console.WriteLine("Options:");
\r
95 p.WriteOptionDescriptions(Console.Out);
\r
98 if (extra.Count > 0) {
\r
99 Console.WriteLine("Unexpected arguments passed on cmd line");
\r
102 if (target == null || complist == null){
\r
103 Console.WriteLine("No target/complist passed");
\r
107 if (!File.Exists(complist)) {
\r
108 Console.WriteLine("Could not find file: "+complist);
\r
112 LCLicenseContext ctx = new LCLicenseContext();
\r
113 ctx.LicxFilename = complist;
\r
114 if (verbose) Console.WriteLine("Input file: "+complist);
\r
115 ctx.OutputFilename = Path.Combine(targetdir ??".", target)+".licenses";
\r
116 if (verbose) Console.WriteLine("Output filename: "+ctx.OutputFilename);
\r
117 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
\r
118 privatePaths.Add(".");
\r
119 Dictionary<string, Assembly> loaded = new Dictionary<string, Assembly>();
\r
120 foreach (string reference in references) {
\r
121 string path = Path.GetDirectoryName(reference);
\r
122 if (!privatePaths.Contains(path))
\r
124 if (verbose) Console.WriteLine("Adding " + Path.GetDirectoryName(reference) + " to private paths");
\r
125 privatePaths.Add(path);
\r
127 Assembly asm = Assembly.LoadFrom(reference);
\r
128 loaded.Add(asm.GetName().Name, asm);
\r
129 if (verbose) Console.WriteLine("Loaded assembly: "+asm.GetName().ToString());
\r
133 using (StreamReader sr = new StreamReader(complist))
\r
137 while (sr.Peek() != -1)
\r
141 line = sr.ReadLine();
\r
142 if (line == null || line == "" || line[0] == '#' ) continue;
\r
143 if (verbose) Console.WriteLine("Generating license for: "+line);
\r
145 string[] sLine = line.Split(new char[] { ',' }, 2);
\r
147 if (sLine.Length == 1)
\r
149 stype = Type.GetType(line, false, true);
\r
152 foreach (KeyValuePair<string, Assembly> et in loaded)
\r
154 stype = et.Value.GetType(sLine[0], false, true);
\r
155 if (stype != null) {
\r
156 if (verbose) Console.WriteLine("Found type in "+et.Key);
\r
164 if (sLine[1].IndexOf(',') >= 0)
\r
166 stype = Type.GetType(line, false, true);
\r
170 string s = sLine[1].Trim();
\r
171 foreach (KeyValuePair<string, Assembly> et in loaded)
\r
173 if (String.Compare(et.Key, s, true, CultureInfo.InvariantCulture) == 0)
\r
175 stype = et.Value.GetType(sLine[0], false, true);
\r
176 if (stype != null) {
\r
177 if (verbose) Console.WriteLine("Found type in "+et.Key);
\r
184 foreach (KeyValuePair<string, Assembly> et in loaded)
\r
186 stype = et.Value.GetType(sLine[0], false, true);
\r
187 if (stype != null) {
\r
188 if (verbose) Console.WriteLine("Found type in "+et.Key);
\r
196 throw new Exception("Unable to find type: " + line);
\r
197 LicenseManager.CreateWithContext(stype, ctx);
\r
201 Console.WriteLine("Exception during compiling " + complist + ": " + lineno);
\r
202 Console.WriteLine(e.ToString());
\r
207 using (FileStream fs = new FileStream(ctx.OutputFilename, FileMode.Create)) {
\r
209 DesigntimeLicenseContextSerializer.Serialize(fs, target.ToUpper(CultureInfo.InvariantCulture), ctx);
\r
211 if (fs.Length == 0) // older mono does not support this, but when it does, we should use the proper version.
\r
212 IntSerialize(fs, target.ToUpper(CultureInfo.InvariantCulture), ctx);
\r
215 Console.WriteLine("Saved to: "+ Path.GetFullPath(ctx.OutputFilename));
\r
217 } catch(Exception e){
\r
218 Console.WriteLine("Exception: "+e.ToString());
\r
225 private static void IntSerialize(Stream o,
\r
227 DesigntimeLicenseContext context)
\r
229 Object[] lData = new Object[2];
\r
230 lData[0] = cryptoKey;
\r
231 Hashtable lNewTable = new Hashtable();
\r
233 typeof(DesigntimeLicenseContext).GetField("savedLicenseKeys", BindingFlags.NonPublic | BindingFlags.Instance) ??
\r
234 typeof(DesigntimeLicenseContext).GetField("keys", BindingFlags.NonPublic | BindingFlags.Instance)
\r
236 Hashtable lOrgTable = (Hashtable)fi.GetValue(context);
\r
237 foreach (DictionaryEntry et in lOrgTable)
\r
239 if (et.Key is string)
\r
240 lNewTable.Add(et.Key, et.Value);
\r
242 lNewTable.Add(((Type)et.Key).AssemblyQualifiedName, et.Value);
\r
244 lData[1] = lNewTable;
\r
246 BinaryFormatter lFormatter = new BinaryFormatter();
\r
247 lFormatter.Serialize(o, lData);
\r
250 static Dictionary<string, Assembly> loadedAssemblies = new Dictionary<string, Assembly>();
\r
252 static bool CompareAssemblyName(string s1, string s2)
\r
254 s1 = s1.ToLowerInvariant().Replace(" ", "");
\r
255 s2 = s2.ToLowerInvariant().Replace(" ", "");
\r
259 static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
\r
261 string[] lArgs = args.Name.Split(',');
\r
262 string lName = lArgs[0].Trim();
\r
263 if (loadedAssemblies.ContainsKey(args.Name))
\r
265 return loadedAssemblies[args.Name];
\r
267 for (int i = 0; i < privatePaths.Count; i++)
\r
269 string sPath = Path.Combine(privatePaths[i].ToString(), lName);
\r
270 if (File.Exists(sPath + ".dll"))
\r
272 else if (File.Exists(sPath + ".DLL"))
\r
274 else if (File.Exists(sPath + ".exe"))
\r
276 else if (File.Exists(sPath + ".EXE"))
\r
280 AssemblyName an2 = AssemblyName.GetAssemblyName(sPath);
\r
281 if (CompareAssemblyName(an2.ToString(), args.Name) || (lArgs.Length == 1 && CompareAssemblyName(an2.Name, lName)))
\r
286 asm = Assembly.LoadFrom(sPath);
\r
290 asm = Assembly.LoadFile(sPath);
\r
294 loadedAssemblies.Add(args.Name, asm);
\r
299 throw new Exception("Unable to find assembly "+args.Name);
\r