Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

112
mcs/tools/mconfig/ChangeLog Normal file
View File

@@ -0,0 +1,112 @@
2009-01-26 Marek Habersack <mhabersack@novell.com>
* data/config.xml: added a definition for .NET 3.5 AJAX entries
(feature AJAX) and moved the 1.0 entries to feature AJAX1.
2008-10-23 Atsushi Enomoto <atsushi@ximian.com>
* data/config.xml : add sections for DynamicData feature.
2007-12-08 Marek Habersack <mhabersack@novell.com>
* data/config.xml: added a feature to protect the 'settings.map'
file from download, if used by the application.
2007-11-21 Marek Habersack <mhabersack@novell.com>
* mconfig.cs: drop the -F and -C parameters, default config files,
features and commands are now listed when mconfig is ran without
any parameters or when no commands are given.
* Mono.MonoConfig/FeatureNodeHandler.cs: do not append leading and
trailing newlines to feature description.
2007-11-13 Marek Habersack <mhabersack@novell.com>
* data/config.xml: replaced the possibly conflicting default block
names with ones that are less likely to cause conflicts and
modified feature and default config entries to use the new names,
via the defaultBlockName attribute of the section element.
* Mono.MonoConfig/Section.cs: added DefaultBlockName property,
which defaults to Name if not parsed from the XML node.
* Mono.MonoConfig/FeatureNodeHandler.cs: Use the defaultBlockName
attribute when searching for the default sections.
* mconfig.cs: better error handling. Print inner exception
message, if any, in addition to the outer one.
* Mono.MonoConfig/Configuration.cs: do not ignore XmlException
when loading configuration files.
* Mono.MonoConfig/DefaultConfigFileNodeHandler.cs: use
DefaultConfigFile.FileName when writing a file or invoking the
OnOverwriteFile event handler.
Use the defaultBlockName attribute when searching for the default
sections.
2007-11-12 Marek Habersack <mhabersack@novell.com>
* Makefile (LOCAL_MCS_FLAGS): Mono.GetOptions.dll is not needed.
* Mono.MonoConfig/FeatureAction.cs: extracted command execution
code to a separate method.
Script code must be flushed before passing it to the shell.
Implemented Exec action support.
2007-11-10 Marek Habersack <mhabersack@novell.com>
* Mono.MonoConfig/Helpers.cs: added a method for breaking long
text lines to fit them within the console window.
* Mono.MonoConfig/FeatureNode.cs: added support for feature
actions.
* Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature
actions.
* Mono.MonoConfig/FeatureAction.cs: added
* mconfig.exe.sources: added Mono.MonoConfig/FeatureAction.cs
2007-11-09 Marek Habersack <mhabersack@novell.com>
* Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature
descriptions.
* Mono.MonoConfig/FeatureNode.cs: a new container for the
'feature' block data.
* data/config.xml: feature storage type has changed.
* mconfig.exe.sources: added Mono.MonoConfig/FeatureNode.cs
2007-11-08 Marek Habersack <mhabersack@novell.com>
* Mono.MonoConfig/consts.cs.in: use @MONO_SYSCONFDIR@ instead of
@MONO_PREFIX@ when pre-setting the location of the default config
file.
2007-11-08 Wade Berrier <wberrier@novell.com>
* Makefile: install the config.xml to $sysconfdir instead
2007-10-22 Marek Habersack <mhabersack@novell.com>
* mconfig.cs: do not use Mono.GetOptions. Added own option parsing
code instead.
2007-10-19 Marek Habersack <mhabersack@novell.com>
* Makefile: include consts.cs.in in the dist tarball.
Extra distribution files should be named in EXTRA_DISTFILES.
2007-10-19 Marek Habersack <mhabersack@novell.com>
* Makefile (DISTFILES): added
2007-10-19 Marek Habersack <mhabersack@novell.com>
* Initial import

View File

@@ -0,0 +1,21 @@
thisdir = tools/mconfig
SUBDIRS =
include ../../build/rules.make
LOCAL_MCS_FLAGS = -r:System.Xml.dll
PROGRAM = mconfig.exe
BUILT_SOURCES=Mono.MonoConfig/consts.cs
Mono.MonoConfig/consts.cs: Mono.MonoConfig/consts.cs.in
sed -e "s;@MONO_SYSCONFDIR@;$(sysconfdir);g" < $< > $@
install-local: install-local-data
install-local-data:
$(MKINSTALLDIRS) $(DESTDIR)$(sysconfdir)/mono/mconfig/
$(INSTALL_DATA) data/config.xml $(DESTDIR)$(sysconfdir)/mono/mconfig
EXTRA_DISTFILES = TODO data/config.xml Mono.MonoConfig/consts.cs.in
include ../../build/executable.make

View File

@@ -0,0 +1,49 @@
//
// AssemblyInfo.cs
//
// Author:
// Marek Habersack <mhabersack@novell.com>
//
// (C) 2007 Marek Habersack
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle ("Mono.MonoConfig")]
[assembly: AssemblyDescription ("Utility for modifying .NET configuration files")]
[assembly: AssemblyConfiguration ("Development version")]
[assembly: AssemblyProduct ("mconfig")]
[assembly: AssemblyCompany ("MONO development team")]
[assembly: AssemblyCopyright ("Copyright (c) 2007 Novell, Inc")]
[assembly: AssemblyCulture ("")]
[assembly: CLSCompliant (false)]
[assembly: ComVisible (false)]
[assembly: AssemblyVersion ("0.1.0.0")]
#if KEYFILE
[assembly: AssemblyKeyFile("../../mono.snk")]
#endif

View File

