Browse Source

Conditions are now supported in the <Runtime> section of the .addin files. This allows choosing different assemblies based on properties like ${Platform} (Win32 or Win64).

The new <DisableAddIn> element can be used to disable AddIns completely based on conditions, e.g. when a platform is not supported at all.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1177 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
3e7560380f
  1. 3
      src/AddIns/Misc/AddInManager/Project/Src/AddInControl.cs
  2. 9
      src/AddIns/Misc/AddInManager/Project/Src/ManagerForm.cs
  3. 5
      src/AddIns/Misc/SubversionAddIn/Project/ICSharpCode.Svn.addin
  4. 35
      src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs
  5. 24
      src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs
  6. 17
      src/Main/Core/Project/Src/AddInTree/AddIn/Condition.cs
  7. 5
      src/Main/Core/Project/Src/AddInTree/AddIn/ExtensionPath.cs
  8. 99
      src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs
  9. 3
      src/Main/Core/Project/Src/AddInTree/AddInManager.cs
  10. 21
      src/Main/Core/Project/Src/AddInTree/AddInTree.cs
  11. 9
      src/Main/Core/Project/Src/Services/StringParser/StringParser.cs

3
src/AddIns/Misc/AddInManager/Project/Src/AddInControl.cs

@ -182,6 +182,9 @@ namespace ICSharpCode.AddInManager @@ -182,6 +182,9 @@ namespace ICSharpCode.AddInManager
case AddInAction.DependencyError:
textBrush = Brushes.Red;
return ResourceService.GetString("AddInManager.AddInDependencyFailed");
case AddInAction.CustomError:
textBrush = Brushes.Red;
return StringParser.Parse(addIn.CustomErrorMessage);
default:
textBrush = Brushes.Yellow;
return addIn.Action.ToString();

9
src/AddIns/Misc/AddInManager/Project/Src/ManagerForm.cs

@ -199,6 +199,13 @@ namespace ICSharpCode.AddInManager @@ -199,6 +199,13 @@ namespace ICSharpCode.AddInManager
List<AddIn> selected;
AddInAction selectedAction;
static bool IsErrorAction(AddInAction action)
{
return action == AddInAction.DependencyError
|| action == AddInAction.InstalledTwice
|| action == AddInAction.CustomError;
}
void UpdateActionBox()
{
ignoreFocusChange = true;
@ -227,7 +234,7 @@ namespace ICSharpCode.AddInManager @@ -227,7 +234,7 @@ namespace ICSharpCode.AddInManager
break;
}
allEnabled &= addIn.Action == AddInAction.Enable;
if (addIn.Action == AddInAction.DependencyError || addIn.Action == AddInAction.InstalledTwice)
if (IsErrorAction(addIn.Action))
hasErrors = true;
else
allDisabled &= addIn.Action == AddInAction.Disable;

5
src/AddIns/Misc/SubversionAddIn/Project/ICSharpCode.Svn.addin

@ -8,7 +8,10 @@ @@ -8,7 +8,10 @@
</Manifest>
<Runtime>
<Import assembly="SubversionAddIn.dll"/>
<Condition name = "Compare" string = "${Platform}" equals = "Win64">
<DisableAddIn message = "This AddIn does not work in the x64 Edition of Windows."/>
</Condition>
<Import assembly = "SubversionAddIn.dll"/>
</Runtime>
<Path name = "/Workspace/Autostart">

35
src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs

@ -50,6 +50,24 @@ namespace ICSharpCode.Core @@ -50,6 +50,24 @@ namespace ICSharpCode.Core
return "[AddIn: " + Name + "]";
}
string customErrorMessage;
/// <summary>
/// Gets the message of a custom load error. Used only when AddInAction is set to CustomError.
/// </summary>
public string CustomErrorMessage {
get {
return customErrorMessage;
}
internal set {
if (value != null) {
Enabled = false;
Action = AddInAction.CustomError;
}
customErrorMessage = value;
}
}
/// <summary>
/// Action to execute when the application is restarted.
/// </summary>
@ -136,7 +154,7 @@ namespace ICSharpCode.Core @@ -136,7 +154,7 @@ namespace ICSharpCode.Core
{
}
static void SetupAddIn(XmlTextReader reader, AddIn addIn, string hintPath)
static void SetupAddIn(XmlReader reader, AddIn addIn, string hintPath)
{
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.Element && reader.IsStartElement()) {
@ -160,20 +178,7 @@ namespace ICSharpCode.Core @@ -160,20 +178,7 @@ namespace ICSharpCode.Core
break;
case "Runtime":
if (!reader.IsEmptyElement) {
while (reader.Read()){
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "Runtime") {
break;
}
if (reader.NodeType == XmlNodeType.Element && reader.IsStartElement()) {
switch (reader.LocalName) {
case "Import":
addIn.runtimes.Add(Runtime.Read(addIn, reader, hintPath));
break;
default:
throw new AddInLoadException("Unknown node in runtime section :" + reader.LocalName);
}
}
}
Runtime.ReadSection(reader, addIn, hintPath);
}
break;
case "Include":

