200 lines
6.5 KiB
C#
200 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using Microsoft.Scripting;
|
|
using Microsoft.Scripting.Hosting;
|
|
|
|
namespace umbraco.MacroEngines.Scripting
|
|
{
|
|
internal class MacroScriptEngine
|
|
{
|
|
ScriptRuntime m_runTime;
|
|
ScriptEngine m_engine;
|
|
ExceptionOperations m_exceptionOperations;
|
|
SortedDictionary<string, object> m_inputVariables;
|
|
SortedDictionary<string, object> m_outputVariables;
|
|
string m_script;
|
|
MemoryStream m_output;
|
|
|
|
internal MacroScriptEngine() { }
|
|
|
|
internal MacroScriptEngine(string scriptType)
|
|
{
|
|
loadRunTime();
|
|
m_engine = m_runTime.GetEngine(scriptType);
|
|
m_exceptionOperations = m_engine.GetService<ExceptionOperations>();
|
|
}
|
|
|
|
internal static MacroScriptEngine LoadEngineByFileExtension(string fileExtension)
|
|
{
|
|
MacroScriptEngine mse = new MacroScriptEngine();
|
|
mse.loadRunTime();
|
|
mse.m_engine = mse.m_runTime.GetEngineByFileExtension(fileExtension);
|
|
mse.m_exceptionOperations = mse.m_engine.GetService<ExceptionOperations>();
|
|
return mse;
|
|
}
|
|
|
|
internal static MacroScriptEngine GetEngineByType(string scriptType)
|
|
{
|
|
MacroScriptEngine mse = new MacroScriptEngine();
|
|
mse.loadRunTime();
|
|
mse.m_engine = mse.m_runTime.GetEngine(scriptType);
|
|
mse.m_exceptionOperations = mse.m_engine.GetService<ExceptionOperations>();
|
|
return mse;
|
|
}
|
|
|
|
private void loadRunTime()
|
|
{
|
|
m_output = new MemoryStream();
|
|
m_runTime = ScriptRuntime.CreateFromConfiguration();
|
|
|
|
m_runTime.IO.SetOutput(m_output, new StreamWriter(m_output));
|
|
m_runTime.IO.SetErrorOutput(m_output, new StreamWriter(m_output));
|
|
|
|
Assembly pluginsAssembly = Assembly.LoadFile(IO.IOHelper.MapPath(IO.SystemDirectories.Bin + "/umbraco.dll"));
|
|
m_runTime.LoadAssembly(pluginsAssembly);
|
|
|
|
m_runTime.LoadAssembly(typeof(String).Assembly);
|
|
m_runTime.LoadAssembly(typeof(Uri).Assembly);
|
|
m_runTime.LoadAssembly(typeof(umbraco.presentation.nodeFactory.Node).Assembly);
|
|
}
|
|
|
|
|
|
internal SortedDictionary<string, object> ScriptVariables
|
|
{
|
|
set { m_inputVariables = value; }
|
|
}
|
|
|
|
internal SortedDictionary<string, object> OutPutVariables
|
|
{
|
|
get { return m_outputVariables; }
|
|
}
|
|
|
|
internal string Script
|
|
{
|
|
set { m_script = value; }
|
|
}
|
|
|
|
internal ExceptionOperations ExceptionOperations
|
|
{
|
|
get { return m_exceptionOperations; }
|
|
}
|
|
|
|
internal string Evaluate()
|
|
{
|
|
//Create structures
|
|
SourceCodeKind sc = SourceCodeKind.Expression;
|
|
ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
|
|
ScriptScope scope = m_engine.CreateScope();
|
|
|
|
//Fill input variables
|
|
foreach (KeyValuePair<string, object> variable in m_inputVariables)
|
|
{
|
|
scope.SetVariable(variable.Key, variable.Value);
|
|
}
|
|
|
|
string result = "";
|
|
|
|
try
|
|
{
|
|
object r = source.Execute(scope);
|
|
|
|
if (r != null)
|
|
result = r.ToString();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, e.ToString());
|
|
result = m_exceptionOperations.FormatException(e);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal string Execute()
|
|
{
|
|
SourceCodeKind sc = SourceCodeKind.Statements;
|
|
ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
|
|
ScriptScope scope = m_engine.CreateScope();
|
|
|
|
//Fill input variables
|
|
foreach (KeyValuePair<string, object> variable in m_inputVariables)
|
|
{
|
|
scope.SetVariable(variable.Key, variable.Value);
|
|
}
|
|
|
|
source.Execute(scope);
|
|
|
|
m_outputVariables = new SortedDictionary<string, object>();
|
|
foreach (string variable in scope.GetVariableNames())
|
|
{
|
|
m_outputVariables.Add(variable, scope.GetVariable(variable));
|
|
}
|
|
|
|
return ReadFromStream(m_output);
|
|
}
|
|
|
|
internal string ExecuteFile(string path)
|
|
{
|
|
string rbCode;
|
|
|
|
// OpenText will strip the BOM and keep the Unicode intact
|
|
using (var rdr = File.OpenText(path))
|
|
{
|
|
rbCode = rdr.ReadToEnd();
|
|
}
|
|
|
|
m_script = rbCode;
|
|
return Execute();
|
|
}
|
|
|
|
internal SortedDictionary<string, object> _Execute()
|
|
{
|
|
//Create structures
|
|
SourceCodeKind sc = SourceCodeKind.Statements;
|
|
ScriptSource source = m_engine.CreateScriptSourceFromString(m_script, sc);
|
|
ScriptScope scope = m_engine.CreateScope();
|
|
|
|
//Fill input variables
|
|
foreach (KeyValuePair<string, object> variable in m_inputVariables)
|
|
{
|
|
scope.SetVariable(variable.Key, variable.Value);
|
|
}
|
|
|
|
SortedDictionary<string, object> outputVariables = new SortedDictionary<string, object>();
|
|
//Execute the script
|
|
try
|
|
{
|
|
|
|
source.Execute(scope);
|
|
//Recover variables
|
|
foreach (string variable in scope.GetVariableNames())
|
|
{
|
|
outputVariables.Add(variable, scope.GetVariable(variable));
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
string error = m_exceptionOperations.FormatException(e);
|
|
//Do something with the pretty printed error
|
|
throw;
|
|
}
|
|
return outputVariables;
|
|
}
|
|
|
|
private static string ReadFromStream(MemoryStream ms)
|
|
{
|
|
int length = (int)ms.Length;
|
|
Byte[] bytes = new Byte[length];
|
|
|
|
ms.Seek(0, SeekOrigin.Begin);
|
|
ms.Read(bytes, 0, (int)ms.Length);
|
|
|
|
return Encoding.GetEncoding("utf-8").GetString(bytes, 0, (int)ms.Length);
|
|
}
|
|
}
|
|
}
|