private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId, ScriptedJsonPatcherOperationScope scope) { Engine jintEngine; try { jintEngine = ScriptsCache.CheckoutScript(CreateEngine, patch); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JavaScriptException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } try { PrepareEngine(patch, docId, size, scope, jintEngine); var jsObject = scope.ToJsObject(jintEngine, doc); jintEngine.Invoke("ExecutePatchScript", jsObject); CleanupEngine(patch, jintEngine); OutputLog(jintEngine); ScriptsCache.CheckinScript(patch, jintEngine); return scope.ConvertReturnValue(jsObject); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { jintEngine.ResetStatementsCount(); OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script; var error = errorEx as JavaScriptException; if (error != null) errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Error); if (Debug.Count != 0) errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); var targetEx = errorEx as TargetInvocationException; if (targetEx != null && targetEx.InnerException != null) throw new InvalidOperationException(errorMsg, targetEx.InnerException); throw new InvalidOperationException(errorMsg, errorEx); } }
private void CleanupEngine(ScriptedPatchRequest patch, Engine jintEngine, ScriptedJsonPatcherOperationScope scope) { foreach (var kvp in patch.Values) { jintEngine.Global.Delete(kvp.Key, true); } jintEngine.Global.Delete("__document_id", true); RemoveEngineCustomizations(jintEngine, scope); }
protected override void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope) { base.RemoveEngineCustomizations(engine, scope); engine.Global.Delete("documentId", true); engine.Global.Delete("replicateTo", true); engine.Global.Delete("toVarchar", true); engine.Global.Delete("toNVarchar", true); foreach (var sqlReplicationTable in config.SqlReplicationTables) { engine.Global.Delete("replicateTo" + sqlReplicationTable.TableName, true); } }
protected override void CustomizeEngine(Engine jintEngine, ScriptedJsonPatcherOperationScope scope) { jintEngine.SetValue("documentId", docId); jintEngine.SetValue("replicateTo", new Action<string,object>(ReplicateToFunction)); foreach (var sqlReplicationTable in config.SqlReplicationTables) { var current = sqlReplicationTable; jintEngine.SetValue("replicateTo" + sqlReplicationTable.TableName, (Action<object>)(cols => { var tableName = current.TableName; ReplicateToFunction(tableName, cols); })); } }
public virtual RavenJObject Apply(ScriptedJsonPatcherOperationScope scope, RavenJObject document, ScriptedPatchRequest patch, int size = 0, string docId = null) { if (document == null) return null; if (String.IsNullOrEmpty(patch.Script)) throw new InvalidOperationException("Patch script must be non-null and not empty"); var resultDocument = ApplySingleScript(document, patch, size, docId, scope); if (resultDocument != null) document = resultDocument; return document; }
protected virtual void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope) { RavenJToken functions; if (scope.CustomFunctions == null || scope.CustomFunctions.DataAsJson.TryGetValue("Functions", out functions) == false) { return; } engine.Execute(@" if(customFunctions) { for(var customFunction in customFunctions) { delete this[customFunction]; }; };"); engine.SetValue("customFunctions", JsValue.Undefined); }
protected virtual void CustomizeEngine(Engine engine, ScriptedJsonPatcherOperationScope scope) { RavenJToken functions; if (scope.CustomFunctions == null || scope.CustomFunctions.DataAsJson.TryGetValue("Functions", out functions) == false) { return; } engine.Execute(string.Format(@" var customFunctions = function() {{ var exports = {{ }}; {0}; return exports; }}(); for(var customFunction in customFunctions) {{ this[customFunction] = customFunctions[customFunction]; }};", functions)); }
protected override void CustomizeEngine(Engine engine, ScriptedJsonPatcherOperationScope scope) { base.CustomizeEngine(engine, scope); engine.SetValue("documentId", docId); engine.SetValue("replicateTo", new Action<string,object>(ReplicateToFunction)); foreach (var sqlReplicationTable in config.SqlReplicationTables) { var current = sqlReplicationTable; engine.SetValue("replicateTo" + sqlReplicationTable.TableName, (Action<object>)(cols => { var tableName = current.TableName; ReplicateToFunction(tableName, cols); })); } engine.SetValue("toVarchar", (Func<string, int,ValueTypLengthTriple>)(ToVarchar)); engine.SetValue("toNVarchar", (Func<string, int, ValueTypLengthTriple>)(ToNVarchar)); }
public virtual RavenJObject Apply(ScriptedJsonPatcherOperationScope scope, RavenJObject document, ScriptedPatchRequest patch, int size = 0, string docId = null) { if (document == null) { return(null); } if (String.IsNullOrEmpty(patch.Script)) { throw new InvalidOperationException("Patch script must be non-null and not empty"); } var resultDocument = ApplySingleScript(document, patch, size, docId, scope); if (resultDocument != null) { document = resultDocument; } return(document); }
private void PrepareEngine(ScriptedPatchRequest patch, string docId, int size, ScriptedJsonPatcherOperationScope scope, Engine jintEngine) { jintEngine.Global.Delete("PutDocument", false); jintEngine.Global.Delete("LoadDocument", false); jintEngine.Global.Delete("DeleteDocument", false); CustomizeEngine(jintEngine, scope); jintEngine.SetValue("PutDocument", (Action <string, object, object>)((key, document, metadata) => scope.PutDocument(key, document, metadata, jintEngine))); jintEngine.SetValue("LoadDocument", (Func <string, JsValue>)(key => scope.LoadDocument(key, jintEngine))); jintEngine.SetValue("DeleteDocument", (Action <string>)(scope.DeleteDocument)); jintEngine.SetValue("__document_id", docId); foreach (var kvp in patch.Values) { var token = kvp.Value as RavenJToken; if (token != null) { jintEngine.SetValue(kvp.Key, scope.ToJsInstance(jintEngine, token)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = scope.ToJsInstance(jintEngine, rjt); jintEngine.SetValue(kvp.Key, jsInstance); } } jintEngine.ResetStatementsCount(); if (size != 0) { jintEngine.Options.MaxStatements(maxSteps + (size * additionalStepsPerSize)); } }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId, ScriptedJsonPatcherOperationScope scope) { Engine jintEngine; var customFunctions = scope.CustomFunctions != null ? scope.CustomFunctions.DataAsJson : null; try { jintEngine = ScriptsCache.CheckoutScript(CreateEngine, patch, customFunctions); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JavaScriptException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } try { PrepareEngine(patch, docId, size, scope, jintEngine); var jsObject = scope.ToJsObject(jintEngine, doc); jintEngine.Invoke("ExecutePatchScript", jsObject); CleanupEngine(patch, jintEngine, scope); OutputLog(jintEngine); if (scope.DebugMode) Debug.Add(string.Format("Statements executed: {0}", jintEngine.StatementsCount)); ScriptsCache.CheckinScript(patch, jintEngine, customFunctions); return scope.ConvertReturnValue(jsObject); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { jintEngine.ResetStatementsCount(); OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script + Environment.NewLine; var error = errorEx as JavaScriptException; if (error != null) errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Error); if (Debug.Count != 0) errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); if (error != null) errorMsg += Environment.NewLine + "Stacktrace:" + Environment.NewLine + error.CallStack; var targetEx = errorEx as TargetInvocationException; if (targetEx != null && targetEx.InnerException != null) throw new InvalidOperationException(errorMsg, targetEx.InnerException); var recursionEx = errorEx as RecursionDepthOverflowException; if (recursionEx != null) errorMsg += Environment.NewLine + "Max recursion depth is limited to: " + MaxRecursionDepth; throw new InvalidOperationException(errorMsg, errorEx); } }
private void CleanupEngine(ScriptedPatchRequest patch, Engine jintEngine, ScriptedJsonPatcherOperationScope scope) { foreach (var kvp in patch.Values) jintEngine.Global.Delete(kvp.Key, true); jintEngine.Global.Delete("__document_id", true); RemoveEngineCustomizations(jintEngine, scope); }
protected virtual void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope) { }
protected virtual void CustomizeEngine(Engine engine, ScriptedJsonPatcherOperationScope scope) { }
private void PrepareEngine(ScriptedPatchRequest patch, string docId, int size, ScriptedJsonPatcherOperationScope scope, Engine jintEngine) { scope.AdditionalStepsPerSize = additionalStepsPerSize; scope.MaxSteps = maxSteps; if (size != 0) { totalScriptSteps = maxSteps + (size * additionalStepsPerSize); jintEngine.Options.MaxStatements(TotalScriptSteps); } jintEngine.Global.Delete("PutDocument", false); jintEngine.Global.Delete("LoadDocument", false); jintEngine.Global.Delete("DeleteDocument", false); jintEngine.Global.Delete("IncreaseNumberOfAllowedStepsBy", false); CustomizeEngine(jintEngine, scope); jintEngine.SetValue("PutDocument", (Func <string, object, object, string>)((key, document, metadata) => scope.PutDocument(key, document, metadata, jintEngine))); jintEngine.SetValue("LoadDocument", (Func <string, JsValue>)(key => scope.LoadDocument(key, jintEngine, ref totalScriptSteps))); jintEngine.SetValue("DeleteDocument", (Action <string>)(scope.DeleteDocument)); jintEngine.SetValue("__document_id", docId); jintEngine.SetValue("IncreaseNumberOfAllowedStepsBy", (Action <int>)(number => { if (database != null && database.Configuration.AllowScriptsToAdjustNumberOfSteps) { scope.MaxSteps += number; jintEngine.Options.MaxStatements(totalScriptSteps + number); return; } throw new InvalidOperationException("Cannot use 'IncreaseNumberOfAllowedStepsBy' method, because `Raven/AllowScriptsToAdjustNumberOfSteps` is set to false."); })); foreach (var kvp in patch.Values) { var token = kvp.Value as RavenJToken; if (token != null) { jintEngine.SetValue(kvp.Key, scope.ToJsInstance(jintEngine, token)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = scope.ToJsInstance(jintEngine, rjt); jintEngine.SetValue(kvp.Key, jsInstance); } } jintEngine.ResetStatementsCount(); }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId, ScriptedJsonPatcherOperationScope scope) { Engine jintEngine; var customFunctions = scope.CustomFunctions != null ? scope.CustomFunctions.DataAsJson : null; try { jintEngine = ScriptsCache.CheckoutScript(CreateEngine, patch, customFunctions); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JavaScriptException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } try { PrepareEngine(patch, docId, size, scope, jintEngine); var jsObject = scope.ToJsObject(jintEngine, doc); jintEngine.Invoke("ExecutePatchScript", jsObject); CleanupEngine(patch, jintEngine, scope); OutputLog(jintEngine); if (scope.DebugMode) { Debug.Add(string.Format("Statements executed: {0}", jintEngine.StatementsCount)); } ScriptsCache.CheckinScript(patch, jintEngine, customFunctions); return(scope.ConvertReturnValue(jsObject)); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { jintEngine.ResetStatementsCount(); OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script + Environment.NewLine; var error = errorEx as JavaScriptException; if (error != null) { errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Error); } if (Debug.Count != 0) { errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); } if (error != null) { errorMsg += Environment.NewLine + "Stacktrace:" + Environment.NewLine + error.CallStack; } var targetEx = errorEx as TargetInvocationException; if (targetEx != null && targetEx.InnerException != null) { throw new InvalidOperationException(errorMsg, targetEx.InnerException); } var recursionEx = errorEx as RecursionDepthOverflowException; if (recursionEx != null) { errorMsg += Environment.NewLine + "Max recursion depth is limited to: " + MaxRecursionDepth; } throw new InvalidOperationException(errorMsg, errorEx); } }
protected virtual void CustomizeEngine(Engine engine, ScriptedJsonPatcherOperationScope scope) { RavenJToken functions; if (scope.CustomFunctions == null || scope.CustomFunctions.DataAsJson.TryGetValue("Functions", out functions) == false) return; engine.Execute(string.Format(@"var customFunctions = function() {{ var exports = {{ }}; {0}; return exports; }}(); for(var customFunction in customFunctions) {{ this[customFunction] = customFunctions[customFunction]; }};", functions), new ParserOptions { Source = "customFunctions.js"}); }
protected virtual void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope) { RavenJToken functions; if (scope.CustomFunctions == null || scope.CustomFunctions.DataAsJson.TryGetValue("Functions", out functions) == false) return; engine.Execute(@" if(customFunctions) { for(var customFunction in customFunctions) { delete this[customFunction]; }; };"); engine.SetValue("customFunctions", JsValue.Undefined); }
protected virtual void CustomizeEngine(Engine jintEngine, ScriptedJsonPatcherOperationScope scope) { }
private void PrepareEngine(ScriptedPatchRequest patch, string docId, int size, ScriptedJsonPatcherOperationScope scope, Engine jintEngine) { jintEngine.Global.Delete("PutDocument", false); jintEngine.Global.Delete("LoadDocument", false); jintEngine.Global.Delete("DeleteDocument", false); CustomizeEngine(jintEngine, scope); jintEngine.SetValue("PutDocument", (Action<string, object, object>)((key, document, metadata) => scope.PutDocument(key, document, metadata, jintEngine))); jintEngine.SetValue("LoadDocument", (Func<string, JsValue>)(key => scope.LoadDocument(key, jintEngine))); jintEngine.SetValue("DeleteDocument", (Action<string>)(scope.DeleteDocument)); jintEngine.SetValue("__document_id", docId); foreach (var kvp in patch.Values) { var token = kvp.Value as RavenJToken; if (token != null) { jintEngine.SetValue(kvp.Key, scope.ToJsInstance(jintEngine, token)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = scope.ToJsInstance(jintEngine, rjt); jintEngine.SetValue(kvp.Key, jsInstance); } } jintEngine.ResetStatementsCount(); if (size != 0) jintEngine.Options.MaxStatements(maxSteps + (size * additionalStepsPerSize)); }
private RavenJObject ApplySingleScript(RavenJObject doc, ScriptedPatchRequest patch, int size, string docId, ScriptedJsonPatcherOperationScope scope) { Engine jintEngine; try { jintEngine = ScriptsCache.CheckoutScript(CreateEngine, patch); } catch (NotSupportedException e) { throw new ParseException("Could not parse script", e); } catch (JavaScriptException e) { throw new ParseException("Could not parse script", e); } catch (Exception e) { throw new ParseException("Could not parse: " + Environment.NewLine + patch.Script, e); } try { PrepareEngine(patch, docId, size, scope, jintEngine); var jsObject = scope.ToJsObject(jintEngine, doc); jintEngine.Invoke("ExecutePatchScript", jsObject); CleanupEngine(patch, jintEngine, scope); OutputLog(jintEngine); ScriptsCache.CheckinScript(patch, jintEngine); return(scope.ConvertReturnValue(jsObject)); } catch (ConcurrencyException) { throw; } catch (Exception errorEx) { jintEngine.ResetStatementsCount(); OutputLog(jintEngine); var errorMsg = "Unable to execute JavaScript: " + Environment.NewLine + patch.Script; var error = errorEx as JavaScriptException; if (error != null) { errorMsg += Environment.NewLine + "Error: " + Environment.NewLine + string.Join(Environment.NewLine, error.Error); } if (Debug.Count != 0) { errorMsg += Environment.NewLine + "Debug information: " + Environment.NewLine + string.Join(Environment.NewLine, Debug); } var targetEx = errorEx as TargetInvocationException; if (targetEx != null && targetEx.InnerException != null) { throw new InvalidOperationException(errorMsg, targetEx.InnerException); } throw new InvalidOperationException(errorMsg, errorEx); } }
private void PrepareEngine(ScriptedPatchRequest patch, string docId, int size, ScriptedJsonPatcherOperationScope scope, Engine jintEngine) { scope.AdditionalStepsPerSize = additionalStepsPerSize; scope.MaxSteps = maxSteps; if (size != 0) { totalScriptSteps = maxSteps + (size * additionalStepsPerSize); jintEngine.Options.MaxStatements(TotalScriptSteps); } jintEngine.Global.Delete("PutDocument", false); jintEngine.Global.Delete("LoadDocument", false); jintEngine.Global.Delete("DeleteDocument", false); jintEngine.Global.Delete("IncreaseNumberOfAllowedStepsBy", false); CustomizeEngine(jintEngine, scope); jintEngine.SetValue("PutDocument", (Func<string, object, object, string>)((key, document, metadata) => scope.PutDocument(key, document, metadata, jintEngine))); jintEngine.SetValue("LoadDocument", (Func<string, JsValue>)(key => scope.LoadDocument(key, jintEngine, ref totalScriptSteps))); jintEngine.SetValue("DeleteDocument", (Action<string>)(scope.DeleteDocument)); jintEngine.SetValue("__document_id", docId); jintEngine.SetValue("IncreaseNumberOfAllowedStepsBy", (Action<int>)(number => { if (database != null && database.Configuration.AllowScriptsToAdjustNumberOfSteps) { scope.MaxSteps += number; jintEngine.Options.MaxStatements(totalScriptSteps + number); return; } throw new InvalidOperationException("Cannot use 'IncreaseNumberOfAllowedStepsBy' method, because `Raven/AllowScriptsToAdjustNumberOfSteps` is set to false."); })); foreach (var kvp in patch.Values) { var token = kvp.Value as RavenJToken; if (token != null) { jintEngine.SetValue(kvp.Key, scope.ToJsInstance(jintEngine, token)); } else { var rjt = RavenJToken.FromObject(kvp.Value); var jsInstance = scope.ToJsInstance(jintEngine, rjt); jintEngine.SetValue(kvp.Key, jsInstance); } } jintEngine.ResetStatementsCount(); }