24
src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs

@ -92,31 +92,17 @@ namespace ICSharpCode.Core @@ -92,31 +92,17 @@ namespace ICSharpCode.Core
public ConditionFailedAction GetFailedAction(object caller)
{
ConditionFailedAction action = ConditionFailedAction.Nothing;
foreach (ICondition condition in conditions) {
try {
if (!condition.IsValid(caller)) {
if (condition.Action == ConditionFailedAction.Disable) {
action = ConditionFailedAction.Disable;
} else {
return action = ConditionFailedAction.Exclude;
}
}
} catch {
LoggingService.Error("Exception while getting failed action from " + addIn.FileName);
throw;
}
}
return action;
return Condition.GetFailedAction(conditions, caller);
}
//
//
// public void BinarySerialize(BinaryWriter writer)
// {
// writer.Write(AddInTree.GetNameOffset(name));
// writer.Write(AddInTree.GetAddInOffset(addIn));
// properties.BinarySerialize(writer);
// }
//
//
public object BuildItem(object owner, ArrayList subItems)
{
try {
@ -137,7 +123,7 @@ namespace ICSharpCode.Core @@ -137,7 +123,7 @@ namespace ICSharpCode.Core
{
return String.Format("[Codon: name = {0}, addIn={1}]",
name,
addIn.FileName);
addIn.FileName);
}
}
}

17
src/Main/Core/Project/Src/AddInTree/AddIn/Condition.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.Core @@ -93,7 +93,7 @@ namespace ICSharpCode.Core
case "Condition":
condition = Condition.Read(reader);
goto exit;
}
}
break;
}
}
@ -135,5 +135,20 @@ namespace ICSharpCode.Core @@ -135,5 +135,20 @@ namespace ICSharpCode.Core
}
return conditions.ToArray();
}
public static ConditionFailedAction GetFailedAction(IEnumerable<ICondition> conditionList, object caller)
{
ConditionFailedAction action = ConditionFailedAction.Nothing;
foreach (ICondition condition in conditionList) {
if (!condition.IsValid(caller)) {
if (condition.Action == ConditionFailedAction.Disable) {
action = ConditionFailedAction.Disable;
} else {
return ConditionFailedAction.Exclude;
}
}
}
return action;
}
}
}

