예제 #1
0
        public void By_CacheableObject_ShouldBeCacheKeyString()
        {
            const int    number = 5;
            const string text   = "test";
            var          obj    = new CacheableObject(number, text);
            var          key    = _cacheKeyBuilder.By(obj).ToString();

            key.Should().Be(CacheKeyHelper.Format(number) + CacheKeyHelper.Format(text));
        }
        protected override void DoInsert(object key, object value, TimeSpan timeToLive)
        {
            string coKey = GetCachableKey(key);

            if (value.GetType().IsSerializable == false)
            {
                throw new ArgumentException(String.Format("The value type [{0}] is not Serializable", value.GetType()));
            }

            CacheableObject coValue = CacheableObject.Create(value);

            region.Put(coKey, coValue);
        }
        public override object Get(object key)
        {
            string          cachableKey    = GetCachableKey(key);
            IGFSerializable cacheableValue = region.Get(cachableKey);

            if (cacheableValue == null)
            {
                return(null);
            }

            CacheableObject cacheableObject = cacheableValue as CacheableObject;

            if (cacheableObject != null)
            {
                return(cacheableObject.Value);
            }
            throw new ArgumentException(String.Format("The value type [{0}] is not CacheableObject", cacheableValue.GetType()));
        }
예제 #4
0
        /// <summary>
        /// Removes a link to an entity in the container and sets the entity's parent to null
        /// </summary>
        /// <param name="id">The ID of the entity to unlink</param>
        /// <param name="entity">A reference to the entity to be removed for event subscription purposes</param>
        /// <param name="updatePersistence">Whether to update persistence cache</param>
        /// <remarks>This method removes an entity and unsubscribes from cache removal notifications.</remarks>
        private void RemoveEntity(uint?id, CacheableObject entity, bool updatePersistence)
        {
            if (id == null)
            {
                return;
            }

            _entityList.Remove((uint)id);
            OnEntityRemoved(new CacheObjectEventArgs((uint)id, CacheType));

            if (entity != null)
            {
                if (CacheType == CacheType.Instance)
                {
                    entity.InstanceParent = null;
                }
                else
                {
                    entity.PrototypeParents.Remove((uint)Prototype);
                }

                entity.CacheObjectRemoved -= OnCacheObjectRemoved;

                // TODO: Is this needed? The save checks seem odd -- if it's prototype, it should always be saved when changed.
                // Always persist target entity to disk since the data structure has changed
                if (CacheType == CacheType.Prototype)
                {
                    DataPersistence.SaveObject(entity);
                }
            }

            // Persist this entity to disk (if requested) since the data structure has changed
            if (CacheType == CacheType.Prototype && updatePersistence)
            {
                DataPersistence.SaveObject(this);
            }
        }
        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           = FluorineFx.Configuration.CacheMap.GenerateCacheKey(source, parameterList);
                    if (FluorineConfiguration.Instance.CacheMap.ContainsValue(key))
                    {
                        object result = FluorineFx.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;
                        }
                    }

                    object          instance;
                    FactoryInstance factoryInstance = destination.GetFactoryInstance();
                    lock (factoryInstance)
                    {
                        factoryInstance.Source = amfBody.TypeName;
                        if (FluorineContext.Current.ActivationMode != null)//query string can override the activation mode
                        {
                            factoryInstance.Scope = FluorineContext.Current.ActivationMode;
                        }
                        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, parameterList);
                            }
                            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 + String.Format(" (Type: {0}, Method: {1})", amfBody.TypeName, amfBody.Method), exception);
                    }
                    responseBody = new ErrorResponseBody(amfBody, exception);
                }
                messageOutput.AddBody(responseBody);
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
 /// <summary>
 /// Removes a link to an entity in the container and sets the entity's parent to null.
 /// </summary>
 /// <param name="id">The ID of the entity to unlink</param>
 /// <param name="entity">A reference to the entity to be removed for event subscription purposes</param>
 /// <remarks>This method removes an entity and unsubscribes from cache removal notifications.</remarks>
 public void RemoveEntity(uint?id, CacheableObject entity)
 {
     RemoveEntity(id, entity, true);
 }