@@ -0,0 +1,59 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public class ConfigBlockBlock
{
string name;
Section requires;
string contents;
public string Name {
get { return name; }
}
public Section Requires {
get { return requires; }
}
public string Contents {
get { return contents; }
}
public ConfigBlockBlock (string name, Section requires, string contents)
{
this.name = name;
this.requires = requires;
this.contents = contents;
}
}
}

View File

@@ -0,0 +1,97 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public class ConfigBlockNodeHandler : IDocumentNodeHandler, IStorageConsumer, IConfigBlockContainer
{
string name;
Section requirements;
string contents;
Dictionary <string, ConfigBlockBlock> storage;
public void ReadConfiguration (XPathNavigator nav)
{
name = Helpers.GetRequiredNonEmptyAttribute (nav, "name");
requirements = new Section ();
Helpers.BuildSectionTree (nav.Select ("requires/section[string-length(@name) > 0]"), requirements);
XPathNodeIterator iter = nav.Select ("contents/text()");
StringBuilder sb = new StringBuilder ();
while (iter.MoveNext ())
sb.Append (iter.Current.Value);
if (sb.Length > 0)
contents = sb.ToString ();
}
public void StoreConfiguration ()
{
AssertStorage ();
ConfigBlockBlock block = new ConfigBlockBlock (name, requirements, contents);
if (storage.ContainsKey (name))
storage [name] = block; // allow for silent override
else
storage.Add (name, block);
// Prepare to handle more sections
requirements = new Section ();
contents = null;
}
public void SetStorage (object storage)
{
this.storage = storage as Dictionary <string, ConfigBlockBlock>;
if (this.storage == null)
throw new ApplicationException ("Invalid storage type.");
}
public ConfigBlockBlock FindConfigBlock (string name)
{
AssertStorage ();
if (storage.ContainsKey (name))
return storage [name];
return null;
}
void AssertStorage ()
{
if (storage == null)
throw new ApplicationException ("No storage attached");
}
}
}

View File

@@ -0,0 +1,337 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
class HandlerDescription
{
Type handlerType;
Type handlerStorageType;
string section;
object handler;
object storage;
public object Handler {
get {
if (handler != null)
return handler;
handler = Activator.CreateInstance (handlerType);
return handler;
}
}
public object Storage {
get {
if (storage != null)
return storage;
storage = Activator.CreateInstance (handlerStorageType);
return storage;
}
}
public string Section {
get { return section; }
}
public bool Implements (string interfaceName)
{
return handlerType.GetInterface (interfaceName) != null;
}
public HandlerDescription (string handlerTypeName, string handlerStorageTypeName, string section)
{
handlerType = Type.GetType (handlerTypeName, true);
if (handlerType.GetInterface ("Mono.MonoConfig.IDocumentNodeHandler") == null)
throw new ApplicationException (
String.Format ("Handler for section '{0}' must implement the '{1}' interface",
section, typeof (Mono.MonoConfig.IDocumentNodeHandler)));
handlerStorageType = Type.GetType (handlerStorageTypeName, true);
this.section = section;
}
}
public class Configuration
{
string[] configs;
Dictionary <string, HandlerDescription> section_handlers;
List <HandlerDescription> section_handlers_ordered;
List <XPathDocument> config_documents;
bool loaded;
public Configuration () : this (null)
{}
public Configuration (string[] configs)
{
this.configs = configs;
section_handlers = new Dictionary <string, HandlerDescription> ();
section_handlers_ordered = new List <HandlerDescription> ();
config_documents = new List <XPathDocument> (configs != null ? configs.Length : 1);
}
public void WriteDefaultConfigFile (string name, string path, FeatureTarget target)
{
AssertLoaded ();
if (String.IsNullOrEmpty (name))
throw new ArgumentException ("name", "Must not be null or empty");
IDefaultConfigFileContainer[] containers = GetHandlersForInterface <IDefaultConfigFileContainer> ();
if (containers == null || containers.Length == 0)
throw new ApplicationException ("Cannot find any handler for writing default config files");
IDefaultContainer[] defaults = GetHandlersForInterface <IDefaultContainer> ();
bool written = false;
foreach (IDefaultConfigFileContainer container in containers) {
if (container.HasDefaultConfigFile (name, target)) {
container.WriteDefaultConfigFile (name, target, path, defaults);
written = true;
break;
}
}
if (!written)
throw new ApplicationException (
String.Format ("Definition of default config file '{0}' for target '{1}' not found.",
name, target));
}
public string[] DefaultConfigFiles {
get {
AssertLoaded ();
IDefaultConfigFileContainer[] containers = GetHandlersForInterface <IDefaultConfigFileContainer> ();
if (containers == null || containers.Length == 0)
return null;
List <string> defaults = new List <string> ();
foreach (IDefaultConfigFileContainer container in containers)
defaults.AddRange (container.DefaultConfigFiles);
defaults.Sort ();
return defaults.ToArray ();
}
}
public void AddFeature (string configFilePath, FeatureTarget target, string featureName)
{
AssertLoaded ();
if (String.IsNullOrEmpty (configFilePath))
throw new ArgumentException ("configFilePath", "Must not be null or empty");
if (String.IsNullOrEmpty (featureName))
throw new ArgumentException ("featureName", "Must not be null or empty");
IFeatureGenerator[] generators = GetHandlersForInterface <IFeatureGenerator> ();
if (generators == null || generators.Length == 0)
throw new ApplicationException ("Cannot find any feature generator");
IDefaultContainer[] defaults = GetHandlersForInterface <IDefaultContainer> ();
IConfigBlockContainer[] configBlocks = GetHandlersForInterface <IConfigBlockContainer> ();
bool added = false;
foreach (IFeatureGenerator generator in generators) {
if (generator.HasFeature (featureName)) {
generator.AddFeature (configFilePath, featureName, target, defaults, configBlocks);
added = true;
break;
}
}
if (!added)
throw new ApplicationException (
String.Format ("Definition of feature '{0}' for target '{1}' not found.",
featureName, target));
}
public string[] Features {
get {
AssertLoaded ();
IFeatureGenerator[] generators = GetHandlersForInterface <IFeatureGenerator> ();
if (generators == null || generators.Length == 0)
return null;
List <string> features = new List <string> ();
foreach (IFeatureGenerator generator in generators)
features.AddRange (generator.Features);
features.Sort ();
return features.ToArray ();
}
}
public void Load (string[] configs)
{
this.configs = configs;
Load ();
}
public void Load ()
{
if (configs == null || configs.Length == 0)
return;
if (loaded) {
section_handlers.Clear ();
section_handlers_ordered.Clear ();
config_documents.Clear ();
loaded = false;
}
XPathDocument doc;
foreach (string config in configs) {
if (String.IsNullOrEmpty (config))
continue;
try {
doc = new XPathDocument (config);
config_documents.Add (doc);
} catch (XmlException ex) {
throw new ApplicationException (
String.Format ("Failed to parse config file '{0}'.", config),
ex);
} catch (Exception) {
continue;
}
}
XPathNavigator nav;
XPathNodeIterator iter;
// First configure section handlers
List <HandlerDescription> handlers_from_file = new List <HandlerDescription> ();
foreach (XPathDocument xpdoc in config_documents) {
handlers_from_file.Clear ();
nav = xpdoc.CreateNavigator ();
iter = nav.Select ("//mconfig/configuration/handlers/handler[string-length (@section) > 0]");
while (iter.MoveNext ())
AddSectionHandler (iter.Current, handlers_from_file);
section_handlers_ordered.InsertRange (0, handlers_from_file);
}
// Process all configs looking for all sections with known handlers
foreach (XPathDocument xpdoc in config_documents) {
nav = xpdoc.CreateNavigator ();
iter = nav.Select ("//mconfig/*");
while (iter.MoveNext ())
HandleTopLevelNode (iter.Current);
}
loaded = true;
}
public T[] GetHandlersForInterface <T> ()
{
AssertLoaded ();
string typeName = typeof (T).ToString ();
object handler;
List <T> handlers = null;
foreach (HandlerDescription hd in section_handlers_ordered) {
if (hd.Implements (typeName)) {
if (handlers == null)
handlers = new List <T> (1);
handler = hd.Handler;
if (handler is IStorageConsumer)
((IStorageConsumer) handler).SetStorage (hd.Storage);
handlers.Add ((T)handler);
}
}
if (handlers == null)
return null;
return handlers.ToArray ();
}
void HandleTopLevelNode (XPathNavigator nav)
{
string section = nav.LocalName;
if (!section_handlers.ContainsKey (section))
return;
HandlerDescription hd = section_handlers [section];
if (hd == null)
return;
IDocumentNodeHandler handler = hd.Handler as IDocumentNodeHandler;
object storage = hd.Storage;
if (handler == null || storage == null)
return;
if (handler is IStorageConsumer)
((IStorageConsumer) handler).SetStorage (storage);
handler.ReadConfiguration (nav);
handler.StoreConfiguration ();
}
void AddSectionHandler (XPathNavigator nav, List <HandlerDescription> handlers)
{
string section = Helpers.GetRequiredNonEmptyAttribute (nav, "section");
HandlerDescription hd = new HandlerDescription (Helpers.GetRequiredNonEmptyAttribute (nav, "type"),
Helpers.GetRequiredNonEmptyAttribute (nav, "storageType"),
section);
if (section_handlers.ContainsKey (section)) {
HandlerDescription old = section_handlers [section];
section_handlers [section] = hd;
handlers.Remove (old);
handlers.Add (hd);
} else {
section_handlers.Add (section, hd);
handlers.Add (hd);
}
}
void AssertLoaded ()
{
if (!loaded)
throw new ApplicationException ("Configuration not loaded yet");
}
}
}

