/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: Manifest.cs // // Note: Creates and binds endpoints using a manifest. // using System; using System.Text; using System.Collections; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.Singularity.Extending; using Microsoft.Singularity.Io; using Microsoft.Singularity.Memory; using Microsoft.Singularity.Xml; namespace Microsoft.Singularity.Applications { /// /// This is a placeholder class for an application's manifest. /// At present the application manifest is represented by a hashtable. /// The hashtable has several important properties: /// - name: the name of the application /// - path: path to the application executable /// public class Manifest { /// /// We treat the application manifest as a collection of /// key, value pairs. /// private Hashtable! data = new Hashtable(); private const string pipeContract = "Microsoft.Singularity.Io.UnicodePipeContract"; private string name; private string path; private readonly XmlNode! applicationNode; private readonly XmlNode! processNode; private readonly XmlNode actionNode; private readonly XmlNode categoriesNode; private readonly XmlNode stringParametersNode; private readonly XmlNode stringArrayParametersNode; private readonly XmlNode longParametersNode; private readonly XmlNode boolParametersNode; private static StringBuilder sb; /// /// Create a manifest object from the given xml representation /// [Microsoft.Contracts.NotDelayed] public Manifest(byte[] xml) { XmlReader! reader = new XmlReader(xml); XmlNode! doc = (!)reader.Parse(); this(doc); } [Microsoft.Contracts.NotDelayed] private Manifest(XmlNode! doc) { XmlNode app = (!)doc.GetChild("application"); name = app["name"]; XmlNode proc = null; foreach (XmlNode! process in app.Children) { if (process.Name != "process") { continue; } if (process.GetAttribute("main", "false") == "true") { path = process["path"]; proc = process; break; } } applicationNode = (!)app; XmlNode! processNode = this.processNode = (!)proc; base(); categoriesNode = processNode.GetChild("categories"); if (categoriesNode != null) { return; } else { DebugStub.WriteLine("::: no category"); } } public XmlNode GetCategoriesNode() { return categoriesNode; } public void SetProperty(object! name, object value) { data[name] = value; } public string Name { get { return name; } } public string Path { get { return path; } } public string GetHelpMessage(XmlNode categoryNode) { return categoryNode == null? null : categoryNode.GetAttribute("HelpMessage", null); } // given an action find the corresponding category node public XmlNode GetCategoryNode(string actionName) { if (categoriesNode == null) { //Console.WriteLine("GetCategoryNode: no categories!"); return null; } if (actionName == null) { // return the 1st one if there is one //Console.WriteLine("GetCategoryNode: Selecting default!"); XmlNode n = categoriesNode.GetChild("category"); if (n == null) { return null; } else return n; } else { foreach (XmlNode! c in categoriesNode.Children) { string a = c.GetAttribute("Action",null); //Console.WriteLine("action= {0}.",a); if ( a != null && a == actionName) { //Console.WriteLine("found a match for action {0}",actionName); return c; } } return null; } } public XmlNode GetBoolParameterNode(XmlNode! category) { return category.GetChild("BoolParameters"); } public XmlNode GetStringArrayParameterNode(XmlNode! category) { return category.GetChild("StringArrayParameters"); } public XmlNode GetStringParameterNode(XmlNode! category) { return category.GetChild("StringParameters"); } public XmlNode GetLongParameterNode(XmlNode! category) { return category.GetChild("LongParameters"); } public bool HasParameters() { return (categoriesNode != null); } #if false public void ShowParameters() { if (categoryNode == null) { Console.WriteLine("::: no category"); return; } if (stringParametersNode == null) { Console.WriteLine("::: no strings"); } if (longParametersNode == null) { Console.WriteLine("::: no integers"); } } #endif public int SetEndpoints(Process process, string action, bool show) { // walk the XmlTree looking endpoints // these will be used by the binder to setup and transfer to // the starting process much like what is done for drivers XmlNode categoryNode = GetCategoryNode(action); //Console.WriteLine(" Set endpoints"); if (categoryNode == null) { Console.WriteLine("No endpoints in console app!"); //DebugStub.Break(); return 0; } XmlNode endpoints = categoryNode.GetChild("endpoints"); if (endpoints == null) { //DebugStub.Break(); return 0; } int endpointCount = endpoints.GetAttribute("length", 0); if (endpointCount == 0) { DebugStub.Break(); return 0; } //fill in ep set foreach (XmlNode! endpoint in endpoints.Children) { string! contract = (!)endpoint.GetAttribute("contractName", ""); int index = endpoint.GetAttribute("id", -1); if (endpoint.Name == "endpoint") { // FIXFIX -- if it is a pipe ignore it for now if (show) { Console.WriteLine(" endpoint: {0}", contract); } else { if (contract != pipeContract) { // get a pre-bound generic endpoint to a service from the // resource tracker if (process == null) { throw new Exception("Process arg was null."); } if (!Binder.BindServiceUser(process, index, contract, endpoint)) { return -1; } } else { DebugStub.WriteLine("shell.manifest.SetEndpoints: skipping pipe at {0}", __arglist(index)); } } } } return endpointCount; } #if false public override string! ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat("", Name); // the main executable sb.AppendFormat("", Path); foreach(DataItem item in data.Values) { if (item.Directory == null) { sb.AppendFormat("", item.Name, item.Value); } else { sb.AppendFormat("", item.Directory, item.Name, item.Value); } } sb.Append(""); sb.Append(""); sb.Append(""); sb.Append(""); return sb.ToString(); } public byte[] Serialize() { return (new UTF8Encoding()).GetBytes(ToString()); } #endif } }