/*=============================================================================
Project: SharpImage
Module: siScriptManager.cs
Language: C#
Author: Dan Mueller
Date: $Date: 2007-07-06 10:57:00 +1000 (Fri, 06 Jul 2007) $
Revision: $Revision: 2 $
Copyright (c) Queensland University of Technology (QUT) 2007.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=============================================================================*/
using System;
using System.IO;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using IronPython.Hosting;
using IronPython.Runtime.Exceptions;
using SharpImage.Main;
namespace SharpImage.Script
{
#region siScriptCommandNotSupportedException
//=========================================================================
public class siScriptCommandNotSupportedException : ArgumentException
{
public siScriptCommandNotSupportedException(string message, string command)
: base(message, command)
{
}
}
//=========================================================================
#endregion
#region siScriptManager Class
//=========================================================================
public class siScriptManager : IDisposable
{
#region Instance Variables
//=====================================================================
private bool m_IsDisposed = false;
private bool m_HasScriptBeenFinalised = false;
private bool m_HasScriptBeenCompleted = false;
private TimeSpan m_SpanScriptStarted;
//=====================================================================
#endregion
#region Construction and Disposal
//=====================================================================
///
/// Protected constructor.
///
///
protected siScriptManager(IApplication parent)
{
this.m_ParentApplication = parent;
this.m_Engine = new PythonEngine();
}
///
/// Public constructor.
///
/// The parent application.
/// The full file path of the script
/// to manage.
public siScriptManager(IApplication parent, string scriptFilePath)
: this(parent)
{
// Set member properties
this.m_ScriptFilePath = scriptFilePath;
// Initialise the Engine
this.m_Engine = new PythonEngine();
this.GetScriptPathHierarchy(true);
this.Engine.Import("Site");
this.Engine.Import("System");
this.Engine.Import("clr");
// Add IApplication to Engine.Globals
this.Engine.Globals["ParentApplication"] = parent;
this.Engine.Globals["ScriptFilePath"] = this.ScriptFilePath;
// Add event handlers dictionary to Engine.Globals
Dictionary handlers = new Dictionary();
handlers["ScriptRegisterName"] = new ScriptStringHandler(this.RegisterScriptNameHandler);
handlers["ScriptWriteLineToConsole"] = new ScriptStringHandler(this.OnScriptWriteLineToConsole);
handlers["ScriptStarted"] = new ScriptEmptyHandler(this.OnScriptStarted);
handlers["ScriptCompleted"] = new ScriptCompletedHandler(this.OnScriptCompleted);
handlers["ScriptFinalised"] = new ScriptEmptyHandler(this.OnScriptFinalised);
handlers["ScriptException"] = new ScriptExceptionHandler(this.OnScriptException);
handlers["ScriptFilterStarted"] = new itk.itkTimedEventHandler(this.OnScriptFilterStarted);
handlers["ScriptFilterEnded"] = new itk.itkTimedEventHandler(this.OnScriptFilterEnded);
handlers["ScriptFilterProgress"] = new itk.itkProgressHandler(this.OnScriptFilterProgress);
this.Engine.Globals["Handlers"] = handlers;
}
///
/// Protected constructor.
///
///
///
/// The value to init the ScriptCommand property with.
/// The value to init the ScriptParameters property with.
protected siScriptManager(IApplication parent, string scriptFilePath, string command, string parameters)
: this(parent, scriptFilePath)
{
this.m_ScriptCommand = command;
this.m_ScriptParameters = parameters;
}
///
/// Deconstructor.
///
~siScriptManager()
{
this.Dispose();
}
///
/// Dispose of resources.
///
public void Dispose()
{
if (this.m_IsDisposed)
return;
// Dispose of Engine resource
if (this.m_Engine != null)
{
this.m_Engine.Shutdown();
this.m_Engine.Dispose();
this.m_Engine = null;
}
// Flag that we are disposed
this.m_IsDisposed = true;
// Tell the GC that the Finalize process no longer needs
// to be run for this object.
GC.SuppressFinalize(this);
}
//=====================================================================
#endregion
#region Properties
//=====================================================================
#region ParentApplication
//=====================================================================
private IApplication m_ParentApplication = null;
///
/// Gets parent application.
///
public IApplication ParentApplication
{
get { return this.m_ParentApplication; }
}
//=====================================================================
#endregion
#region Engine
//=====================================================================
private PythonEngine m_Engine = null;
///
/// Gets the PythonEngine associated with this script.
///
private PythonEngine Engine
{
get { return this.m_Engine; }
}
//=====================================================================
#endregion
#region Code
//=====================================================================
private CompiledCode m_Code = null;
private bool m_IsCodeCompiled = false;
///
/// Gets the CompiledCode associated with this script.
/// This is only valid after calling CompileScript().
///
protected CompiledCode Code
{
get { return this.m_Code; }
}
///
/// Gets if the code has been successfully compiled.
///
protected bool IsCodeCompiled
{
get { return this.m_IsCodeCompiled; }
}
//=====================================================================
#endregion
#region ScriptFilePath
//=====================================================================
private string m_ScriptFilePath = string.Empty;
///
/// Gets the full path of the script file associated with this
/// ScriptManager instance.
///
public string ScriptFilePath
{
get { return this.m_ScriptFilePath; }
}
//=====================================================================
#endregion
#region ScriptName
//=====================================================================
private string m_ScriptName = string.Empty;
///
/// Gets the name the script uses to identify itself. This property is
/// only valid after a successful call to InitializeScript().
///
public string ScriptName
{
get { return this.m_ScriptName; }
}
//=====================================================================
#endregion
#region ScriptCommand
//=====================================================================
private string m_ScriptCommand = "run";
///
/// Gets a specific command to execute.
/// To run the script the command should be "run", to display help
/// information the command should be "help". "run" is the default
/// command for newly created ScriptManagers.
///
public string ScriptCommand
{
get { return this.m_ScriptCommand; }
}
//=====================================================================
#endregion
#region ScriptParameters
//=====================================================================
private string m_ScriptParameters = string.Empty;
///
/// Gets the parameters to initialise the script object.
/// Each name-value pair is separated by a space.
/// For example: "ThresholdLower=50 ThresholdUpper=100"
///
public string ScriptParameters
{
get { return this.m_ScriptParameters; }
}
//=====================================================================
#endregion
//=====================================================================
#endregion
#region Events and Delegates
//=====================================================================
public delegate void ScriptHandler(siScriptManager manager);
private delegate void ScriptEmptyHandler();
private delegate void ScriptCompletedHandler(bool success);
private delegate void ScriptStringHandler(string info);
private delegate void ScriptExceptionHandler(Exception ex);
#region ScriptFinalised
//============================================================================
private ScriptHandler m_EventStorage_ScriptFinalised;
///
/// An event raised when the itk.itkProcessObject has
/// started processing.
///
public event ScriptHandler ScriptFinalised
{
add { this.m_EventStorage_ScriptFinalised += value; }
remove { this.m_EventStorage_ScriptFinalised -= value; }
}
///
/// Raise the ScriptCompleted event.
///
///
public void RaiseScriptFinalised()
{
// Check we have not already raised this event
if (!this.m_HasScriptBeenFinalised)
{
// Flag we have raised the finalised event
this.m_HasScriptBeenFinalised = true;
// Raise event
if (this.m_EventStorage_ScriptFinalised != null)
this.m_EventStorage_ScriptFinalised(this);
}
}
//============================================================================
#endregion
//=====================================================================
#endregion
#region Public Static Methods
//=====================================================================
///
/// Creates a ScriptManager from the given command string.
/// Returns null if an error occurred while executing the command.
/// The error is displayed in the script console.
///
///
///
/// The absolute path of the current directory.
/// The newly created script manager waiting to be
/// executed OR null on error.
public static siScriptManager CreateFromCommand(IApplication parent,
string command,
string currentDirectory)
{
siScriptManager result = null;
try
{
// Check command is not empty
if (command == null || command.Length == 0)
throw new siScriptCommandNotSupportedException("You entered an empty command. Please enter either 'run