View File

@@ -0,0 +1,284 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
class DefaultConfigFile
{
string name;
string fileName;
FeatureTarget target;
Section sections;
public string Name {
get { return name; }
}
public string FileName {
get {
if (!String.IsNullOrEmpty (fileName))
return fileName;
return Name;
}
}
public FeatureTarget Target {
get { return target; }
}
public Section Sections {
get { return sections; }
}
public DefaultConfigFile (string name, string fileName, FeatureTarget target, Section sections)
{
this.name = name;
this.fileName = fileName;
this.target = target;
this.sections = sections;
}
}
public delegate void OverwriteFileEventHandler (object sender, OverwriteFileEventArgs e);
public sealed class OverwriteFileEventArgs : System.EventArgs
{
string name;
string path;
FeatureTarget target;
bool overwrite;
public string Name {
get { return name; }
}
public string Path {
get { return path; }
}
public FeatureTarget Target {
get { return target; }
}
public bool Overwrite {
get { return overwrite; }
set { overwrite = value; }
}
public OverwriteFileEventArgs (string name, string path, FeatureTarget target, bool overwrite)
{
this.name = name;
this.path = path;
this.target = target;
this.overwrite = overwrite;
}
}
public class DefaultConfigFileNodeHandler : IDocumentNodeHandler, IDefaultConfigFileContainer, IStorageConsumer
{
string name;
string fileName;
FeatureTarget target;
Section sections;
Dictionary <string, DefaultConfigFile> storage;
public event OverwriteFileEventHandler OverwriteFile;
public void ReadConfiguration (XPathNavigator nav)
{
name = Helpers.GetRequiredNonEmptyAttribute (nav, "name");
target = Helpers.ConvertEnum <FeatureTarget> (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target");
fileName = Helpers.GetOptionalAttribute (nav, "fileName");
if (String.IsNullOrEmpty (fileName))
fileName = name;
sections = new Section ();
Helpers.BuildSectionTree (nav.Select ("./section[string-length (@name) > 0]"), sections);
}
public void StoreConfiguration ()
{
AssertStorage ();
DefaultConfigFile dcf = new DefaultConfigFile (name, fileName, target, sections);
if (storage.ContainsKey (name))
storage [name] = dcf;
else
storage.Add (name, dcf);
name = null;
fileName = null;
sections = null;
}
public void SetStorage (object storage)
{
this.storage = storage as Dictionary <string, DefaultConfigFile>;
if (this.storage == null)
throw new ApplicationException ("Invalid storage type");
}
public ICollection <string> DefaultConfigFiles {
get {
AssertStorage ();
if (storage.Count == 0)
return null;
List <string> ret = new List <string>(storage.Count);
DefaultConfigFile dcf;
foreach (KeyValuePair <string, DefaultConfigFile> kvp in storage) {
dcf = kvp.Value;
ret.Add (String.Format ("{0} (Target: {1}; Output file: {2})",
kvp.Key, dcf.Target, dcf.FileName));
}
return ret;
}
}
public bool HasDefaultConfigFile (string name, FeatureTarget target)
{
AssertStorage ();
if (storage.ContainsKey (name)) {
DefaultConfigFile dcf = storage [name];
if (dcf == null)
return false;
if (target != FeatureTarget.Any && dcf.Target != target)
return false;
return true;
}
return false;
}
public void WriteDefaultConfigFile (string name, FeatureTarget target, string path, IDefaultContainer[] defaults)
{
AssertStorage ();
DefaultConfigFile dcf;
if (!storage.ContainsKey (name) || (dcf = storage [name]) == null)
throw new ApplicationException (
String.Format ("Definition of the '{0}' default config file not found.", name));
if (target != FeatureTarget.Any && dcf.Target != target)
throw new ApplicationException (
String.Format ("Config file '{0}' can be generated only for the '{1}' target",
name, target));
string targetFile = Path.Combine (path, dcf.FileName);
if (File.Exists (targetFile)) {
OverwriteFileEventArgs args = new OverwriteFileEventArgs (
dcf.FileName,
path,
target,
true
);
OnOverwriteFile (args);
if (!args.Overwrite)
return;
}
try {
if (!Directory.Exists (path))
Directory.CreateDirectory (path);
} catch (Exception ex) {
throw new ApplicationException (
String.Format ("Could not create directory '{0}'", path),
ex);
}
XmlDocument doc = new XmlDocument ();
PopulateDocument (name, target, doc, dcf, defaults);
Helpers.SaveXml (doc, targetFile);
}
void OnOverwriteFile (OverwriteFileEventArgs args)
{
if (OverwriteFile == null)
return;
OverwriteFile (this, args);
}
void PopulateDocument (string name, FeatureTarget target, XmlDocument doc, DefaultConfigFile dcf,
IDefaultContainer[] defaults)
{
List <Section> children = dcf.Sections != null ? dcf.Sections.Children : null;
if (children == null || children.Count == 0)
return;
PopulateDocument (name, target, doc, doc, defaults, children);
}
void PopulateDocument (string name, FeatureTarget target, XmlDocument doc, XmlNode parent,
IDefaultContainer[] defaults, List <Section> children)
{
if (defaults == null || defaults.Length == 0)
return;
XmlNode node;
XmlDocument tmp;
foreach (Section s in children) {
tmp = Helpers.FindDefault (defaults, s.DefaultBlockName, target);
if (tmp == null)
continue;
node = doc.ImportNode (tmp.DocumentElement.FirstChild, true);
try {
PopulateDocument (name, target, doc, node, defaults, s.Children);
} catch (Exception ex) {
throw new ApplicationException (
String.Format ("Error building default config file '{0}'", name),
ex);
}
parent.AppendChild (node);
}
}
void AssertStorage ()
{
if (storage == null)
throw new ApplicationException ("No storage attached");
}
}
}

