public static BrewResponse Eval(BrewRequest request) { if (request == null) { throw new ArgumentNullException("request"); } var response = new BrewResponse { ContentType = request.Headers.ContentType }; BaristaContext.Current = new BaristaContext(request, response); var instanceSettings = BaristaContext.Current.Request.ParseInstanceSettings(); Mutex syncRoot = null; if (instanceSettings.InstanceMode != BaristaInstanceMode.PerCall) { syncRoot = new Mutex(false, "Barista_ScriptEngineInstance_" + instanceSettings.InstanceName); } var webBundle = new BaristaWebBundle(); var source = new BaristaScriptSource(request.Code, request.CodePath); if (syncRoot != null) { syncRoot.WaitOne(); } try { bool isNewScriptEngineInstance; bool errorInInitialization; var scriptEngineFactory = new BaristaScriptEngineFactory(); var engine = scriptEngineFactory.GetScriptEngine(webBundle, out isNewScriptEngineInstance, out errorInInitialization); if (engine == null) { throw new InvalidOperationException("Unable to obtain a script engine instance."); } if (errorInInitialization) { return(response); } try { var result = engine.Evaluate(source); var isRaw = false; //If the web instance has been initialized on the web bundle, use the value set via script, otherwise use defaults. if (webBundle.WebInstance == null || webBundle.WebInstance.Response.AutoDetectContentType) { response.ContentType = BrewResponse.AutoDetectContentTypeFromResult(result, response.ContentType); var arrayResult = result as Barista.Library.Base64EncodedByteArrayInstance; if (arrayResult != null && arrayResult.FileName.IsNullOrWhiteSpace() == false && response.Headers != null && response.Headers.ContainsKey("Content-Disposition") == false) { var br = BrowserUserAgentParser.GetDefault(); var clientInfo = br.Parse(request.Headers.UserAgent); if (clientInfo.UserAgent.Family == "IE" && (clientInfo.UserAgent.Major == "7" || clientInfo.UserAgent.Major == "8")) { response.Headers.Add("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(arrayResult.FileName)); } else if (clientInfo.UserAgent.Family == "Safari") { response.Headers.Add("Content-Disposition", "attachment; filename=" + arrayResult.FileName); } else { response.Headers.Add("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(arrayResult.FileName) + "\""); } } } if (webBundle.WebInstance != null) { isRaw = webBundle.WebInstance.Response.IsRaw; } response.SetContentsFromResultObject(engine, result, isRaw); } catch (JavaScriptException ex) { //BaristaDiagnosticsService.Local.LogException(ex, BaristaDiagnosticCategory.JavaScriptException, "A JavaScript exception was thrown while evaluating script: "); scriptEngineFactory.UpdateResponseWithJavaScriptExceptionDetails(engine, ex, response); } catch (Exception ex) { //BaristaDiagnosticsService.Local.LogException(ex, BaristaDiagnosticCategory.Runtime, "An internal error occurred while evaluating script: "); scriptEngineFactory.UpdateResponseWithExceptionDetails(ex, response); } finally { //Cleanup // ReSharper disable RedundantAssignment engine = null; // ReSharper restore RedundantAssignment if (BaristaContext.Current != null) { BaristaContext.Current.Dispose(); } BaristaContext.Current = null; } } finally { if (syncRoot != null) { syncRoot.ReleaseMutex(); } } return(response); }
public BrewResponse Eval(BrewRequest request) { if (request == null) { throw new ArgumentNullException("request"); } var response = new BrewResponse { ContentType = request.Headers.ContentType }; SPBaristaContext.Current = new SPBaristaContext(request, response); var instanceSettings = SPBaristaContext.Current.Request.ParseInstanceSettings(); Mutex syncRoot = null; if (instanceSettings.InstanceMode != BaristaInstanceMode.PerCall) { syncRoot = new Mutex(false, "Barista_ScriptEngineInstance_" + instanceSettings.InstanceName); } var webBundle = new SPWebBundle(); var source = new BaristaScriptSource(request.Code, request.CodePath); if (syncRoot != null) { syncRoot.WaitOne(); } try { bool isNewScriptEngineInstance; bool errorInInitialization; if (request.ScriptEngineFactory.IsNullOrWhiteSpace()) { throw new InvalidOperationException("A ScriptEngineFactory must be specified as part of a BrewRequest."); } var baristaScriptEngineFactoryType = Type.GetType(request.ScriptEngineFactory, true); if (baristaScriptEngineFactoryType == null) { throw new InvalidOperationException("Unable to locate the specified ScriptEngineFactory: " + request.ScriptEngineFactory); } var scriptEngineFactory = (ScriptEngineFactory)Activator.CreateInstance(baristaScriptEngineFactoryType); var engine = scriptEngineFactory.GetScriptEngine(webBundle, out isNewScriptEngineInstance, out errorInInitialization); if (engine == null) { throw new InvalidOperationException("Unable to obtain a script engine instance."); } if (errorInInitialization) { return(response); } if (engine is EdgeJSScriptEngine) { SetBaristaV2Flags(source, request, response); } try { //Default execution timeout to be 60 seconds. if (request.ExecutionTimeout <= 0) { request.ExecutionTimeout = 60 * 1000; } object result; using (new SPMonitoredScope("Barista Script Eval", request.ExecutionTimeout, new SPCriticalTraceCounter(), new SPExecutionTimeCounter(request.ExecutionTimeout), new SPRequestUsageCounter(), new SPSqlQueryCounter())) { //var mre = new ManualResetEvent(false); //var scopeEngine = engine; //var actionThread = new Thread(() => //{ // result = scopeEngine.Evaluate(source); //always call endinvoke // mre.Set(); //}); //actionThread.Start(); //mre.WaitOne(TimeSpan.FromMilliseconds(request.ExecutionTimeout)); //if (actionThread.IsAlive) // actionThread.Abort(); result = engine.Evaluate(source); } if (engine is EdgeJSScriptEngine) { //EdgeJSScriptEngine takes care of itself, just need to set the response as the response object. if (result != null) { var resultData = (dynamic)result; response = JsonConvert.DeserializeObject <BrewResponse>((string)resultData.response); } } else { var isRaw = false; //If the web instance has been initialized on the web bundle, use the value set via script, otherwise use defaults. if (webBundle.WebInstance == null || webBundle.WebInstance.Response.AutoDetectContentType) { response.ContentType = BrewResponse.AutoDetectContentTypeFromResult(result, response.ContentType); var arrayResult = result as Barista.Library.Base64EncodedByteArrayInstance; if (arrayResult != null) { if (arrayResult.FileName.IsNullOrWhiteSpace() == false && response.Headers != null && response.Headers.ContainsKey("Content-Disposition") == false) { var br = BrowserUserAgentParser.GetDefault(); var clientInfo = br.Parse(request.Headers.UserAgent); if (clientInfo.UserAgent.Family == "IE" && (clientInfo.UserAgent.Major == "7" || clientInfo.UserAgent.Major == "8")) { response.Headers.Add("Content-Disposition", "attachment; filename=" + Barista.Helpers.HttpUtility.UrlEncode(arrayResult.FileName)); } else if (clientInfo.UserAgent.Family == "Safari") { response.Headers.Add("Content-Disposition", "attachment; filename=" + arrayResult.FileName); } else { response.Headers.Add("Content-Disposition", "attachment; filename=\"" + Barista.Helpers.HttpUtility.UrlEncode(arrayResult.FileName) + "\""); } } //Set the ETag on the response if the Base64EncodedByteArrayInstance defines an ETag and one has not already been set. if (arrayResult.ETag.IsNullOrWhiteSpace() == false && response.Headers != null && response.Headers.ContainsKey("ETag") == false) { response.Headers.Add("ETag", arrayResult.ETag); } } } if (webBundle.WebInstance != null) { isRaw = webBundle.WebInstance.Response.IsRaw; } response.SetContentsFromResultObject(engine, result, isRaw); } } catch (JavaScriptException ex) { try { BaristaDiagnosticsService.Local.LogException(ex, BaristaDiagnosticCategory.JavaScriptException, "A JavaScript exception was thrown while evaluating script: "); } catch { //Do Nothing... } scriptEngineFactory.UpdateResponseWithJavaScriptExceptionDetails(engine, ex, response); } catch (Exception ex) { try { BaristaDiagnosticsService.Local.LogException(ex, BaristaDiagnosticCategory.Runtime, "An internal error occurred while evaluating script: "); } catch { //Do Nothing... } scriptEngineFactory.UpdateResponseWithExceptionDetails(ex, response); } finally { var engineDisposable = engine as IDisposable; if (engineDisposable != null) { engineDisposable.Dispose(); } //Cleanup // ReSharper disable RedundantAssignment engine = null; // ReSharper restore RedundantAssignment if (SPBaristaContext.Current != null) { SPBaristaContext.Current.Dispose(); } SPBaristaContext.Current = null; } } finally { if (syncRoot != null) { syncRoot.ReleaseMutex(); } } return(response); }