/// <summary> /// Creates a Javascript execution environment /// </summary> /// <param name="fileContainer">The object that will be accessed through Javascript</param> /// <param name="javascriptContainer">The text file that contains the javascript</param> public ExecutionEnvironment( FileHandlerFactoryLocator fileHandlerFactoryLocator, IFileContainer javascriptContainer, IFileContainer fileContainer, SubProcess subProcess, ParentScope parentScope) { _FileHandlerFactoryLocator = fileHandlerFactoryLocator; _JavascriptContainer = javascriptContainer; _JavascriptLastModified = javascriptContainer.LastModified; parentScope.WebHandlersWithThisAsParent.Enqueue(fileContainer.WebHandler); object toDiscard; ISession ownerSession = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { if (null != fileContainer.Owner) ownerSession.Login(fileContainer.Owner); IWebConnection ownerWebConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, ownerSession, fileContainer.FullPath, null, null, new CookiesFromBrowser(), CallingFrom.Web, WebMethod.GET); ScopeWrapper = new ScopeWrapper( fileHandlerFactoryLocator, subProcess, fileContainer, parentScope, ownerWebConnection, out toDiscard); } catch (Exception e) { // If the Javascript has an error in it, it must be ignored. If an error were returned, then malformed Javascript could hose the system! this._ExecutionEnvironmentErrors = e.ToString(); log.Error("Error creating scope", e); } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(ownerSession.SessionId); } }
/// <summary> /// Creates a scope wrapper /// </summary> /// <param name="fileHandlerFactoryLocator"></param> /// <param name="webConnection"></param> /// <param name="javascript"></param> /// <param name="fileContainer"></param> /// <param name="constructScopeResults"></param> public ScopeWrapper( FileHandlerFactoryLocator fileHandlerFactoryLocator, SubProcess subProcess, IFileContainer fileContainer, ParentScope parentScope, IWebConnection constructWebConnection, out object constructScopeResults) { _FileContainer = fileContainer; _SubProcess = subProcess; _ParentScope = parentScope; _ScopeId = GetScopeID(); _FileHandlerFactoryLocator = fileHandlerFactoryLocator; constructScopeResults = ConstructScope(constructWebConnection); }
private ParentScope CreateParentScope(IFileContainer javascriptContainer) { List<string> scriptsToEval = new List<string>(); List<string> requestedScripts = new List<string>(new string[] { "/API/AJAX_serverside.js", "/API/json2.js" }); string fileType = null; StringBuilder javascriptBuilder = new StringBuilder(); foreach (string line in javascriptContainer.CastFileHandler<ITextHandler>().ReadLines()) { // find file type if (line.Trim().StartsWith("// FileType:")) fileType = line.Substring(12).Trim(); // Find dependant scripts else if (line.Trim().StartsWith("// Scripts:")) foreach (string script in line.Substring(11).Split(',')) requestedScripts.Add(script.Trim()); else javascriptBuilder.AppendFormat("{0}\n", line); } string javascript = javascriptBuilder.ToString(); Dictionary<string, MethodInfo> functionsInScope = new Dictionary<string, MethodInfo>(); List<KeyValuePair<IFileContainer, DateTime>> loadedScriptsModifiedTimes = new List<KeyValuePair<IFileContainer, DateTime>>(); ISession ownerSession = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { ownerSession.Login(javascriptContainer.Owner); IWebConnection ownerWebConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, ownerSession, javascriptContainer.FullPath, null, null, new CookiesFromBrowser(), CallingFrom.Web, WebMethod.GET); IEnumerable<ScriptAndMD5> dependantScriptsAndMD5s = FileHandlerFactoryLocator.WebServer.WebComponentResolver.DetermineDependantScripts( requestedScripts, ownerWebConnection); // Load static methods that are passed into the Javascript environment as-is foreach (Type javascriptFunctionsType in GetTypesThatHaveJavascriptFunctions(fileType)) foreach (MethodInfo method in javascriptFunctionsType.GetMethods(BindingFlags.Static | BindingFlags.Public)) functionsInScope[method.Name] = method; // Load all dependant scripts foreach (ScriptAndMD5 dependantScript in dependantScriptsAndMD5s) { string scriptName = dependantScript.ScriptName; if (scriptName.Contains("?")) scriptsToEval.Add(ownerWebConnection.ShellTo(scriptName).ResultsAsString); else { IFileContainer scriptFileContainer = FileHandlerFactoryLocator.FileSystemResolver.ResolveFile(scriptName); if (scriptFileContainer.FileHandler is ITextHandler) { loadedScriptsModifiedTimes.Add(new KeyValuePair<IFileContainer, DateTime>(scriptFileContainer, scriptFileContainer.LastModified)); scriptsToEval.Add(scriptFileContainer.CastFileHandler<ITextHandler>().ReadAll()); } else scriptsToEval.Add(ownerWebConnection.ShellTo(scriptName).ResultsAsString); } } loadedScriptsModifiedTimes.Add(new KeyValuePair<IFileContainer, DateTime>(javascriptContainer, javascriptContainer.LastModified)); // Construct Javascript to shell to the "base" webHandler HashSet<Type> webHandlerTypes = new HashSet<Type>(FileHandlerFactoryLocator.WebHandlerPlugins); if (null != fileType) webHandlerTypes.Add(FileHandlerFactoryLocator.WebHandlerClasses[fileType]); string baseWrapper = GetJavascriptWrapperForBase("base", webHandlerTypes); scriptsToEval.Add(baseWrapper); scriptsToEval.Add(javascript); scriptsToEval.Add("if (this.options) options; else null;"); ParentScope parentScope = new ParentScope(loadedScriptsModifiedTimes, functionsInScope); Dictionary<string, object> data = new Dictionary<string, object>(); data["Scripts"] = scriptsToEval; data["Functions"] = functionsInScope.Keys; _SubProcess.CreateParentScope(parentScope.ParentScopeId, Thread.CurrentThread.ManagedThreadId, data); return parentScope; } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(ownerSession.SessionId); } }