View File

@@ -0,0 +1,121 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
class DefaultNode
{
string contents;
FeatureTarget target;
public string Contents {
get { return contents; }
}
public FeatureTarget Target {
get { return target; }
}
public DefaultNode (string contents, FeatureTarget target)
{
this.contents = contents;
this.target = target;
}
}
public class DefaultNodeHandler : IDocumentNodeHandler, IDefaultContainer, IStorageConsumer
{
string section;
string contents;
FeatureTarget target;
Dictionary <string, DefaultNode> storage;
public void ReadConfiguration (XPathNavigator nav)
{
section = Helpers.GetRequiredNonEmptyAttribute (nav, "section");
target = Helpers.ConvertEnum <FeatureTarget> (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target");
XPathNodeIterator iter = nav.Select ("./text()");
StringBuilder sb = new StringBuilder ();
while (iter.MoveNext ())
sb.Append (iter.Current.Value);
if (sb.Length > 0)
contents = sb.ToString ();
}
public void StoreConfiguration ()
{
AssertStorage ();
DefaultNode dn = new DefaultNode (contents, target);
if (storage.ContainsKey (section))
storage [section] = dn;
else
storage.Add (section, dn);
section = null;
contents = null;
storage = null;
}
public string FindDefault (string sectionName, FeatureTarget target)
{
AssertStorage ();
if (storage.ContainsKey (sectionName)) {
DefaultNode dn = storage [sectionName];
if (target == FeatureTarget.Any || dn.Target == FeatureTarget.Any || dn.Target == target)
return dn.Contents;
}
return null;
}
public void SetStorage (object storage)
{
this.storage = storage as Dictionary <string, DefaultNode>;
if (this.storage == null)
throw new ApplicationException ("Invalid storage type");
}
void AssertStorage ()
{
if (storage == null)
throw new ApplicationException ("No storage attached");
}
}
}

View File

