123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794 |
- #region BSD License
- /*
- Copyright (c) 2004-2008
- Matthew Holmes ([email protected]),
- Dan Moorehead ([email protected]),
- Rob Loach (http://www.robloach.net),
- C.J. Adams-Collier ([email protected])
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- */
- #endregion
- #region CVS Information
- /*
- * $Source$
- * $Author: cjcollier $
- * $Date: 2008-02-08 01:31:29 +0900 (Fri, 08 Feb 2008) $
- * $Revision: 256 $
- */
- #endregion
- using System;
- using System.Diagnostics;
- using System.Collections;
- using System.Collections.Specialized;
- using System.IO;
- using System.Reflection;
- using System.Xml;
- using System.Xml.Schema;
- using System.Text;
- using Prebuild.Core.Attributes;
- using Prebuild.Core.Interfaces;
- using Prebuild.Core.Nodes;
- using Prebuild.Core.Parse;
- using Prebuild.Core.Utilities;
- namespace Prebuild.Core
- {
- /// <summary>
- ///
- /// </summary>
- public class Kernel : IDisposable
- {
- #region Inner Classes
- private struct NodeEntry
- {
- public Type Type;
- public DataNodeAttribute Attribute;
- }
- #endregion
- #region Fields
- private static Kernel m_Instance = new Kernel();
- /// <summary>
- /// This must match the version of the schema that is embeeded
- /// </summary>
- private static string m_SchemaVersion = "1.7";
- private static string m_Schema = "prebuild-" + m_SchemaVersion + ".xsd";
- private static string m_SchemaURI = "http://dnpb.sourceforge.net/schemas/" + m_Schema;
- bool disposed;
- private Version m_Version;
- private string m_Revision = "";
- private CommandLineCollection m_CommandLine;
- private Log m_Log;
- private CurrentDirectory m_CurrentWorkingDirectory;
- private XmlSchemaCollection m_Schemas;
-
- private Hashtable m_Targets;
- private Hashtable m_Nodes;
-
- ArrayList m_Solutions;
- string m_Target;
- string m_Clean;
- string[] m_RemoveDirectories;
- string m_CurrentFile;
- XmlDocument m_CurrentDoc;
- bool m_PauseAfterFinish;
- string[] m_ProjectGroups;
- StringCollection m_Refs;
-
- #endregion
- #region Constructors
- private Kernel()
- {
- }
- #endregion
- #region Properties
- /// <summary>
- /// Gets a value indicating whether [pause after finish].
- /// </summary>
- /// <value><c>true</c> if [pause after finish]; otherwise, <c>false</c>.</value>
- public bool PauseAfterFinish
- {
- get
- {
- return m_PauseAfterFinish;
- }
- }
- /// <summary>
- /// Gets the instance.
- /// </summary>
- /// <value>The instance.</value>
- public static Kernel Instance
- {
- get
- {
- return m_Instance;
- }
- }
- /// <summary>
- /// Gets the version.
- /// </summary>
- /// <value>The version.</value>
- public string Version
- {
- get
- {
- return String.Format("{0}.{1}.{2}{3}", m_Version.Major, m_Version.Minor, m_Version.Build, m_Revision);
- }
- }
- /// <summary>
- /// Gets the command line.
- /// </summary>
- /// <value>The command line.</value>
- public CommandLineCollection CommandLine
- {
- get
- {
- return m_CommandLine;
- }
- }
- /// <summary>
- /// Gets the targets.
- /// </summary>
- /// <value>The targets.</value>
- public Hashtable Targets
- {
- get
- {
- return m_Targets;
- }
- }
- /// <summary>
- /// Gets the log.
- /// </summary>
- /// <value>The log.</value>
- public Log Log
- {
- get
- {
- return m_Log;
- }
- }
- /// <summary>
- /// Gets the current working directory.
- /// </summary>
- /// <value>The current working directory.</value>
- public CurrentDirectory CurrentWorkingDirectory
- {
- get
- {
- return m_CurrentWorkingDirectory;
- }
- }
- /// <summary>
- /// Gets the solutions.
- /// </summary>
- /// <value>The solutions.</value>
- public ArrayList Solutions
- {
- get
- {
- return m_Solutions;
- }
- }
-
- /// <summary>
- /// Gets the XmlDocument object representing the prebuild.xml
- /// being processed
- /// </summary>
- /// <value>The XmlDocument object</value>
- public XmlDocument CurrentDoc
- {
- get
- {
- return m_CurrentDoc;
- }
- }
- #endregion
- #region Private Methods
- private void RemoveDirectories(string rootDir, string[] dirNames)
- {
- foreach(string dir in Directory.GetDirectories(rootDir))
- {
- string simpleName = Path.GetFileName(dir);
- if(Array.IndexOf(dirNames, simpleName) != -1)
- {
- //delete if the name matches one of the directory names to delete
- string fullDirPath = Path.GetFullPath(dir);
- Directory.Delete(fullDirPath,true);
- }
- else//not a match, so check children
- {
- RemoveDirectories(dir,dirNames);
- //recurse, checking children for them
- }
- }
- }
- // private void RemoveDirectoryMatches(string rootDir, string dirPattern)
- // {
- // foreach(string dir in Directory.GetDirectories(rootDir))
- // {
- // foreach(string match in Directory.GetDirectories(dir))
- // {//delete all child directories that match
- // Directory.Delete(Path.GetFullPath(match),true);
- // }
- // //recure through the rest checking for nested matches to delete
- // RemoveDirectoryMatches(dir,dirPattern);
- // }
- // }
- private void LoadSchema()
- {
- Assembly assembly = this.GetType().Assembly;
- Stream stream = assembly.GetManifestResourceStream("Prebuild.data." + m_Schema);
- if(stream == null)
- {
- //try without the default namespace prepending to it in case was compiled with SharpDevelop or MonoDevelop instead of Visual Studio .NET
- stream = assembly.GetManifestResourceStream(m_Schema);
- if(stream == null)
- {
- throw new System.Reflection.TargetException(string.Format("Could not find the scheme embedded resource file '{0}'.", m_Schema));
- }
- }
- XmlReader schema = new XmlTextReader(stream);
-
- m_Schemas = new XmlSchemaCollection();
- m_Schemas.Add(m_SchemaURI, schema);
- }
- private void CacheVersion()
- {
- m_Version = Assembly.GetEntryAssembly().GetName().Version;
- }
- private void CacheTargets(Assembly assm)
- {
- foreach(Type t in assm.GetTypes())
- {
- TargetAttribute ta = (TargetAttribute)Helper.CheckType(t, typeof(TargetAttribute), typeof(ITarget));
- if(ta == null)
- {
- continue;
- }
- ITarget target = (ITarget)assm.CreateInstance(t.FullName);
- if(target == null)
- {
- throw new MissingMethodException("Could not create ITarget instance");
- }
- m_Targets[ta.Name] = target;
- }
- }
- private void CacheNodeTypes(Assembly assm)
- {
- foreach(Type t in assm.GetTypes())
- {
- DataNodeAttribute dna = (DataNodeAttribute)Helper.CheckType(t, typeof(DataNodeAttribute), typeof(IDataNode));
- if(dna == null)
- {
- continue;
- }
- NodeEntry ne = new NodeEntry();
- ne.Type = t;
- ne.Attribute = dna;
- m_Nodes[dna.Name] = ne;
- }
- }
- private void LogBanner()
- {
- m_Log.Write("Prebuild v" + this.Version);
- m_Log.Write("Copyright (c) 2004-2008");
- m_Log.Write("Matthew Holmes ([email protected]),");
- m_Log.Write("Dan Moorehead ([email protected]),");
- m_Log.Write("David Hudson ([email protected]),");
- m_Log.Write("Rob Loach (http://www.robloach.net),");
- m_Log.Write("C.J. Adams-Collier ([email protected]),");
- m_Log.Write("See 'prebuild /usage' for help");
- m_Log.Write();
- }
- private void ProcessFile(string file)
- {
- m_CurrentWorkingDirectory.Push();
-
- string path = file;
- try
- {
- try
- {
- path = Helper.ResolvePath(path);
- }
- catch(ArgumentException)
- {
- m_Log.Write("Could not open Prebuild file: " + path);
- m_CurrentWorkingDirectory.Pop();
- return;
- }
- m_CurrentFile = path;
- Helper.SetCurrentDir(Path.GetDirectoryName(path));
-
- XmlTextReader reader = new XmlTextReader(path);
- Core.Parse.Preprocessor pre = new Core.Parse.Preprocessor();
- //register command line arguments as XML variables
- IDictionaryEnumerator dict = m_CommandLine.GetEnumerator();
- while (dict.MoveNext())
- {
- string name = dict.Key.ToString().Trim();
- if (name.Length > 0)
- pre.RegisterVariable(name, dict.Value.ToString());
- }
- string xml = pre.Process(reader);//remove script and evaulate pre-proccessing to get schema-conforming XML
-
- m_CurrentDoc = new XmlDocument();
- try
- {
- XmlValidatingReader validator = new XmlValidatingReader(new XmlTextReader(new StringReader(xml)));
- //validate while reading from string into XmlDocument DOM structure in memory
- foreach(XmlSchema schema in m_Schemas)
- {
- validator.Schemas.Add(schema);
- }
- m_CurrentDoc.Load(validator);
- }
- catch(XmlException e)
- {
- throw new XmlException(e.ToString());
- }
- //is there a purpose to writing it? An syntax/schema problem would have been found during pre.Process() and reported with details
- if(m_CommandLine.WasPassed("ppo"))
- {
- string ppoFile = m_CommandLine["ppo"];
- if(ppoFile == null || ppoFile.Trim().Length < 1)
- {
- ppoFile = "preprocessed.xml";
- }
- StreamWriter writer = null;
- try
- {
- writer = new StreamWriter(ppoFile);
- writer.Write(xml);
- }
- catch(IOException ex)
- {
- Console.WriteLine("Could not write PPO file '{0}': {1}", ppoFile, ex.Message);
- }
- finally
- {
- if(writer != null)
- {
- writer.Close();
- }
- }
- return;
- }
- //start reading the xml config file
- XmlElement rootNode = m_CurrentDoc.DocumentElement;
- //string suggestedVersion = Helper.AttributeValue(rootNode,"version","1.0");
- Helper.CheckForOSVariables = Helper.ParseBoolean(rootNode,"checkOsVars",false);
- foreach(XmlNode node in rootNode.ChildNodes)//solutions or if pre-proc instructions
- {
- IDataNode dataNode = ParseNode(node, null);
- if(dataNode is ProcessNode)
- {
- ProcessNode proc = (ProcessNode)dataNode;
- if(proc.IsValid)
- {
- ProcessFile(proc.Path);
- }
- }
- else if(dataNode is SolutionNode)
- {
- m_Solutions.Add(dataNode);
- }
- }
- }
- catch(XmlSchemaException xse)
- {
- m_Log.Write("XML validation error at line {0} in {1}:\n\n{2}",
- xse.LineNumber, path, xse.Message);
- }
- finally
- {
- m_CurrentWorkingDirectory.Pop();
- }
- }
- #endregion
- #region Public Methods
- /// <summary>
- /// Allows the project.
- /// </summary>
- /// <param name="projectGroupsFlags">The project groups flags.</param>
- /// <returns></returns>
- public bool AllowProject(string projectGroupsFlags)
- {
- if(m_ProjectGroups != null && m_ProjectGroups.Length > 0)
- {
- if(projectGroupsFlags != null && projectGroupsFlags.Length == 0)
- {
- foreach(string group in projectGroupsFlags.Split('|'))
- {
- if(Array.IndexOf(m_ProjectGroups, group) != -1) //if included in the filter list
- {
- return true;
- }
- }
- }
- return false;//not included in the list or no groups specified for the project
- }
- return true;//no filter specified in the command line args
- }
- /// <summary>
- /// Gets the type of the node.
- /// </summary>
- /// <param name="node">The node.</param>
- /// <returns></returns>
- public Type GetNodeType(XmlNode node)
- {
- if( node == null )
- {
- throw new ArgumentNullException("node");
- }
- if(!m_Nodes.ContainsKey(node.Name))
- {
- return null;
- }
- NodeEntry ne = (NodeEntry)m_Nodes[node.Name];
- return ne.Type;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="node"></param>
- /// <param name="parent"></param>
- /// <returns></returns>
- public IDataNode ParseNode(XmlNode node, IDataNode parent)
- {
- return ParseNode(node, parent, null);
- }
- //Create an instance of the data node type that is mapped to the name of the xml DOM node
- /// <summary>
- /// Parses the node.
- /// </summary>
- /// <param name="node">The node.</param>
- /// <param name="parent">The parent.</param>
- /// <param name="preNode">The pre node.</param>
- /// <returns></returns>
- public IDataNode ParseNode(XmlNode node, IDataNode parent, IDataNode preNode)
- {
- IDataNode dataNode = null;
- try
- {
- if( node == null )
- {
- throw new ArgumentNullException("node");
- }
- if(preNode == null)
- {
- if(!m_Nodes.ContainsKey(node.Name))
- {
- //throw new XmlException("Unknown XML node: " + node.Name);
- return null;
- }
- NodeEntry ne = (NodeEntry)m_Nodes[node.Name];
- Type type = ne.Type;
- //DataNodeAttribute dna = ne.Attribute;
- dataNode = (IDataNode)type.Assembly.CreateInstance(type.FullName);
- if(dataNode == null)
- {
- throw new System.Reflection.TargetException("Could not create new parser instance: " + type.FullName);
- }
- }
- else
- dataNode = preNode;
- dataNode.Parent = parent;
- dataNode.Parse(node);
- }
- catch(WarningException wex)
- {
- m_Log.Write(LogType.Warning, wex.Message);
- return null;
- }
- catch(FatalException fex)
- {
- m_Log.WriteException(LogType.Error, fex);
- throw;
- }
- catch(Exception ex)
- {
- m_Log.WriteException(LogType.Error, ex);
- throw;
- }
- return dataNode;
- }
- /// <summary>
- /// Initializes the specified target.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="args">The args.</param>
- public void Initialize(LogTargets target, string[] args)
- {
- m_Targets = new Hashtable();
- CacheTargets(this.GetType().Assembly);
- m_Nodes = new Hashtable();
- CacheNodeTypes(this.GetType().Assembly);
- CacheVersion();
- m_CommandLine = new CommandLineCollection(args);
-
- string logFile = null;
- if(m_CommandLine.WasPassed("log"))
- {
- logFile = m_CommandLine["log"];
- if(logFile != null && logFile.Length == 0)
- {
- logFile = "Prebuild.log";
- }
- }
- else
- {
- target = target & ~LogTargets.File; //dont output to a file
- }
-
- m_Log = new Log(target, logFile);
- LogBanner();
- m_CurrentWorkingDirectory = new CurrentDirectory();
- m_Target = m_CommandLine["target"];
- m_Clean = m_CommandLine["clean"];
- string removeDirs = m_CommandLine["removedir"];
- if(removeDirs != null && removeDirs.Length == 0)
- {
- m_RemoveDirectories = removeDirs.Split('|');
- }
- string flags = m_CommandLine["allowedgroups"];//allows filtering by specifying a pipe-delimited list of groups to include
- if(flags != null && flags.Length == 0)
- {
- m_ProjectGroups = flags.Split('|');
- }
- m_PauseAfterFinish = m_CommandLine.WasPassed("pause");
- LoadSchema();
- m_Solutions = new ArrayList();
- m_Refs = new StringCollection();
- }
- /// <summary>
- /// Processes this instance.
- /// </summary>
- public void Process()
- {
- bool perfomedOtherTask = false;
- if(m_RemoveDirectories != null && m_RemoveDirectories.Length > 0)
- {
- try
- {
- RemoveDirectories(".",m_RemoveDirectories);
- }
- catch(IOException e)
- {
- m_Log.Write("Failed to remove directories named {0}",m_RemoveDirectories);
- m_Log.WriteException(LogType.Error,e);
- }
- catch(UnauthorizedAccessException e)
- {
- m_Log.Write("Failed to remove directories named {0}",m_RemoveDirectories);
- m_Log.WriteException(LogType.Error,e);
- }
- perfomedOtherTask = true;
- }
- if(m_Target != null && m_Clean != null)
- {
- m_Log.Write(LogType.Error, "The options /target and /clean cannot be passed together");
- return;
- }
- else if(m_Target == null && m_Clean == null)
- {
- if(perfomedOtherTask) //finished
- {
- return;
- }
- m_Log.Write(LogType.Error, "Must pass either /target or /clean to process a Prebuild file");
- return;
- }
- string file = "./prebuild.xml";
- if(m_CommandLine.WasPassed("file"))
- {
- file = m_CommandLine["file"];
- }
- ProcessFile(file);
- string target = (m_Target != null ? m_Target.ToLower() : m_Clean.ToLower());
- bool clean = (m_Target == null);
- if(clean && target != null && target.Length == 0)
- {
- target = "all";
- }
- if(clean && target == "all")//default to all if no target was specified for clean
- {
- //check if they passed yes
- if (!m_CommandLine.WasPassed("yes"))
- {
- Console.WriteLine("WARNING: This operation will clean ALL project files for all targets, are you sure? (y/n):");
- string ret = Console.ReadLine();
- if(ret == null)
- {
- return;
- }
- ret = ret.Trim().ToLower();
- if((ret.ToLower() != "y" && ret.ToLower() != "yes"))
- {
- return;
- }
- }
- //clean all targets (just cleaning vs2002 target didn't clean nant)
- foreach(ITarget targ in m_Targets.Values)
- {
- targ.Clean(this);
- }
- }
- else
- {
- if (!m_Targets.Contains(target)) {
- m_Log.Write(LogType.Error, "Unknown Target \"{0}\"", target);
- return;
- }
- ITarget targ = (ITarget)m_Targets[target];
- if(clean)
- {
- targ.Clean(this);
- }
- else
- {
- targ.Write(this);
- }
- }
- m_Log.Flush();
- }
- #endregion
- #region IDisposable Members
- /// <summary>
- ///
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- /// <summary>
- /// Dispose objects
- /// </summary>
- /// <param name="disposing">
- /// If true, it will dispose close the handle
- /// </param>
- /// <remarks>
- /// Will dispose managed and unmanaged resources.
- /// </remarks>
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposed)
- {
- if (disposing)
- {
- if (this.m_Log != null)
- {
- this.m_Log.Close();
- this.m_Log = null;
- }
- }
- }
- this.disposed = true;
- }
- /// <summary>
- ///
- /// </summary>
- ~Kernel()
- {
- this.Dispose(false);
- }
-
- /// <summary>
- /// Closes and destroys this object
- /// </summary>
- /// <remarks>
- /// Same as Dispose(true)
- /// </remarks>
- public void Close()
- {
- Dispose();
- }
- #endregion
- }
- }
|