Exemple #1
0
        public void OnStreamEvent(Notify notify)
        {
            bool onStatus = notify.ServiceCall.ServiceMethodName.Equals("onStatus");
            if (!onStatus)
            {
                if (notify.ServiceCall.ServiceMethodName.Equals("onMetaData"))
                    RaiseOnMetaData(notify.ServiceCall.Arguments[0] as IDictionary);
                if (notify.ServiceCall.ServiceMethodName.Equals("onPlayStatus"))
                    RaiseOnPlayStatus(notify.ServiceCall.Arguments[0] as IDictionary);

                MethodInfo mi = MethodHandler.GetMethod(_client.GetType(), notify.ServiceCall.ServiceMethodName, notify.ServiceCall.Arguments, false, false);
                if (mi != null)
                {
                    ParameterInfo[] parameterInfos = mi.GetParameters();
                    object[] args = new object[parameterInfos.Length];
                    notify.ServiceCall.Arguments.CopyTo(args, 0);
                    TypeHelper.NarrowValues(args, parameterInfos);
                    try
                    {
                        InvocationHandler invocationHandler = new InvocationHandler(mi);
                        object result = invocationHandler.Invoke(_client, args);
                    }
                    catch (Exception exception)
                    {
                        notify.ServiceCall.Exception = exception;
                        notify.ServiceCall.Status = dotFlex.Messaging.Rtmp.Service.Call.STATUS_INVOCATION_EXCEPTION;
                        //log.Error("Error while invoking method " + call.ServiceMethodName + " on client", exception);
                    }
                }
                else
                {
                    string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, notify.ServiceCall.ServiceMethodName);
                    this.RaiseNetStatus(new FluorineException(msg));
                }
            }
            else
            {
                object[] args = notify.ServiceCall.Arguments;
                ASObject statusASO = null;
                if ((args != null) && (args.Length > 0))
                    statusASO = args[0] as ASObject;
                this.RaiseNetStatus(statusASO);
            }
        }
		public override object Invoke(IMessage message)
		{
			object result = null;
			RemotingMessage remotingMessage = message as RemotingMessage;
			string operation = remotingMessage.operation;
            string className = this.DestinationDefinition.Properties.Source;
            //This property is provided for backwards compatibility. The best practice, however, is to not expose the underlying source of a 
            //RemoteObject destination on the client and only one source to a destination.
            if (remotingMessage.source != null && remotingMessage.source != string.Empty)
            {
                if (className == "*")
                    className = remotingMessage.source;
                if (className != remotingMessage.source)
                {
                    string msg = __Res.GetString(__Res.Type_MismatchMissingSource, remotingMessage.source, this.DestinationDefinition.Properties.Source as string);
                    throw new MessageException(msg, new TypeLoadException(msg));
                }
            }

            if( className == null )
				throw new TypeInitializationException("null", null);

            //Service mapping obsolete for Flex Remoting
            /*
            if (FluorineConfiguration.Instance.ServiceMap != null)
            {
                string method = remotingMessage.operation;
                if (FluorineConfiguration.Instance.ServiceMap.Contains(className))
                {
                    string serviceLocation = FluorineConfiguration.Instance.ServiceMap.GetServiceLocation(className);
                    method = FluorineConfiguration.Instance.ServiceMap.GetMethod(className, method);
                    if (log != null && log.IsDebugEnabled)
                        log.Debug(__Res.GetString(__Res.Service_Mapping, className + "." + remotingMessage.operation, serviceLocation + "." + method));

                    className = serviceLocation;
                    remotingMessage.operation = method;
                }
            }
            */
            //Cache check
            string source = className + "." + operation;
			IList parameterList = remotingMessage.body as IList;
            string key = dotFlex.Configuration.CacheMap.GenerateCacheKey(source, parameterList);
            if (FluorineConfiguration.Instance.CacheMap.ContainsValue(key))
            {
                result = dotFlex.Configuration.FluorineConfiguration.Instance.CacheMap.Get(key);
                if (result != null)
                {
                    if (log != null && log.IsDebugEnabled)
                        log.Debug(__Res.GetString(__Res.Cache_HitKey, operation, key));
                    return result;
                }
            }

			FactoryInstance factoryInstance = this.Destination.GetFactoryInstance();
			factoryInstance.Source = className;
			object instance = factoryInstance.Lookup();

			if( instance != null )
			{
                try
                {
                    Type type = instance.GetType();
                    bool isAccessible = TypeHelper.GetTypeIsAccessible(type);
                    if (!isAccessible)
                    {
                        string msg = __Res.GetString(__Res.Type_InitError, type.FullName);
                        throw new MessageException(msg, new TypeLoadException(msg));
                    }

                    MethodInfo mi = MethodHandler.GetMethod(type, operation, parameterList);
                    if (mi != null)
                    {
                        try
                        {
                            //Messagebroker checked xml configured security, check attributes too
                            object[] roleAttributes = mi.GetCustomAttributes(typeof(RoleAttribute), true);
                            if (roleAttributes != null && roleAttributes.Length == 1)
                            {
                                RoleAttribute roleAttribute = roleAttributes[0] as RoleAttribute;
                                string[] roles = roleAttribute.Roles.Split(',');

                                bool authorized = this.Destination.Service.GetMessageBroker().LoginManager.DoAuthorization(roles);
                                if (!authorized)
                                    throw new UnauthorizedAccessException(__Res.GetString(__Res.Security_AccessNotAllowed));
                            }

                            ParameterInfo[] parameterInfos = mi.GetParameters();
                            object[] args = new object[parameterInfos.Length];
                            parameterList.CopyTo(args, 0);
                            TypeHelper.NarrowValues(args, parameterInfos);
                            InvocationHandler invocationHandler = new InvocationHandler(mi);
                            result = invocationHandler.Invoke(instance, args);
                        }
                        catch (TargetInvocationException exception)
                        {
                            MessageException messageException = null;
                            if (exception.InnerException is MessageException)
                                messageException = exception.InnerException as MessageException;//User code throws MessageException
                            else
                                messageException = new MessageException(exception.InnerException);

                            if (log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, messageException.Message));
                            return messageException.GetErrorMessage();
                            //Do not throw here, we do not want to log user code exceptions.
                            //throw messageException;
                        }

                    }
                    else
                        throw new MessageException(new MissingMethodException(className, operation));
                }
                catch (MessageException)
                {
                    throw;
                }
                catch (Exception exception)
                {
                    MessageException messageException = new MessageException(exception);
                    throw messageException;
                }
                finally
                {
                    factoryInstance.OnOperationComplete(instance);
                }
			}
			else
				throw new MessageException( new TypeInitializationException(className, null) );

            if (FluorineConfiguration.Instance.CacheMap != null && FluorineConfiguration.Instance.CacheMap.ContainsCacheDescriptor(source))
            {
                //The result should be cached
                CacheableObject cacheableObject = new CacheableObject(source, key, result);
                FluorineConfiguration.Instance.CacheMap.Add(cacheableObject.Source, cacheableObject.CacheKey, cacheableObject);
                result = cacheableObject;
            }
			return result;
		}
		public void SendMessage(string handler, IList arguments)
		{
            BeginUpdate();
            try
            {
                _so.SendMessage(handler, arguments);
            }
            finally
            {
                EndUpdate();
            }

			// Invoke method on registered handler
			string serviceName, serviceMethod;
			int dotPos = handler.LastIndexOf(".");
			if(dotPos != -1) 
			{
				serviceName = handler.Substring(0, dotPos);
				serviceMethod = handler.Substring(dotPos + 1);
			} 
			else 
			{
				serviceName = string.Empty;
				serviceMethod = handler;
			}

			object soHandler = GetServiceHandler(serviceName);
			if(soHandler == null && this.HasParent) 
			{
				// No custom handler, check for service defined in the scope's context
				IScopeContext context = this.Parent.Context;
				try 
				{
                    //Search for a handler only if there is a service name specified
                    if (serviceName != string.Empty)
                    {
                        // The type must have a name of "SharedObjectName.DottedServiceName"
                        soHandler = ObjectFactory.CreateInstance(_so.Name + "." + serviceName);
                    }
				} 
				catch(Exception) 
				{
					// No such type.
                    log.Debug(__Res.GetString(__Res.Type_InitError, _so.Name + "." + serviceName));
				}
			}

			if(soHandler != null) 
			{
				MethodInfo mi = MethodHandler.GetMethod(soHandler.GetType(), serviceMethod, arguments);
				if(mi != null) 
				{
					ParameterInfo[] parameterInfos = mi.GetParameters();
					object[] args = new object[parameterInfos.Length];
					arguments.CopyTo(args, 0);
					TypeHelper.NarrowValues( args, parameterInfos);
					try 
					{
						InvocationHandler invocationHandler = new InvocationHandler(mi);
						object result = invocationHandler.Invoke(soHandler, args);
					} 
					catch(Exception exception) 
					{
						log.Error(__Res.GetString(__Res.ServiceHandler_InvocationFailed, serviceMethod, handler), exception);
					}
				}
			}

			// Notify server listeners
			foreach(ISharedObjectListener listener in _serverListeners)
			{
				listener.OnSharedObjectSend(this, handler, arguments);
			}		
		}
		public override void Invoke(AMFContext context)
		{
			MessageOutput messageOutput = context.MessageOutput;
			for(int i = 0; i < context.AMFMessage.BodyCount; i++)
			{
				AMFBody amfBody = context.AMFMessage.GetBodyAt(i);
				ResponseBody responseBody = null;
				//Check for Flex2 messages and skip
				if( amfBody.IsEmptyTarget )
					continue;

				if( amfBody.IsDebug )
					continue;
				if( amfBody.IsDescribeService )
				{
					responseBody = new ResponseBody();
					responseBody.IgnoreResults = amfBody.IgnoreResults;
                    responseBody.Target = amfBody.Response + AMFBody.OnResult;
					responseBody.Response = null;
					DescribeService describeService = new DescribeService( amfBody );
					responseBody.Content = describeService.GetDescription();
					messageOutput.AddBody(responseBody);
					continue;
				}

				//Check if response exists.
				responseBody = messageOutput.GetResponse(amfBody);
				if( responseBody != null )
				{
					continue;
				}

				try
				{
				    MessageBroker messageBroker = _endpoint.GetMessageBroker();
                    RemotingService remotingService = messageBroker.GetService(RemotingService.RemotingServiceId) as RemotingService;
                    if (remotingService == null)
                    {
                        string serviceNotFound = __Res.GetString(__Res.Service_NotFound, RemotingService.RemotingServiceId);
                        responseBody = new ErrorResponseBody(amfBody, new FluorineException(serviceNotFound));
                        messageOutput.AddBody(responseBody);
                        if (log.IsErrorEnabled)
                            log.Error(serviceNotFound);
                        continue;
                    }
                    Destination destination = null;
                    if (destination == null)
                        destination = remotingService.GetDestinationWithSource(amfBody.TypeName);
                    if (destination == null)
                        destination = remotingService.DefaultDestination;
                    //At this moment we got a destination with the exact source or we have a default destination with the "*" source.
                    if (destination == null)
                    {
                        string destinationNotFound = __Res.GetString(__Res.Destination_NotFound, amfBody.TypeName);
                        responseBody = new ErrorResponseBody(amfBody, new FluorineException(destinationNotFound));
                        messageOutput.AddBody(responseBody);
                        if (log.IsErrorEnabled)
                            log.Error(destinationNotFound);
                        continue;
                    }

                    try
                    {
                        remotingService.CheckSecurity(destination);
                    }
                    catch (UnauthorizedAccessException exception)
                    {
                        responseBody = new ErrorResponseBody(amfBody, exception);
                        if (log.IsDebugEnabled)
                            log.Debug(exception.Message);
                        continue;
                    }

                    //Cache check
                    string source = amfBody.TypeName + "." + amfBody.Method;
                    IList parameterList = amfBody.GetParameterList();
                    string key = dotFlex.Configuration.CacheMap.GenerateCacheKey(source, parameterList);
                    if (FluorineConfiguration.Instance.CacheMap.ContainsValue(key))
                    {
                        object result = dotFlex.Configuration.FluorineConfiguration.Instance.CacheMap.Get(key);
                        if (result != null)
                        {
                            if (log != null && log.IsDebugEnabled)
                                log.Debug(__Res.GetString(__Res.Cache_HitKey, source, key));
                            responseBody = new ResponseBody(amfBody, result);
                            messageOutput.AddBody(responseBody);
                            continue;
                        }
                    }

				    FactoryInstance factoryInstance = destination.GetFactoryInstance();
				    factoryInstance.Source = amfBody.TypeName;
				    if( FluorineContext.Current.ActivationMode != null )//query string can override the activation mode
					    factoryInstance.Scope = FluorineContext.Current.ActivationMode;
				    object instance = factoryInstance.Lookup();

				    if( instance != null )
                    {
                        try
                        {
                            bool isAccessible = TypeHelper.GetTypeIsAccessible(instance.GetType());
                            if (!isAccessible)
                            {
                                string msg = __Res.GetString(__Res.Type_InitError, amfBody.TypeName);
                                if (log.IsErrorEnabled)
                                    log.Error(msg);
                                responseBody = new ErrorResponseBody(amfBody, new FluorineException(msg));
                                messageOutput.AddBody(responseBody);
                                continue;
                            }

                            MethodInfo mi = null;
                            if (!amfBody.IsRecordsetDelivery)
                            {
                                mi = MethodHandler.GetMethod(instance.GetType(), amfBody.Method, amfBody.GetParameterList());
                            }
                            else
                            {
                                //will receive recordsetid only (ignore)
                                mi = instance.GetType().GetMethod(amfBody.Method);
                            }
                            if (mi != null)
                            {
                                object[] roleAttributes = mi.GetCustomAttributes(typeof(RoleAttribute), true);
                                if (roleAttributes != null && roleAttributes.Length == 1)
                                {
                                    RoleAttribute roleAttribute = roleAttributes[0] as RoleAttribute;
                                    string[] roles = roleAttribute.Roles.Split(',');

                                    bool authorized = messageBroker.LoginManager.DoAuthorization(roles);
                                    if (!authorized)
                                        throw new UnauthorizedAccessException(__Res.GetString(__Res.Security_AccessNotAllowed));
                                }

                                #region Invocation handling
                                PageSizeAttribute pageSizeAttribute = null;
                                MethodInfo miCounter = null;
                                object[] pageSizeAttributes = mi.GetCustomAttributes(typeof(PageSizeAttribute), true);
                                if (pageSizeAttributes != null && pageSizeAttributes.Length == 1)
                                {
                                    pageSizeAttribute = pageSizeAttributes[0] as PageSizeAttribute;
                                    miCounter = instance.GetType().GetMethod(amfBody.Method + "Count");
                                    if (miCounter != null && miCounter.ReturnType != typeof(System.Int32))
                                        miCounter = null; //check signature
                                }
                                ParameterInfo[] parameterInfos = mi.GetParameters();
                                //Try to handle missing/optional parameters.
                                object[] args = new object[parameterInfos.Length];
                                if (!amfBody.IsRecordsetDelivery)
                                {
                                    if (args.Length != parameterList.Count)
                                    {
                                        string msg = __Res.GetString(__Res.Arg_Mismatch, parameterList.Count, mi.Name, args.Length);
                                        if (log != null && log.IsErrorEnabled)
                                            log.Error(msg);
                                        responseBody = new ErrorResponseBody(amfBody, new ArgumentException(msg));
                                        messageOutput.AddBody(responseBody);
                                        continue;
                                    }
                                    parameterList.CopyTo(args, 0);
                                    if (pageSizeAttribute != null)
                                    {
                                        PagingContext pagingContext = new PagingContext(pageSizeAttribute.Offset, pageSizeAttribute.Limit);
                                        PagingContext.SetPagingContext(pagingContext);
                                    }
                                }
                                else
                                {
                                    if (amfBody.Target.EndsWith(".release"))
                                    {
                                        responseBody = new ResponseBody(amfBody, null);
                                        messageOutput.AddBody(responseBody);
                                        continue;
                                    }
                                    string recordsetId = parameterList[0] as string;
                                    string recordetDeliveryParameters = amfBody.GetRecordsetArgs();
                                    byte[] buffer = System.Convert.FromBase64String(recordetDeliveryParameters);
                                    recordetDeliveryParameters = System.Text.Encoding.UTF8.GetString(buffer);
                                    if (recordetDeliveryParameters != null && recordetDeliveryParameters != string.Empty)
                                    {
                                        string[] stringParameters = recordetDeliveryParameters.Split(new char[] { ',' });
                                        for (int j = 0; j < stringParameters.Length; j++)
                                        {
                                            if (stringParameters[j] == string.Empty)
                                                args[j] = null;
                                            else
                                                args[j] = stringParameters[j];
                                        }
                                        //TypeHelper.NarrowValues(argsStore, parameterInfos);
                                    }
                                    PagingContext pagingContext = new PagingContext(System.Convert.ToInt32(parameterList[1]), System.Convert.ToInt32(parameterList[2]));
                                    PagingContext.SetPagingContext(pagingContext);
                                }

                                TypeHelper.NarrowValues(args, parameterInfos);

                                try
                                {
                                    InvocationHandler invocationHandler = new InvocationHandler(mi);
                                    object result = invocationHandler.Invoke(instance, args);

                                    if (FluorineConfiguration.Instance.CacheMap != null && FluorineConfiguration.Instance.CacheMap.ContainsCacheDescriptor(source))
                                    {
                                        //The result should be cached
                                        CacheableObject cacheableObject = new CacheableObject(source, key, result);
                                        FluorineConfiguration.Instance.CacheMap.Add(cacheableObject.Source, cacheableObject.CacheKey, cacheableObject);
                                        result = cacheableObject;
                                    }
                                    responseBody = new ResponseBody(amfBody, result);

                                    if (pageSizeAttribute != null)
                                    {
                                        int totalCount = 0;
                                        string recordsetId = null;

                                        IList list = amfBody.GetParameterList();
                                        string recordetDeliveryParameters = null;
                                        if (!amfBody.IsRecordsetDelivery)
                                        {
                                            //fist call paging
                                            object[] argsStore = new object[list.Count];
                                            list.CopyTo(argsStore, 0);
                                            recordsetId = System.Guid.NewGuid().ToString();
                                            if (miCounter != null)
                                            {
                                                //object[] counterArgs = new object[0];
                                                totalCount = (int)miCounter.Invoke(instance, args);
                                            }
                                            string[] stringParameters = new string[argsStore.Length];
                                            for (int j = 0; j < argsStore.Length; j++)
                                            {
                                                if (argsStore[j] != null)
                                                    stringParameters[j] = argsStore[j].ToString();
                                                else
                                                    stringParameters[j] = string.Empty;
                                            }
                                            recordetDeliveryParameters = string.Join(",", stringParameters);
                                            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(recordetDeliveryParameters);
                                            recordetDeliveryParameters = System.Convert.ToBase64String(buffer);
                                        }
                                        else
                                        {
                                            recordsetId = amfBody.GetParameterList()[0] as string;
                                        }
                                        if (result is DataTable)
                                        {
                                            DataTable dataTable = result as DataTable;
                                            dataTable.ExtendedProperties["TotalCount"] = totalCount;
                                            dataTable.ExtendedProperties["Service"] = recordetDeliveryParameters + "/" + amfBody.Target;
                                            dataTable.ExtendedProperties["RecordsetId"] = recordsetId;
                                            if (amfBody.IsRecordsetDelivery)
                                            {
                                                dataTable.ExtendedProperties["Cursor"] = Convert.ToInt32(list[list.Count - 2]);
                                                dataTable.ExtendedProperties["DynamicPage"] = true;
                                            }
                                        }
                                    }
                                }
                                catch (UnauthorizedAccessException exception)
                                {
                                    responseBody = new ErrorResponseBody(amfBody, exception);
                                    if (log.IsDebugEnabled)
                                        log.Debug(exception.Message);
                                }
                                catch (Exception exception)
                                {
                                    if (exception is TargetInvocationException && exception.InnerException != null)
                                        responseBody = new ErrorResponseBody(amfBody, exception.InnerException);
                                    else
                                        responseBody = new ErrorResponseBody(amfBody, exception);
                                    if (log.IsDebugEnabled)
                                        log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.Message));
                                }
                                #endregion Invocation handling
                            }
                            else
                                responseBody = new ErrorResponseBody(amfBody, new MissingMethodException(amfBody.TypeName, amfBody.Method));
                        }
                        finally
                        {
                            factoryInstance.OnOperationComplete(instance);
                        }
                    }
                    else
                        responseBody = new ErrorResponseBody(amfBody, new TypeInitializationException(amfBody.TypeName, null));
                }
			    catch(Exception exception)
			    {
					if( log != null && log.IsErrorEnabled )
                        log.Error(exception.Message, exception);
				    responseBody = new ErrorResponseBody(amfBody, exception);
			    }
				messageOutput.AddBody(responseBody);
			}
		}
		public bool Invoke(IServiceCall call, object service)
		{
            string serviceMethod = call.ServiceMethodName;
            object[] arguments = call.Arguments;

            // First, search for method with exact parameter type match
            MethodInfo mi = MethodHandler.GetMethod(service.GetType(), serviceMethod, arguments, true, false, false);
            if (mi == null)
            {
                // Second, search for method with type conversions
                // This second call will trace 'suitable method' errors too
                mi = MethodHandler.GetMethod(service.GetType(), serviceMethod, arguments, false, false, true);
                if (mi == null)
                {
                    string msg = __Res.GetString(__Res.Invocation_NoSuitableMethod, serviceMethod);
                    call.Status = Call.STATUS_METHOD_NOT_FOUND;
                    call.Exception = new FluorineException(msg);
                    return false;
                }
            }

            try
            {
                ParameterInfo[] parameterInfos = mi.GetParameters();
                object[] parameters = new object[parameterInfos.Length];
                arguments.CopyTo(parameters, 0);
                TypeHelper.NarrowValues(parameters, parameterInfos);

                object result = null;
                if (mi.ReturnType == typeof(void))
                {
                    InvocationHandler invocationHandler = new InvocationHandler(mi);
                    invocationHandler.Invoke(service, parameters);
                    call.Status = Call.STATUS_SUCCESS_VOID;
                }
                else
                {
                    InvocationHandler invocationHandler = new InvocationHandler(mi);
                    result = invocationHandler.Invoke(service, parameters);
                    call.Status = result == null ? Call.STATUS_SUCCESS_NULL : Call.STATUS_SUCCESS_RESULT;
                }
                if (call is IPendingServiceCall)
                    (call as IPendingServiceCall).Result = result;
            }
            catch (SecurityException exception)
            {
                call.Exception = exception;
                call.Status = Call.STATUS_ACCESS_DENIED;
                if (log.IsDebugEnabled)
                    log.Debug(exception.Message);
                return false;
            }
            catch (UnauthorizedAccessException exception)
            {
                call.Exception = exception;
                call.Status = Call.STATUS_ACCESS_DENIED;
                if (log.IsDebugEnabled)
                    log.Debug(exception.Message);
                return false;
            }
            catch (TargetInvocationException exception)
            {
                call.Exception = exception.InnerException;
                call.Status = Call.STATUS_INVOCATION_EXCEPTION;
                if (log.IsDebugEnabled)
                    log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.InnerException.Message));
                return false;
            }
            catch (Exception exception)
            {
                call.Exception = exception;
                call.Status = Call.STATUS_GENERAL_EXCEPTION;
                if (log.IsDebugEnabled)
                    log.Debug(__Res.GetString(__Res.Invocation_Failed, mi.Name, exception.Message));
                return false;
            }
            return true;
		}