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);
			}
		}
Example #2
0
        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;
		}
Example #6
0
        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);
        }
Example #7
0
        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));
		}
Example #9
0
        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);
        }
Example #10
0
        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));
            }
        }
Example #11
0
        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);
		}
Example #13
0
 protected virtual void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope)
 {
 }
Example #14
0
 protected virtual void CustomizeEngine(Engine engine, ScriptedJsonPatcherOperationScope scope)
 {
 }
Example #15
0
        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();
        }
Example #16
0
        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);
            }
        }
Example #17
0
 protected virtual void RemoveEngineCustomizations(Engine engine, ScriptedJsonPatcherOperationScope scope)
 {
 }
		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));
		}
Example #22
0
        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);
            }
        }
Example #23
0
        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();
        }