@@ -0,0 +1,219 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public enum ActionType
{
Message,
ShellScript,
Exec
}
public enum ActionWhen
{
Before,
After
}
public class FeatureAction
{
ActionType type;
ActionWhen when;
string command;
string commandArguments;
string message;
string script;
public ActionWhen When {
get { return when; }
}
public FeatureAction (XPathNavigator nav)
{
string val = Helpers.GetRequiredNonEmptyAttribute (nav, "type");
type = Helpers.ConvertEnum <ActionType> (val, "type");
val = Helpers.GetRequiredNonEmptyAttribute (nav, "when");
when = Helpers.ConvertEnum <ActionWhen> (val, "when");
XPathNodeIterator iter;
StringBuilder sb = new StringBuilder ();
switch (type) {
case ActionType.Message:
case ActionType.ShellScript:
iter = nav.Select ("./text()");
while (iter.MoveNext ())
sb.Append (iter.Current.Value);
if (type == ActionType.Message)
message = sb.ToString ();
else
script = sb.ToString ();
break;
case ActionType.Exec:
command = Helpers.GetRequiredNonEmptyAttribute (nav, "command");
commandArguments = Helpers.GetOptionalAttribute (nav, "commndArguments");
break;
}
}
public void Execute ()
{
switch (type) {
case ActionType.Message:
ExecuteMessage ();
break;
case ActionType.ShellScript:
ExecuteShellScript ();
break;
case ActionType.Exec:
ExecuteExec ();
break;
}
}
void ExecuteMessage ()
{
if (String.IsNullOrEmpty (message))
return;
string[] lines = message.Split ('\n');
string line;
int maxLineWidth = Console.WindowWidth;
StringBuilder sb = new StringBuilder ();
foreach (string l in lines) {
if (l.Length == 0) {
sb.Append ("\n");
continue;
}
line = l.Trim ();
if (line.Length > maxLineWidth)
sb.AppendFormat ("{0}\n", Helpers.BreakLongLine (line, String.Empty, maxLineWidth));
else
sb.AppendFormat ("{0}{1}\n", String.Empty, line);
}
Console.WriteLine (sb.ToString ());
}
void ExecuteShellScript ()
{
if (String.IsNullOrEmpty (script))
return;
string script_temp = Path.GetTempFileName ();
StreamWriter s = null;
try {
s = new StreamWriter (script_temp);
s.Write (script);
s.Flush ();
s.Close ();
RunCommand ("/bin/sh", script_temp);
} catch (Exception ex) {
throw new ApplicationException ("Error executing feature 'shell script' action.", ex);
} finally {
if (s != null)
s.Close ();
try {
File.Delete (script_temp);
} catch (Exception) {
// ignore
}
}
}
void ExecuteExec ()
{
if (String.IsNullOrEmpty (command))
return;
try {
RunCommand (command, commandArguments);
} catch (Exception ex) {
throw new ApplicationException ("Error executing feature 'exec' action.", ex);
}
}
void RunCommand (string commandPath, string format, params object[] arguments)
{
if (String.IsNullOrEmpty (commandPath))
return;
string args;
if (!String.IsNullOrEmpty (format))
args = String.Format (format, arguments);
else
args = String.Empty;
Process p = null;
try {
p = new Process ();
ProcessStartInfo pinfo = p.StartInfo;
pinfo.UseShellExecute = false;
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardError = true;
pinfo.FileName = commandPath;
pinfo.Arguments = args;
p.Start ();
string stdout = p.StandardOutput.ReadToEnd ();
string stderr = p.StandardError.ReadToEnd ();
p.WaitForExit ();
if (!String.IsNullOrEmpty (stdout))
Console.WriteLine (stdout);
if (!String.IsNullOrEmpty (stderr))
Console.Error.WriteLine (stderr);
int exitCode = p.ExitCode;
if (exitCode != 0)
throw new ApplicationException (
String.Format ("Process signalled failure code: {0}", exitCode));
} finally {
if (p != null)
p.Close ();
}
}
}
}

View File

@@ -0,0 +1,53 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public class FeatureBlock
{
string name;
FeatureTarget target;
public string Name {
get { return name; }
}
public FeatureTarget Target {
get { return target; }
}
public FeatureBlock (XPathNavigator node, FeatureTarget target)
{
this.name = Helpers.GetRequiredNonEmptyAttribute (node, "name");
this.target = target;
}
}
}

View File

@@ -0,0 +1,75 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
namespace Mono.MonoConfig
{
public class FeatureNode
{
List <FeatureBlock> blocks;
List <FeatureAction> actionsBefore;
List <FeatureAction> actionsAfter;
string description;
public List <FeatureBlock> Blocks {
get {
if (blocks != null)
return blocks;
return new List <FeatureBlock> ();
}
}
public string Description {
get {
if (description != null)
return description;
return String.Empty;
}
}
public List <FeatureAction> ActionsBefore {
get { return actionsBefore; }
}
public List <FeatureAction> ActionsAfter {
get { return actionsAfter; }
}
public FeatureNode (List <FeatureBlock> blocks, string description,
List <FeatureAction> actionsBefore, List <FeatureAction> actionsAfter)
{
this.blocks = blocks;
this.description = description;
this.actionsBefore = actionsBefore;
this.actionsAfter = actionsAfter;
}
}
}

View File