5
src/Main/Core/Project/Src/AddInTree/AddIn/ExtensionPath.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Core @@ -44,7 +44,7 @@ namespace ICSharpCode.Core
this.name = name;
}
public static void SetUp(ExtensionPath extensionPath, XmlTextReader reader, string endElement)
public static void SetUp(ExtensionPath extensionPath, XmlReader reader, string endElement)
{
Stack<ICondition> conditionStack = new Stack<ICondition>();
while (reader.Read()) {
@ -59,8 +59,7 @@ namespace ICSharpCode.Core @@ -59,8 +59,7 @@ namespace ICSharpCode.Core
case XmlNodeType.Element:
string elementName = reader.LocalName;
if (elementName == "Condition") {
ICondition newCondition = Condition.Read(reader);
conditionStack.Push(newCondition);
conditionStack.Push(Condition.Read(reader));
} else if (elementName == "ComplexCondition") {
conditionStack.Push(Condition.ReadComplexCondition(reader));
} else {

99
src/Main/Core/Project/Src/AddInTree/AddIn/Runtime.cs

@ -15,11 +15,25 @@ namespace ICSharpCode.Core @@ -15,11 +15,25 @@ namespace ICSharpCode.Core
{
public class Runtime
{
string hintPath;
string assembly;
Assembly loadedAssembly = null;
List<Properties> definedDoozers = new List<Properties>(1);
List<Properties> definedConditionEvaluators = new List<Properties>(1);
string hintPath;
string assembly;
Assembly loadedAssembly = null;
IList<LazyLoadDoozer> definedDoozers = new List<LazyLoadDoozer>();
IList<LazyConditionEvaluator> definedConditionEvaluators = new List<LazyConditionEvaluator>();
ICondition[] conditions;
bool isActive = true;
bool isAssemblyLoaded;
public bool IsActive {
get {
if (conditions != null) {
isActive = Condition.GetFailedAction(conditions, this) == ConditionFailedAction.Nothing;
conditions = null;
}
return isActive;
}
}
public Runtime(string assembly, string hintPath)
{
@ -33,8 +47,6 @@ namespace ICSharpCode.Core @@ -33,8 +47,6 @@ namespace ICSharpCode.Core
}
}
bool isAssemblyLoaded;
public Assembly LoadedAssembly {
get {
if (!isAssemblyLoaded) {
@ -79,13 +91,13 @@ namespace ICSharpCode.Core @@ -79,13 +91,13 @@ namespace ICSharpCode.Core
}
}
public List<Properties> DefinedDoozers {
public IList<LazyLoadDoozer> DefinedDoozers {
get {
return definedDoozers;
}
}
public List<Properties> DefinedConditionEvaluators {
public IList<LazyConditionEvaluator> DefinedConditionEvaluators {
get {
return definedConditionEvaluators;
}
@ -93,18 +105,62 @@ namespace ICSharpCode.Core @@ -93,18 +105,62 @@ namespace ICSharpCode.Core
public object CreateInstance(string instance)
{
Assembly asm = LoadedAssembly;
if (asm == null)
if (IsActive) {
Assembly asm = LoadedAssembly;
if (asm == null)
return null;
return asm.CreateInstance(instance);
} else {
return null;
return asm.CreateInstance(instance);
}
}
internal static Runtime Read(AddIn addIn, XmlTextReader reader, string hintPath)
internal static void ReadSection(XmlReader reader, AddIn addIn, string hintPath)
{
Stack<ICondition> conditionStack = new Stack<ICondition>();
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.EndElement:
if (reader.LocalName == "Condition" || reader.LocalName == "ComplexCondition") {
conditionStack.Pop();
} else if (reader.LocalName == "Runtime") {
return;
}
break;
case XmlNodeType.Element:
switch (reader.LocalName) {
case "Condition":
conditionStack.Push(Condition.Read(reader));
break;
case "ComplexCondition":
conditionStack.Push(Condition.ReadComplexCondition(reader));
break;
case "Import":
addIn.Runtimes.Add(Runtime.Read(addIn, reader, hintPath, conditionStack));
break;
case "DisableAddIn":
if (Condition.GetFailedAction(conditionStack, addIn) == ConditionFailedAction.Nothing) {
// The DisableAddIn node not was not disabled by a condition
addIn.CustomErrorMessage = reader.GetAttribute("message");
}
break;
default:
throw new AddInLoadException("Unknown node in runtime section :" + reader.LocalName);
}
break;
}
}
}
internal static Runtime Read(AddIn addIn, XmlReader reader, string hintPath, Stack<ICondition> conditionStack)
{
if (reader.AttributeCount != 1) {
throw new AddInLoadException("Import node requires ONE attribute.");
}
Runtime runtime = new Runtime(reader.GetAttribute(0), hintPath);
if (conditionStack.Count > 0) {
runtime.conditions = conditionStack.ToArray();
}
if (!reader.IsEmptyElement) {
while (reader.Read()) {
switch (reader.NodeType) {
@ -121,24 +177,13 @@ namespace ICSharpCode.Core @@ -121,24 +177,13 @@ namespace ICSharpCode.Core
if (!reader.IsEmptyElement) {
throw new AddInLoadException("Doozer nodes must be empty!");
}
LazyLoadDoozer lazyLoadDoozer = new LazyLoadDoozer(addIn, properties);
if (AddInTree.Doozers.ContainsKey(lazyLoadDoozer.Name)) {
throw new AddInLoadException("Duplicate doozer: " + lazyLoadDoozer.Name);
}
AddInTree.Doozers.Add(lazyLoadDoozer.Name, lazyLoadDoozer);
runtime.definedDoozers.Add(properties);
runtime.definedDoozers.Add(new LazyLoadDoozer(addIn, properties));
break;
case "ConditionEvaluator":
if (!reader.IsEmptyElement) {
throw new AddInLoadException("ConditionEvaluator nodes must be empty!");
}
LazyConditionEvaluator lazyLoadConditionEvaluator = new LazyConditionEvaluator(addIn, properties);
if (AddInTree.ConditionEvaluators.ContainsKey(lazyLoadConditionEvaluator.Name)) {
throw new AddInLoadException("Duplicate condition evaluator: " + lazyLoadConditionEvaluator.Name);
}
AddInTree.ConditionEvaluators.Add(lazyLoadConditionEvaluator.Name, lazyLoadConditionEvaluator);
runtime.definedConditionEvaluators.Add(properties);
runtime.definedConditionEvaluators.Add(new LazyConditionEvaluator(addIn, properties));
break;
default:
throw new AddInLoadException("Unknown node in Import section:" + nodeName);
@ -147,6 +192,8 @@ namespace ICSharpCode.Core @@ -147,6 +192,8 @@ namespace ICSharpCode.Core
}
}
}
runtime.definedDoozers = (runtime.definedDoozers as List<LazyLoadDoozer>).AsReadOnly();
runtime.definedConditionEvaluators = (runtime.definedConditionEvaluators as List<LazyConditionEvaluator>).AsReadOnly();
return runtime;
}
}

3
src/Main/Core/Project/Src/AddInTree/AddInManager.cs

@ -21,7 +21,8 @@ namespace ICSharpCode.Core @@ -21,7 +21,8 @@ namespace ICSharpCode.Core
Uninstall,
Update,
InstalledTwice,
DependencyError
DependencyError,
CustomError
}
public static class AddInManager

21
src/Main/Core/Project/Src/AddInTree/AddInTree.cs

@ -165,6 +165,23 @@ namespace ICSharpCode.Core @@ -165,6 +165,23 @@ namespace ICSharpCode.Core
AddExtensionPath(path);
}
foreach (Runtime runtime in addIn.Runtimes) {
if (runtime.IsActive) {
foreach (LazyLoadDoozer doozer in runtime.DefinedDoozers) {
if (AddInTree.Doozers.ContainsKey(doozer.Name)) {
throw new AddInLoadException("Duplicate doozer: " + doozer.Name);
}
AddInTree.Doozers.Add(doozer.Name, doozer);
}
foreach (LazyConditionEvaluator condition in runtime.DefinedConditionEvaluators) {
if (AddInTree.ConditionEvaluators.ContainsKey(condition.Name)) {
throw new AddInLoadException("Duplicate condition evaluator: " + condition.Name);
}
AddInTree.ConditionEvaluators.Add(condition.Name, condition);
}
}
}
string addInRoot = Path.GetDirectoryName(addIn.FileName);
foreach(string bitmapResource in addIn.BitmapResources)
{
@ -245,6 +262,10 @@ namespace ICSharpCode.Core @@ -245,6 +262,10 @@ namespace ICSharpCode.Core
Dictionary<string, AddIn> addInDict = new Dictionary<string, AddIn>();
foreach (string fileName in addInFiles) {
AddIn addIn = AddIn.Load(fileName);
if (addIn.Action == AddInAction.CustomError) {
list.Add(addIn);
continue;
}
addIn.Enabled = true;
if (disabledAddIns != null && disabledAddIns.Count > 0) {
foreach (string name in addIn.Manifest.Identities.Keys) {

9
src/Main/Core/Project/Src/Services/StringParser/StringParser.cs

@ -52,6 +52,15 @@ namespace ICSharpCode.Core @@ -52,6 +52,15 @@ namespace ICSharpCode.Core
propertyObjects["exe"] = FileVersionInfo.GetVersionInfo(exeName);
}
properties["USER"] = Environment.UserName;
// Maybe test for Mono?
if (IntPtr.Size == 4) {
properties["Platform"] = "Win32";
} else if (IntPtr.Size == 8) {
properties["Platform"] = "Win64";
} else {
properties["Platform"] = "unknown";
}
}
public static string Parse(string input)

Loading…
Cancel
Save