public object Process(ProcessRequest request) { var assembly = string.Empty; var typeName = string.Empty; var methodName = string.Empty; var appDomainKey = string.Empty; MuleMessage result; MuleMessage muleMessage = new MuleMessage(); IMuleInstrumentation instrumentation = new MuleInstrumentation(Instrument, request.NotifyEvents); if (string.IsNullOrWhiteSpace(request.AssemblyName)) { throw new ArgumentNullException("assemblyName"); } var split = request.AssemblyName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (split.Length == 0) { throw new ArgumentException("Invalid .NET Assembly Type. The .NET Assembly Type should be: partially qualified \"Namespace.Type, AssemblyName\" or fully qualified name \"Namespace.Type, AssemblyName, [Version], [Culture], [PublicKey]\""); } typeName = split[0].Trim(); if (split.Length == 2) { assembly = split[1].Trim(); appDomainKey = string.Format("{0}_{1}", request.AssemblyPath, assembly); } else // remove type from assembly name { assembly = request.AssemblyName.Substring(request.AssemblyName.IndexOf(",") + 1).Trim(); appDomainKey = assembly; } if (string.IsNullOrWhiteSpace(request.MethodName)) { throw new ArgumentNullException("The method name cannot be empty."); } // add trust to key appDomainKey = string.Concat(appDomainKey, request.FullTrust); // add timestamp to assembly not in GAC if (request.AssemblyPath.EndsWith(".dll")) { appDomainKey = string.Concat(appDomainKey, "_", File.GetLastWriteTime(request.AssemblyPath).Ticks.ToString()); } methodName = request.MethodName; muleMessage.Arguments = request.MethodArguments; muleMessage.InboundProperties = new ReadOnlyDictionary<string, object>(request.InboundProperties); muleMessage.SessionProperties = request.SessionProperties; muleMessage.InvocationProperties = request.InvocationProperties; muleMessage.OutboundProperties = request.OutboundProperties; var requestPath = muleMessage.InboundProperties.ContainsKey(MuleMessage.RequestKey) ? muleMessage.InboundProperties[MuleMessage.RequestKey] : string.Empty; muleMessage.Payload = muleMessage.Arguments.ContainsKey(MuleMessage.DataKey) ? muleMessage.Arguments[MuleMessage.DataKey] : requestPath; var queryString = muleMessage.InboundProperties.ContainsKey("http.query.string") ? muleMessage.InboundProperties["http.query.string"].ToString().Replace("{", "").Replace("}", "").Replace(" ", "").Replace(",", "&") : string.Empty; muleMessage.QueryStrings = string.IsNullOrWhiteSpace(queryString) ? new NameValueCollection() : HttpUtility.ParseQueryString(queryString); if (string.IsNullOrWhiteSpace(request.AssemblyPath)) { request.AssemblyPath = componentPath; } componentManager = appDomains.GetOrAdd(appDomainKey, (key) => { var cm = new ComponentManager(); cm.AppDomainKey = appDomainKey; //Bypass assemblies installed in the GAC if (request.AssemblyPath.EndsWith(".dll")) { // Add FileSystemWatcher to watch any updates on the requested assembly, if changes occur, unload AppDoamin and create a new one var watcher = new FileSystemWatcher(); watcher.Path = Path.GetDirectoryName(request.AssemblyPath); watcher.NotifyFilter = NotifyFilters.LastWrite; watcher.Filter = "*.dll"; watcher.Changed += (o, e) => { var componentWatcher = cm; watcher.EnableRaisingEvents = false; var retry = 0; var maxRetries = 10; // wait until AppDomain is idle to unload it while (componentWatcher.State != ComponentState.Idle && retry < maxRetries) { Thread.Sleep(15000); retry++; } AppDomain.Unload(componentWatcher.LoaderDomain); appDomains.TryRemove(appDomainKey, out componentWatcher); if (retry >= maxRetries) { throw new Exception(string.Format("The AppDomain couldn't be unloaded normally after {0} attempts.", retry)); } }; watcher.EnableRaisingEvents = true; } cm.Init(componentPath, request.AssemblyPath, request.FullTrust, logger); return cm; }); try { // Execute method string assemblyName; // Check if it's an assembly in the GAC or one specified by the user if (request.AssemblyPath.EndsWith(".dll")) { assemblyName = AssemblyName.GetAssemblyName(request.AssemblyPath).FullName; } else { assemblyName = assembly; } if(request.Log) { Log(string.Format("Start execution of component: {0}.{1}", typeName, methodName)); } //logger.Write(string.Format("Start execution of component: {0}.{1}", typeName, methodName), LoggerLevel.Trace); result = (MuleMessage)componentManager.Execute(assemblyName, typeName, methodName, muleMessage, request.IsSingleton, instrumentation); //logger.Write("End execution {0}.{1}", LoggerLevel.Trace, typeName, methodName); if(request.Log) { Log(string.Format("End execution {0}.{1}", typeName, methodName)); } } catch (Exception ex) { Log(string.Format("Error executing component {0}.{1} : {2}", typeName, methodName, ex.Message)); throw; } return ToProcessRequest(result); }
public object Process(ProcessRequest request) { var assembly = string.Empty; var typeName = string.Empty; var methodName = string.Empty; var appDomainKey = string.Empty; MuleMessage result; MuleMessage muleMessage = new MuleMessage(); IMuleInstrumentation instrumentation = new MuleInstrumentation(Instrument, request.NotifyEvents); if (string.IsNullOrWhiteSpace(request.AssemblyName)) { throw new ArgumentNullException("assemblyName"); } var split = request.AssemblyName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (split.Length == 0) { throw new ArgumentException("Invalid .NET Assembly Type. The .NET Assembly Type should be: partially qualified \"Namespace.Type, AssemblyName\" or fully qualified name \"Namespace.Type, AssemblyName, [Version], [Culture], [PublicKey]\""); } typeName = split[0].Trim(); if (split.Length == 2) { assembly = split[1].Trim(); appDomainKey = string.Format("{0}_{1}", request.AssemblyPath, assembly); } else // remove type from assembly name { assembly = request.AssemblyName.Substring(request.AssemblyName.IndexOf(",") + 1).Trim(); appDomainKey = assembly; } if (string.IsNullOrWhiteSpace(request.MethodName)) { throw new ArgumentNullException("The method name cannot be empty."); } // add trust to key appDomainKey = string.Concat(appDomainKey, request.FullTrust); // add timestamp to assembly not in GAC if (request.AssemblyPath.EndsWith(".dll")) { appDomainKey = string.Concat(appDomainKey, "_", File.GetLastWriteTime(request.AssemblyPath).Ticks.ToString()); } methodName = request.MethodName; muleMessage.Arguments = request.MethodArguments; muleMessage.InboundProperties = new ReadOnlyDictionary <string, object>(request.InboundProperties); muleMessage.SessionProperties = request.SessionProperties; muleMessage.InvocationProperties = request.InvocationProperties; muleMessage.OutboundProperties = request.OutboundProperties; var requestPath = muleMessage.InboundProperties.ContainsKey(MuleMessage.RequestKey) ? muleMessage.InboundProperties[MuleMessage.RequestKey] : string.Empty; muleMessage.Payload = muleMessage.Arguments.ContainsKey(MuleMessage.DataKey) ? muleMessage.Arguments[MuleMessage.DataKey] : requestPath; var queryString = muleMessage.InboundProperties.ContainsKey("http.query.string") ? muleMessage.InboundProperties["http.query.string"].ToString().Replace("{", "").Replace("}", "").Replace(" ", "").Replace(",", "&") : string.Empty; muleMessage.QueryStrings = string.IsNullOrWhiteSpace(queryString) ? new NameValueCollection() : HttpUtility.ParseQueryString(queryString); if (string.IsNullOrWhiteSpace(request.AssemblyPath)) { request.AssemblyPath = componentPath; } componentManager = appDomains.GetOrAdd(appDomainKey, (key) => { var cm = new ComponentManager(); cm.AppDomainKey = appDomainKey; //Bypass assemblies installed in the GAC if (request.AssemblyPath.EndsWith(".dll")) { // Add FileSystemWatcher to watch any updates on the requested assembly, if changes occur, unload AppDoamin and create a new one var watcher = new FileSystemWatcher(); watcher.Path = Path.GetDirectoryName(request.AssemblyPath); watcher.NotifyFilter = NotifyFilters.LastWrite; watcher.Filter = "*.dll"; watcher.Changed += (o, e) => { var componentWatcher = cm; watcher.EnableRaisingEvents = false; var retry = 0; var maxRetries = 10; // wait until AppDomain is idle to unload it while (componentWatcher.State != ComponentState.Idle && retry < maxRetries) { Thread.Sleep(15000); retry++; } AppDomain.Unload(componentWatcher.LoaderDomain); appDomains.TryRemove(appDomainKey, out componentWatcher); if (retry >= maxRetries) { throw new Exception(string.Format("The AppDomain couldn't be unloaded normally after {0} attempts.", retry)); } }; watcher.EnableRaisingEvents = true; } cm.Init(componentPath, request.AssemblyPath, request.FullTrust, logger); return(cm); }); try { // Execute method string assemblyName; // Check if it's an assembly in the GAC or one specified by the user if (request.AssemblyPath.EndsWith(".dll")) { assemblyName = AssemblyName.GetAssemblyName(request.AssemblyPath).FullName; } else { assemblyName = assembly; } if (request.Log) { Log(string.Format("Start execution of component: {0}.{1}", typeName, methodName)); } //logger.Write(string.Format("Start execution of component: {0}.{1}", typeName, methodName), LoggerLevel.Trace); result = (MuleMessage)componentManager.Execute(assemblyName, typeName, methodName, muleMessage, request.IsSingleton, instrumentation); //logger.Write("End execution {0}.{1}", LoggerLevel.Trace, typeName, methodName); if (request.Log) { Log(string.Format("End execution {0}.{1}", typeName, methodName)); } } catch (Exception ex) { Log(string.Format("Error executing component {0}.{1} : {2}", typeName, methodName, ex.Message)); throw; } return(ToProcessRequest(result)); }