@@ -0,0 +1,439 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public class FeatureNodeHandler : IDocumentNodeHandler, IStorageConsumer, IFeatureGenerator
{
string name;
FeatureTarget target;
List <FeatureBlock> blocks;
List <FeatureAction> actionsBefore;
List <FeatureAction> actionsAfter;
Dictionary <string, FeatureNode> storage;
StringBuilder description;
public FeatureNodeHandler ()
{
blocks = new List <FeatureBlock> ();
actionsBefore = new List <FeatureAction> ();
actionsAfter = new List <FeatureAction> ();
description = new StringBuilder ();
}
public void ReadConfiguration (XPathNavigator nav)
{
name = Helpers.GetRequiredNonEmptyAttribute (nav, "name");
target = Helpers.ConvertEnum <FeatureTarget> (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target");
XPathNodeIterator iter = nav.Select ("blocks/block[string-length (@name) > 0]");
while (iter.MoveNext ())
blocks.Add (new FeatureBlock (iter.Current, target));
iter = nav.Select ("description/text()");
string val;
while (iter.MoveNext ()) {
val = iter.Current.Value;
if (String.IsNullOrEmpty (val))
continue;
description.Append (val);
}
FeatureAction action;
iter = nav.Select ("actions/action[string-length (@type) > 0 and string-length (@when) > 0]");
while (iter.MoveNext ()) {
action = new FeatureAction (iter.Current);
switch (action.When) {
case ActionWhen.Before:
actionsBefore.Add (action);
break;
case ActionWhen.After:
actionsAfter.Add (action);
break;
default:
throw new ApplicationException (
String.Format ("Unknown 'when' attribute: {0}", action.When));
}
}
}
public void StoreConfiguration ()
{
AssertStorage ();
List <FeatureBlock> blocksClone = new List <FeatureBlock> (blocks.Count);
List <FeatureAction> abc = new List <FeatureAction> (actionsBefore.Count);
List <FeatureAction> aac = new List <FeatureAction> (actionsAfter.Count);
blocksClone.AddRange (blocks);
abc.AddRange (actionsBefore);
aac.AddRange (actionsAfter);
FeatureNode fn = new FeatureNode (blocksClone, description.ToString (), abc, aac);
if (storage.ContainsKey (name))
storage [name] = fn; // allow for silent override
else
storage.Add (name, fn);
blocks.Clear ();
actionsBefore.Clear ();
actionsAfter.Clear ();
description.Length = 0;
}
public void SetStorage (object storage)
{
this.storage = storage as Dictionary <string, FeatureNode>;
if (this.storage == null)
throw new ApplicationException ("Invalid storage type");
}
public ICollection <string> Features {
get {
AssertStorage ();
if (storage.Count == 0)
return null;
List <string> ret = new List <string> (storage.Count);
string desc;
foreach (KeyValuePair <string, FeatureNode> kvp in storage) {
desc = FormatFeatureDescription (kvp.Key, kvp.Value);
if (String.IsNullOrEmpty (desc))
continue;
ret.Add (desc);
}
return ret;
}
}
string FormatFeatureDescription (string name, FeatureNode fn)
{
if (fn == null)
return null;
List <FeatureBlock> lfb = fn.Blocks;
if (lfb == null || lfb.Count == 0)
return null;
StringBuilder ret = new StringBuilder ();
ret.AppendFormat ("{0} (Target: {1})", name, lfb [0].Target);
List <FeatureAction> al = fn.ActionsBefore;
if (al != null && al.Count > 0)
ret.AppendFormat ("; {0} actions before", al.Count);
al = fn.ActionsAfter;
if (al != null && al.Count > 0)
ret.AppendFormat ("; {0} actions after", al.Count);
ret.Append ("\n");
string desc = fn.Description;
if (String.IsNullOrEmpty (desc))
return ret.ToString ();
string indent = " ";
int maxLineWidth = Console.WindowWidth - indent.Length;
string[] dlines = desc.Trim ().Split ('\n');
string line;
foreach (string l in dlines) {
if (l.Length == 0) {
ret.Append ("\n");
continue;
}
line = l.Trim ();
if (line.Length > maxLineWidth)
ret.AppendFormat ("{0}\n", Helpers.BreakLongLine (line, indent, maxLineWidth));
else
ret.AppendFormat ("{0}{1}\n", indent, line);
}
ret.Append ("\n");
return ret.ToString ();
}
public bool HasFeature (string featureName)
{
AssertStorage ();
if (!storage.ContainsKey (featureName))
return false;
FeatureNode fn = storage [featureName];
if (fn == null)
return false;
List <FeatureBlock> blocks = fn.Blocks;
if (blocks == null || blocks.Count == 0)
return false;
return true;
}
public void AddFeature (string configFilePath, string featureName, FeatureTarget target,
IDefaultContainer[] defaults, IConfigBlockContainer[] configBlocks)
{
AssertStorage ();
FeatureNode fn;
if (!storage.ContainsKey (featureName) || (fn = storage [featureName]) == null)
throw new ApplicationException (String.Format ("Missing definition of feature '{0}'", featureName));
List <FeatureBlock> blocks = fn.Blocks;
if (blocks == null || blocks.Count == 0)
throw new ApplicationException (String.Format ("Definition of feature '{0}' is empty", featureName));
RunActions (fn.ActionsBefore);
XmlDocument doc = new XmlDocument ();
if (File.Exists (configFilePath))
doc.Load (configFilePath);
foreach (FeatureBlock block in blocks)
AddFeatureBlock (doc, block, target, defaults, configBlocks);
Helpers.SaveXml (doc, configFilePath);
RunActions (fn.ActionsAfter);
}
void RunActions (List <FeatureAction> actions)
{
if (actions == null || actions.Count == 0)
return;
foreach (FeatureAction action in actions) {
if (action == null)
continue;
action.Execute ();
}
}
void AddFeatureBlock (XmlDocument doc, FeatureBlock block, FeatureTarget target, IDefaultContainer[] defaults,
IConfigBlockContainer[] configBlocks)
{
if (target != FeatureTarget.Any && block.Target != target)
return;
ConfigBlockBlock configBlock = Helpers.FindConfigBlock (configBlocks, block.Name);
if (configBlock == null)
throw new ApplicationException (String.Format ("Config block '{0}' cannot be found", block.Name));
XmlNode attachPoint = null;
ProcessSections (doc, doc, "/", configBlock.Requires, defaults, configBlock.Name, ref attachPoint);
if (attachPoint == null)
attachPoint = FindDefaultAttachPoint (doc, configBlock.Requires);
if (attachPoint == null)
throw new ApplicationException (
String.Format ("Missing attachment point for block '{0}'", configBlock.Name));
XmlDocument contents = new XmlDocument ();
contents.LoadXml (String.Format ("<{0}>{1}</{0}>", Helpers.FakeRootName, configBlock.Contents));
AddFeatureRecursively (doc, attachPoint, contents.DocumentElement);
}
// TODO: handle comment and text nodes to avoid their duplication
void AddFeatureRecursively (XmlDocument doc, XmlNode attachPoint, XmlNode top)
{
bool topIsFake = top.Name == Helpers.FakeRootName;
XmlNode parent = null;
string xpath;
if (top.NodeType == XmlNodeType.Element) {
xpath = BuildFeaturePath (attachPoint, topIsFake ? null : top);
parent = DocumentHasFeatureFragment (doc, top, xpath);
}
if (!topIsFake && parent == null) {
parent = doc.ImportNode (top, false);
attachPoint.AppendChild (parent);
if (parent.NodeType == XmlNodeType.Comment)
return;
}
if (top.HasChildNodes)
foreach (XmlNode node in top.ChildNodes)
AddFeatureRecursively (doc, topIsFake ? attachPoint : parent, node);
}
XmlNode FindDefaultAttachPoint (XmlDocument doc, Section req)
{
List <Section> children = req.Children;
if (children == null || children.Count == 0)
return null;
StringBuilder sb = new StringBuilder ("/");
BuildPathToLastRequirement (sb, children);
return doc.SelectSingleNode (sb.ToString ());
}
void BuildPathToLastRequirement (StringBuilder sb, List <Section> sections)
{
Section last = sections [sections.Count - 1];
sb.AppendFormat ("/{0}", last.Name);
List <Section> children = last.Children;
if (children == null || children.Count == 0)
return;
BuildPathToLastRequirement (sb, children);
}
XmlNode DocumentHasFeatureFragment (XmlDocument doc, XmlNode top, string xpath)
{
if (top.NodeType == XmlNodeType.Comment)
return null;
return doc.SelectSingleNode (xpath);
}
string BuildFeaturePath (XmlNode parent, XmlNode child)
{
if (parent == null)
return "/";
List <string> path = new List <string> ();
XmlNode cur = parent, last = null;
while (cur != null && cur.NodeType != XmlNodeType.Document) {
if (cur.NodeType == XmlNodeType.Element && cur.Name != Helpers.FakeRootName)
path.Insert (0, cur.Name);
last = cur;
cur = cur.ParentNode;
}
string attributes = null;
if (child != null && last.Name != child.Name) {
if (child.NodeType == XmlNodeType.Element)
path.Add (child.Name);
attributes = BuildXPathFromAttributes (child);
} else if (last != null)
attributes = BuildXPathFromAttributes (last);
path [path.Count - 1] += attributes;
path.Insert (0, "/");
return String.Join ("/", path.ToArray ());
}
string BuildXPathFromAttributes (XmlNode node)
{
XmlAttributeCollection attrs = node.Attributes;
StringBuilder sb = new StringBuilder ();
string and = String.Empty;
bool first = true;
foreach (XmlAttribute attr in attrs) {
sb.AppendFormat ("{0}@{1}=\"{2}\"",
and,
attr.Name,
attr.Value);
if (first) {
first = false;
and = " and ";
}
}
if (sb.Length == 0)
return String.Empty;
sb.Insert (0, "[");
sb.Append ("]");
return sb.ToString ();
}
void ProcessSections (XmlDocument doc, XmlNode parent, string topPath, Section top, IDefaultContainer[] defaults,
string blockName, ref XmlNode attachPoint)
{
List <Section> topChildren, children;
if (top == null || (topChildren = top.Children) == null)
return;
XmlNode node;
string curPath;
foreach (Section s in topChildren) {
curPath = String.Format ("{0}/{1}", topPath, s.Name);
node = FindNodeOrAddDefault (doc, s.DefaultBlockName, curPath, defaults);
if (node != null && s.AttachPoint) {
if (attachPoint != null)
throw new ApplicationException (
String.Format ("Config block '{0}' has more than one attachment point",
blockName));
attachPoint = node;
}
parent.AppendChild (node);
if ((children = s.Children) != null && children.Count > 0)
ProcessSections (doc, node, curPath, s, defaults, blockName, ref attachPoint);
}
return;
}
XmlNode FindNodeOrAddDefault (XmlDocument doc, string nodeName, string nodePath, IDefaultContainer[] defaults)
{
XmlNode ret = doc.SelectSingleNode (nodePath);
if (ret != null)
return ret;
XmlDocument defDoc = Helpers.FindDefault (defaults, nodeName, FeatureTarget.Any);
if (defDoc == null)
throw new ApplicationException (
String.Format ("Document doesn't contain node '{0}' and no default can be found",
nodePath));
return doc.ImportNode (defDoc.DocumentElement.FirstChild, true);
}
void AssertStorage ()
{
if (storage == null)
throw new ApplicationException ("No storage attached");
}
}
}