예제 #8
0
 public void PushCacheableObject(CacheableObject obj)
 {
     obj.Reset();
     if (_objects.Count >= _maxSize) return;
     _objects.Enqueue(obj);
 }
예제 #9
0
        public override object Invoke(IMessage message)
        {
            object           obj2 = null;
            string           str3;
            MessageException innerException;
            RemotingMessage  message2     = message as RemotingMessage;
            string           operation    = message2.operation;
            string           fullTypeName = base.DestinationSettings.Properties["source"] as string;

            if ((message2.source != null) && (message2.source != string.Empty))
            {
                if (fullTypeName == "*")
                {
                    fullTypeName = message2.source;
                }
                if (fullTypeName != message2.source)
                {
                    str3 = __Res.GetString("Type_MismatchMissingSource", new object[] { message2.source, base.DestinationSettings.Properties["source"] as string });
                    throw new MessageException(str3, new TypeLoadException(str3));
                }
            }
            if (fullTypeName == null)
            {
                throw new TypeInitializationException("null", null);
            }
            string source   = fullTypeName + "." + operation;
            IList  body     = message2.body as IList;
            string cacheKey = CacheMap.GenerateCacheKey(source, body);

            if (FluorineConfiguration.Instance.CacheMap.ContainsValue(cacheKey))
            {
                obj2 = FluorineConfiguration.Instance.CacheMap.Get(cacheKey);
                if (obj2 != null)
                {
                    if ((log != null) && log.get_IsDebugEnabled())
                    {
                        log.Debug(__Res.GetString("Cache_HitKey", new object[] { operation, cacheKey }));
                    }
                    return(obj2);
                }
            }
            FactoryInstance factoryInstance = base.Destination.GetFactoryInstance();

            factoryInstance.Source = fullTypeName;
            object obj3 = factoryInstance.Lookup();

            if (obj3 == null)
            {
                throw new MessageException(new TypeInitializationException(fullTypeName, null));
            }
            Type type = obj3.GetType();

            if (!TypeHelper.GetTypeIsAccessible(type))
            {
                str3 = __Res.GetString("Type_InitError", new object[] { type.FullName });
                throw new MessageException(str3, new TypeLoadException(str3));
            }
            try
            {
                MethodInfo methodInfo = MethodHandler.GetMethod(type, operation, body);
                if (methodInfo == null)
                {
                    throw new MessageException(new MissingMethodException(fullTypeName, operation));
                }
                object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RoleAttribute), true);
                if ((customAttributes != null) && (customAttributes.Length == 1))
                {
                    RoleAttribute attribute = customAttributes[0] as RoleAttribute;
                    string[]      roles     = attribute.Roles.Split(new char[] { ',' });
                    if (!base.Destination.Service.DoAuthorization(roles))
                    {
                        throw new UnauthorizedAccessException(__Res.GetString("Security_AccessNotAllowed"));
                    }
                }
                ParameterInfo[] parameters = methodInfo.GetParameters();
                object[]        array      = new object[parameters.Length];
                body.CopyTo(array, 0);
                TypeHelper.NarrowValues(array, parameters);
                obj2 = new InvocationHandler(methodInfo).Invoke(obj3, array);
            }
            catch (TargetInvocationException exception)
            {
                innerException = null;
                if (exception.InnerException is MessageException)
                {
                    innerException = exception.InnerException as MessageException;
                }
                else
                {
                    innerException = new MessageException(exception.InnerException);
                }
                throw innerException;
            }
            catch (Exception exception3)
            {
                innerException = new MessageException(exception3);
                throw innerException;
            }
            if ((FluorineConfiguration.Instance.CacheMap != null) && FluorineConfiguration.Instance.CacheMap.ContainsCacheDescriptor(source))
            {
                CacheableObject obj4 = new CacheableObject(source, cacheKey, obj2);
                FluorineConfiguration.Instance.CacheMap.Add(obj4.Source, obj4.CacheKey, obj4);
                obj2 = obj4;
            }
            return(obj2);
        }
예제 #10
0
        public static void Run()
        {
            int initialVSyncSetting = 0;

            try {
                initialVSyncSetting = GL.GetBufferSwapInterval();
                GameConfig.Load();

                GameDebugger.EngineLog(LogLevel.Debug, "Running application specific configuration event handlers");
                if (ConfigureEvent != null)
                {
                    ConfigureEvent();
                }

                GameDebugger.EngineLog(LogLevel.Debug, "Opening display device '{0}'", GameConfig.DisplayDevice);
                IDisplayDevice cur_dev = API.GetDisplayDevice(GameConfig.DisplayDevice);
                // GameDebugger.Log("Primary display device {0}", cur_dev.ToString());
                if (GameConfig.DisplayDevice != null && !GameConfig.DisplayDevice.Equals(cur_dev.Id))
                {
                    GameConfig.DisplayDevice = null;                     // needed to save a "primary display device" setting since the one in config was not found
                }
                List <IMonitor> monitors = cur_dev.GetMonitors();
                if (monitors == null || monitors.Count == 0)
                {
                    throw new UserFriendlyException("No monitors could be found on the selected device. Could there be a bug somewhere?", "Failed initializing graphics");
                }
                IMonitor first_monitor = monitors[0];
                // foreach( Rectangle mon in monitors )
                //	GameDebugger.Log("\tMonitor at {0}", mon.ToString());

                // Thanks to someone in Microsoft determining current refresh rate and bits per pixel of a monitor is quite a pain in the ass
                int current_width        = first_monitor.Width;
                int current_height       = first_monitor.Height;
                int current_bpp          = first_monitor.BitsPerPixel;
                int current_refresh_rate = first_monitor.RefreshRate;

                int cfg_width        = (GameConfig.ResX <= 0 || GameConfig.ResY <= 0) ? current_width : GameConfig.ResX;
                int cfg_height       = (GameConfig.ResX <= 0 || GameConfig.ResY <= 0) ? current_height : GameConfig.ResY;
                int cfg_bpp          = (GameConfig.BitsPerPixel <= 0) ? current_bpp : GameConfig.BitsPerPixel;
                int cfg_refresh_rate = (GameConfig.RefreshRate <= 0) ? current_refresh_rate : GameConfig.RefreshRate;

                // GameDebugger.Log("Searching for {0}bit {1}x{2} @{3}", GameConfig.BitsPerPixel, GameConfig.ResX, GameConfig.ResY, GameConfig.RefreshRate);

                if (GameConfig.FullScreen)
                {
                    List <IDisplayMode> modes = cur_dev.GetModes();
                    if (modes == null || modes.Count == 0)
                    {
                        throw new Exception(String.Format("Device {0} is invalid and has no modes suitable for graphics", cur_dev.ToString()));
                    }

                    IDisplayMode selected_mode = null;
                    foreach (IDisplayMode mode in modes)
                    {
                        // GameDebugger.Log("\t{0}", mode.ToString()); // Uncomment this to log all supported video modes for the chosen display device
                        if (cfg_width == mode.Width &&
                            cfg_height == mode.Height &&
                            cfg_bpp == mode.BitsPerPixel &&
                            cfg_refresh_rate == mode.RefreshRate)
                        {
                            selected_mode = mode;
                            // GameDebugger.Log("Selected mode: {0}", selected_mode.ToString());
                            //break;
                        }
                    }

                    if (selected_mode == null)
                    {
                        // in case the mode in the config is specified incorrectly we try to use current screen settings. also reset config so later it won't try this bothersome thing
                        GameConfig.ResX         = -1;
                        GameConfig.ResY         = -1;
                        GameConfig.BitsPerPixel = -1;
                        GameConfig.RefreshRate  = -1;
                        foreach (IDisplayMode mode in modes)
                        {
                            //GameDebugger.Log("\t{0}", mode.ToString());
                            if (current_width == mode.Width &&
                                current_height == mode.Height &&
                                current_bpp == mode.BitsPerPixel &&
                                current_refresh_rate == mode.RefreshRate)
                            {
                                selected_mode = mode;
                                break;
                            }
                        }
                    }

                    if (selected_mode == null)
                    {
                        // this should not happen but still ... if no current resolution we deperately search for any 1024x768x32 mode (should be present on all computers by now)
                        foreach (IDisplayMode mode in modes)
                        {
                            //GameDebugger.Log("\t{0}", mode.ToString());
                            if (1024 == mode.Width &&
                                768 == mode.Height &&
                                32 == mode.BitsPerPixel)
                            {
                                selected_mode = mode;
                                break;
                            }
                        }
                    }

                    //
                    if (selected_mode == null)
                    {
                        // OMG this is totally f****d up! just pick out the first one :|
                        selected_mode = modes[0];
                    }

                    if (selected_mode.Width != current_width ||
                        selected_mode.Height != current_height ||
                        selected_mode.BitsPerPixel != current_bpp ||
                        selected_mode.RefreshRate != current_refresh_rate)
                    {
                        // TODO: add support for non full screen modes
                        if (selected_mode.Set(true))
                        {
                            current_width        = selected_mode.Width;
                            current_height       = selected_mode.Height;
                            current_bpp          = selected_mode.BitsPerPixel;
                            current_refresh_rate = selected_mode.RefreshRate;
                        }

                        // After changing resolution monitor positions will change so we have to read them again!
                        monitors = cur_dev.GetMonitors();
                        if (monitors == null || monitors.Count == 0)
                        {
                            throw new Exception("No monitors could be found on the selected device. Could there be a bug somewhere?");
                        }
                        first_monitor = monitors[0];
                    }
                }
                else
                {
                    Size2 size = API.AdjustWindowSize(cfg_width, cfg_height);
                    current_width  = size.Width;
                    current_height = size.Height;
                }

                // GameDebugger.Log("{0},{1}-{2},{3}", first_monitor.X, first_monitor.Y, current_width, current_height);

                using (IOpenGLWindow window = GL.CreateWindow(null, first_monitor.X, first_monitor.Y, current_width, current_height)) {
                    m_Window = window;
                    window.BeforeRenderFrameEvent += OnBeforeFrame;
                    window.RenderFrameEvent       += OnFrame;
                    window.AfterRenderFrameEvent  += OnAfterFrame;
                    window.ResizeEvent            += OnResize;

                    m_Keyboard = IL.FirstKeyboardDevice;

                    Mouse         = IL.FirstMouseDevice;
                    Mouse.Window  = window;                    // mouse must be attached to window before showing since it watches move and resize events
                    Mouse.Visible = GameConfig.ShowHardwareCursor;
                    Mouse.Clipped = GameConfig.ClipMouseCursor;

                    window.Show();

                    GL.SetBufferSwapInterval(GameConfig.VSync ? 1 : 0);
                    GameConfig.VSyncChangedEvent += OnVSyncSettingChanged;

                    OnLoad();
                    if (LoadEvent != null)
                    {
                        LoadEvent();
                    }
                    // GameDebugger.Log("Running main loop at last");
                    Application.Run();
                    // GameDebugger.Log("ByeBye!");
                }
            }

            catch (Exception ex) {
                GameDebugger.EngineLog(LogLevel.Error, "IGE or application has crashed!");
                GameDebugger.EngineLog(LogLevel.Error, ex);
            }

            finally {
                try {
                    CacheableObject.DisposeAll();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE automatic resource unloading has crashed!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try {
                    if (UnloadEvent != null)
                    {
                        UnloadEvent();
                    }
                }
                catch (Exception ex) {
                    GameDebugger.Log(LogLevel.Error, "Application has crashed on UnloadEvent!");
                    GameDebugger.Log(LogLevel.Error, ex);
                }

                try {
                    OnUnload();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE final unloading has crashed!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try {
                    GameConfig.Save();
                }
                catch (Exception ex) {
                    GameDebugger.EngineLog(LogLevel.Error, "IGE could not automatically save the configuration!");
                    GameDebugger.EngineLog(LogLevel.Error, ex);
                }

                try { GameConfig.VSyncChangedEvent -= OnVSyncSettingChanged; } catch {}

                GL.SetBufferSwapInterval(initialVSyncSetting);
                m_Window = null;
            }
        }