View File

@@ -0,0 +1,38 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.MonoConfig
{
public enum FeatureTarget
{
Any,
Web,
Application
};
}

View File

@@ -0,0 +1,192 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public static class Helpers
{
public const string FakeRootName = "F_a_K_e_R_o_O_t_M_o_N_o_C_o_N_f_I_g_N_o_D_e";
public static EnumType ConvertEnum <EnumType> (string value, string attrName)
{
try {
EnumConverter cvt = new EnumConverter (typeof (EnumType));
return (EnumType) cvt.ConvertFromInvariantString (value);
} catch (Exception) {
throw new ApplicationException (
String.Format ("Failed to parse the '{0}' attribute '{1}'", attrName, value));
}
}
public static string BreakLongLine (string line, string indent, int maxLineWidth)
{
StringBuilder sb = new StringBuilder ();
int lineLen = line.Length;
int segments = lineLen / maxLineWidth;
int segmentStart = 0;
int segmentLen = maxLineWidth - 1;
int idx;
while (segments-- >= 0) {
idx = line.LastIndexOf (' ', segmentStart + segmentLen);
if (idx > 0)
segmentLen = idx - segmentStart;
else
idx = segmentLen - 1;
sb.AppendFormat ("{0}{1}\n", indent, line.Substring (segmentStart, segmentLen));
segmentStart = idx + 1;
if (lineLen - segmentStart > maxLineWidth)
segmentLen = maxLineWidth;
else
segmentLen = lineLen - segmentStart - 1;
}
return sb.ToString ();
}
public static string GetRequiredNonEmptyAttribute (XPathNavigator node, string name)
{
string val = GetOptionalAttribute (node, name);
if (String.IsNullOrEmpty (val))
ThrowMissingRequiredAttribute (node, name);
return val;
}
public static string GetOptionalAttribute (XPathNavigator node, string name)
{
return node.GetAttribute (name, String.Empty);
}
static void ThrowMissingRequiredAttribute (XPathNavigator node, string name)
{
throw new ApplicationException (String.Format ("Element '{0}' is missing required attribute '{1}'",
node.LocalName, name));
}
public static void BuildSectionTree (XPathNodeIterator iter, Section section)
{
XPathNavigator nav, tmp;
XPathNodeIterator children;
List <Section> sectionChildren = section.Children;
Section newSection, curSection;
while (iter.MoveNext ()) {
nav = iter.Current;
children = nav.Select ("section[string-length(@name) > 0]");
curSection = new Section (nav);
while (children.MoveNext ()) {
tmp = children.Current;
newSection = new Section (tmp);
BuildSectionTree (tmp.Select ("section[string-length(@name) > 0]"), newSection);
curSection.Children.Add (newSection);
}
sectionChildren.Add (curSection);
}
}
public static XmlDocument FindDefault (IDefaultContainer[] defaults, string name, FeatureTarget target)
{
int len;
if (defaults == null || (len = defaults.Length) == 0)
return null;
IDefaultContainer cur;
string text = null;
for (int i = 0; i < len; i++) {
cur = defaults [i];
text = cur.FindDefault (name, target);
if (text != null)
break;
}
if (text == null)
return null;
XmlDocument ret = new XmlDocument ();
ret.LoadXml (String.Format ("<{0}>{1}</{0}>", FakeRootName, text));
return ret;
}
public static ConfigBlockBlock FindConfigBlock (IConfigBlockContainer[] configBlocks, string name)
{
int len;
if (configBlocks == null || (len = configBlocks.Length) == 0)
return null;
IConfigBlockContainer cur;
ConfigBlockBlock ret = null;
for (int i = 0; i < len; i++) {
cur = configBlocks [i];
ret = cur.FindConfigBlock (name);
if (ret != null)
break;
}
return ret;
}
public static void SaveXml (XmlDocument doc, string targetFile)
{
XmlWriterSettings settings = new XmlWriterSettings ();
settings.CloseOutput = true;
settings.CheckCharacters = true;
settings.Indent = true;
settings.Encoding = Encoding.UTF8;
settings.IndentChars = "\t";
settings.NewLineHandling = NewLineHandling.Replace;
XmlWriter writer = null;
try {
writer = XmlWriter.Create (targetFile, settings);
doc.Save (writer);
writer.Flush ();
} catch (Exception ex) {
throw new ApplicationException (
String.Format ("Failed to write XML file {1}", targetFile), ex);
} finally {
if (writer != null)
writer.Close ();
}
}
}
}

View File

@@ -0,0 +1,36 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.MonoConfig
{
public interface IConfigBlockContainer
{
ConfigBlockBlock FindConfigBlock (string name);
}
}

View File

@@ -0,0 +1,43 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
namespace Mono.MonoConfig
{
public interface IDefaultConfigFileContainer
{
event OverwriteFileEventHandler OverwriteFile;
bool HasDefaultConfigFile (string name, FeatureTarget target);
void WriteDefaultConfigFile (string name, FeatureTarget target, string path, IDefaultContainer[] defaults);
ICollection <string> DefaultConfigFiles {
get;
}
}
}

View File

@@ -0,0 +1,36 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.MonoConfig
{
public interface IDefaultContainer
{
string FindDefault (string sectionName, FeatureTarget target);
}
}

View File

@@ -0,0 +1,41 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
namespace Mono.MonoConfig
{
public interface IDocumentNodeHandler
{
void ReadConfiguration (XPathNavigator nav);
void StoreConfiguration ();
}
}

View File

@@ -0,0 +1,42 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
namespace Mono.MonoConfig
{
public interface IFeatureGenerator
{
bool HasFeature (string featureName);
void AddFeature (string configFilePath, string featureName, FeatureTarget target,
IDefaultContainer[] defaults, IConfigBlockContainer[] configBlocks);
ICollection <string> Features {
get;
}
}
}

View File

@@ -0,0 +1,36 @@
//
// Authors:
// Marek Habersack (mhabersack@novell.com)
//
// (C) 2007 Novell, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace Mono.MonoConfig
{
public interface IStorageConsumer
{
void SetStorage (object storage);
}
}

Some files were not shown because too many files have changed in this diff Show More