From 5b8c95c760840f09910730943b21391e47187315 Mon Sep 17 00:00:00 2001
From: hefeixia <593428420@qq.com>
Date: 星期四, 18 二月 2021 20:41:02 +0800
Subject: [PATCH] IM服务端

---
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyReader.class                            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/jna-platform-4.5.2.jar                                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDispatcher.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContent.class                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/Json.jar                                                                |    0 
 IMserver/medeasy/src/chat/module/entity/FriendShip.java                                                      |  125 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultItem.class                                   |    0 
 IMserver/medeasy/src/chat/server/call/MethodPublisher.java                                                   |   70 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/DTDResolver.class                                       |    0 
 IMserver/medeasy/src/chat/user/UserStore.java                                                                |  282 
 IMserver/medeasy/src/frame/persist/DataBaseType.java                                                         |   29 
 IMserver/medeasy/src/chat/server/netty/NettyHttpChannelInitializer.java                                      |   33 
 IMserver/medeasy/src/frame/variant/translator/DoubleTranslator.java                                          |  144 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SensitiveHandler.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/commons-codec-1.13.jar                                                  |    0 
 IMserver/medeasy/src/chat/module/entity/PrivateFriend.java                                                   |  129 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLLoader.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/jedis-3.3.0.jar                                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Node.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/UserStore.class                                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-buffer-4.1.12.Final.jar                                           |    0 
 IMserver/medeasy/src/chat/server/call/JSONObject.java                                                        |  164 
 IMserver/medeasy/src/frame/object/reader/EntityReaderContainer.java                                          |   74 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJsonProvider.class                                |    0 
 IMserver/medeasy/src/frame/variant/translator/DateTranslator.java                                            |  147 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChannelBucket.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckMessage.class                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/MessageShardingUtil.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Entity.class                                      |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttDispatcher.java                                                |  249 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializerContainer.class                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantParser.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/DataLoader.class                               |    0 
 IMserver/medeasy/src/frame/variant/expression/GlobalVariant.java                                             |  132 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PrivateFriend.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$Result.class                  |    0 
 IMserver/medeasy/src/chat/server/call/MultiCounter.java                                                      |   10 
 IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubAckMessage.java                                   |   14 
 IMserver/medeasy/src/chat/module/entity/FriendshipStatus.java                                                |   12 
 IMserver/medeasy/src/chat/server/call/CallObject.java                                                        |   71 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/APIPath.class                                           |    0 
 IMserver/medeasy/src/frame/persist/Result.java                                                               |   81 
 IMserver/medeasy/src/chat/server/netty/ByteBufToWebSocketFrameEncoder.java                                   |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChatroomState.class                      |    0 
 IMserver/medeasy/src/chat/module/entity/Group.java                                                           |  229 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageRunner.class                                    |    0 
 IMserver/medeasy/src/chat/message/MessageRunner.java                                                         |   61 
 IMserver/medeasy/src/frame/object/data/EntityTree.java                                                       |   95 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SystemSettingType.class                  |    0 
 IMserver/medeasy/src/chat/server/moquette/BytesMetricsCollector.java                                         |   24 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataSet.class                                 |    0 
 IMserver/medeasy/src/chat/handler/FriendshipHandler.java                                                     |  103 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IDoubleSavable.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantParseListener.class                |    0 
 IMserver/medeasy/src/chat/upload/UploadFile.java                                                             |  274 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Result.class                                          |    0 
 IMserver/medeasy/src/chat/message/MessageServer.java                                                         |   50 
 IMserver/medeasy/src/chat/handler/ChatRoomHandler.java                                                       |  216 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubAckMessage.class              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/RelationshipBucket.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Status.class                                              |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttMessageLoggerHandler.java                                      |   90 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdleTimeoutHandler.class                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/Callback.class                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLBuilder.class                                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/GUID.class                                               |    0 
 IMserver/medeasy/src/chat/server/netty/NettySSLChannelInitializer.java                                       |   59 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterSegment.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PublishOperator.class                            |    0 
 IMserver/medeasy/.settings/org.eclipse.jdt.core.prefs                                                        |    7 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISavable.class                                        |    0 
 IMserver/medeasy/src/frame/object/meta/MetaFieldReader.java                                                  |   87 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/medeasy/HttpClientUtil.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/UserMessageList.class                                   |    0 
 IMserver/medeasy/src/frame/persist/DBDate.java                                                               |   46 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DatasuorceLoader.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContextListener.class                                   |    0 
 IMserver/medeasy/src/frame/variant/IVariantsConsumer.java                                                    |   17 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance$MessagePos.class                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageType.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/ContentBuilder.class                                     |    0 
 IMserver/medeasy/src/chat/tools/Utils.java                                                                   |   26 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/SendMessageCallback.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/c3p0-0.9.5.4.jar                                                        |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttTopicSubscription.java                                 |   32 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLContainer.class                               |    0 
 IMserver/medeasy/src/chat/user/Notify.java                                                                   |  185 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterItem.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Group.class                                      |    0 
 IMserver/medeasy/src/frame/persist/SQLVariant.java                                                           |   29 
 IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.name                                            |    1 
 IMserver/medeasy/WebRoot/WEB-INF/config/sqllist.dtd                                                          |   20 
 IMserver/medeasy/WebRoot/WEB-INF/config/config.xml                                                           |   76 
 IMserver/medeasy/WebRoot/WEB-INF/web.xml                                                                     |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Session.class                                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-cache-4.5.13.jar                                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializer.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/druid-0.2.18.jar                                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/DES.class                                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckVariableHeader.class        |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttMessage.java                                           |   64 
 IMserver/medeasy/src/chat/security/AES.java                                                                  |  165 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-win-4.5.13.jar                                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectPropertyRecorder.class                    |    0 
 IMserver/medeasy/src/chat/module/UserMessageList.java                                                        |   33 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DateTranslator.class                       |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnectMessage.java                                    |   19 
 IMserver/medeasy/src/chat/server/moquette/message/ModifiedMqttPubAckMessage.java                             |   15 
 IMserver/medeasy/src/chat/module/friendcircle/Forward.java                                                   |   34 
 IMserver/medeasy/src/frame/variant/expression/IVariantParseListener.java                                     |    9 
 IMserver/medeasy/src/frame/object/reader/EntityReader.java                                                   |   76 
 IMserver/medeasy/src/frame/variant/IVariantsProvider.java                                                    |   13 
 IMserver/medeasy/src/frame/object/reader/ObjectPropertyRecorder.java                                         |  103 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObject.class                                  |    0 
 IMserver/medeasy/config/i18n/messages_zh.properties                                                          |    2 
 IMserver/medeasy/src/chat/server/Test.java                                                                   |   23 
 IMserver/medeasy/src/frame/object/data/DataObjectContainer.java                                              |   46 
 IMserver/medeasy/src/chat/server/moquette/MqttIdentifierRejectedException.java                               |   53 
 IMserver/medeasy/src/frame/object/data/EntityInitializerContainer.java                                       |   10 
 IMserver/medeasy/src/chat/user/Client.java                                                                   |  125 
 IMserver/medeasy/src/frame/object/meta/MetaDirection.java                                                    |    7 
 IMserver/medeasy/config/i18n/messages.properties                                                             |    3 
 IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckPayload.java                                     |   52 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/RobotHandler.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Token.class                                               |    0 
 IMserver/medeasy/src/frame/object/dao/MethodPublisher.java                                                   |   54 
 IMserver/medeasy/src/frame/variant/NameValuePair.java                                                        |   36 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult$RestCode.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultOutputType.class                             |    0 
 IMserver/medeasy/src/chat/module/RelationshipBucket.java                                                     |   38 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttEncodHandler.class                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/redis/RedisUtil.class                                          |    0 
 IMserver/medeasy/src/chat/module/friendcircle/FriendCircleLoader.java                                        |    6 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BooleanTranslator.class                    |    0 
 IMserver/medeasy/src/chat/user/ClientStore.java                                                              |  147 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckMessage.class               |    0 
 IMserver/medeasy/src/chat/consts/ProtoConstants.java                                                         |  188 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLCreator.class                                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/protobuf-java-2.5.0.jar                                                 |    0 
 IMserver/medeasy/src/frame/variant/translator/BooleanTranslator.java                                         |  141 
 IMserver/medeasy/src/frame/object/data/Index.java                                                            |   57 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultMetaFieldReader.class                    |    0 
 IMserver/medeasy/src/chat/handler/ClientHandler.java                                                         |  906 +
 IMserver/medeasy/WebRoot/WEB-INF/lib/fastjson-1.2.46.jar                                                     |    0 
 IMserver/medeasy/src/chat/user/NotifyContent.java                                                            |   24 
 IMserver/medeasy/src/frame/object/data/DataObject.java                                                       |  128 
 IMserver/medeasy/.settings/org.eclipse.core.resources.prefs                                                  |    3 
 IMserver/medeasy/src/chat/message/SendMessageCallback.java                                                   |   25 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Test.class                                              |    0 
 IMserver/medeasy/src/chat/module/ModuleLoader.java                                                           |  361 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/RequestType.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReaderContainer.class                     |    0 
 IMserver/medeasy/src/frame/object/meta/MetadataMeta.java                                                     |   11 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageLoggerHandler.class                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapList.class                                            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/PropertyIterator.class                                |    0 
 IMserver/medeasy/src/chat/module/entity/FriendRequest.java                                                   |   48 
 IMserver/medeasy/src/frame/variant/translator/Translator.java                                                |  312 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/User.class                                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ValueLoader.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/FriendRequstBucket.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/Metrics.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/sql.dtd                                                              |   24 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Channel.class                                    |    0 
 IMserver/medeasy/src/frame/object/meta/EntityMetaLoader.java                                                 |   40 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChatroomBucket.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/Value.class                                           |    0 
 IMserver/medeasy/src/frame/persist/DataSourceManager.java                                                    |   83 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapTree.class                                            |    0 
 IMserver/medeasy/src/frame/object/data/EntityInitializer.java                                                |   42 
 IMserver/medeasy/src/chat/consts/BrokerConstants.java                                                        |  149 
 IMserver/medeasy/src/frame/variant/expression/VariantExistsException.java                                    |   11 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContentDetail.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContainerIterator.class                                 |    0 
 IMserver/medeasy/src/frame/object/dao/Page.java                                                              |  197 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyAcceptor.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-handler-4.1.12.Final.jar                                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant$GlobalVariantProvider.class  |    0 
 IMserver/medeasy/src/chat/module/friendcircle/CommentList.java                                               |   42 
 IMserver/medeasy/src/chat/redis/RedisUtil.java                                                               |   24 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/MapReader.class                                 |    0 
 IMserver/medeasy/src/frame/object/meta/IFieldReader.java                                                     |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/ValueType.class                                       |    0 
 IMserver/medeasy/src/chat/sms/SmsService.java                                                                |   57 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ClientStore.class                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/BytesSelfUtil.class                                       |    0 
 IMserver/medeasy/src/chat/server/ContextListener.java                                                        |   28 
 IMserver/medeasy/src/chat/server/call/ResultOutputType.java                                                  |    7 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckVariableHeader.java                             |   33 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ConversationType.class                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJSONWriter.class                                  |    0 
 IMserver/medeasy/src/chat/handler/GroupHandler.java                                                          |  368 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyTCPChannelInitializer.class                  |    0 
 IMserver/medeasy/src/frame/object/reader/NameValuePair.java                                                  |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckPayload.class                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/WebSocketFrameToByteBufDecoder.class              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PersistFlag.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityClassFactory.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-2.15.11.jar                                                      |    0 
 IMserver/medeasy/src/chat/server/call/IJSONWriter.java                                                       |   65 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Doctor.class                                              |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttMessageMetricsHandler.java                                     |   72 
 IMserver/medeasy/src/chat/server/moquette/message/MqttMessageFactory.java                                    |   70 
 IMserver/medeasy/src/frame/persist/ISavable.java                                                             |   10 
 IMserver/medeasy/src/chat/handler/SystemHandler.java                                                         |  236 
 IMserver/medeasy/src/chat/module/entity/PublishOperator.java                                                 |    8 
 IMserver/medeasy/src/frame/object/meta/EntityMeta.java                                                       |  196 
 IMserver/medeasy/src/frame/persist/NamedSQL.java                                                             |  530 +
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/NameValuePair.class                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MessageMetricsCollector.class                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageMetricsHandler.class                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataMeta.class                                |    0 
 IMserver/medeasy/src/frame/object/data/DataException.java                                                    |   18 
 IMserver/medeasy/src/chat/server/ServerInstance.java                                                         |  145 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$FriendRequestStatus.class                |    0 
 IMserver/medeasy/src/frame/object/data/IIndex.java                                                           |   10 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IMetaDataLoader.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/AES.class                                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/MessageHandler.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChatRoomHandler.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/commons-httpclient-3.1.jar                                              |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttPublishMessage.java                                    |   99 
 IMserver/medeasy/src/chat/user/NotifySubject.java                                                            |   43 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SystemHandler.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribePayload.class           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Notify.class                                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CachedJSONWriter.class                             |    0 
 IMserver/medeasy/src/frame/object/data/ObjectList.java                                                       |   45 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribeMessage.class           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Filter.class                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ManagerNotifyHandler.class                             |    0 
 IMserver/medeasy/src/frame/variant/expression/Segment.java                                                   |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObject.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ILoader.class                                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/timer.properties                                                     |   20 
 IMserver/medeasy/src/frame/object/dao/OrderBy.java                                                           |   53 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/OrderBy.class                                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-epoll-4.1.12.Final-linux-x86_64.jar              |    0 
 IMserver/medeasy/src/chat/handler/ManagerNotifyHandler.java                                                  |   41 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntitySetLoader.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/ByteBufToWebSocketFrameEncoder.class              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendshipHandler.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedDataSource.class                                 |    0 
 IMserver/medeasy/src/chat/server/netty/WebSocketFrameToByteBufDecoder.java                                   |   20 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IMetaDataLoader.class                             |    0 
 IMserver/medeasy/src/chat/util/I18n.java                                                                     |   82 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/GroupType.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService$AliyunCommonResponse.class                      |    0 
 IMserver/medeasy/src/chat/module/friendcircle/CircleObject.java                                              |  239 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyGroupInfoType.class                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettySSLChannelInitializer.class                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ID.class                                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/datasource.dtd                                                       |   27 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CircleObject.class                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/SpinLock.class                                            |    0 
 IMserver/medeasy/src/chat/util/SpinLock.java                                                                 |   21 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persistence/MemoryMessagesStore.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/NameValuePair.class                                   |    0 
 IMserver/medeasy/src/chat/module/Bucket.java                                                                 |  249 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/Translator.class                           |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttQoS.java                                               |   29 
 IMserver/medeasy/src/frame/object/reader/CollectionReader.java                                               |  120 
 IMserver/medeasy/src/frame/variant/expression/VariantContext.java                                            |   70 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler.class                         |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnectPayload.java                                    |   58 
 IMserver/medeasy/src/frame/persist/ISQLContext.java                                                          |    8 
 IMserver/medeasy/src/chat/user/Status.java                                                                   |    5 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Container.class                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyHttpChannelInitializer.class                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessagesPublisher.class                                |    0 
 IMserver/medeasy/src/chat/module/entity/MessageContainer.java                                                |  579 +
 IMserver/medeasy/src/frame/object/meta/MetadataSet.java                                                      |   15 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ConfigerLoader.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyStore.class                                         |    0 
 IMserver/medeasy/src/chat/server/im/OperateTable.java                                                        |  224 
 IMserver/medeasy/src/frame/object/data/Indexes.java                                                          |   61 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectReturnCode.class            |    0 
 IMserver/medeasy/src/chat/handler/SensitiveHandler.java                                                      |   13 
 IMserver/medeasy/src/frame/object/reader/MapReader.java                                                      |  131 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantContext.class                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMTopic.class                                        |    0 
 IMserver/medeasy/src/chat/sms/Aaa.java                                                                       |   25 
 IMserver/medeasy/src/frame/persist/SQLBuilder.java                                                           |  104 
 IMserver/medeasy/src/frame/util/MapTree.java                                                                 |  105 
 IMserver/medeasy/src/chat/server/netty/NettyTCPChannelInitializer.java                                       |   61 
 IMserver/medeasy/WebRoot/WEB-INF/config/job.xml                                                              |   12 
 IMserver/medeasy/.settings/org.eclipse.wst.common.component                                                  |    8 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsProvider.class                               |    0 
 IMserver/medeasy/src/chat/handler/MessageHandler.java                                                        |   13 
 IMserver/medeasy/.classpath                                                                                  |   25 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ConcurrentMapList.class                                 |    0 
 IMserver/medeasy/src/chat/server/call/HttpEnvelopWriter.java                                                 |  292 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Loader.class                                            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantRequestListener.class              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar                                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Member.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyServerBootstrap.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/FriendData.class                                  |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribePayload.java                                |   30 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupMemberType.class                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityTree.class                                  |    0 
 IMserver/medeasy/src/frame/util/MapList.java                                                                 |  178 
 IMserver/medeasy/src/chat/module/entity/Notify.java                                                          |  136 
 IMserver/medeasy/src/chat/server/call/ResultItem.java                                                        |   51 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnectVariableHeader.java                             |   80 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRelation.class                            |    0 
 IMserver/medeasy/src/frame/persist/IStepLoadable.java                                                        |   15 
 IMserver/medeasy/src/chat/server/moquette/message/ClientID.java                                              |   97 
 IMserver/medeasy/WebRoot/WEB-INF/lib/jna-4.5.2.jar                                                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQL.class                                        |    0 
 IMserver/medeasy/src/chat/module/entity/Channel.java                                                         |   19 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/OneClickLogin.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultSetFieldReader.class                     |    0 
 IMserver/medeasy/src/chat/module/entity/ChatSpaceType.java                                                   |   89 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySetIterator.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Notify.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserType.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-resolver-4.1.12.Final.jar                                         |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttVersion.java                                                   |   73 
 IMserver/medeasy/src/chat/module/ChatroomBucket.java                                                         |   33 
 IMserver/medeasy/src/chat/persist/MessageDetail.java                                                         |   78 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BigDecimalTranslator.class                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/I18n.class                                                |    0 
 IMserver/medeasy/src/chat/user/NotifyStore.java                                                              |  115 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribePayload.class             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/commons-logging-1.2.jar                                                 |    0 
 IMserver/medeasy/src/chat/server/ConfigerLoader.java                                                         |   86 
 IMserver/medeasy/src/frame/persist/loader/EntityLoader.java                                                  |   53 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessage.class                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageFactory.class               |    0 
 IMserver/medeasy/src/chat/consts/RestResult.java                                                             |   85 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/IIndex.class                                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/StringSegment.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/sql/data.xml                                                                |  120 
 IMserver/medeasy/src/frame/object/data/EntityFactory.java                                                    |   25 
 IMserver/medeasy/src/frame/util/GUID.java                                                                    |   18 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Comment.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/dom4j-2.0.3.jar                                                         |    0 
 IMserver/medeasy/src/chat/handler/data/DataList.java                                                         |  143 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaDirection.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepLoadable.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendRequest.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/MediaServerConfig.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageIdVariableHeader.class      |    0 
 IMserver/medeasy/src/frame/variant/ValueType.java                                                            |  233 
 IMserver/medeasy/src/chat/server/call/Operator.java                                                          |   57 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MultiCounter.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/hazelcast-3.9.4.jar                                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-osgi-4.5.13.jar                                              |    0 
 IMserver/medeasy/src/chat/module/entity/MessageRelation.java                                                 |  158 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/Field.class                                       |    0 
 IMserver/medeasy/src/frame/variant/expression/StringSegment.java                                             |   26 
 IMserver/medeasy/src/frame/variant/translator/IntegerTranslator.java                                         |  147 
 IMserver/medeasy/src/chat/user/Patient.java                                                                  |    5 
 IMserver/medeasy/src/chat/server/im/DataPool.java                                                            |  370 
 IMserver/medeasy/src/frame/persist/SQLCreator.java                                                           |   94 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Scenario.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/OperateTable.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-unix-common-4.1.12.Final.jar                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Configer.class                                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataException.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantList.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/IEntityReader.class                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpcore-4.4.13.jar                                                     |    0 
 IMserver/medeasy/src/frame/object/reader/IEntityReader.java                                                  |   15 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/LabeList.class                             |    0 
 IMserver/medeasy/src/chat/sms/OneClickLogin.java                                                             |  131 
 IMserver/medeasy/.project                                                                                    |   36 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObjectMap.class                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityFactory.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaField.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyIterator.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttTopicSubscription.class            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-4.1.12.Final.jar                                            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserStatus.class                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLVariant.class                                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttCodecUtil.class                            |    0 
 IMserver/medeasy/src/chat/module/entity/Subscriber.java                                                      |   40 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IExpression.class                          |    0 
 IMserver/medeasy/src/chat/util/BytesSelfUtil.java                                                            |   13 
 IMserver/medeasy/src/frame/object/meta/Field.java                                                            |  420 
 IMserver/medeasy/src/frame/persist/NamedSQLLoader.java                                                       |  135 
 IMserver/medeasy/src/frame/persist/Scenario.java                                                             |   33 
 IMserver/medeasy/src/chat/module/FriendRequstBucket.java                                                     |   78 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/IntegerTranslator.class                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/VariantLink.class                                     |    0 
 IMserver/medeasy/src/chat/server/moquette/MessageMetricsCollector.java                                       |   27 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnectReturnCode.java                                 |   44 
 IMserver/medeasy/src/chat/server/moquette/MqttEncodHandler.java                                              |  451 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$DecoderState.class            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatRoom.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-all-4.5.15.jar                                                   |    0 
 IMserver/medeasy/src/chat/handler/data/FriendData.java                                                       |   82 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ILoadable.class                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReader.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/log4j.properties                                                     |   28 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMDispatcher.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ModuleLoader.class                                      |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttPublishVariableHeader.java                             |   40 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupType.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1$1.class                                |    0 
 IMserver/medeasy/src/chat/consts/UserSettingScope.java                                                       |   17 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntityLoader.class                             |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribeMessage.java                                |   21 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerState.class                                       |    0 
 IMserver/medeasy/src/chat/server/call/IJsonProvider.java                                                     |    9 
 IMserver/medeasy/src/chat/server/DTDResolver.java                                                            |   30 
 IMserver/medeasy/src/chat/server/im/WFCMessageParseTable.java                                                |   58 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1$1.class                                 |    0 
 IMserver/medeasy/src/chat/server/ServerState.java                                                            |    7 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Subscriber.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttBytesMetricsHandler.class                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ClientID.class                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/emoji-java-4.0.0.jar                                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/flyway-core-5.2.4.jar                                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IEnvelop.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDateTime.class                                      |    0 
 IMserver/medeasy/src/chat/module/friendcircle/MediaType.java                                                 |   51 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DoubleTranslator.class                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.1.47.jar                                         |    0 
 IMserver/medeasy/src/frame/variant/expression/IExpression.java                                               |    8 
 IMserver/medeasy/src/frame/persist/IDoubleSavable.java                                                       |   10 
 IMserver/medeasy/src/frame/persist/ILoadable.java                                                            |    9 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepSavable.class                                    |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribeMessage.java                                  |   22 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/StringBuilderJSONWriter.class                      |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ModifiedMqttPubAckMessage.class        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishMessage.class               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageContainer.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribeMessage.class             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/JSONObject.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/UserSettingScope.class                                  |    0 
 IMserver/medeasy/src/chat/user/SessionStore.java                                                             |   97 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Segment.class                              |    0 
 IMserver/medeasy/src/frame/variant/expression/IVariantRequestListener.java                                   |   11 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MessageID.class                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Indexes.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/fluent-hc-4.5.13.jar                                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLRunner.class                                       |    0 
 IMserver/medeasy/src/chat/server/ILoader.java                                                                |   11 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircleLoader.class                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/Util.class                                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdentifierRejectedException.class          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMeta.class                                  |    0 
 IMserver/medeasy/src/frame/variant/translator/ObjectTranslator.java                                          |  281 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/DBUtil.class                                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyChannelInfoType.class              |    0 
 IMserver/medeasy/src/chat/persist/Message.java                                                               |  149 
 IMserver/medeasy/src/frame/variant/translator/ITranslator.java                                               |  141 
 IMserver/medeasy/src/chat/module/GroupBucket.java                                                            |  260 
 IMserver/medeasy/src/frame/persist/IStepSavable.java                                                         |   12 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/GroupBucket.class                                       |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribePayload.java                                  |   30 
 IMserver/medeasy/src/chat/server/moquette/MqttDecodHandler.java                                              |  531 +
 IMserver/medeasy/src/frame/object/dao/Filter.java                                                            |  200 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantRequestParams.class                 |    0 
 IMserver/medeasy/src/chat/consts/APIPath.java                                                                |   79 
 IMserver/medeasy/src/chat/server/moquette/message/MqttMessageIdVariableHeader.java                           |   32 
 IMserver/medeasy/WebRoot/WEB-INF/lib/qiniu-java-sdk-7.3.0.jar                                                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/config.dtd                                                           |   54 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-4.5.13.jar                                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDate.class                                          |    0 
 IMserver/medeasy/src/frame/object/dao/FilterSegment.java                                                     |    5 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$BlacklistStrategy.class                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectReader.class                              |    0 
 IMserver/medeasy/WebRoot/META-INF/MANIFEST.MF                                                                |    3 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/StringTranslator.class                     |    0 
 IMserver/medeasy/src/chat/module/PrivateFriendBucket.java                                                    |   43 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircle.class                         |    0 
 IMserver/medeasy/src/chat/security/DES.java                                                                  |  218 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObjectContainer.class                         |    0 
 IMserver/medeasy/src/frame/persist/DatasuorceLoader.java                                                     |  132 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageServer.class                                    |    0 
 IMserver/medeasy/src/chat/user/Session.java                                                                  |   87 
 IMserver/medeasy/src/chat/message/Callback.java                                                              |   10 
 IMserver/medeasy/src/chat/module/entity/ChatRoom.java                                                        |   19 
 IMserver/medeasy/src/frame/object/dao/FilterItem.java                                                        |   51 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ITranslator.class                          |    0 
 IMserver/medeasy/src/frame/variant/expression/VariantNotFoundException.java                                  |   10 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/WFCMessageParseTable.class                           |    0 
 IMserver/medeasy/src/chat/module/friendcircle/FriendCircle.java                                              |  115 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MethodPublisher.class                              |    0 
 IMserver/medeasy/src/frame/persist/NamedDataSource.java                                                      |   44 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantExistsException.class               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/MessageDetail.class                                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/tools/Utils.class                                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Index.class                                       |    0 
 IMserver/medeasy/src/chat/util/ByteStrToStr.java                                                             |   34 
 IMserver/medeasy/.settings/.jsdtscope                                                                        |   12 
 IMserver/medeasy/src/chat/handler/FriendCircleHandler.java                                                   |  213 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/DataList.class                                    |    0 
 IMserver/medeasy/src/chat/server/call/IEnvelop.java                                                          |   33 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1.class                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ObjectTranslator.class                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectAckPayload.class            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectVariableHeader.class        |    0 
 IMserver/medeasy/src/chat/user/Doctor.java                                                                   |    5 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/ResultPool.class                                     |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckMessage.java                                    |   18 
 IMserver/medeasy/src/chat/module/friendcircle/LabeList.java                                                  |   70 
 IMserver/medeasy/src/frame/variant/Value.java                                                                |  279 
 IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.0.8-bin.jar_bak                                  |    0 
 IMserver/medeasy/src/frame/util/Util.java                                                                    |  666 +
 IMserver/medeasy/src/frame/persist/loader/ResultSetFieldReader.java                                          |   47 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/Message.class                                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ObjectLoader.class                             |    0 
 IMserver/medeasy/WebRoot/WEB-INF/config/wildfirechat.conf                                                    |  228 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile$InvalidateTokenExecption.class               |    0 
 IMserver/medeasy/src/frame/variant/translator/LongTranslator.java                                            |  133 
 IMserver/medeasy/src/chat/server/im/ResultPool.java                                                          |  300 
 IMserver/medeasy/src/chat/server/Loader.java                                                                 |   48 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISQLContext.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Aaa.class                                                  |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantSegment.class                       |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttIdleTimeoutHandler.java                                        |   42 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttUnacceptableProtocolVersionException.class |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/LongTranslator.class                       |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttPubAckMessage.java                                     |   14 
 IMserver/medeasy/src/frame/object/data/Node.java                                                             |   87 
 IMserver/medeasy/src/chat/server/moquette/Metrics.java                                                       |   29 
 IMserver/medeasy/src/chat/message/MessagesPublisher.java                                                     |  134 
 IMserver/medeasy/src/frame/object/data/ID.java                                                               |   53 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataSourceManager.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/aliyun-java-sdk-core-4.1.0.jar                                          |    0 
 IMserver/medeasy/src/chat/user/User.java                                                                     |  716 +
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttVersion.class                              |    0 
 IMserver/medeasy/src/chat/module/entity/Member.java                                                          |  136 
 IMserver/medeasy/src/chat/util/DBUtil.java                                                                   |   95 
 IMserver/medeasy/.settings/org.eclipse.wst.common.project.facet.core.xml                                     |   11 
 IMserver/medeasy/src/frame/object/reader/ObjectReader.java                                                   |  434 
 IMserver/medeasy/src/frame/object/data/EntitySetIterator.java                                                |   33 
 IMserver/medeasy/src/frame/variant/expression/VariantList.java                                               |   12 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/DataPool.class                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/BrokerConstants.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IFieldReader.class                                |    0 
 IMserver/medeasy/src/chat/server/Configer.java                                                               |  201 
 IMserver/medeasy/src/chat/consts/MediaServerConfig.java                                                      |   33 
 IMserver/medeasy/config/i18n/messages_en_US.properties                                                       |    2 
 IMserver/medeasy/src/chat/server/moquette/message/MessageID.java                                             |   33 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CommentList.class                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySet.class                                   |    0 
 IMserver/medeasy/src/chat/server/im/IMTopic.java                                                             |   81 
 IMserver/medeasy/src/chat/server/moquette/message/MqttFixedHeader.java                                       |   56 
 IMserver/medeasy/WebRoot/WEB-INF/lib/httpmime-4.5.13.jar                                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/commons-pool-1.6.jar                                                    |    0 
 IMserver/medeasy/src/chat/module/ConcurrentMapList.java                                                      |  210 
 IMserver/medeasy/src/chat/server/netty/NettyAcceptor.java                                                    |  274 
 IMserver/medeasy/src/chat/handler/RobotHandler.java                                                          |   13 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttQoS.class                          |    0 
 IMserver/medeasy/src/chat/server/call/CallObjectMap.java                                                     |   66 
 IMserver/medeasy/src/frame/variant/expression/VariantSegment.java                                            |   51 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMetaLoader.class                            |    0 
 IMserver/medeasy/src/frame/persist/loader/ResultMetaFieldReader.java                                         |   50 
 IMserver/medeasy/src/chat/persistence/MemoryMessagesStore.java                                               |   33 
 IMserver/medeasy/src/chat/server/moquette/message/MqttMessageType.java                                       |   39 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaFieldReader.class                             |    0 
 IMserver/medeasy/src/frame/persist/loader/ObjectLoader.java                                                  |   58 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService.class                                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Client.class                                              |    0 
 IMserver/medeasy/src/chat/module/friendcircle/Comment.java                                                   |   85 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyWSChannelInitializer.class                   |    0 
 IMserver/medeasy/src/chat/server/im/IMDispatcher.java                                                        |  157 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/AppDispatcher.class                                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Patient.class                                             |    0 
 IMserver/medeasy/src/chat/server/netty/NettyWSChannelInitializer.java                                        |   89 
 IMserver/medeasy/src/frame/object/reader/PropertyIterator.java                                               |   32 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/PrivateFriendBucket.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRecord.class                              |    0 
 IMserver/medeasy/src/chat/module/ChannelBucket.java                                                          |   27 
 IMserver/medeasy/src/chat/module/entity/MessageType.java                                                     |   44 
 IMserver/medeasy/src/frame/variant/translator/BigDecimalTranslator.java                                      |  132 
 IMserver/medeasy/src/chat/server/ContainerIterator.java                                                      |   40 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendShip.class                                 |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SearchUserType.class                     |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/MediaType.class                            |    0 
 IMserver/medeasy/src/frame/object/data/EntityClassFactory.java                                               |   27 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/HttpEnvelopWriter.class                            |    0 
 IMserver/medeasy/src/chat/medeasy/HttpClientUtil.java                                                        |   91 
 IMserver/medeasy/src/chat/handler/ChannelHandler.java                                                        |  148 
 IMserver/medeasy/config/i18n/messages_en.properties                                                          |    2 
 IMserver/medeasy/config/i18n/messages_zh_CN.properties                                                       |    2 
 IMserver/medeasy/src/chat/server/call/ResultCode.java                                                        |   41 
 IMserver/medeasy/src/frame/variant/VariantLink.java                                                          |  100 
 IMserver/medeasy/src/frame/object/meta/MetaField.java                                                        |   37 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$Platform.class                           |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttCodecUtil.java                                                 |  110 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-4.1.12.Final.jar                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PullType.class                           |    0 
 IMserver/medeasy/src/chat/user/Token.java                                                                    |   33 
 IMserver/medeasy/src/frame/persist/loader/ValueLoader.java                                                   |   50 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatSpaceType.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/common-0.49.jar                                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ContentType.class                        |    0 
 IMserver/medeasy/src/frame/object/reader/PropertyReader.java                                                 |  166 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/Bucket.class                                            |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/gson-2.8.2.jar                                                          |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/Operator.class                                     |    0 
 IMserver/medeasy/src/chat/sms/Record.java                                                                    |   25 
 IMserver/medeasy/src/frame/persist/loader/EntitySetLoader.java                                               |   58 
 IMserver/medeasy/src/frame/variant/expression/Expression.java                                                |  208 
 IMserver/medeasy/src/chat/module/entity/MessageRecord.java                                                   |  328 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/MethodPublisher.class                              |    0 
 IMserver/medeasy/src/chat/user/ResultMessage.java                                                            |   29 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishVariableHeader.class        |    0 
 IMserver/medeasy/src/frame/object/meta/IMetaDataLoader.java                                                  |   11 
 IMserver/medeasy/src/frame/object/data/EntitySet.java                                                        |  175 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendshipStatus.class                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultCode.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttFixedHeader.class                  |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttConnectAckPayload.java                                 |   25 
 IMserver/medeasy/src/frame/persist/SQLRunner.java                                                            |  705 +
 IMserver/medeasy/WebRoot/WEB-INF/config/job.dtd                                                              |   14 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifySubject.class                                       |    0 
 IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckMessage.java                                     |   22 
 IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-log4j12-1.7.5.jar                                                 |    0 
 IMserver/medeasy/src/chat/module/entity/GroupType.java                                                       |   12 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataBaseType.class                                    |    0 
 IMserver/medeasy/src/frame/variant/expression/VariantParser.java                                             |  107 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserResultCode.class                     |    0 
 IMserver/medeasy/src/chat/server/call/StringBuilderJSONWriter.java                                           |  358 
 IMserver/medeasy/src/frame/persist/loader/DataLoader.java                                                    |   44 
 IMserver/medeasy/src/frame/variant/translator/StringTranslator.java                                          |  195 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChannelHandler.class                                   |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ObjectList.class                                  |    0 
 IMserver/medeasy/src/frame/persist/loader/ListLoader.java                                                    |   63 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsConsumer.class                               |    0 
 IMserver/medeasy/src/frame/persist/IMetaDataLoader.java                                                      |    9 
 IMserver/medeasy/src/frame/util/ContentBuilder.java                                                          |   83 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendCircleHandler.class                              |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttUnacceptableProtocolVersionException.java                      |   54 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile.class                                        |    0 
 IMserver/medeasy/src/chat/server/AppDispatcher.java                                                          |  166 
 IMserver/medeasy/src/frame/object/data/Entity.java                                                           |  419 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-http-4.1.12.Final.jar                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectMessage.class               |    0 
 IMserver/medeasy/src/chat/server/call/CachedJSONWriter.java                                                  |  269 
 IMserver/medeasy/WebRoot/WEB-INF/lib/netty-common-4.1.12.Final.jar                                           |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantNotFoundException.class             |    0 
 IMserver/medeasy/src/chat/user/NotifyContentDetail.java                                                      |   71 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/ByteStrToStr.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/BytesMetricsCollector.class                    |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ResultMessage.class                                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectPayload.class               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageType.class                  |    0 
 IMserver/medeasy/src/chat/server/netty/NettyServerBootstrap.java                                             |   43 
 IMserver/medeasy/src/chat/util/MessageShardingUtil.java                                                      |  120 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Page.class                                         |    0 
 IMserver/medeasy/WebRoot/WEB-INF/sql/message.xml                                                             |   22 
 IMserver/medeasy/src/frame/persist/NamedSQLContainer.java                                                    |   23 
 IMserver/medeasy/src/frame/variant/PropertyIterator.java                                                     |   35 
 IMserver/medeasy/src/frame/variant/expression/VariantRequestParams.java                                      |   21 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPubAckMessage.class                |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Forward.class                              |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ListLoader.class                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/SessionStore.class                                        |    0 
 IMserver/medeasy/WebRoot/WEB-INF/lib/log4j-1.2.16.jar                                                        |    0 
 IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.container                                       |    1 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/CollectionReader.class                          |    0 
 IMserver/medeasy/src/chat/server/Container.java                                                              |  116 
 IMserver/medeasy/WebRoot/WEB-INF/sql/user.xml                                                                |   71 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Record.class                                               |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChannelState.class                       |    0 
 IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Expression.class                           |    0 
 IMserver/medeasy/src/chat/server/moquette/MqttBytesMetricsHandler.java                                       |   73 
 IMserver/medeasy/src/frame/persist/DBDateTime.java                                                           |   41 
 IMserver/medeasy/WebRoot/WEB-INF/config/datasource.xml                                                       |   23 
 IMserver/medeasy/src/chat/server/im/RequestType.java                                                         |    7 
 674 files changed, 29,887 insertions(+), 0 deletions(-)

diff --git a/IMserver/medeasy/.classpath b/IMserver/medeasy/.classpath
new file mode 100644
index 0000000..cce9abb
--- /dev/null
+++ b/IMserver/medeasy/.classpath
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
+		<attributes>
+			<attribute name="module" value="true"/>
+			<attribute name="owner.project.facets" value="java"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="com.genuitec.runtime.library/com.genuitec.generic_6.0">
+		<attributes>
+			<attribute name="owner.project.facets" value="jst.web"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="con" path="com.genuitec.runtime.library/com.genuitec.jstl_1.2.1">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.dependency" value="WEB-INF/lib"/>
+			<attribute name="owner.project.facets" value="jst.web.jstl"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="WebRoot/WEB-INF/lib/qiniu-java-sdk-7.3.0.jar"/>
+	<classpathentry kind="output" path="WebRoot/WEB-INF/classes"/>
+</classpath>
diff --git a/IMserver/medeasy/.project b/IMserver/medeasy/.project
new file mode 100644
index 0000000..e908228
--- /dev/null
+++ b/IMserver/medeasy/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>medeasy</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.genuitec.eclipse.j2eedt.core.DeploymentDescriptorValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+	</natures>
+</projectDescription>
diff --git a/IMserver/medeasy/.settings/.jsdtscope b/IMserver/medeasy/.settings/.jsdtscope
new file mode 100644
index 0000000..f2f9fad
--- /dev/null
+++ b/IMserver/medeasy/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry excluding="**/bower_components/*|**/node_modules/*|**/*.min.js" kind="src" path="WebRoot"/>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+		<attributes>
+			<attribute name="hide" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+	<classpathentry kind="output" path=""/>
+</classpath>
diff --git a/IMserver/medeasy/.settings/org.eclipse.core.resources.prefs b/IMserver/medeasy/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..1463000
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//WebRoot/WEB-INF/config/wildfirechat.conf=UTF-8
+encoding//src/frame/persist/SQLRunner.java=UTF-8
diff --git a/IMserver/medeasy/.settings/org.eclipse.jdt.core.prefs b/IMserver/medeasy/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/IMserver/medeasy/.settings/org.eclipse.wst.common.component b/IMserver/medeasy/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..5735c56
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="medeasy">
+        <wb-resource deploy-path="/" source-path="/WebRoot" tag="defaultRootSource"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
+        <property name="context-root" value="medeasy"/>
+        <property name="java-output-path" value="/medeasy/WebRoot/WEB-INF/classes"/>
+    </wb-module>
+</project-modules>
diff --git a/IMserver/medeasy/.settings/org.eclipse.wst.common.project.facet.core.xml b/IMserver/medeasy/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d21bee2
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <runtime name="com.genuitec.runtime.generic.jee60"/>
+  <fixed facet="java"/>
+  <fixed facet="jst.web"/>
+  <fixed facet="wst.jsdt.web"/>
+  <installed facet="java" version="1.8"/>
+  <installed facet="jst.web" version="3.0"/>
+  <installed facet="jst.web.jstl" version="1.2.1"/>
+  <installed facet="wst.jsdt.web" version="1.0"/>
+</faceted-project>
diff --git a/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.container b/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.name b/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/IMserver/medeasy/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/IMserver/medeasy/WebRoot/META-INF/MANIFEST.MF b/IMserver/medeasy/WebRoot/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..254272e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/APIPath.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/APIPath.class
new file mode 100644
index 0000000..5221ba2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/APIPath.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/BrokerConstants.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/BrokerConstants.class
new file mode 100644
index 0000000..ef646c3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/BrokerConstants.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/MediaServerConfig.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/MediaServerConfig.class
new file mode 100644
index 0000000..74ef516
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/MediaServerConfig.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$BlacklistStrategy.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$BlacklistStrategy.class
new file mode 100644
index 0000000..41d6b7f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$BlacklistStrategy.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChannelState.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChannelState.class
new file mode 100644
index 0000000..9f3aab8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChannelState.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChatroomState.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChatroomState.class
new file mode 100644
index 0000000..52569a0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ChatroomState.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ContentType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ContentType.class
new file mode 100644
index 0000000..d1fb7b8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ContentType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ConversationType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ConversationType.class
new file mode 100644
index 0000000..f40659a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ConversationType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$FriendRequestStatus.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$FriendRequestStatus.class
new file mode 100644
index 0000000..2b4578c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$FriendRequestStatus.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupMemberType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupMemberType.class
new file mode 100644
index 0000000..9638d90
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupMemberType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupType.class
new file mode 100644
index 0000000..83c9891
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$GroupType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyChannelInfoType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyChannelInfoType.class
new file mode 100644
index 0000000..87626f4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyChannelInfoType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyGroupInfoType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyGroupInfoType.class
new file mode 100644
index 0000000..fb0d3ee
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$ModifyGroupInfoType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PersistFlag.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PersistFlag.class
new file mode 100644
index 0000000..679ae21
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PersistFlag.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$Platform.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$Platform.class
new file mode 100644
index 0000000..7f024f9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$Platform.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PullType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PullType.class
new file mode 100644
index 0000000..042dee4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$PullType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SearchUserType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SearchUserType.class
new file mode 100644
index 0000000..21a129c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SearchUserType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SystemSettingType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SystemSettingType.class
new file mode 100644
index 0000000..2bdac2e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$SystemSettingType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserResultCode.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserResultCode.class
new file mode 100644
index 0000000..887862c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserResultCode.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserStatus.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserStatus.class
new file mode 100644
index 0000000..4630784
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserStatus.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserType.class
new file mode 100644
index 0000000..65972a9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants$UserType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants.class
new file mode 100644
index 0000000..4ce1aec
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/ProtoConstants.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult$RestCode.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult$RestCode.class
new file mode 100644
index 0000000..77ac9cd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult$RestCode.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult.class
new file mode 100644
index 0000000..c38a925
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/RestResult.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/UserSettingScope.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/UserSettingScope.class
new file mode 100644
index 0000000..8afb047
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/consts/UserSettingScope.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChannelHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChannelHandler.class
new file mode 100644
index 0000000..055a76a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChannelHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChatRoomHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChatRoomHandler.class
new file mode 100644
index 0000000..4dd5322
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ChatRoomHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1$1.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1$1.class
new file mode 100644
index 0000000..936ffe7
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1$1.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1.class
new file mode 100644
index 0000000..e7ff26c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler$1.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler.class
new file mode 100644
index 0000000..97e681c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ClientHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendCircleHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendCircleHandler.class
new file mode 100644
index 0000000..2b10e07
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendCircleHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendshipHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendshipHandler.class
new file mode 100644
index 0000000..b48b40e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/FriendshipHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1$1.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1$1.class
new file mode 100644
index 0000000..b36b2c9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1$1.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1.class
new file mode 100644
index 0000000..82f2ece
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler$1.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler.class
new file mode 100644
index 0000000..ff3ce9c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/GroupHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ManagerNotifyHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ManagerNotifyHandler.class
new file mode 100644
index 0000000..410371a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/ManagerNotifyHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/MessageHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/MessageHandler.class
new file mode 100644
index 0000000..6799616
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/MessageHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/RobotHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/RobotHandler.class
new file mode 100644
index 0000000..f3b1834
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/RobotHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SensitiveHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SensitiveHandler.class
new file mode 100644
index 0000000..25dfd83
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SensitiveHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SystemHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SystemHandler.class
new file mode 100644
index 0000000..dfec977
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/SystemHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/DataList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/DataList.class
new file mode 100644
index 0000000..4821401
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/DataList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/FriendData.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/FriendData.class
new file mode 100644
index 0000000..a9d5f4d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/handler/data/FriendData.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/medeasy/HttpClientUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/medeasy/HttpClientUtil.class
new file mode 100644
index 0000000..faded60
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/medeasy/HttpClientUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/Callback.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/Callback.class
new file mode 100644
index 0000000..95316b7
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/Callback.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageRunner.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageRunner.class
new file mode 100644
index 0000000..53ec54c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageRunner.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageServer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageServer.class
new file mode 100644
index 0000000..a1d6919
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessageServer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessagesPublisher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessagesPublisher.class
new file mode 100644
index 0000000..d7a1616
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/MessagesPublisher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/SendMessageCallback.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/SendMessageCallback.class
new file mode 100644
index 0000000..5d4ca16
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/message/SendMessageCallback.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/Bucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/Bucket.class
new file mode 100644
index 0000000..ae5ac1d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/Bucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChannelBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChannelBucket.class
new file mode 100644
index 0000000..ec5fa52
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChannelBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChatroomBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChatroomBucket.class
new file mode 100644
index 0000000..da9f2b3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ChatroomBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ConcurrentMapList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ConcurrentMapList.class
new file mode 100644
index 0000000..cf619c5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ConcurrentMapList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/FriendRequstBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/FriendRequstBucket.class
new file mode 100644
index 0000000..0c50443
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/FriendRequstBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/GroupBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/GroupBucket.class
new file mode 100644
index 0000000..64e23cc
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/GroupBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ModuleLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ModuleLoader.class
new file mode 100644
index 0000000..8b887b5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/ModuleLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/PrivateFriendBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/PrivateFriendBucket.class
new file mode 100644
index 0000000..14f746f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/PrivateFriendBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/RelationshipBucket.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/RelationshipBucket.class
new file mode 100644
index 0000000..6b56e05
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/RelationshipBucket.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/UserMessageList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/UserMessageList.class
new file mode 100644
index 0000000..68d3931
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/UserMessageList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Channel.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Channel.class
new file mode 100644
index 0000000..adc5dcb
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Channel.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatRoom.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatRoom.class
new file mode 100644
index 0000000..e4980c0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatRoom.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatSpaceType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatSpaceType.class
new file mode 100644
index 0000000..6905a08
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/ChatSpaceType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendRequest.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendRequest.class
new file mode 100644
index 0000000..8a71402
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendRequest.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendShip.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendShip.class
new file mode 100644
index 0000000..7ec6635
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendShip.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendshipStatus.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendshipStatus.class
new file mode 100644
index 0000000..1e61154
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/FriendshipStatus.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Group.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Group.class
new file mode 100644
index 0000000..8d22b9e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Group.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/GroupType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/GroupType.class
new file mode 100644
index 0000000..1a2068a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/GroupType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Member.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Member.class
new file mode 100644
index 0000000..4c6b287
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Member.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageContainer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageContainer.class
new file mode 100644
index 0000000..6755f52
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageContainer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRecord.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRecord.class
new file mode 100644
index 0000000..6c7a45c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRecord.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRelation.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRelation.class
new file mode 100644
index 0000000..14e9d08
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageRelation.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageType.class
new file mode 100644
index 0000000..b20d6c1
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/MessageType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Notify.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Notify.class
new file mode 100644
index 0000000..c971b31
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Notify.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PrivateFriend.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PrivateFriend.class
new file mode 100644
index 0000000..a3ad717
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PrivateFriend.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PublishOperator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PublishOperator.class
new file mode 100644
index 0000000..0f91e8f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/PublishOperator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Subscriber.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Subscriber.class
new file mode 100644
index 0000000..b09dae8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/entity/Subscriber.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CircleObject.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CircleObject.class
new file mode 100644
index 0000000..15e3e2e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CircleObject.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Comment.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Comment.class
new file mode 100644
index 0000000..04f13f6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Comment.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CommentList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CommentList.class
new file mode 100644
index 0000000..da4f412
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/CommentList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Forward.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Forward.class
new file mode 100644
index 0000000..ca61821
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/Forward.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircle.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircle.class
new file mode 100644
index 0000000..634ca19
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircle.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircleLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircleLoader.class
new file mode 100644
index 0000000..afaa9aa
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/FriendCircleLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/LabeList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/LabeList.class
new file mode 100644
index 0000000..44a5815
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/LabeList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/MediaType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/MediaType.class
new file mode 100644
index 0000000..d317510
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/module/friendcircle/MediaType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/Message.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/Message.class
new file mode 100644
index 0000000..e47fc12
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/Message.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/MessageDetail.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/MessageDetail.class
new file mode 100644
index 0000000..e6a2d8d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persist/MessageDetail.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persistence/MemoryMessagesStore.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persistence/MemoryMessagesStore.class
new file mode 100644
index 0000000..d18c549
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/persistence/MemoryMessagesStore.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/redis/RedisUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/redis/RedisUtil.class
new file mode 100644
index 0000000..6af9603
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/redis/RedisUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/AES.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/AES.class
new file mode 100644
index 0000000..e51f9b3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/AES.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/DES.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/DES.class
new file mode 100644
index 0000000..8bdde4d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/security/DES.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/AppDispatcher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/AppDispatcher.class
new file mode 100644
index 0000000..173d568
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/AppDispatcher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Configer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Configer.class
new file mode 100644
index 0000000..5cdf0d8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Configer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ConfigerLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ConfigerLoader.class
new file mode 100644
index 0000000..34b3d5d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ConfigerLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Container.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Container.class
new file mode 100644
index 0000000..0a90f08
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Container.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContainerIterator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContainerIterator.class
new file mode 100644
index 0000000..1dc9e5a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContainerIterator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContextListener.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContextListener.class
new file mode 100644
index 0000000..7fd217f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ContextListener.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/DTDResolver.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/DTDResolver.class
new file mode 100644
index 0000000..7a6ed9f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/DTDResolver.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ILoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ILoader.class
new file mode 100644
index 0000000..109c153
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ILoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Loader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Loader.class
new file mode 100644
index 0000000..a51b626
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Loader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance$MessagePos.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance$MessagePos.class
new file mode 100644
index 0000000..30bd61e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance$MessagePos.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance.class
new file mode 100644
index 0000000..10a0c65
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerInstance.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerState.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerState.class
new file mode 100644
index 0000000..0f37150
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/ServerState.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Test.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Test.class
new file mode 100644
index 0000000..8780e30
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/Test.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CachedJSONWriter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CachedJSONWriter.class
new file mode 100644
index 0000000..cb471aa
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CachedJSONWriter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObject.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObject.class
new file mode 100644
index 0000000..062d4f2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObject.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObjectMap.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObjectMap.class
new file mode 100644
index 0000000..c5b28cd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/CallObjectMap.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/HttpEnvelopWriter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/HttpEnvelopWriter.class
new file mode 100644
index 0000000..3f185a7
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/HttpEnvelopWriter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IEnvelop.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IEnvelop.class
new file mode 100644
index 0000000..4240d61
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IEnvelop.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJSONWriter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJSONWriter.class
new file mode 100644
index 0000000..9a01437
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJSONWriter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJsonProvider.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJsonProvider.class
new file mode 100644
index 0000000..acd3755
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/IJsonProvider.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/JSONObject.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/JSONObject.class
new file mode 100644
index 0000000..48a4807
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/JSONObject.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MethodPublisher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MethodPublisher.class
new file mode 100644
index 0000000..ce4c34b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MethodPublisher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MultiCounter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MultiCounter.class
new file mode 100644
index 0000000..54cfb16
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/MultiCounter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/Operator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/Operator.class
new file mode 100644
index 0000000..38a3dbd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/Operator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultCode.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultCode.class
new file mode 100644
index 0000000..89301f1
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultCode.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultItem.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultItem.class
new file mode 100644
index 0000000..34cd817
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultItem.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultOutputType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultOutputType.class
new file mode 100644
index 0000000..21a0279
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/ResultOutputType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/StringBuilderJSONWriter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/StringBuilderJSONWriter.class
new file mode 100644
index 0000000..88d6d07
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/call/StringBuilderJSONWriter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/DataPool.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/DataPool.class
new file mode 100644
index 0000000..f1d410f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/DataPool.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMDispatcher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMDispatcher.class
new file mode 100644
index 0000000..875d10e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMDispatcher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMTopic.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMTopic.class
new file mode 100644
index 0000000..7d85731
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/IMTopic.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/OperateTable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/OperateTable.class
new file mode 100644
index 0000000..607bb42
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/OperateTable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/RequestType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/RequestType.class
new file mode 100644
index 0000000..794afb2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/RequestType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/ResultPool.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/ResultPool.class
new file mode 100644
index 0000000..ae8fb8b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/ResultPool.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/WFCMessageParseTable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/WFCMessageParseTable.class
new file mode 100644
index 0000000..8a6c907
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/im/WFCMessageParseTable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/BytesMetricsCollector.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/BytesMetricsCollector.class
new file mode 100644
index 0000000..5564c38
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/BytesMetricsCollector.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MessageMetricsCollector.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MessageMetricsCollector.class
new file mode 100644
index 0000000..d86a117
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MessageMetricsCollector.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/Metrics.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/Metrics.class
new file mode 100644
index 0000000..f4dd970
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/Metrics.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttBytesMetricsHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttBytesMetricsHandler.class
new file mode 100644
index 0000000..075f3c7
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttBytesMetricsHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttCodecUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttCodecUtil.class
new file mode 100644
index 0000000..3f3af6b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttCodecUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$DecoderState.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$DecoderState.class
new file mode 100644
index 0000000..a40a9b2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$DecoderState.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$Result.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$Result.class
new file mode 100644
index 0000000..ce5dd67
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler$Result.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler.class
new file mode 100644
index 0000000..e20fafe
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDecodHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDispatcher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDispatcher.class
new file mode 100644
index 0000000..22b747a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttDispatcher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttEncodHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttEncodHandler.class
new file mode 100644
index 0000000..990c0c2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttEncodHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdentifierRejectedException.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdentifierRejectedException.class
new file mode 100644
index 0000000..0216419
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdentifierRejectedException.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdleTimeoutHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdleTimeoutHandler.class
new file mode 100644
index 0000000..ffababc
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttIdleTimeoutHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageLoggerHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageLoggerHandler.class
new file mode 100644
index 0000000..e1a3eae
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageLoggerHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageMetricsHandler.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageMetricsHandler.class
new file mode 100644
index 0000000..c360549
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttMessageMetricsHandler.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttUnacceptableProtocolVersionException.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttUnacceptableProtocolVersionException.class
new file mode 100644
index 0000000..dbf0efe
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttUnacceptableProtocolVersionException.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttVersion.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttVersion.class
new file mode 100644
index 0000000..45e782b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/MqttVersion.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ClientID.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ClientID.class
new file mode 100644
index 0000000..ca42c16
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ClientID.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MessageID.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MessageID.class
new file mode 100644
index 0000000..bae157c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MessageID.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ModifiedMqttPubAckMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ModifiedMqttPubAckMessage.class
new file mode 100644
index 0000000..90a91d8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/ModifiedMqttPubAckMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckMessage.class
new file mode 100644
index 0000000..65b3cfe
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckVariableHeader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckVariableHeader.class
new file mode 100644
index 0000000..4fa5a16
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnAckVariableHeader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectAckPayload.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectAckPayload.class
new file mode 100644
index 0000000..e351d5d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectAckPayload.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectMessage.class
new file mode 100644
index 0000000..9238018
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectPayload.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectPayload.class
new file mode 100644
index 0000000..a3d52e3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectPayload.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectReturnCode.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectReturnCode.class
new file mode 100644
index 0000000..714c0ee
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectReturnCode.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectVariableHeader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectVariableHeader.class
new file mode 100644
index 0000000..b23301c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttConnectVariableHeader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttFixedHeader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttFixedHeader.class
new file mode 100644
index 0000000..225beda
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttFixedHeader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessage.class
new file mode 100644
index 0000000..16e6a2f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageFactory.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageFactory.class
new file mode 100644
index 0000000..5426273
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageFactory.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageIdVariableHeader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageIdVariableHeader.class
new file mode 100644
index 0000000..ecc2751
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageIdVariableHeader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageType.class
new file mode 100644
index 0000000..06525e2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttMessageType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPubAckMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPubAckMessage.class
new file mode 100644
index 0000000..c688763
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPubAckMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishMessage.class
new file mode 100644
index 0000000..6a53846
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishVariableHeader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishVariableHeader.class
new file mode 100644
index 0000000..9606e85
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttPublishVariableHeader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttQoS.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttQoS.class
new file mode 100644
index 0000000..b6c010b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttQoS.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckMessage.class
new file mode 100644
index 0000000..6037bc9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckPayload.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckPayload.class
new file mode 100644
index 0000000..74fa4a8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubAckPayload.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribeMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribeMessage.class
new file mode 100644
index 0000000..a601530
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribeMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribePayload.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribePayload.class
new file mode 100644
index 0000000..36dfa14
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttSubscribePayload.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttTopicSubscription.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttTopicSubscription.class
new file mode 100644
index 0000000..1d02d08
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttTopicSubscription.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubAckMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubAckMessage.class
new file mode 100644
index 0000000..780aaa3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubAckMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribeMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribeMessage.class
new file mode 100644
index 0000000..079bf29
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribeMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribePayload.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribePayload.class
new file mode 100644
index 0000000..1401201
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/moquette/message/MqttUnsubscribePayload.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/ByteBufToWebSocketFrameEncoder.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/ByteBufToWebSocketFrameEncoder.class
new file mode 100644
index 0000000..8d41e13
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/ByteBufToWebSocketFrameEncoder.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyAcceptor.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyAcceptor.class
new file mode 100644
index 0000000..d42e2f9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyAcceptor.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyHttpChannelInitializer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyHttpChannelInitializer.class
new file mode 100644
index 0000000..4cf2bb4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyHttpChannelInitializer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettySSLChannelInitializer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettySSLChannelInitializer.class
new file mode 100644
index 0000000..c2e4a2f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettySSLChannelInitializer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyServerBootstrap.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyServerBootstrap.class
new file mode 100644
index 0000000..44b727e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyServerBootstrap.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyTCPChannelInitializer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyTCPChannelInitializer.class
new file mode 100644
index 0000000..40cae0a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyTCPChannelInitializer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyWSChannelInitializer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyWSChannelInitializer.class
new file mode 100644
index 0000000..629dbb5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/NettyWSChannelInitializer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/WebSocketFrameToByteBufDecoder.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/WebSocketFrameToByteBufDecoder.class
new file mode 100644
index 0000000..68572f8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/server/netty/WebSocketFrameToByteBufDecoder.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Aaa.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Aaa.class
new file mode 100644
index 0000000..be0885f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Aaa.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/OneClickLogin.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/OneClickLogin.class
new file mode 100644
index 0000000..a29ad7c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/OneClickLogin.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Record.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Record.class
new file mode 100644
index 0000000..1a6db0e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/Record.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService$AliyunCommonResponse.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService$AliyunCommonResponse.class
new file mode 100644
index 0000000..fd3d18d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService$AliyunCommonResponse.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService.class
new file mode 100644
index 0000000..21a3987
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/sms/SmsService.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/tools/Utils.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/tools/Utils.class
new file mode 100644
index 0000000..ec470ab
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/tools/Utils.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile$InvalidateTokenExecption.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile$InvalidateTokenExecption.class
new file mode 100644
index 0000000..2770412
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile$InvalidateTokenExecption.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile.class
new file mode 100644
index 0000000..6effea5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/upload/UploadFile.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Client.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Client.class
new file mode 100644
index 0000000..4014826
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Client.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ClientStore.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ClientStore.class
new file mode 100644
index 0000000..14f1e72
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ClientStore.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Doctor.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Doctor.class
new file mode 100644
index 0000000..cb40fce
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Doctor.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Notify.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Notify.class
new file mode 100644
index 0000000..6ba0bbe
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Notify.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContent.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContent.class
new file mode 100644
index 0000000..8e9311d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContent.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContentDetail.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContentDetail.class
new file mode 100644
index 0000000..19038b4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyContentDetail.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyStore.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyStore.class
new file mode 100644
index 0000000..427e59d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifyStore.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifySubject.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifySubject.class
new file mode 100644
index 0000000..c27b444
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/NotifySubject.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Patient.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Patient.class
new file mode 100644
index 0000000..d70efb2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Patient.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ResultMessage.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ResultMessage.class
new file mode 100644
index 0000000..a6ab487
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/ResultMessage.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Session.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Session.class
new file mode 100644
index 0000000..df4523a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Session.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/SessionStore.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/SessionStore.class
new file mode 100644
index 0000000..d8317e5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/SessionStore.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Status.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Status.class
new file mode 100644
index 0000000..0a99238
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Status.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Token.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Token.class
new file mode 100644
index 0000000..f6d9cd6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/Token.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/User.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/User.class
new file mode 100644
index 0000000..702256d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/User.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/UserStore.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/UserStore.class
new file mode 100644
index 0000000..1400c80
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/user/UserStore.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/ByteStrToStr.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/ByteStrToStr.class
new file mode 100644
index 0000000..4249621
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/ByteStrToStr.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/BytesSelfUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/BytesSelfUtil.class
new file mode 100644
index 0000000..b19539f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/BytesSelfUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/DBUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/DBUtil.class
new file mode 100644
index 0000000..3a66d8e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/DBUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/I18n.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/I18n.class
new file mode 100644
index 0000000..2a904f8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/I18n.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/MessageShardingUtil.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/MessageShardingUtil.class
new file mode 100644
index 0000000..ce13ce8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/MessageShardingUtil.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/SpinLock.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/SpinLock.class
new file mode 100644
index 0000000..5fd09dc
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/chat/util/SpinLock.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Filter.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Filter.class
new file mode 100644
index 0000000..67ac233
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Filter.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterItem.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterItem.class
new file mode 100644
index 0000000..095dddf
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterItem.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterSegment.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterSegment.class
new file mode 100644
index 0000000..8b671e8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/FilterSegment.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/MethodPublisher.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/MethodPublisher.class
new file mode 100644
index 0000000..d85d58d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/MethodPublisher.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/OrderBy.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/OrderBy.class
new file mode 100644
index 0000000..3babf50
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/OrderBy.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Page.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Page.class
new file mode 100644
index 0000000..d0a5b37
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/dao/Page.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataException.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataException.class
new file mode 100644
index 0000000..c3caec0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataException.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObject.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObject.class
new file mode 100644
index 0000000..959b8db
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObject.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObjectContainer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObjectContainer.class
new file mode 100644
index 0000000..de8f5fe
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/DataObjectContainer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Entity.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Entity.class
new file mode 100644
index 0000000..8817044
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Entity.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityClassFactory.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityClassFactory.class
new file mode 100644
index 0000000..f3b1f8b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityClassFactory.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityFactory.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityFactory.class
new file mode 100644
index 0000000..c196106
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityFactory.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializer.class
new file mode 100644
index 0000000..2e2ae39
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializerContainer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializerContainer.class
new file mode 100644
index 0000000..4912208
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityInitializerContainer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySet.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySet.class
new file mode 100644
index 0000000..b673c23
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySet.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySetIterator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySetIterator.class
new file mode 100644
index 0000000..a90a90c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntitySetIterator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityTree.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityTree.class
new file mode 100644
index 0000000..fe77dc4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/EntityTree.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ID.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ID.class
new file mode 100644
index 0000000..9bb9be3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ID.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/IIndex.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/IIndex.class
new file mode 100644
index 0000000..16c3537
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/IIndex.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Index.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Index.class
new file mode 100644
index 0000000..22dd6f7
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Index.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Indexes.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Indexes.class
new file mode 100644
index 0000000..bacdb30
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Indexes.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Node.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Node.class
new file mode 100644
index 0000000..70f18f2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/Node.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ObjectList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ObjectList.class
new file mode 100644
index 0000000..690dd7a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/data/ObjectList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMeta.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMeta.class
new file mode 100644
index 0000000..c8a1c82
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMeta.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMetaLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMetaLoader.class
new file mode 100644
index 0000000..f0c31cc
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/EntityMetaLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/Field.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/Field.class
new file mode 100644
index 0000000..5587396
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/Field.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IFieldReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IFieldReader.class
new file mode 100644
index 0000000..46c71bb
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IFieldReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IMetaDataLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IMetaDataLoader.class
new file mode 100644
index 0000000..dc8de3c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/IMetaDataLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaDirection.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaDirection.class
new file mode 100644
index 0000000..bbdc02f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaDirection.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaField.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaField.class
new file mode 100644
index 0000000..99341da
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaField.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaFieldReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaFieldReader.class
new file mode 100644
index 0000000..c656da8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetaFieldReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataMeta.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataMeta.class
new file mode 100644
index 0000000..da573fd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataMeta.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataSet.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataSet.class
new file mode 100644
index 0000000..b505ff0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/meta/MetadataSet.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/CollectionReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/CollectionReader.class
new file mode 100644
index 0000000..165f3db
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/CollectionReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReader.class
new file mode 100644
index 0000000..4e9dca9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReaderContainer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReaderContainer.class
new file mode 100644
index 0000000..dc20bf0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/EntityReaderContainer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/IEntityReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/IEntityReader.class
new file mode 100644
index 0000000..ce6763d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/IEntityReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/MapReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/MapReader.class
new file mode 100644
index 0000000..ba9a49e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/MapReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/NameValuePair.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/NameValuePair.class
new file mode 100644
index 0000000..1a89801
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/NameValuePair.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectPropertyRecorder.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectPropertyRecorder.class
new file mode 100644
index 0000000..4038baa
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectPropertyRecorder.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectReader.class
new file mode 100644
index 0000000..9d04268
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/ObjectReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyIterator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyIterator.class
new file mode 100644
index 0000000..6c7ad52
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyIterator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyReader.class
new file mode 100644
index 0000000..9b09352
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/object/reader/PropertyReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDate.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDate.class
new file mode 100644
index 0000000..0d24de4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDate.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDateTime.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDateTime.class
new file mode 100644
index 0000000..1540733
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DBDateTime.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataBaseType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataBaseType.class
new file mode 100644
index 0000000..16bc64e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataBaseType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataSourceManager.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataSourceManager.class
new file mode 100644
index 0000000..cdd13a6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DataSourceManager.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DatasuorceLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DatasuorceLoader.class
new file mode 100644
index 0000000..1495aa6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/DatasuorceLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IDoubleSavable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IDoubleSavable.class
new file mode 100644
index 0000000..20e7dfd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IDoubleSavable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ILoadable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ILoadable.class
new file mode 100644
index 0000000..5e08d52
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ILoadable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IMetaDataLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IMetaDataLoader.class
new file mode 100644
index 0000000..a3eef01
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IMetaDataLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISQLContext.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISQLContext.class
new file mode 100644
index 0000000..c60041f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISQLContext.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISavable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISavable.class
new file mode 100644
index 0000000..cf7d7ab
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/ISavable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepLoadable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepLoadable.class
new file mode 100644
index 0000000..1ae328f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepLoadable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepSavable.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepSavable.class
new file mode 100644
index 0000000..922bb97
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/IStepSavable.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedDataSource.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedDataSource.class
new file mode 100644
index 0000000..8838b19
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedDataSource.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQL.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQL.class
new file mode 100644
index 0000000..f9e8727
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQL.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLContainer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLContainer.class
new file mode 100644
index 0000000..b90ae03
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLContainer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLLoader.class
new file mode 100644
index 0000000..0fd49f1
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/NamedSQLLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Result.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Result.class
new file mode 100644
index 0000000..2b7ad64
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Result.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLBuilder.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLBuilder.class
new file mode 100644
index 0000000..7e38915
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLBuilder.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLCreator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLCreator.class
new file mode 100644
index 0000000..4f3c40b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLCreator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLRunner.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLRunner.class
new file mode 100644
index 0000000..a73404b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLRunner.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLVariant.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLVariant.class
new file mode 100644
index 0000000..1db7924
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/SQLVariant.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Scenario.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Scenario.class
new file mode 100644
index 0000000..d31b7e2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/Scenario.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/DataLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/DataLoader.class
new file mode 100644
index 0000000..94433c0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/DataLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntityLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntityLoader.class
new file mode 100644
index 0000000..db93817
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntityLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntitySetLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntitySetLoader.class
new file mode 100644
index 0000000..56442e9
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/EntitySetLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ListLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ListLoader.class
new file mode 100644
index 0000000..3159b1e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ListLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ObjectLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ObjectLoader.class
new file mode 100644
index 0000000..e1adf8b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ObjectLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultMetaFieldReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultMetaFieldReader.class
new file mode 100644
index 0000000..62cf2f5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultMetaFieldReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultSetFieldReader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultSetFieldReader.class
new file mode 100644
index 0000000..b16b1cb
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ResultSetFieldReader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ValueLoader.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ValueLoader.class
new file mode 100644
index 0000000..e814516
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/persist/loader/ValueLoader.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/ContentBuilder.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/ContentBuilder.class
new file mode 100644
index 0000000..fba14a4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/ContentBuilder.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/GUID.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/GUID.class
new file mode 100644
index 0000000..8e05de0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/GUID.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapList.class
new file mode 100644
index 0000000..b637158
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapTree.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapTree.class
new file mode 100644
index 0000000..8f6d195
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/MapTree.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/Util.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/Util.class
new file mode 100644
index 0000000..d414a1f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/util/Util.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsConsumer.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsConsumer.class
new file mode 100644
index 0000000..5346dec
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsConsumer.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsProvider.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsProvider.class
new file mode 100644
index 0000000..7565b43
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/IVariantsProvider.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/NameValuePair.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/NameValuePair.class
new file mode 100644
index 0000000..165adfc
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/NameValuePair.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/PropertyIterator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/PropertyIterator.class
new file mode 100644
index 0000000..bec6ef0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/PropertyIterator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/Value.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/Value.class
new file mode 100644
index 0000000..ba56916
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/Value.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/ValueType.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/ValueType.class
new file mode 100644
index 0000000..e41a7b6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/ValueType.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/VariantLink.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/VariantLink.class
new file mode 100644
index 0000000..7f9a9a6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/VariantLink.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Expression.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Expression.class
new file mode 100644
index 0000000..7d4829a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Expression.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant$GlobalVariantProvider.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant$GlobalVariantProvider.class
new file mode 100644
index 0000000..b734379
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant$GlobalVariantProvider.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant.class
new file mode 100644
index 0000000..0322290
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/GlobalVariant.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IExpression.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IExpression.class
new file mode 100644
index 0000000..cc9f334
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IExpression.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantParseListener.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantParseListener.class
new file mode 100644
index 0000000..071bf54
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantParseListener.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantRequestListener.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantRequestListener.class
new file mode 100644
index 0000000..57383ee
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/IVariantRequestListener.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Segment.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Segment.class
new file mode 100644
index 0000000..b3447a5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/Segment.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/StringSegment.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/StringSegment.class
new file mode 100644
index 0000000..6f374ed
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/StringSegment.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantContext.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantContext.class
new file mode 100644
index 0000000..8203fb1
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantContext.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantExistsException.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantExistsException.class
new file mode 100644
index 0000000..344d3bf
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantExistsException.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantList.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantList.class
new file mode 100644
index 0000000..cfd646a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantList.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantNotFoundException.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantNotFoundException.class
new file mode 100644
index 0000000..9d1d2f5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantNotFoundException.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantParser.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantParser.class
new file mode 100644
index 0000000..530c6ca
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantParser.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantRequestParams.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantRequestParams.class
new file mode 100644
index 0000000..bed2efb
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantRequestParams.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantSegment.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantSegment.class
new file mode 100644
index 0000000..e191dc6
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/expression/VariantSegment.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BigDecimalTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BigDecimalTranslator.class
new file mode 100644
index 0000000..fa2c298
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BigDecimalTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BooleanTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BooleanTranslator.class
new file mode 100644
index 0000000..0b6f610
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/BooleanTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DateTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DateTranslator.class
new file mode 100644
index 0000000..63fa98e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DateTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DoubleTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DoubleTranslator.class
new file mode 100644
index 0000000..8836267
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/DoubleTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ITranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ITranslator.class
new file mode 100644
index 0000000..c50d94d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ITranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/IntegerTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/IntegerTranslator.class
new file mode 100644
index 0000000..e0540d2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/IntegerTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/LongTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/LongTranslator.class
new file mode 100644
index 0000000..f2c43b2
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/LongTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ObjectTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ObjectTranslator.class
new file mode 100644
index 0000000..ed6ff93
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/ObjectTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/StringTranslator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/StringTranslator.class
new file mode 100644
index 0000000..13b597d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/StringTranslator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/Translator.class b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/Translator.class
new file mode 100644
index 0000000..c9aa707
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/classes/frame/variant/translator/Translator.class
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/config.dtd b/IMserver/medeasy/WebRoot/WEB-INF/config/config.dtd
new file mode 100644
index 0000000..db563d4
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/config.dtd
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!ELEMENT config (param*, freeVisit*, configLoader*, routes*, servers?)+> 
+
+<!ELEMENT param (#PCDATA)> 
+
+<!ATTLIST param
+    name CDATA #REQUIRED
+    value CDATA #REQUIRED
+    remark CDATA #IMPLIED
+    client (T|F) #IMPLIED 
+>
+
+
+<!ELEMENT freeVisit (type*, resource*, call*)+>
+
+<!ELEMENT type (#PCDATA)>
+<!ELEMENT resource (#PCDATA)>
+<!ELEMENT call (#PCDATA)>
+
+<!ELEMENT routes (route*)+>
+<!ELEMENT route (#PCDATA)>
+<!ATTLIST route
+	path CDATA #REQUIRED
+	target CDATA #IMPLIED
+	classname CDATA #IMPLIED
+>
+
+<!ELEMENT configLoader (loader)*>
+
+<!ELEMENT loader (#PCDATA)>
+<!ATTLIST loader
+	name CDATA #REQUIRED
+	classname CDATA #REQUIRED
+	active CDATA #REQUIRED
+>
+
+<!ELEMENT servers (server)*>
+
+<!ELEMENT server (schedules?, servers?)>
+<!ATTLIST server
+	name CDATA #REQUIRED
+	classname CDATA #REQUIRED
+	active CDATA #REQUIRED
+>
+
+<!ELEMENT schedules (schedule)*>
+
+<!ELEMENT schedule (#PCDATA)>
+<!ATTLIST schedule
+	type CDATA #REQUIRED
+	fire CDATA #REQUIRED
+	active CDATA #REQUIRED
+>
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/config.xml b/IMserver/medeasy/WebRoot/WEB-INF/config/config.xml
new file mode 100644
index 0000000..1634694
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/config.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE config PUBLIC "config" "config.dtd" >
+
+<config>
+	<!--绯荤粺鍙傛暟-->
+	<param name="EnvironmentName" value="Capital" client="T" remark="娴嬭瘯鐜銆佺敓浜х幆澧�" />
+	<param name="AuthorizeActive" value="F" remark="鏉冮檺楠岃瘉鏄惁鍚敤" />
+	<param name="DataBaseType" value="MySql" remark="Oracle,SqlServer,MySql" />
+	<param name="ScheduleActive" value="T" remark="Schedule鏄惁婵�娲伙紝T涓烘縺娲伙紝F鍜屾病鏈夐厤缃兘涓嶆縺娲�" />
+	
+	<param name="SendSMS" value="F" remark="鏄惁鍙戦�佺煭淇★紝T锛孎" />
+	<param name="SuperVCode" value="0023" remark="瓒呯骇楠岃瘉鐮�" />
+
+	<!-- 2.璺敱閰嶇疆 -->
+	<routes>
+		<!-- 2.1 璧勬簮璁块棶 -->
+		<route path="/" target="root/module/portal/page/login.html" />
+		<route path="timeout" target="root/module/portal/page/login.html" />
+		<route path="root" target="/ddinet/" />
+		
+		<!-- 2.2 system controller-->
+		<route path="data" classname="frame.object.dao.DataAccessObject" />
+		<route path="system" classname="frame.system.SystemControler" />
+		<route path="onlineUser" classname="frame.system.OnlineUserControler" />
+		
+		<!-- 2.3 project controller -->
+		<route path="app" classname="capital.controller.AppController" />
+		<route path="target" classname="capital.controller.TargetController" />
+		<route path="foot" classname="capital.controller.FootController" />
+		<route path="activity" classname="capital.controller.ActivityController" />
+		<route path="team" classname="capital.controller.TeamController" />
+		<route path="card" classname="capital.controller.CardController" />
+		<route path="bag" classname="capital.controller.BagController" />
+	</routes>
+	
+	<!-- 3.涓嶅彈鏉冮檺鎺у埗鐨勮祫婧� -->
+	<freeVisit>
+		<!-- 3.1涓嶅彈鏉冮檺鎺у埗鐨勮祫婧愮被鍨� -->
+		<type>.js</type>
+		<type>.json</type>
+		<type>.css</type>
+		<type>.jpg</type>
+		<type>.png</type>
+		<type>.gif</type>
+		<type>.bmp</type>
+		<type>.jpeg</type>
+		<type>.zip</type>
+		
+		<!-- 3.2涓嶅彈鏉冮檺鎺у埗鐨勯〉闈� -->
+		<resource>*/timeout.html</resource>
+		<resource>*/login.html</resource>
+		<resource>*/doLogin.html</resource>
+		<resource>*/index.html</resource>
+		<resource>*/download.html</resource>
+		<resource>*/download_test.html</resource>
+		
+		<!-- 2.3涓嶅彈鏉冮檺鎺у埗鐨勫嚱鏁拌皟鐢� -->
+		<call>system/login</call>
+		<call>system/logout</call>
+		<call>system/getvcade</call>
+	</freeVisit>
+
+	<!-- 4.閰嶇疆淇℃伅鍔犺浇鍣ㄥ垪琛�  -->
+	<configLoader>
+		<loader name="datasource" classname="frame.persist.DatasuorceLoader" active="T"/>
+		<loader name="namedSQL" classname="frame.persist.NamedSQLLoader" active="T"/>
+ 		<loader name="fileIO" classname="frame.file.mapping.FileIOLoader" active="F"/>
+ 		<loader name="system" classname="frame.system.DefaultSystemDataLoader" active="T"/>
+ 		<loader name="period" classname="athena.period.ServerPeriodLoader" active="T"/>
+ 		<loader name="dataModule" classname="capital.module.ModuleLoader" active="T"/>
+ 		<loader name="schedule" classname="frame.server.schedule.ScheduleJobLoader" active="T"/>
+ 		
+ 		
+	</configLoader>
+	
+</config>
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.dtd b/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.dtd
new file mode 100644
index 0000000..3fc5844
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.dtd
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!ELEMENT datasource (defination)> 
+
+<!ELEMENT defination (#PCDATA)> 
+
+<!ATTLIST defination
+	driverName CDATA #REQUIRED
+    url CDATA #REQUIRED
+    username CDATA #REQUIRED
+    password CDATA #REQUIRED
+    characterEncoding CDATA #REQUIRED
+    maxActive CDATA #IMPLIED  
+    initialSize CDATA #IMPLIED 
+    maxWait CDATA #IMPLIED  
+    minIdle CDATA #IMPLIED
+    timeBetweenEvictionRunsMillis CDATA #IMPLIED 
+    minEvictableIdleTimeMillis CDATA #IMPLIED  
+    validationQuery CDATA #IMPLIED  
+    testWhileIdle CDATA #IMPLIED  
+    testOnBorrow CDATA #IMPLIED 
+    testOnReturn CDATA #IMPLIED        
+>
+
+
+
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.xml b/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.xml
new file mode 100644
index 0000000..6bfda3c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/datasource.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE datasource PUBLIC "datasource" "datasource.dtd" >
+
+<datasource>
+	<defination 
+		driverName="com.mysql.jdbc.Driver"
+    	url="jdbc:mysql://immy.highdatas.com:9306/medeasy"
+        username="root"
+        password="imuser123"
+        characterEncoding="utf-8"
+        maxActive="20" 
+        initialSize="1" 
+        maxWait="60000" 
+        minIdle="1" 
+        timeBetweenEvictionRunsMillis="3000"
+        minEvictableIdleTimeMillis="300000" 
+        validationQuery="SELECT 'x' from DUAL" 
+        testWhileIdle="true" 
+        testOnBorrow="false" 
+        testOnReturn="false" 
+	/>
+
+</datasource>
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/job.dtd b/IMserver/medeasy/WebRoot/WEB-INF/config/job.dtd
new file mode 100644
index 0000000..6f321e0
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/job.dtd
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!ELEMENT schedule (job*)+> 
+
+<!ELEMENT job (#PCDATA)> 
+
+<!ATTLIST job
+    id CDATA #REQUIRED
+    name CDATA #REQUIRED
+    runtime CDATA #REQUIRED
+    classname CDATA #REQUIRED
+>
+
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/job.xml b/IMserver/medeasy/WebRoot/WEB-INF/config/job.xml
new file mode 100644
index 0000000..4e496cf
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/job.xml
@@ -0,0 +1,12 @@
+锘�<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE schedule PUBLIC "schedule" "job.dtd">
+
+<schedule>
+	
+	<!--姣忓ぉ鏅氫笂11鐐规墽琛岃仛鍚堜换鍔� -->
+	<job  
+		id="PeriodLoader"  
+		name="text" 
+		runtime="0 0 2 * * ?"  
+		classname="capital.schedule.PeriodChecker"/>
+</schedule>
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/log4j.properties b/IMserver/medeasy/WebRoot/WEB-INF/config/log4j.properties
new file mode 100644
index 0000000..4a5b6e3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/log4j.properties
@@ -0,0 +1,28 @@
+log4j.rootLogger=debug, A1
+#log4j.rootLogger=info, A1, A2
+
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+#log4j.appender.A2=org.apache.log4j.RollingFileAppender
+#log4j.appender.A2.File=D:/Project/fulltext/data/fulltext.log
+#log4j.appender.A2.MaxFileSize=1024KB
+
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+#log4j.appender.A2.layout=org.apache.log4j.PatternLayout
+
+
+#log4j.appender.A1.layout.ConversionPattern=%-5p [%t] %37c %3x - %m%n
+log4j.appender.A1.layout.ConversionPattern=%-5p [%t] %37c %3x - %m%n
+
+log4j.logger.frame.server.config.ContextConfigerLoader = WARN
+log4j.logger.org.quartz = WARN
+log4j.logger.com.alibaba.druid = WARN
+log4j.logger.frame.server.schedule.ScheduleJob = WARN
+
+log4j.logger.io.netty.util = info
+log4j.logger.io.netty.channel = info
+log4j.logger.io.netty.buffer = info
+
+log4j.logger.chat.server.moquette.MqttDecodHandler = WARN
+
+log4j.logger.druid = WARN
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/sql.dtd b/IMserver/medeasy/WebRoot/WEB-INF/config/sql.dtd
new file mode 100644
index 0000000..2d72646
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/sql.dtd
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!ELEMENT sqls (dataSpace*)+>
+<!ATTLIST sqls
+	xmlns:fo CDATA #IMPLIED
+	namespace CDATA #IMPLIED
+	active (true|false) #IMPLIED
+>
+
+<!ELEMENT dataSpace (sql*)+>
+<!ATTLIST dataSpace
+	name CDATA #IMPLIED
+>
+
+<!ELEMENT sql (#PCDATA|condition)*>
+<!ATTLIST sql
+	name CDATA #REQUIRED
+	timeout CDATA #IMPLIED
+>
+
+<!ELEMENT condition (#PCDATA)>
+<!ATTLIST condition
+	value CDATA #REQUIRED
+>
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/sqllist.dtd b/IMserver/medeasy/WebRoot/WEB-INF/config/sqllist.dtd
new file mode 100644
index 0000000..4f6f3e1
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/sqllist.dtd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!ELEMENT sqllist (dataSpace*)+>
+<!ATTLIST sqllist
+	xmlns:fo CDATA #IMPLIED
+	namespace CDATA #IMPLIED
+>
+
+<!ELEMENT dataSpace (sql* )+>
+<!ATTLIST dataSpace
+	name CDATA #IMPLIED
+	base CDATA #IMPLIED
+>
+
+<!ELEMENT sql (#PCDATA)>
+<!ATTLIST sql
+	name CDATA #REQUIRED
+	id CDATA #IMPLIED
+>
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/timer.properties b/IMserver/medeasy/WebRoot/WEB-INF/config/timer.properties
new file mode 100644
index 0000000..45ecd20
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/timer.properties
@@ -0,0 +1,20 @@
+
+#============================================================================
+# Configure Main Scheduler Properties  
+#============================================================================
+
+org.quartz.scheduler.instanceName: FoundationScheduler
+org.quartz.scheduler.instanceId: AUTO
+
+org.quartz.scheduler.skipUpdateCheck: true
+
+#============================================================================
+# Configure ThreadPool  
+#============================================================================
+
+org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
+org.quartz.threadPool.threadCount: 1
+org.quartz.threadPool.threadPriority: 5
+
+
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/config/wildfirechat.conf b/IMserver/medeasy/WebRoot/WEB-INF/config/wildfirechat.conf
new file mode 100644
index 0000000..9d0d8ad
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/config/wildfirechat.conf
@@ -0,0 +1,228 @@
+#*********************************************************************
+# Server configuration
+#*********************************************************************
+#鏈嶅姟鍣ㄧ殑鎺ュ叆IP銆傜粰瀹㈡埛绔彁渚涙槸${server.ip}鍜�${http_port}銆�
+#瀹㈡埛绔細浠�${http_port}绔彛鑾峰彇鍒伴暱閾炬帴绔彛銆傝繖涓湴鍧�涓�瀹氳鏀规垚瀹㈡埛绔彲浠ヨ闂埌鐨処P鍦板潃
+# 锛堝鏋滄偍閮ㄧ讲浜戞湇鍔″櫒涓婃垨鑰呭叿鏈夌嫭绔嬪叕缃戝嚭鍙g殑鏈嶅姟鍣ㄤ笂锛岃鏀逛负瀵瑰簲鐨勫叕缃慖P锛涘鏋滄偍閮ㄧ讲鍦ㄥ湪鍐呯綉鐜涓嬶紝鍦ㄥ唴缃戜娇鐢紝杩欎釜鍦版柟鏀规垚鍐呯綉鍦板潃锛�
+server.ip 0.0.0.0
+
+##鍘熺敓瀹㈡埛绔暱閾炬帴绔彛
+port 1883
+
+##瀹㈡埛绔煭閾炬帴绔彛
+http_port 80
+
+##WEB瀹㈡埛绔暱閾炬帴绔彛
+websocket_port 9083
+
+#绠$悊绔彛
+http.admin.port 9880
+
+##鑺傜偣ID锛屽綋闆嗙兢閮ㄧ讲鏃讹紝涓�瀹氫笉鑳芥湁閲嶅銆�
+node_id 1
+
+##缁戝畾IP锛屼繚鎸佷笉鍙樺嵆鍙�
+host 0.0.0.0
+
+##鏈湴缁戝畾绔彛
+local_port 9008
+
+##鏄惁浣跨敤鍐呯疆DB銆�0浣跨敤mysql锛�1浣跨敤h2db锛�2浣跨敤mysql+mongodb銆傜ぞ鍖虹増鍙敮鎸�0鍜�1锛屼笓涓氱増鏀寔2
+embed.db 0
+
+##鏈嶅姟鍣ㄧ鐞嗘帴鍙e瘑閽�
+http.admin.secret_key 123456
+
+##鏈嶅姟鍣ˋPI鎺ュ彛鍙傛暟鏄惁妫�鏌ユ椂闂淬�傚綋璁剧疆涓篺alse鏃讹紝鎵�鏈夌殑璇锋眰浼氭鏌ユ椂闂寸殑鏈夋晥鎬э紱褰撹缃负true鏃讹紝鍙互鍦╤ttp.admin.secret_key淇濇寔涓嶅彉鐨勬儏鍐典笅锛屼娇鐢ㄥ浐瀹氱殑鏈嶅姟API绛惧悕
+##nonce = "76616", timestamp = "1558350862502", sign = "b98f9b0717f59febccf1440067a7f50d9b31bdde"
+http.admin.no_check_time false
+
+##瀹㈡埛绔崗璁爤瀵嗛挜锛岄渶瑕佷笌瀹㈡埛绔崗璁爤鏂囦欢libemqq.cc鏂囦欢涓殑aes_key鍊间繚鎸佷竴鑷达紝16杩涘埗byte鐢ㄩ�楀彿鍒嗗壊銆傝繖涓瘑閽ヤ笉鑳戒慨鏀癸紒锛侊紒
+client.proto.secret_key 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F
+
+##鐢ㄦ潵鐢熶骇im token鐨勭閽ワ紝鍙湪鏈嶅姟鍣ㄤ娇鐢紝瀹㈡埛绔笉鐢ㄣ�傛寮忎娇鐢ㄦ椂涓轰簡瀹夊叏涓�瀹氳淇敼杩欎釜鍊硷紝鍒囪鍒囪
+token.key testim
+
+##token鐨勮繃鏈熸椂闂达紝鍗曚綅涓烘绉掞紝榛樿涓烘棤闄愭湡銆傚鏋滈渶瑕佽缃棤闄愭湡锛屽鎴风涓婁竴瀹氶渶瑕佸姞涓妕oken杩囨湡鐨勫鐞嗐�倀oken杩囨湡鐨勫鐞嗚鍙傝�冩枃妗g殑甯歌闂
+##token.expire_time 2592000000
+
+##棣栨鐧诲綍锛屾槸鍚︽帴鏀朵箣鍓嶇殑鍘嗗彶娑堟伅銆�
+##0 涓嶆帴鏀跺巻鍙叉秷鎭紝鍙帴鏀�5鍒嗛挓浠ュ唴鐨勬秷鎭紝鐢变簬鏈嶅姟鍣ㄦ病鏈変繚瀛樺凡缁忔敹鍙栬褰曪紝鎵�浠ュ鏋滄湁瓒呰繃5鍒嗛挓涔嬪墠鏈敹鍙栫殑娑堟伅涔熶笉浼氭敹鍙栦笅鎷夛紱
+##1鎺ユ敹锛屼細鎺ユ敹 message.max_queue 閰嶇疆鐨勬潯鏁扮殑鍘嗗彶娑堟伅
+message.roaming 0
+
+##鏄惁寮�鍚媺鍙栬繙绋嬪巻鍙叉秷鎭�傚鏋滀负1锛屽鎴风鍦ㄤ細璇濆唴濡傛灉鏈湴娑堟伅璇诲彇瀹屼簡锛屽彲浠ヤ笅鎷夌户缁姞杞藉湪鏈嶅姟鍣ㄤ笂鐨勮浼氳瘽鐨勬秷鎭紱濡傛灉涓�0鍒欎笉鑳姐��
+message.remote_history_message 0
+
+##鏈嶅姟鍣ㄤ负姣忎釜鐢ㄦ埛缂撳瓨鐨勬秷鎭暟閲忋�傝繖涓�兼敼寰楀お澶э紝鎷夊彇娑堟伅鏃堕棿鍙橀暱锛屽彟澶栦細鍗犵敤澶ч噺鍐呭瓨銆�
+message.max_queue 1024
+
+##鏄惁绂佹闄岀敓浜鸿亰澶�
+message.disable_stranger_chat false
+
+##榛戝悕鍗曠瓥鐣ワ紝0 鍙戦�佸け璐ワ紝杩斿洖琚媺榛戠殑閿欒鐮侊紱1 鍙戦�佹垚鍔熶絾娑堟伅琚湇鍔″櫒鐩存帴涓㈠純
+message.blacklist.strategy 0
+
+##鏄惁绂佹鏈嶅姟鍣ㄧ娑堟伅鎼滅储锛岃鍔熻兘鏆傛湭瀹炵幇銆傜洰鍓嶇殑褰卞搷鏄鏋滄墦寮�锛屽垯瀛樺偍娑堟伅鏃朵笉鍗曠嫭淇濆瓨_searchable_content瀛楁
+message.disable_remote_search  false
+
+##鍏佽瀹㈡埛绔挙鍥炴秷鎭椂闄愶紝鍗曚綅鏄銆傜兢缁勭鐞嗗憳鎴栫兢涓绘挙鍥炵兢鎴愬憳娑堟伅銆乻erver api涓嶅彈姝ら檺鍒讹紝鍙互鎾ゅ洖浠绘剰鏃堕檺鍐呯殑娑堟伅
+message.recall_time_limit 120
+
+##绂佹鎼滅储鐢ㄦ埛
+friend.disable_search false
+
+##绂佹鎸夌収鏄电О鎼滅储鐢ㄦ埛銆�
+friend.disable_nick_name_search false
+
+##绂佹鍙戦�佸ソ鍙嬮個璇凤紝閫氳繃server api娣诲姞濂藉弸涓嶅彈姝ら檺鍒�
+friend.disable_friend_request false
+
+##濂藉弸璇锋眰閲嶅鍙戦�佺殑闂撮殧锛屽崟浣嶆槸姣锛岄粯璁ゆ槸7澶╋紝0涓轰笉闄愬埗
+friend.repeat_request_duration 604800000
+
+##濂藉弸璇锋眰琚嫆缁濆悗鍐嶆鍙戦�佺殑闂撮殧锛屽崟浣嶆槸姣锛岄粯璁ゆ槸30澶╋紝0涓轰笉闄愬埗
+friend.reject_request_duration 2592000000
+
+##濂藉弸璇锋眰杩囨湡鏃堕棿锛屽崟浣嶆槸姣锛岄粯璁ゆ槸7澶╋紝0涓轰笉闄愬埗
+friend.request_expiration_duration 604800000
+
+##娣诲姞濂藉弸鍚庝細鍙戦�佹杩庢秷鎭紝姣斿"浣犱滑宸茬粡鏄ソ鍙嬩簡锛屽彲浠ヨ亰澶╀簡"銆傝繖涓紑鍏虫帶鍒舵槸鐢ㄦ棫鐨勬柟寮忚繕鏄敤鏂扮殑鏂瑰紡銆�
+##鏃х殑鏂瑰紡浼氬彂閫乶otification娑堟伅锛坈ontenttype鏄�80锛夛紝鍐呭浼氭牴鎹ソ鍙嬫帴鏀惰�呯殑璇█閫夋嫨瀵瑰簲鐨勮瑷�锛屽鏋滃弻鏂硅瑷�涓嶄竴鑷翠細瀵艰嚧鍙﹀涓�鏂圭湅鍒扮殑涓嶆槸鏈湴璇█銆�
+##鏂扮殑鏂瑰紡浼氬彂閫佹坊鍔犲ソ鍙嬫秷鎭紙contenttype鏄�93锛夊拰娆㈣繋娑堟伅锛坈ontenttype鏄�92锛夛紝闇�瑕佸鎴风瀹炵幇杩欎袱绉嶆秷鎭��
+##濡傛灉瀹㈡埛绔凡缁忓疄鐜拌繖涓ょ娑堟伅鍙互鎵撳紑杩欎釜寮�鍏�
+friend.new_welcome_message false
+
+## 鑱婂ぉ瀹よ浼楃┖闂查��鍑烘椂闂达紝鍗曚綅涓烘绉掞紝榛樿涓�15鍒嗛挓锛�0涓烘案杩滀笉閫�鍑�
+chatroom.participant_idle_time 900000
+
+## 鐢ㄦ埛鍚戣亰澶╁鍙戦�佹秷鎭紝鑷姩鍔犲叆鑱婂ぉ瀹�
+chatroom.rejoin_when_active true
+
+#*********************************************************************
+# hazelcase configuration
+#*********************************************************************
+hazelcast.configuration config/hazelcast.xml
+
+#*********************************************************************
+# Media server configuration
+#*********************************************************************
+##鏄惁浣跨敤涓冪墰浜戝瓨鍌ㄣ��1浣跨敤涓冪墰锛�0浣跨敤鍐呭瓨鏂囦欢鏈嶅姟鍣ㄣ�傞粯璁ょ殑涓冪墰璐︽埛淇℃伅涓嶅彲鐢紝璇峰湪涓冪墰瀹樼綉鐢宠璐︽埛骞堕厤缃�
+## https://docs.wildfirechat.cn/server/media_server.html
+media.server.use_qiniu 0
+
+##濯掍綋绫诲瀷鍒嗙被
+#Media_Type_GENERAL = 0,
+#Media_Type_IMAGE = 1,
+#Media_Type_VOICE = 2,
+#Media_Type_VIDEO = 3,
+#Media_Type_FILE = 4,
+#Media_Type_PORTRAIT = 5,
+#Media_Type_FAVORITE = 6
+
+# qiniu media server configuration
+## 涓婁紶鍦板潃锛屼笉鍚岀殑鍖哄煙锛屼笂浼犲湴鍧�涔熶笉鍚岋紝璇锋敞鎰忕幇鍦ㄦ纭殑鍦板潃
+qiniu.server_url  http://up.qbox.me
+qiniu.access_key tU3vdBK5BL5j4N7jI5N5uZgq_HQDo170w5C9Amnn
+qiniu.secret_key YfQIJdgp5YGhwEw14vGpaD2HJZsuJldWtqens7i5
+## bucket鍚嶅瓧鍙奃omain
+qiniu.bucket_general_name media
+qiniu.bucket_general_domain http://cdn.wildfirechat.cn
+qiniu.bucket_image_name media
+qiniu.bucket_image_domain http://cdn.wildfirechat.cn
+qiniu.bucket_voice_name media
+qiniu.bucket_voice_domain http://cdn.wildfirechat.cn
+qiniu.bucket_video_name media
+qiniu.bucket_video_domain http://cdn.wildfirechat.cn
+qiniu.bucket_file_name media
+qiniu.bucket_file_domain http://cdn.wildfirechat.cn
+qiniu.bucket_sticker_name media
+qiniu.bucket_sticker_domain http://cdn.wildfirechat.cn
+qiniu.bucket_moments_name media
+qiniu.bucket_moments_domain http://cdn.wildfirechat.cn
+qiniu.bucket_portrait_name storage
+qiniu.bucket_portrait_domain http://cdn2.wildfirechat.cn
+qiniu.bucket_favorite_name storage
+qiniu.bucket_favorite_domain http://cdn2.wildfirechat.cn
+
+
+# local media server configuration
+# 鏈湴濯掍綋鏈嶅姟鍣ㄩ厤缃��
+local.media.storage.root ./media
+
+
+# 鏄惁鏀寔澶氱鐧婚檰锛屼负true鏃舵敮鎸佷换鎰忓钩鍙颁换鎰忓涓鎴风鍚屾椂鐧诲綍锛涗负false鏃舵瘡涓钩鍙板彧鏀寔涓�涓鐧诲綍锛屼絾涓嶅悓骞冲彴鍙互鍚屾椂鐧诲綍銆�
+server.multi_endpoint false
+
+# 澶氬钩鍙拌繛鎺ョ姸鎬侀�氱煡锛堜粎褰搈ulti_endpoint涓篺alse鏃舵湁鏁堬級锛宼rue鏃剁Щ鍔ㄧ鍙互鏀跺埌pc鎴杦eb绔櫥褰曠殑閫氱煡銆�
+server.multi_platform_notification false
+
+#*********************************************************************
+# Push server configuration
+#*********************************************************************
+##瀹夊崜鎺ㄩ�佹湇鍔″櫒鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+push.android.server.address http://localhost:8085/android/push
+
+##鑻规灉鎺ㄩ�佹湇鍔″櫒鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+push.ios.server.address http://localhost:8085/ios/push
+
+#*********************************************************************
+# 鍚勭浜嬩欢鍥炶皟
+#*********************************************************************
+##鐢ㄦ埛鍦ㄧ嚎鐘舵�佷簨浠跺洖璋冨湴鍧�
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#user.online_status_callback http://localhost:8888/im_event/user/online
+
+##鐢ㄦ埛淇℃伅鍙樺姩浜嬩欢鍥炶皟鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#relation.relation_update_callback http://localhost:8888/im_event/user/relation
+
+##鐢ㄦ埛淇℃伅鍙樺姩浜嬩欢鍥炶皟鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#user.user_info_update_callback http://localhost:8888/im_event/user/info
+
+##娑堟伅杞彂鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#message.forward.url http://localhost:8087/im_event/message
+
+##璁惧淇℃伅杞彂鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#things_message.forward.url http://localhost:8087/im_event/things/message
+
+##缇ょ粍淇℃伅鍙樺姩浜嬩欢鍥炶皟鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#group.group_info_update_callback http://localhost:8888/im_event/group/info
+
+##缇ょ粍淇℃伅鍙樺姩浜嬩欢鍥炶皟鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#group.group_member_update_callback http://localhost:8888/im_event/group/member
+
+##棰戦亾淇℃伅鍙樺姩鍥炶皟鍦板潃
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#channel.channel_info_update_callback http://localhost:8888/im_event/channel/info
+
+##鑱婂ぉ瀹や俊鎭彉鍔ㄥ洖璋冨湴鍧�
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#chatroom.chatroom_info_update_callback http://localhost:8888/im_event/chatroom/info
+
+##鑱婂ぉ瀹ゆ垚鍛樺彉鍔ㄥ洖璋冨湴鍧�
+##娉ㄦ剰鍥炶皟鏄崟绾跨▼鍥炶皟锛屾帴鏀舵湇鍔″繀椤诲湪鍚屼竴鍐呯綉锛屼笖寮傛澶勭悊蹇�熻繑鍥烇紝鍚﹀垯浼氭湁寤惰繜闂锛侊紒
+#chatroom.chatroom_member_update_callback http://localhost:8888/im_event/chatroom/member
+
+#*********************************************************************
+# Netty Configuration
+#
+# Linux systems can use epoll instead of nio. To get a performance
+# gain and reduced GC.
+# http://netty.io/wiki/native-transports.html for more information
+#*********************************************************************
+# 濡傛灉鏄痩inux绯荤粺锛屼竴瀹氳鎵撳紑涓嬮潰杩欎釜鍙傛暟锛岃兘澶у箙搴︽彁楂樻�ц兘
+#netty.epoll true
+
+#*********************************************************************
+# Sensitive configuration
+#*********************************************************************
+##鏂囨湰鏁忔劅璇嶈繃婊ゅ鐞嗘柟娉曪紝0 鍙戦�佸け璐ワ紱1 鍙戦�佹垚鍔熶絾娑堟伅琚湇鍔″櫒鐩存帴涓㈠純锛�2 鍛戒腑鐨勬晱鎰熻瘝琚浛鎹㈡垚***
+sensitive.filter.type 0
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/Json.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/Json.jar
new file mode 100644
index 0000000..471dd40
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/Json.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/aliyun-java-sdk-core-4.1.0.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/aliyun-java-sdk-core-4.1.0.jar
new file mode 100644
index 0000000..cc7da01
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/aliyun-java-sdk-core-4.1.0.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/c3p0-0.9.5.4.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/c3p0-0.9.5.4.jar
new file mode 100644
index 0000000..a71b468
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/c3p0-0.9.5.4.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/common-0.49.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/common-0.49.jar
new file mode 100644
index 0000000..a5c1697
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/common-0.49.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-codec-1.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-codec-1.13.jar
new file mode 100644
index 0000000..bf6ccb3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-codec-1.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-httpclient-3.1.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-httpclient-3.1.jar
new file mode 100644
index 0000000..7c59774
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-httpclient-3.1.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-logging-1.2.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-logging-1.2.jar
new file mode 100644
index 0000000..93a3b9f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-logging-1.2.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-pool-1.6.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-pool-1.6.jar
new file mode 100644
index 0000000..72ca75a
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/commons-pool-1.6.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/dom4j-2.0.3.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/dom4j-2.0.3.jar
new file mode 100644
index 0000000..1ef5c52
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/dom4j-2.0.3.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/druid-0.2.18.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/druid-0.2.18.jar
new file mode 100644
index 0000000..0eb0791
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/druid-0.2.18.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/emoji-java-4.0.0.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/emoji-java-4.0.0.jar
new file mode 100644
index 0000000..3210b99
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/emoji-java-4.0.0.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/fastjson-1.2.46.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/fastjson-1.2.46.jar
new file mode 100644
index 0000000..e528b31
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/fastjson-1.2.46.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/fluent-hc-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/fluent-hc-4.5.13.jar
new file mode 100644
index 0000000..e796d85
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/fluent-hc-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/flyway-core-5.2.4.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/flyway-core-5.2.4.jar
new file mode 100644
index 0000000..61ae3aa
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/flyway-core-5.2.4.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/gson-2.8.2.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/gson-2.8.2.jar
new file mode 100644
index 0000000..d0d030c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/gson-2.8.2.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/hazelcast-3.9.4.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/hazelcast-3.9.4.jar
new file mode 100644
index 0000000..926f186
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/hazelcast-3.9.4.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-4.5.13.jar
new file mode 100644
index 0000000..218ee25
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-cache-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-cache-4.5.13.jar
new file mode 100644
index 0000000..a6cb27f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-cache-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-osgi-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-osgi-4.5.13.jar
new file mode 100644
index 0000000..c2f9ac3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-osgi-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-win-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-win-4.5.13.jar
new file mode 100644
index 0000000..be17606
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpclient-win-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpcore-4.4.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpcore-4.4.13.jar
new file mode 100644
index 0000000..163dc43
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpcore-4.4.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/httpmime-4.5.13.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpmime-4.5.13.jar
new file mode 100644
index 0000000..cc52f44
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/httpmime-4.5.13.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-2.15.11.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-2.15.11.jar
new file mode 100644
index 0000000..7671a0d
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-2.15.11.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-all-4.5.15.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-all-4.5.15.jar
new file mode 100644
index 0000000..c83e25f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/hutool-all-4.5.15.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/jedis-3.3.0.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/jedis-3.3.0.jar
new file mode 100644
index 0000000..1d04c64
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/jedis-3.3.0.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-4.5.2.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-4.5.2.jar
new file mode 100644
index 0000000..78e2058
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-4.5.2.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-platform-4.5.2.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-platform-4.5.2.jar
new file mode 100644
index 0000000..aa34419
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/jna-platform-4.5.2.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/log4j-1.2.16.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/log4j-1.2.16.jar
new file mode 100644
index 0000000..3f9d847
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/log4j-1.2.16.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.0.8-bin.jar_bak b/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.0.8-bin.jar_bak
new file mode 100644
index 0000000..0170c3e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.0.8-bin.jar_bak
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.1.47.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.1.47.jar
new file mode 100644
index 0000000..8816c7e
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/mysql-connector-java-5.1.47.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-buffer-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-buffer-4.1.12.Final.jar
new file mode 100644
index 0000000..e0398ef
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-buffer-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-4.1.12.Final.jar
new file mode 100644
index 0000000..a9f5062
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-http-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-http-4.1.12.Final.jar
new file mode 100644
index 0000000..e92975c
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-codec-http-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-common-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-common-4.1.12.Final.jar
new file mode 100644
index 0000000..e2bd0f3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-common-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-handler-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-handler-4.1.12.Final.jar
new file mode 100644
index 0000000..589f3ff
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-handler-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-resolver-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-resolver-4.1.12.Final.jar
new file mode 100644
index 0000000..4ecb497
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-resolver-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-4.1.12.Final.jar
new file mode 100644
index 0000000..13e235f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-epoll-4.1.12.Final-linux-x86_64.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-epoll-4.1.12.Final-linux-x86_64.jar
new file mode 100644
index 0000000..25e526f
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-epoll-4.1.12.Final-linux-x86_64.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-unix-common-4.1.12.Final.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-unix-common-4.1.12.Final.jar
new file mode 100644
index 0000000..be12509
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/netty-transport-native-unix-common-4.1.12.Final.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/protobuf-java-2.5.0.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/protobuf-java-2.5.0.jar
new file mode 100644
index 0000000..4c4e686
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/protobuf-java-2.5.0.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/qiniu-java-sdk-7.3.0.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/qiniu-java-sdk-7.3.0.jar
new file mode 100644
index 0000000..c4e389b
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/qiniu-java-sdk-7.3.0.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar
new file mode 100644
index 0000000..8f004d3
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-api-1.7.5.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-log4j12-1.7.5.jar b/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-log4j12-1.7.5.jar
new file mode 100644
index 0000000..f5298b5
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/lib/slf4j-log4j12-1.7.5.jar
Binary files differ
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/sql/data.xml b/IMserver/medeasy/WebRoot/WEB-INF/sql/data.xml
new file mode 100644
index 0000000..41af9c8
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/sql/data.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<?DOCTYPE sqls SYSTEM "../config/sql.dtd" ?>
+	
+<sqls>
+	<dataSpace name="system_default">
+	
+		<!-- 		Data Object        -->
+		<sql name="getDataObjectList">
+		    <![CDATA[
+		         select * from sys_dataobject order by orderno
+		    ]]>		
+		</sql>
+		
+		<sql name="getDataObjectPropertys">
+			<![CDATA[
+		         select * from sys_dataProperty where parentid = @{parentid} order by orderno
+		    ]]>		
+		</sql>
+		
+		<sql name="getDataObjectSQLs">
+			<![CDATA[
+		         select * from sys_datasql where parentid = @{parentid} order by typecode
+		    ]]>			
+		</sql>
+		
+		<!-- 		get       -->		
+		<sql name="getEntity">
+			<![CDATA[
+		         select * from @{tablename} where @{filter} @{orderby} @{limit}
+		    ]]>			
+		</sql>
+		
+		<sql name="getEntitySet">
+			<![CDATA[
+                 select * from @{tablename} where @{filter} @{orderby} @{limit}
+		    ]]>		
+		</sql>
+
+		<sql name="getFirstEntity">
+			<![CDATA[
+		         select * from @{tablename} limit 0, 1
+		    ]]>			
+		</sql>		
+		
+		<sql name="getCount">
+			<![CDATA[
+		         select count(1) from @{tablename} where @{filter}
+		    ]]>			
+		</sql>
+
+		<!-- 		set       -->
+		<sql name="insertEntity">
+			<![CDATA[
+		         insert into @{tablename} (@{fieldNames}) values(@{fieldValues})
+		    ]]>			
+		</sql>
+	  
+		<sql name="updateById">
+			<![CDATA[
+		         update @{tablename} set @{fieldNameValues} where id = '@{id}'
+		    ]]>			
+		</sql>
+		
+		<sql name="updateByOther">
+		    <![CDATA[
+		   		 update @{tablename} set @{fieldNameValues} where @{appointColumn} = '@{appointValue}'
+		    ]]>
+		</sql>
+		
+		<sql name="updateByCriteria">
+			<![CDATA[
+		         update @{tablename} set @{entity} where @{filter}
+		    ]]>			
+		</sql>
+
+		<sql name="deleteById">
+			<![CDATA[
+		         delete from @{tablename} where id = '@{id}'
+		    ]]>			
+		</sql>
+		
+		<sql name="deleteChildrenById">
+			<![CDATA[
+		         delete from @{tablename} where parentid = '@{id}'
+		    ]]>			
+		</sql>
+	  
+		<sql name="deleteByCriteria">
+			<![CDATA[
+		         delete from @{tablename} where @{filter} 
+		    ]]>			
+		</sql>
+
+		<sql name="emptyTable">
+		    <![CDATA[
+		         truncate table @{tablename}
+		    ]]>
+		</sql>
+		
+		<sql name="insertCreateTime">
+		    <![CDATA[
+		         insert test (id, createtime) values (replace(uuid(),'-',''), '@{createtime}');
+		    ]]>
+		</sql>
+		
+		<sql name="nextval">
+		    <![CDATA[
+		         select nextval('@{name}')
+		    ]]>
+		</sql>
+		
+		<sql name="currval">
+		    <![CDATA[
+		         select currval('@{name}')
+		    ]]>
+		</sql>
+		
+	</dataSpace>
+
+</sqls>
\ No newline at end of file
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/sql/message.xml b/IMserver/medeasy/WebRoot/WEB-INF/sql/message.xml
new file mode 100644
index 0000000..3cc5fec
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/sql/message.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE sql PUBLIC "sqllist" "sqllist.dtd" >
+ 
+<sqllist>
+	<dataSpace name="Message">
+	
+		<sql name="getUserMessage">
+			<![CDATA[
+				select _seq, _mid from @{tableName} where _uid = @{uid} order by _seq DESC limit 1024
+			]]>
+		</sql>
+		
+		<sql name="addUserMessage">
+			<![CDATA[
+				insert into @{tableName} (_mid, _uid, _seq) values(@{mid}, '@{uid}', @{seq})
+			]]>
+		</sql>
+	
+	</dataSpace>
+	
+</sqllist>
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/sql/user.xml b/IMserver/medeasy/WebRoot/WEB-INF/sql/user.xml
new file mode 100644
index 0000000..4c18d04
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/sql/user.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE sql PUBLIC "sqllist" "sqllist.dtd" >
+ 
+<sqllist>
+	<dataSpace name="User">
+	
+		<sql name="getOneClient">
+			<![CDATA[
+				select * from client where id = '@{id}'
+			]]>
+		</sql>
+		
+		<sql name="getOneNotify">
+			<![CDATA[
+				select * from notify where id = '@{id}'
+			]]>
+		</sql>		
+		
+		<sql name="getOneUserById">
+			<![CDATA[
+				select * from usr where id = '@{id}'
+			]]>
+		</sql>
+		
+		<sql name="getOneUserByPhone">
+			<![CDATA[
+				select * from usr where mobile = '@{phone}'
+			]]>
+		</sql>
+		
+		<sql name="getOneUserByClientId">
+			<![CDATA[
+				select * from usr where exists (
+					select 1 from client where id = '@{clientId}'
+				)
+			]]>
+		</sql>
+		
+		<sql name="getUserSession">
+			<![CDATA[
+				select _cid, _package_name, _token, _voip_token, _secret, _db_secret, _platform, _push_type, 
+				       _device_name, _device_version, _phone_name, _language, _carrier_name, _dt 
+				from t_user_session 
+				where _uid = '@{uid}'
+				  and _deleted = 0
+			]]>
+		</sql>		
+	
+	</dataSpace>
+	
+	<dataSpace name="Friendship">
+	
+		<sql name="getActiveFriendship">
+			<![CDATA[
+				select * from friendship 
+				where statusCode = 'open' or (
+					  statusCode = 'apply' and TO_DAYS(NOW()) - TO_DAYS(createtime) <= 3
+				)
+				order by userid
+			]]>
+		</sql>
+		
+		<sql name="addUserMessage">
+			<![CDATA[
+				insert into @{tableName} (_mid, _uid, _seq) values(@{mid}, '@{uid}', @{seq})
+			]]>
+		</sql>
+	
+	</dataSpace>	
+</sqllist>
+
diff --git a/IMserver/medeasy/WebRoot/WEB-INF/web.xml b/IMserver/medeasy/WebRoot/WEB-INF/web.xml
new file mode 100644
index 0000000..0614bfd
--- /dev/null
+++ b/IMserver/medeasy/WebRoot/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?> 
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
+  <filter>
+    <filter-name>dispatcher</filter-name>
+    <filter-class>chat.server.AppDispatcher</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>dispatcher</filter-name>
+    <url-pattern>*</url-pattern>
+  </filter-mapping>
+  <listener>
+    <listener-class>chat.server.ContextListener</listener-class>
+  </listener>
+  <session-config>
+    <session-timeout>30</session-timeout>
+  </session-config>
+  <welcome-file-list>
+    <welcome-file>/module/system/console.html</welcome-file>
+  </welcome-file-list>
+</web-app>
\ No newline at end of file
diff --git a/IMserver/medeasy/config/i18n/messages.properties b/IMserver/medeasy/config/i18n/messages.properties
new file mode 100644
index 0000000..e65697c
--- /dev/null
+++ b/IMserver/medeasy/config/i18n/messages.properties
@@ -0,0 +1,3 @@
+#native2ascii -encoding UTF-8 messages.properties temp_messages.properties
+Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
+Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
diff --git a/IMserver/medeasy/config/i18n/messages_en.properties b/IMserver/medeasy/config/i18n/messages_en.properties
new file mode 100644
index 0000000..cd14274
--- /dev/null
+++ b/IMserver/medeasy/config/i18n/messages_en.properties
@@ -0,0 +1,2 @@
+Above_Greeting_Message=This's the greeting
+Friend_Can_Start_Chat=You're already friend, start chat now.
diff --git a/IMserver/medeasy/config/i18n/messages_en_US.properties b/IMserver/medeasy/config/i18n/messages_en_US.properties
new file mode 100644
index 0000000..cd14274
--- /dev/null
+++ b/IMserver/medeasy/config/i18n/messages_en_US.properties
@@ -0,0 +1,2 @@
+Above_Greeting_Message=This's the greeting
+Friend_Can_Start_Chat=You're already friend, start chat now.
diff --git a/IMserver/medeasy/config/i18n/messages_zh.properties b/IMserver/medeasy/config/i18n/messages_zh.properties
new file mode 100644
index 0000000..cc22382
--- /dev/null
+++ b/IMserver/medeasy/config/i18n/messages_zh.properties
@@ -0,0 +1,2 @@
+Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
+Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
diff --git a/IMserver/medeasy/config/i18n/messages_zh_CN.properties b/IMserver/medeasy/config/i18n/messages_zh_CN.properties
new file mode 100644
index 0000000..cc22382
--- /dev/null
+++ b/IMserver/medeasy/config/i18n/messages_zh_CN.properties
@@ -0,0 +1,2 @@
+Above_Greeting_Message=\u4ee5\u4e0a\u662f\u6253\u62db\u547c\u4fe1\u606f
+Friend_Can_Start_Chat=\u4f60\u4eec\u5df2\u7ecf\u6210\u4e3a\u597d\u53cb\u4e86\uff0c\u73b0\u5728\u53ef\u4ee5\u5f00\u59cb\u804a\u5929\u4e86
diff --git a/IMserver/medeasy/src/chat/consts/APIPath.java b/IMserver/medeasy/src/chat/consts/APIPath.java
new file mode 100644
index 0000000..2545979
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/APIPath.java
@@ -0,0 +1,79 @@
+package chat.consts;
+
+public interface APIPath {
+	
+    String Create_Chatroom = "/admin/chatroom/create";
+    String Chatroom_Destroy = "/admin/chatroom/del";
+    String Chatroom_Info = "/admin/chatroom/info";
+    String Chatroom_GetMembers = "/admin/chatroom/members";
+    String Chatroom_SetBlacklist = "/admin/chatroom/set_black_status";
+    String Chatroom_GetBlacklist = "/admin/chatroom/get_black_status";
+    String Chatroom_SetManager = "/admin/chatroom/set_manager";
+    String Chatroom_GetManagerList = "/admin/chatroom/get_manager_list";
+    String Chatroom_MuteAll = "/admin/chatroom/mute_all";
+
+
+    String Sensitive_Add = "/admin/sensitive/add";
+    String Sensitive_Del = "/admin/sensitive/del";
+    String Sensitive_Query = "/admin/sensitive/query";
+
+    String Create_User = "/admin/user/create";
+    String Destroy_User = "/admin/user/destroy";
+    String Create_Robot = "/admin/robot/create";
+    String CreateOrUpdate_Device = "/admin/device/create";
+    String Get_Device = "/admin/device/get";
+    String Get_User_Devices = "/admin/device/user_devices";
+    String User_Get_Token = "/admin/user/get_token";
+    String User_Update_Block_Status = "/admin/user/update_block_status";
+    String User_Get_Info = "/admin/user/get_info";
+    String User_Get_Blocked_List = "/admin/user/get_blocked_list";
+    String User_Check_Block_Status = "/admin/user/check_block_status";
+    String User_Get_Online_Status = "/admin/user/onlinestatus";
+
+
+    String Friend_Update_Status = "/admin/friend/status";
+    String Friend_Get_List = "/admin/friend/list";
+    String Blacklist_Update_Status = "/admin/blacklist/status";
+    String Blacklist_Get_List = "/admin/blacklist/list";
+    String Friend_Get_Alias = "/admin/friend/get_alias";
+    String Friend_Set_Alias = "/admin/friend/set_alias";
+    String Friend_Send_Request = "/admin/friend/send_request";
+    String Friend_Get_Requests = "/admin/friend/get_requests";
+
+    String Msg_Send = "/admin/message/send";
+    String Msg_Recall = "/admin/message/recall";
+    String Msg_Delete = "/admin/message/delete";
+    String Msg_Broadcast = "/admin/message/broadcast";
+    String Msg_Multicast = "/admin/message/multicast";
+    String Msg_RecallBroadCast = "/admin/message/recall_broadcast";
+    String Msg_RecallMultiCast = "/admin/message/recall_multicast";
+
+    String Create_Group = "/admin/group/create";
+    String Group_Dismiss = "/admin/group/del";
+    String Group_Transfer = "/admin/group/transfer";
+    String Group_Get_Info = "/admin/group/get_info";
+    String Group_Modify_Info = "/admin/group/modify";
+    String Group_Member_List = "/admin/group/member/list";
+    String Group_Member_Add = "/admin/group/member/add";
+    String Group_Member_Kickoff = "/admin/group/member/del";
+    String Group_Member_Quit = "/admin/group/member/quit";
+    String Group_Set_Manager = "/admin/group/manager/set";
+    String Group_Mute_Member = "/admin/group/manager/mute";
+    String Group_Allow_Member = "/admin/group/manager/allow";
+    String Get_User_Groups = "/admin/group/of_user";
+
+
+    String Create_Channel = "/admin/channel/create";
+    String Get_System_Setting = "/admin/system/get_setting";
+    String Put_System_Setting = "/admin/system/put_setting";
+
+    String Channel_User_Info = "/channel/user_info";
+    String Channel_Update_Profile = "/channel/update_profile";
+    String Channel_Get_Profile = "/channel/get_profile";
+    String Channel_Message_Send = "/channel/message/send";
+    String Channel_Subscribe = "/channel/subscribe";
+    String Channel_Subscriber_List = "/channel/subscriber_list";
+
+    String Robot_User_Info = "/robot/user_info";
+    String Robot_Message_Send = "/robot/message/send";
+}
diff --git a/IMserver/medeasy/src/chat/consts/BrokerConstants.java b/IMserver/medeasy/src/chat/consts/BrokerConstants.java
new file mode 100644
index 0000000..d0f3e0e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/BrokerConstants.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012-2017 The original author or authors
+ * ------------------------------------------------------
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * The Apache License v2.0 is available at
+ * http://www.opensource.org/licenses/apache2.0.php
+ *
+ * You may elect to redistribute this code under either of these licenses.
+ */
+
+package chat.consts;
+
+import java.io.File;
+
+public final class BrokerConstants {
+
+    public static final String INTERCEPT_HANDLER_PROPERTY_NAME = "intercept.handler";
+    public static final String BROKER_INTERCEPTOR_THREAD_POOL_SIZE = "intercept.thread_pool.size";
+    public static final String PERSISTENT_STORE_PROPERTY_NAME = "persistent_store";
+    public static final String SERVER_IP_PROPERTY_NAME = "server.ip";
+    public static final String PORT_PROPERTY_NAME = "port";
+    public static final String HOST_PROPERTY_NAME = "host";
+    public static final String HTTP_SERVER_PORT = "http_port";
+    public static final String HTTP_LOCAL_PORT = "local_port";
+
+    public static final String HTTP_ADMIN_PORT = "http.admin.port";
+    public static final String NODE_ID = "node_id";
+    public static final String NODE_IDS = "node_ids";
+    public static final String DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME = "moquette_store.mapdb";
+    public static final String DEFAULT_PERSISTENT_PATH = System.getProperty("user.dir") + File.separator
+            + DEFAULT_MOQUETTE_STORE_MAP_DB_FILENAME;
+    public static final String WEB_SOCKET_PORT_PROPERTY_NAME = "websocket_port";
+    public static final String WSS_PORT_PROPERTY_NAME = "secure_websocket_port";
+    public static final String SSL_PORT_PROPERTY_NAME = "ssl_port";
+    public static final String JKS_PATH_PROPERTY_NAME = "jks_path";
+    public static final String KEY_STORE_PASSWORD_PROPERTY_NAME = "key_store_password";
+    public static final String KEY_MANAGER_PASSWORD_PROPERTY_NAME = "key_manager_password";
+    public static final String AUTHORIZATOR_CLASS_NAME = "authorizator_class";
+    public static final String DB_AUTHENTICATOR_DRIVER = "authenticator.db.driver";
+    public static final String DB_AUTHENTICATOR_URL = "authenticator.db.url";
+    public static final String DB_AUTHENTICATOR_QUERY = "authenticator.db.query";
+    public static final String DB_AUTHENTICATOR_DIGEST = "authenticator.db.digest";
+    public static final int PORT = 1883;
+    public static final int WEBSOCKET_PORT = 8080;
+    public static final String DISABLED_PORT_BIND = "disabled";
+    public static final String HOST = "0.0.0.0";
+    public static final String NEED_CLIENT_AUTH = "need_client_auth";
+    public static final String HAZELCAST_CONFIGURATION = "hazelcast.configuration";
+    public static final String HAZELCAST_CLIENT_IP = "hazelcast.client.ip";
+    public static final String HAZELCAST_CLIENT_PORT = "hazelcast.client.port";
+    public static final String NETTY_SO_BACKLOG_PROPERTY_NAME = "netty.so_backlog";
+    public static final String NETTY_SO_REUSEADDR_PROPERTY_NAME = "netty.so_reuseaddr";
+    public static final String NETTY_TCP_NODELAY_PROPERTY_NAME = "netty.tcp_nodelay";
+    public static final String NETTY_SO_KEEPALIVE_PROPERTY_NAME = "netty.so_keepalive";
+    public static final String NETTY_CHANNEL_TIMEOUT_SECONDS_PROPERTY_NAME = "netty.channel_timeout.seconds";
+    public static final String NETTY_EPOLL_PROPERTY_NAME = "netty.epoll";
+
+    public static final String STORAGE_CLASS_NAME = "storage_class";
+
+    public static final String QINIU_SERVER_URL= "qiniu.server_url";
+	public static final String QINIU_ACCESS_KEY = "qiniu.access_key";
+	public static final String QINIU_SECRET_KEY = "qiniu.secret_key";
+
+    public static final String QINIU_BUCKET_GENERAL_NAME= "qiniu.bucket_general_name";
+    public static final String QINIU_BUCKET_GENERAL_DOMAIN = "qiniu.bucket_general_domain";
+    public static final String QINIU_BUCKET_IMAGE_NAME= "qiniu.bucket_image_name";
+    public static final String QINIU_BUCKET_IMAGE_DOMAIN = "qiniu.bucket_image_domain";
+    public static final String QINIU_BUCKET_VOICE_NAME= "qiniu.bucket_voice_name";
+    public static final String QINIU_BUCKET_VOICE_DOMAIN = "qiniu.bucket_voice_domain";
+    public static final String QINIU_BUCKET_VIDEO_NAME= "qiniu.bucket_video_name";
+    public static final String QINIU_BUCKET_VIDEO_DOMAIN = "qiniu.bucket_video_domain";
+    public static final String QINIU_BUCKET_FILE_NAME= "qiniu.bucket_file_name";
+    public static final String QINIU_BUCKET_FILE_DOMAIN = "qiniu.bucket_file_domain";
+    public static final String QINIU_BUCKET_STICKER_NAME= "qiniu.bucket_sticker_name";
+    public static final String QINIU_BUCKET_STICKER_DOMAIN = "qiniu.bucket_sticker_domain";
+    public static final String QINIU_BUCKET_MOMENTS_NAME= "qiniu.bucket_moments_name";
+    public static final String QINIU_BUCKET_MOMENTS_DOMAIN = "qiniu.bucket_moments_domain";
+    public static final String QINIU_BUCKET_PORTRAIT_NAME= "qiniu.bucket_portrait_name";
+    public static final String QINIU_BUCKET_PORTRAIT_DOMAIN = "qiniu.bucket_portrait_domain";
+    public static final String QINIU_BUCKET_FAVORITE_NAME= "qiniu.bucket_favorite_name";
+    public static final String QINIU_BUCKET_FAVORITE_DOMAIN = "qiniu.bucket_favorite_domain";
+
+    public static final String FILE_STORAGE_ROOT = "local.media.storage.root";
+    public static final String USER_QINIU = "media.server.use_qiniu";
+
+    public static final String PUSH_ANDROID_SERVER_ADDRESS = "push.android.server.address";
+    public static final String PUSH_IOS_SERVER_ADDRESS = "push.ios.server.address";
+
+    public static final String USER_ONLINE_STATUS_CALLBACK = "user.online_status_callback";
+
+    public static final String HZ_Cluster_Node_External_IP = "node_external_ip";
+    public static final String HZ_Cluster_Node_External_Long_Port = "node_external_long_port";
+    public static final String HZ_Cluster_Node_External_Short_Port = "node_external_short_port";
+    public static final String HZ_Cluster_Node_ID = "node_id";
+    public static final String HTTP_SERVER_SECRET_KEY = "http.admin.secret_key";
+    public static final String HTTP_SERVER_API_NO_CHECK_TIME = "http.admin.no_check_time";
+
+    public static final String CLIENT_PROTO_SECRET_KEY = "client.proto.secret_key";
+    public static final String TOKEN_SECRET_KEY = "token.key";
+    public static final String TOKEN_EXPIRE_TIME = "token.expire_time";
+
+    public static final String EMBED_DB_PROPERTY_NAME = "embed.db";
+
+    public static final String HZ_Cluster_Master_Node = "master_node";
+
+    public static final String SENSITIVE_Filter_Type = "sensitive.filter.type";
+
+    public static final String MESSAGE_Forward_Url = "message.forward.url";
+
+    public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint";
+    public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification";
+
+    public static final String MONGODB_Client_URI = "mongodb.client_uri";
+    public static final String MONGODB_Database = "mongodb.database";
+    public static final String MONGODB_Data_Expire_Days = "mongodb.data_expire_days";
+
+    public static final String MESSAGE_ROAMING = "message.roaming";
+    public static final String MESSAGE_Remote_History_Message = "message.remote_history_message";
+
+    public static final String MESSAGE_Max_Queue = "message.max_queue";
+
+    public static final String MESSAGE_Disable_Stranger_Chat = "message.disable_stranger_chat";
+
+    public static final String MESSAGE_Blacklist_Strategy = "message.blacklist.strategy";
+
+    public static final String FRIEND_Disable_Search = "friend.disable_search";
+    public static final String FRIEND_Disable_NickName_Search = "friend.disable_nick_name_search";
+    public static final String FRIEND_Disable_Friend_Request = "friend.disable_friend_request";
+    public static final String FRIEND_Repeat_Request_Duration = "friend.repeat_request_duration";
+    public static final String FRIEND_Reject_Request_Duration = "friend.reject_request_duration";
+    public static final String FRIEND_Request_Expiration_Duration = "friend.request_expiration_duration";
+    public static final String FRIEND_New_Welcome_Message = "friend.new_welcome_message";
+
+    public static final String CHATROOM_Participant_Idle_Time = "chatroom.participant_idle_time";
+    public static final String CHATROOM_Rejoin_When_Active = "chatroom.rejoin_when_active";
+
+    public static final String MESSAGES_DISABLE_REMOTE_SEARCH = "message.disable_remote_search";
+
+    public static final String MESSAGES_RECALL_TIME_LIMIT = "message.recall_time_limit";
+
+    private BrokerConstants() {
+    }
+}
diff --git a/IMserver/medeasy/src/chat/consts/MediaServerConfig.java b/IMserver/medeasy/src/chat/consts/MediaServerConfig.java
new file mode 100644
index 0000000..bfb69c2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/MediaServerConfig.java
@@ -0,0 +1,33 @@
+package chat.consts;
+
+public class MediaServerConfig {
+	public static String QINIU_SERVER_URL = "up.qbox.me";
+	public static String QINIU_ACCESS_KEY = "tU3vdBK5BL5j4N7jI5N5uZgq_HQDo170w5C9Amnn";
+	public static String QINIU_SECRET_KEY = "YfQIJdgp5YGhwEw14vGpaD2HJZsuJldWtqens7i5";
+
+    public static String QINIU_BUCKET_GENERAL_NAME;
+    public static String QINIU_BUCKET_GENERAL_DOMAIN;
+    public static String QINIU_BUCKET_IMAGE_NAME;
+    public static String QINIU_BUCKET_IMAGE_DOMAIN;
+    public static String QINIU_BUCKET_VOICE_NAME;
+    public static String QINIU_BUCKET_VOICE_DOMAIN;
+    public static String QINIU_BUCKET_VIDEO_NAME;
+    public static String QINIU_BUCKET_VIDEO_DOMAIN;
+    public static String QINIU_BUCKET_FILE_NAME;
+    public static String QINIU_BUCKET_FILE_DOMAIN;
+    public static String QINIU_BUCKET_STICKER_NAME;
+    public static String QINIU_BUCKET_STICKER_DOMAIN;
+    public static String QINIU_BUCKET_MOMENTS_NAME;
+    public static String QINIU_BUCKET_MOMENTS_DOMAIN;
+    public static String QINIU_BUCKET_PORTRAIT_NAME;
+    public static String QINIU_BUCKET_PORTRAIT_DOMAIN;
+    public static String QINIU_BUCKET_FAVORITE_NAME;
+    public static String QINIU_BUCKET_FAVORITE_DOMAIN;
+    
+    public static String SERVER_IP = "192.168.31.117";//47.92.101.186  192.168.31.117
+    public static int HTTP_SERVER_PORT = 80;
+    public static String FILE_STROAGE_ROOT = "fs";
+    public static boolean USER_QINIU = false;
+
+
+}
diff --git a/IMserver/medeasy/src/chat/consts/ProtoConstants.java b/IMserver/medeasy/src/chat/consts/ProtoConstants.java
new file mode 100644
index 0000000..5c7465b
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/ProtoConstants.java
@@ -0,0 +1,188 @@
+package chat.consts;
+
+public class ProtoConstants {
+
+    //message Conversation -> type
+    public interface ConversationType {
+        int ConversationType_Private = 0;
+        int ConversationType_Group = 1;
+        int ConversationType_ChatRoom = 2;
+        int ConversationType_Channel = 3;
+        int ConversationType_Things = 4;
+    }
+
+    //message GroupInfo -> type
+    public interface GroupType {
+        //member can add quit change group name and portrait, owner can do all the operations
+        int GroupType_Normal = 0;
+        //every member can add quit change group name and portrait, no one can kickoff others
+        int GroupType_Free = 1;
+        //member can only quit, owner can do all the operations
+        int GroupType_Restricted = 2;
+    }
+
+    //message GroupMember -> type
+    public interface GroupMemberType {
+        int GroupMemberType_Normal = 0;
+        int GroupMemberType_Manager = 1;
+        int GroupMemberType_Owner = 2;
+        int GroupMemberType_Silent = 3;
+        int GroupMemberType_Removed = 4;
+        int GroupMemberType_Allowed = 5;
+    }
+
+    //message FriendRequest -> status
+    public interface FriendRequestStatus {
+        int RequestStatus_Sent = 0;
+        int RequestStatus_Accepted = 1;
+        int RequestStatus_Rejected = 2;
+    }
+
+    //message UploadDeviceTokenRequest -> platform
+    public interface Platform {
+        int Platform_UNSET = 0;
+        int Platform_iOS = 1;
+        int Platform_Android = 2;
+        int Platform_Windows = 3;
+        int Platform_OSX = 4;
+        int Platform_WEB = 5;
+        int Platform_WX = 6;
+        int Platform_LINUX = 7;
+    }
+
+    //message NotifyMessage & PullMessageRequest -> type
+    public interface PullType {
+        int Pull_Normal = 0;
+        int Pull_ChatRoom = 1;
+        int Pull_Group = 2;
+    }
+
+    //message UserResult -> code
+    public interface UserResultCode {
+        int Success = 0;
+        int NotFound = 1;
+        int NotModified = 2;
+    }
+
+    //message ChatroomInfo -> state
+    public interface ChatroomState {
+        int Chatroom_State_Normal = 0;
+        int Chatroom_State_NotStart = 1;
+        int Chatroom_State_End = 2;
+    }
+
+
+    //message MessageContent -> contentType
+    public interface ContentType {
+        int Unknown = 0;
+        int Text = 1;
+        int Voice = 2;
+        int Image = 3;
+        int Location = 4;
+        int File = 5;
+        int Video = 6;
+        int Sticker = 7;
+        int RichMedia = 8;
+    }
+
+    //ModifyGroupInfoRequest -> type
+    public interface ModifyGroupInfoType {
+        int Modify_Group_Name = 0;
+        int Modify_Group_Portrait = 1;
+        int Modify_Group_Extra = 2;
+        int Modify_Group_Mute = 3;
+        int Modify_Group_JoinType = 4;
+        int Modify_Group_PrivateChat = 5;
+        int Modify_Group_Searchable = 6;
+    }
+
+    //ModifyGroupInfoRequest -> type
+    public interface PersistFlag {
+        int Not_Persist = 0;
+        int Persist = 1;
+        int Persist_And_Count = 3;
+        int Transparent = 4;
+    }
+
+
+    //ModifyChannelInfoRequest -> type
+    public interface ModifyChannelInfoType {
+        int Modify_Channel_Name = 0;
+        int Modify_Channel_Portrait = 1;
+        int Modify_Channel_Desc = 2;
+        int Modify_Channel_Extra = 3;
+        int Modify_Channel_Secret = 4;
+        int Modify_Channel_Callback = 5;
+        int Modify_Channel_OnlyCallback = 6;
+    }
+
+    //Channel -> status
+    //绗�0浣嶈〃绀烘槸鍚﹀厑璁告煡鐪嬬敤鎴锋墍鏈変俊鎭紝杩樻槸鍙厑璁哥湅鐢ㄦ埛id锛岀敤鎴峰悕绉帮紝鐢ㄦ埛鏄电О鍜岀敤鎴峰ご鍍�
+    //绗�1浣嶈〃绀烘槸鍚﹀厑璁告煡鐪嬮潪璁㈤槄鐢ㄦ埛淇℃伅
+    //绗�2浣嶈〃绀烘槸鍚﹀厑璁镐富鍔ㄦ坊鍔犵敤鎴疯闃呭叧绯�
+    //绗�3浣嶈〃绀烘槸鍚﹀厑璁哥粰闈炶闃呯敤鎴峰彂閫佹秷鎭�
+    //绗�4浣嶈〃绀烘槸鍚︾鏈�
+    //绗�6浣嶈〃绀烘槸鍚﹀垹闄�
+    public interface ChannelState {
+        int Channel_State_Mask_FullInfo = 0x01;
+        int Channel_State_Mask_Unsubscribed_User_Access = 0x02;
+        int Channel_State_Mask_Active_Subscribe = 0x04;
+        int Channel_State_Mask_Message_Unsubscribed = 0x08;
+        int Channel_State_Mask_Private = 0x10;
+        int Channel_State_Mask_Deleted = 0x40;
+    }
+
+
+    public interface UserType {
+        int UserType_Normal = 0;
+        int UserType_Robot = 1;
+        int UserType_Device = 2;
+        int UserType_Admin = 3;
+        int UserType_Super_Admin = 100;
+    }
+
+
+    public interface SystemSettingType {
+        int Group_Max_Member_Count = 1;
+    }
+
+    public interface SearchUserType {
+        int SearchUserType_General = 0;
+        int SearchUserType_Name_Mobile = 1;
+        int SearchUserType_Name = 2;
+        int SearchUserType_Mobile = 3;
+    }
+
+    public interface UserStatus {
+        int Normal = 0;
+        int Muted = 1;
+        int Forbidden = 2;
+    }
+
+    public interface BlacklistStrategy {
+        int Message_Reject = 0;
+        int Message_Ignore = 1;
+    }
+
+
+
+    public static final int MESSAGE_CONTENT_TYPE_CREATE_GROUP = 104;
+    public static final int MESSAGE_CONTENT_TYPE_ADD_GROUP_MEMBER = 105;
+    public static final int MESSAGE_CONTENT_TYPE_KICKOF_GROUP_MEMBER = 106;
+    public static final int MESSAGE_CONTENT_TYPE_QUIT_GROUP = 107;
+    public static final int MESSAGE_CONTENT_TYPE_DISMISS_GROUP = 108;
+    public static final int MESSAGE_CONTENT_TYPE_TRANSFER_GROUP_OWNER = 109;
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_GROUP_NAME = 110;
+    public static final int MESSAGE_CONTENT_TYPE_MODIFY_GROUP_ALIAS = 111;
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_GROUP_PORTRAIT = 112;
+
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_MUTE = 113;
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_JOINTYPE = 114;
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_PRIVATECHAT = 115;
+    public static final int MESSAGE_CONTENT_TYPE_CHANGE_SEARCHABLE = 116;
+
+    public static final int MESSAGE_CONTENT_TYPE_SET_MANAGER = 117;
+    public static final int MESSAGE_CONTENT_TYPE_MUTE_MEMBER = 118;
+    public static final int MESSAGE_CONTENT_TYPE_ALLOW_MEMBER = 119;
+}
+
diff --git a/IMserver/medeasy/src/chat/consts/RestResult.java b/IMserver/medeasy/src/chat/consts/RestResult.java
new file mode 100644
index 0000000..7c6c4f7
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/RestResult.java
@@ -0,0 +1,85 @@
+package chat.consts;
+
+public class RestResult {
+    public enum  RestCode {
+        SUCCESS(0, "success"),
+        ERROR_INVALID_MOBILE(1, "鏃犳晥鐨勭數璇濆彿鐮�"),
+        ERROR_SEND_SMS_OVER_FREQUENCY(3, "璇锋眰楠岃瘉鐮佸お棰戠箒"),
+        ERROR_SERVER_ERROR(4, "鏈嶅姟鍣ㄥ紓甯�"),
+        ERROR_CODE_EXPIRED(5, "楠岃瘉鐮佸凡杩囨湡"),
+        ERROR_CODE_INCORRECT(6, "楠岃瘉鐮侀敊璇�"),
+        ERROR_SERVER_CONFIG_ERROR(7, "鏈嶅姟鍣ㄩ厤缃敊璇�"),
+        ERROR_SESSION_EXPIRED(8, "浼氳瘽涓嶅瓨鍦ㄦ垨宸茶繃鏈�"),
+        ERROR_SESSION_NOT_VERIFIED(9, "浼氳瘽娌℃湁楠岃瘉"),
+        ERROR_SESSION_NOT_SCANED(10, "浼氳瘽娌℃湁琚壂鐮�"),
+        ERROR_SERVER_NOT_IMPLEMENT(11, "鍔熻兘娌℃湁瀹炵幇"),
+        ERROR_GROUP_ANNOUNCEMENT_NOT_EXIST(12, "缇ゅ叕鍛婁笉瀛樺湪"),
+        ERROR_NOT_LOGIN(13, "娌℃湁鐧诲綍"),
+        ERROR_NO_RIGHT(14, "娌℃湁鏉冮檺"),
+        ERROR_INVALID_PARAMETER(15, "鏃犳晥鍙傛暟"),
+        ERROR_NOT_EXIST(16, "瀵硅薄涓嶅瓨鍦�"),
+        ERROR_USER_NAME_ALREADY_EXIST(17, "鐢ㄦ埛鍚嶅凡缁忓瓨鍦�"),
+        ERROR_SESSION_CANCELED(18, "浼氳瘽宸茬粡鍙栨秷");
+    	
+        public int code;
+        public String msg;
+
+        RestCode(int code, String msg) {
+            this.code = code;
+            this.msg = msg;
+        }
+
+    }
+    private int code;
+    private String message;
+    private Object result;
+
+    public static RestResult ok(Object object) {
+        return new RestResult(RestCode.SUCCESS, object);
+    }
+
+    public static RestResult error(RestCode code) {
+        return new RestResult(code, null);
+    }
+
+    public static RestResult result(RestCode code, Object object){
+        return new RestResult(code, object);
+    }
+
+    public static RestResult result(int code, String message, Object object){
+        RestResult r = new RestResult(RestCode.SUCCESS, object);
+        r.code = code;
+        r.message = message;
+        return r;
+    }
+
+    private RestResult(RestCode code, Object result) {
+        this.code = code.code;
+        this.message = code.msg;
+        this.result = result;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Object getResult() {
+        return result;
+    }
+
+    public void setResult(Object result) {
+        this.result = result;
+    }
+}
diff --git a/IMserver/medeasy/src/chat/consts/UserSettingScope.java b/IMserver/medeasy/src/chat/consts/UserSettingScope.java
new file mode 100644
index 0000000..dfdc0cb
--- /dev/null
+++ b/IMserver/medeasy/src/chat/consts/UserSettingScope.java
@@ -0,0 +1,17 @@
+package chat.consts;
+
+public interface UserSettingScope {
+    int kUserSettingConversationSilent = 1;
+    int kUserSettingGlobalSilent = 2;
+    int kUserSettingConversationTop = 3;
+
+    int kUserSettingHiddenNotificationDetail = 4;
+    int kUserSettinGroupHideNickname = 5;
+    int kUserSettingFavouriteGroup = 6;
+    int kUserSettingConversationSync = 7;
+    int kUserSettingMyChannels = 8;
+    int kUserSettingListenedChannels = 9;
+    int kUserSettingPCOnline = 10;
+
+    int kUserSettingCustomBegin = 1000;
+}
diff --git a/IMserver/medeasy/src/chat/handler/ChannelHandler.java b/IMserver/medeasy/src/chat/handler/ChannelHandler.java
new file mode 100644
index 0000000..4dd735e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/ChannelHandler.java
@@ -0,0 +1,148 @@
+package chat.handler;
+
+import java.util.Date;
+import java.util.List;
+
+import chat.module.ChannelBucket;
+import chat.module.entity.Channel;
+import chat.module.entity.MessageRecord;
+import chat.module.entity.PublishOperator;
+import chat.server.call.CallObject;
+import cn.wildfirechat.proto.WFCMessage;
+
+public class ChannelHandler extends CallObject {
+
+	private static ChannelBucket channelBucket;
+	
+	static {
+		channelBucket = ChannelBucket.getInstance();
+	}
+	
+	@Override
+	protected void publishMethod() {
+		addOneMethod("create");
+		addOneMethod("destroy");
+		addOneMethod("getInfo");
+		addOneMethod("getRoomList");
+		addOneMethod("join");
+		addOneMethod("leave");
+		addOneMethod("kickoff");
+		addOneMethod("pull");
+		addOneMethod("publish");
+	}
+	
+	public void create() {
+		String channelName = dataPool.getString("channelName");
+		
+		//1. create 
+//		channelBucket.createOne(channelName, user);
+		
+		//2. result
+		resultPool.success();
+	}
+	
+	public void destroy() {
+		String channelId = dataPool.getString("channelId");
+		
+		Channel channel = channelBucket.getOne(channelId);
+		
+		if (channel == null) {
+			return;
+		}
+		
+		//1. notify members
+		channel.notify(PublishOperator.Destroy, user);
+		
+		//2. delete room
+		channelBucket.deleteOne(channelId);
+		
+		//3. result
+		resultPool.success();
+	}
+	
+	public void pullChannel() throws Exception {
+		//澶�
+		WFCMessage.PullChannelInfo request = (WFCMessage.PullChannelInfo) dataPool.getWFCMessage(WFCMessage.PullChannelInfo.class);
+		
+		//灏�
+		WFCMessage.ChannelInfo info = null;//m_messagesStore.getChannelInfo(request.getChannelId());
+		byte[] resBytes = info.toByteArray();
+		resultPool.setBytes(resBytes);
+	}
+
+	public void getInfo() {
+		String channelId = dataPool.getString("channelId");
+		Channel channel = channelBucket.getOne(channelId);
+		
+		resultPool.add(channel);
+	}
+	
+	public void getChannelList() {
+		List<Channel> channeList = channelBucket.getAll();
+		resultPool.add(channeList);
+	}
+	
+	public void subscribe() {
+		String channelId = dataPool.getString("channelId");
+		
+		Channel channel = channelBucket.getOne(channelId);
+		
+		if (channel == null) {
+			return;
+		}
+		
+		//1. add subscriber
+		channel.join(channelId, user);
+	}
+	
+	public void unsubscribe() {
+		String channelId = dataPool.getString("channelId");
+		
+		Channel channel = channelBucket.getOne(channelId);
+		
+		if (channel == null) {
+			return;
+		}
+		
+		//1. delete member
+		channel.leave(user);
+	}
+	
+	protected void pull() {
+		String channelId = dataPool.getString("channelId");
+		long timeStamp = Long.parseLong(dataPool.getString("timePoint"));
+		
+		Channel channel = channelBucket.getOne(channelId);
+		
+		if (channel == null) {
+			return;
+		}
+		
+		//1. get message list
+		List<MessageRecord> messageList = channel.getMessageList(timeStamp);
+		
+		//2. result
+		resultPool.add(messageList);
+	}
+	
+	protected void publish() {
+		//1.
+		String channelId = dataPool.getString("channelId");
+		MessageRecord record = dataPool.getMessageRecord();
+		
+		Channel channel = channelBucket.getOne(channelId);
+		
+		if (channel == null) {
+			return;
+		}
+		
+		//1. add to message list
+		//channel.publishOneMessage(record, user, true, null);
+		
+		//2. publish
+		channel.notify(PublishOperator.PublishMessage, record, user);
+		
+		//3. result
+		resultPool.success();
+	}
+}
diff --git a/IMserver/medeasy/src/chat/handler/ChatRoomHandler.java b/IMserver/medeasy/src/chat/handler/ChatRoomHandler.java
new file mode 100644
index 0000000..498407e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/ChatRoomHandler.java
@@ -0,0 +1,216 @@
+package chat.handler;
+
+import java.util.Date;
+import java.util.List;
+
+import com.google.gson.Gson;
+
+import chat.module.ChatroomBucket;
+import chat.module.entity.ChatRoom;
+import chat.module.entity.Member;
+import chat.module.entity.MessageRecord;
+import chat.module.entity.PublishOperator;
+import chat.server.call.CallObject;
+import cn.wildfirechat.proto.WFCMessage;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+public class ChatRoomHandler extends CallObject {
+	
+	private static ChatroomBucket chatroomBucket;
+	
+	static {
+		chatroomBucket = ChatroomBucket.getInstance();
+	}
+
+	@Override
+	protected void publishMethod() {
+		addOneMethod("create");
+		addOneMethod("destroy");
+		addOneMethod("getInfo");
+		addOneMethod("getRoomList");
+		addOneMethod("join");
+		addOneMethod("leave");
+		addOneMethod("kickoff");
+		addOneMethod("pull");
+		addOneMethod("publish");
+	}
+	
+	public void create() {
+		String roomName = dataPool.getString("roomName");
+		
+		//1. add room
+//		chatroomBucket.createOne(roomName, user);
+		
+		//2. result
+		resultPool.success();
+	}
+	
+	public void destroy() {
+		String userId = user.getId();
+		String roomId = dataPool.getString("roomId");
+		
+		//1. notify members
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		chatRoom.notify(PublishOperator.Destroy, userId);
+		
+		//2. delete room
+		chatroomBucket.deleteOne(roomId);
+		
+		//3. result
+		resultPool.success();
+	}
+	
+	public void chatRoomInfo() throws Exception {
+		//澶�
+		WFCMessage.GetChatroomInfoRequest request = (WFCMessage.GetChatroomInfoRequest) dataPool.getWFCMessage(WFCMessage.GetChatroomInfoRequest.class);
+		
+				
+		//涓� 鐭繛鎺ヤ娇鐢�
+//		RestResult result = null;
+//		dataPool.getResponse().setStatus(HttpResponseStatus.OK);
+//		dataPool.getResponse().setContent(new Gson().toJson(result));
+		
+		//灏�
+		//handle
+		WFCMessage.ChatroomInfo info = null;
+		int memberCount = 10;
+        byte[] bytes = info.toBuilder().setMemberCount(memberCount).build().toByteArray();
+        
+        resultPool.setBytes(bytes);
+	}
+	
+	public void getChatRoomMember() throws Exception {
+		//澶�
+		WFCMessage.GetChatroomMemberInfoRequest request = (WFCMessage.GetChatroomMemberInfoRequest) dataPool.getWFCMessage(WFCMessage.GetChatroomMemberInfoRequest.class);
+		
+		//涓� 鐭繛鎺�
+//		RestResult result = null;
+//		dataPool.getResponse().setStatus(HttpResponseStatus.OK);
+//		dataPool.getResponse().setContent(new Gson().toJson(result));
+		
+		//灏�
+		WFCMessage.ChatroomMemberInfo info = null;
+		byte[] bytes = info.toByteArray();
+		
+		resultPool.setBytes(bytes);
+	}
+	
+	public void joinChatRoom() throws Exception {
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+
+	public void getInfo() {
+		String roomId = dataPool.getString("roomId");
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		resultPool.add(chatRoom);
+	}
+	
+	public void getRoomList() {
+		List<ChatRoom> roomlist = chatroomBucket.getAll();
+		resultPool.add(roomlist);
+	}
+	
+	public void join() {
+		String userId = user.getId();
+		String roomId = dataPool.getString("roomId");
+		
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		if (chatRoom == null) {
+			return;
+		}
+		
+		//1. notify
+		chatRoom.notify(PublishOperator.Join, userId);
+		
+		//2. add member
+		Member member = new Member(roomId, "");
+		chatRoom.addOneMember(member);
+		
+		//3. result
+		resultPool.success();
+	}
+	
+	public void leave() throws Exception {
+		String userId = user.getId();
+		String roomId = dataPool.getString("roomId");
+		
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		if (chatRoom == null) {
+			return;
+		}
+		
+		//1. notify
+		chatRoom.notify(PublishOperator.Leave, userId);
+		
+		//2. delete member
+		chatRoom.deleteOneMember(userId);
+		
+		//3. result
+		resultPool.success();
+	}
+	
+	public void kickoff() throws Exception {
+		String userId = user.getId();
+		String roomId = dataPool.getString("roomId");
+		
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		if (chatRoom == null) {
+			return;
+		}
+		
+		//1. notify
+		chatRoom.notify(PublishOperator.KickOff, userId);
+		
+		//2. delete member
+		chatRoom.deleteOneMember(userId);
+		
+		//3. result
+		resultPool.success();
+	}
+	
+	protected void pull() {
+		String roomId = dataPool.getString("roomId");
+		long timeStamp = Long.parseLong(dataPool.getString("timePoint"));
+		
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		if (chatRoom == null) {
+			return;
+		}
+		
+		//1. get message list
+		List<MessageRecord> messageList = chatRoom.getMessageList(timeStamp);
+		
+		//2. result
+		resultPool.add(messageList);
+	}
+	
+	protected void publish() {
+		//1.
+		String roomId = dataPool.getString("roomId");
+		MessageRecord record = dataPool.getMessageRecord();
+		
+		ChatRoom chatRoom = chatroomBucket.getOne(roomId);
+		
+		if (chatRoom == null) {
+			return;
+		}
+		
+		//1. add to message list
+		//chatRoom.publishOneMessage(record, user, true, null);
+		
+		//2. publish
+		chatRoom.notify(PublishOperator.PublishMessage, record, user);
+		
+		//3. result
+		resultPool.success();
+	}
+}
diff --git a/IMserver/medeasy/src/chat/handler/ClientHandler.java b/IMserver/medeasy/src/chat/handler/ClientHandler.java
new file mode 100644
index 0000000..ecda5ea
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/ClientHandler.java
@@ -0,0 +1,906 @@
+package chat.handler;
+
+import static chat.consts.UserSettingScope.kUserSettingMyChannels;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+import org.json.JSONObject;
+
+import com.google.gson.Gson;
+
+import com.vdurmont.emoji.EmojiParser;
+
+import chat.consts.RestResult;
+import chat.handler.data.DataList;
+import chat.handler.data.FriendData;
+import chat.module.Bucket;
+import chat.module.FriendRequstBucket;
+import chat.module.ModuleLoader;
+import chat.module.entity.ChatSpaceType;
+import chat.module.entity.FriendShip;
+import chat.module.entity.MessageRecord;
+import chat.security.AES;
+import chat.server.call.CallObject;
+import chat.server.im.IMDispatcher;
+import chat.server.im.IMTopic;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.sms.OneClickLogin;
+import chat.sms.Record;
+import chat.sms.SmsService;
+import chat.tools.Utils;
+import chat.user.Client;
+import chat.user.ClientStore;
+import chat.user.Notify;
+import chat.user.NotifyContent;
+import chat.user.NotifyContentDetail;
+import chat.user.NotifyStore;
+import chat.user.NotifySubject;
+import chat.user.ResultMessage;
+import chat.user.Session;
+import chat.user.Token;
+import chat.user.User;
+import chat.user.UserStore;
+import chat.util.I18n;
+import chat.util.MessageShardingUtil;
+import cn.wildfirechat.common.ErrorCode;
+import cn.wildfirechat.proto.ProtoConstants;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.IMHttpWrapper;
+import frame.object.data.ID;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.util.internal.StringUtil;
+
+public class ClientHandler extends CallObject {
+	
+	private static FriendRequstBucket friendRequstBucket;
+	private ScheduledExecutorService mScheduledExecutorService = Executors.newScheduledThreadPool(4);
+	private static ConcurrentHashMap<String, Record> mRecords = new ConcurrentHashMap<String, Record>();
+	private static ConcurrentHashMap<String, String> mOneLoginPhone = new ConcurrentHashMap<String, String>();;
+	private static String clientType;
+	protected static Logger logger;
+	
+	static {
+		friendRequstBucket = FriendRequstBucket.getInstance();
+		logger = Logger.getLogger(IMDispatcher.class);
+	}
+	
+	@Override
+	protected void publishMethod() {
+		addOneMethod("login");
+		addOneMethod("sendSMSCode");
+		addOneMethod("oneLogin");
+		addOneMethod("getUser");
+		addOneMethod("pullMessage");
+		addOneMethod("notifyMessage");
+		
+		addOneMethod("pullFriend");
+		addOneMethod("pullRequestFriend");
+		addOneMethod("addFriend");
+		addOneMethod("handleFriend");
+		addOneMethod("setFriendAlias");
+		addOneMethod("notifyFriend");
+		addOneMethod("notifyMesage");
+		
+		addOneMethod("loadRemoteMessage");
+		addOneMethod("getClient");
+		addOneMethod("getUserSetting");
+		addOneMethod("putUserSetting");
+		addOneMethod("getUserInfo");
+		addOneMethod("setUserInfo");
+		addOneMethod("getBlacklist");
+		addOneMethod("blackListUser");
+		addOneMethod("userSearch");
+		addOneMethod("getToken");
+		addOneMethod("broadCastMessage");
+		addOneMethod("channelListen");
+		addOneMethod("channelSearch");
+		addOneMethod("createChannel");
+		addOneMethod("deleteFriend");
+		addOneMethod("destoryUser");
+		addOneMethod("dismissGroup");
+		addOneMethod("destoryChannel");
+		addOneMethod("pullChannel");
+		addOneMethod("chatRoomInfo");
+		addOneMethod("getChatRoomMember");
+		addOneMethod("joinChatRoom");
+		addOneMethod("quitChatRoom");
+		
+		addOneMethod("kickOffGroup");
+		addOneMethod("kickoffPCClient");
+		addOneMethod("modifyChannel");
+		addOneMethod("transferChannel");
+	}
+	
+	//鎺ユ敹浠庡尰瑙嗘棤蹇у彂杩囨潵鐨勬柊澧炵敤鎴蜂俊鎭�
+	public ResultMessage createOneUser(NotifyContentDetail contentDetail) throws Exception {
+		ResultMessage resultMessage;
+		
+		User user = User.setUserInfo(contentDetail);
+		
+		if (UserStore.getByExtra(contentDetail.getDoctorId()) != null) {
+			resultMessage = new ResultMessage(false, "鐢ㄦ埛淇℃伅宸叉坊鍔犺繃锛屾娆′笉娣诲姞!");
+			return resultMessage;
+		}
+		
+		User resultUser = UserStore.createOneUser(user);
+				
+		resultPool.setNeedReturnCode(false);
+		if (resultUser != null) {
+			//淇濆瓨鍒板唴瀛樹腑
+			UserStore.addOne(user);
+			resultMessage = new ResultMessage(true, "鐢ㄦ埛淇℃伅娣诲姞鎴愬姛!");
+		}
+		else {
+			resultMessage = new ResultMessage(false, "鐢ㄦ埛淇℃伅娣诲姞澶辫触!");
+		}
+		
+		return resultMessage;
+	}
+	
+	//鎺ユ敹浠庡尰瑙嗘棤蹇у彂杩囨潵鐨勪慨鏀圭敤鎴蜂俊鎭�
+	public ResultMessage modifyOneUser(NotifyContentDetail contentDetail) throws Exception {
+		ResultMessage resultMessage;
+		User user = User.setUserInfo(contentDetail);
+		
+		//鏇存柊绗簩涓弬鏁�:纭畾鍞竴璁板綍鐨勫瓧娈�;绗笁涓弬鏁�:鏇存柊鎺掗櫎鐨勫瓧娈�;
+		Map<String, String> excludeColumn = new HashMap<String, String>();
+		excludeColumn.put("id", "id");
+		int resultRecord = UserStore.modifyUser(user, "extra", excludeColumn);
+				
+		resultPool.setNeedReturnCode(false);
+		if (resultRecord > 0) {
+			//淇敼鍐呭瓨涓殑鏁版嵁
+			User modifyUser = UserStore.getByExtra(user.getExtra());
+			modifyUser.reLoad(user);
+			
+			resultMessage = new ResultMessage(true, "鐢ㄦ埛淇℃伅淇敼鎴愬姛!");
+		}
+		else if (resultRecord == -1){
+			resultMessage = new ResultMessage(false, "鐢ㄦ埛鍞竴璁板綍鐨勫瓧娈礗D鍊间负绌�");
+		}
+		else {
+			resultMessage = new ResultMessage(false, "鐢ㄦ埛淇℃伅淇敼澶辫触!");
+		}
+		
+		return resultMessage;
+	}
+	
+	//鎺ユ敹浠庡尰瑙嗘棤蹇у彂杩囨潵鐨勬秷鎭�  澧炲姞JSON瑙f瀽
+	public void notifyMesage() throws Exception {
+		ResultMessage resultMessage = null;
+		
+		if (dataPool != null) {
+			if (dataPool.getBody() == null || dataPool.getBody().equals("")) {
+				return;
+			}			
+		}
+		else {
+			return;
+		}
+		
+		NotifySubject notifySubject = new Gson().fromJson(dataPool.getBody(), NotifySubject.class);
+		
+		//1.鍒ゆ柇鏄惁鏄鍔犮�佷慨鏀广�佸熀纭�娑堟伅
+		if (notifySubject.getMsgtitle().contains("addUser") || notifySubject.getMsgtitle().contains("modifyUser")) {//澧炲姞
+			NotifyContentDetail contentDetail = notifySubject.getMsgcontent().getContent();
+			if (notifySubject.getMsgtitle().contains("addUser")) {
+				resultMessage = createOneUser(contentDetail);
+			} else if (notifySubject.getMsgtitle().contains("modifyUser")) {
+				resultMessage = modifyOneUser(contentDetail);
+			}
+		}
+		else {//鍩虹娑堟伅
+			Notify notify = new Notify();
+			notify.setId(ID.newValue());
+			notify.setSender(notifySubject.getSender());
+			notify.setRoletype(notifySubject.getMsgcontent().getContent().getRoletype());
+			notify.setTarget(notifySubject.getMsgcontent().getContent().getDoctorId());
+			notify.setMsgtitle(notifySubject.getMsgcontent().getTitle());
+			notify.setMsgcontent(notifySubject.getMsgtitle());
+			notify.setMsgtime(notifySubject.getMsgtime());
+			notify.setIsread("F");
+
+			boolean result = Notify.saveNotify(notify);
+			if (result) {
+				//淇濆瓨鍐呭瓨
+				NotifyStore.addOne(notify);
+				resultMessage = new ResultMessage(true, "閫氱煡鎺ユ敹鎴愬姛!");
+			} else {
+				resultMessage = new ResultMessage(false, "閫氱煡鎺ユ敹澶辫触!");
+			}
+		}
+		
+		resultPool.setNeedReturnCode(false);
+		
+		resultPool.add("success", resultMessage.isFlag());
+		resultPool.add("msg", resultMessage.getMessage(), false);
+		resultPool.add("timestamp", System.currentTimeMillis());
+	}
+	
+	public void login() throws Exception {
+		//0. load client type
+		clientType = dataPool.getString("roletype");
+		//1. load client
+		Client client = ClientStore.getOrCreate(dataPool);
+		//2. load user
+		client.createSession();
+		
+		//3. write back
+		User user = client.getUser();
+		Session session = client.getSession();
+		Token token = session.getToken();
+		
+	    String mobile = "";
+	    String code = "";
+		
+		//濡傛灉锛屼笉鏄竴閿櫥闄�
+		if(dataPool.getString("token") == null || mOneLoginPhone.get(dataPool.getString("token")) == null) {
+	       //鐭俊楠岃瘉鐮�
+	       mobile = dataPool.getString("mobile");
+	       code = dataPool.getString("code");
+	       //鐭俊楠岃瘉
+	       if (mRecords.get(mobile) != null) {
+		       if (mRecords.get(mobile).getCode().equalsIgnoreCase(code)) {
+		       	   mRecords.remove(mobile);
+		       } else {
+		       	   return;
+		       }	    	   
+	       } 
+	       else if (!"66666".equals(code)) {//瓒呯骇瀵嗙爜閿欒
+	    	   return;
+	       }
+		} else {
+		   mobile = mOneLoginPhone.get(dataPool.getString("token"));
+		   mOneLoginPhone.remove(dataPool.getString("token"));
+		}
+		
+		byte[] tokenByte = token.getFullValue();
+		tokenByte = AES.AESEncrypt(tokenByte, "");
+		String tokenValue = Base64.getEncoder().encodeToString(tokenByte);
+		
+		resultPool.add("userId", user.getId());
+		resultPool.add("username", user.getName());
+		resultPool.add("token", tokenValue, false);
+		resultPool.add("portrait", user.getPortrait());
+		resultPool.add("isregister", true);
+		resultPool.add("doctorId", user.getExtra() == null ? "" : user.getExtra());
+	}
+	
+	public void oneLogin() throws Exception {
+		String token = dataPool.getString("token");
+		OneClickLogin oneLogin = new OneClickLogin();
+		String phone = oneLogin.mobileLogin(token);
+		mOneLoginPhone.put(token, phone);
+		dataPool.setPhone(phone);
+		login();
+	}
+	
+	public void sendSMSCode() throws Exception {
+		RestResult result = null;
+		String message = "";
+		String mobile = dataPool.getString("mobile");
+		String code = Utils.getRandomCode(4);
+		SmsService smsService = new SmsService();
+		Record record = mRecords.get(mobile);
+		if(record != null) {
+			resultPool.add("code", 0);
+			resultPool.add("message", "ERROR_SEND_SMS_OVER_FREQUENCY");
+			resultPool.add("result", result);
+			return;
+		}
+		mRecords.put(mobile, new Record(code, mobile));
+		
+		RestResult.RestCode restCode = smsService.sendAliyunCode(mobile, code);
+        if (restCode == RestResult.RestCode.SUCCESS) {
+        	result = RestResult.ok(restCode);
+        	message = "SUCCESS";
+        } else {
+        	result = RestResult.error(restCode);
+        	message = "ERROR_NOT_LOGIN";
+        }
+        
+		resultPool.add("code", 0);
+		resultPool.add("message", message);
+		resultPool.add("result", result);
+	}
+	
+	//鐢ㄦ埛鐧婚檰鍔犺浇濂藉弸鍒楄〃
+	public void pullFriend() {
+		//1.寰楀埌瀵瑰簲鐢ㄦ埛鎵�鏈夌殑鏈嬪弸
+		List<FriendData> friendDataList = new ArrayList<FriendData>();
+		
+		List<FriendShip> checkUser = user.getFriendship(user.getId());
+		
+		if (checkUser == null) {
+			resultPool.setBytes(null);
+			return;
+		}
+
+		for (FriendShip friendShip : user.getFriendship(user.getId())) {
+			 friendDataList.add(new FriendData(friendShip.getUserid(), friendShip.getFriendid(), 
+					                           UserStore.getById(friendShip.getFriendid()).getDisplayName(), "", 0, 0, System.currentTimeMillis()));
+		}
+		
+//		List<FriendData> friendDataList = DataList.getFriendList();
+        
+        WFCMessage.GetFriendsResult.Builder builder = WFCMessage.GetFriendsResult.newBuilder();
+        for (FriendData data : friendDataList) {
+            WFCMessage.Friend.Builder builder1 = WFCMessage.Friend.newBuilder();
+            
+            builder1.setState(data.getState());
+            builder1.setBlacked(data.getBlacked());
+            builder1.setUid(data.getFriendUid());
+            builder1.setUpdateDt(data.getTimestamp());
+            
+            if (!StringUtil.isNullOrEmpty(data.getAlias())) {
+                builder1.setAlias(data.getAlias());
+            }
+            if (!StringUtil.isNullOrEmpty(data.getExtra())) {
+                builder1.setExtra(data.getExtra());
+            }
+            
+            builder.addEntry(builder1.build());
+        }
+        
+        byte[] bytes = builder.build().toByteArray();
+		resultPool.setBytes(bytes);
+	}
+	
+	//鐢ㄦ埛鐧婚檰娣诲姞濂藉弸璇锋眰
+	public void pullRequestFriend() {
+		//WFCMessage.Version request = (WFCMessage.Version) dataPool.getWFCMessage(WFCMessage.Version.class);
+		
+		List<WFCMessage.FriendRequest> friendDatas = new ArrayList<WFCMessage.FriendRequest>();
+		List<FriendShip> friendShipList = user.getApplyFriendShip(user.getId());
+		
+		if (friendShipList != null) {
+			for (FriendShip friendShip : friendShipList) {
+				 friendDatas.add(friendShip.getFriendRequest());
+			}			
+		}
+		
+		WFCMessage.GetFriendRequestResult.Builder builder = WFCMessage.GetFriendRequestResult.newBuilder();
+		builder.addAllEntry(friendDatas);
+		
+		byte[] bytes = builder.build().toByteArray();
+		resultPool.setBytes(bytes);
+	}	
+	
+	//MN
+	public void notifyMessage() {
+		//
+		System.out.println("瑙﹀彂MN娑堟伅");
+	}
+	
+	//MP
+	public void pullMessage() throws Exception {
+		//1.杈撳叆鍙傛暟
+		WFCMessage.PullMessageRequest request = (WFCMessage.PullMessageRequest) dataPool.getWFCMessage(WFCMessage.PullMessageRequest.class);
+		
+		if (request == null) {
+			return;
+		}
+		
+		WFCMessage.PullMessageResult.Builder builder = WFCMessage.PullMessageResult.newBuilder();
+		
+		List<WFCMessage.Message> messageList = user.getUnreceivedMessageList();
+		
+        for (WFCMessage.Message message: messageList) {
+        	builder.addMessage(message);
+        }
+
+        //2.
+        builder.setCurrent(DataList.timestamp);
+        builder.setHead(DataList.timestamp);
+        
+        //3.
+        byte[] bytes =  builder.build().toByteArray();
+		resultPool.setBytes(bytes);
+	}
+	
+	//FAR
+	public void addFriend() {
+		try {
+//			String userId = dataPool.getString("userId");
+//			
+//			WFCMessage.AddFriendRequest.Builder addFriendRequestBuild = WFCMessage.AddFriendRequest.newBuilder();
+//			addFriendRequestBuild.setReason(dataPool.getString("reason"));
+//			addFriendRequestBuild.setTargetUid(dataPool.getString("friendUid"));			
+//			
+//			WFCMessage.AddFriendRequest addFriendRequest = addFriendRequestBuild.build();
+			WFCMessage.AddFriendRequest friendRequest = (WFCMessage.AddFriendRequest) dataPool.getWFCMessage(WFCMessage.AddFriendRequest.class);
+			
+			//灏嗙敤鎴疯姹傛秷鎭寕鍒拌姹傜殑user涓嬮潰
+			user.addUserFriendShip(user.getId(), friendRequest);
+			
+			//澧炲姞鐢ㄦ埛楠岃瘉璇锋眰
+			//friendRequstBucket.createFriendRequest(userId, addFriendRequest, head);
+			resultPool.setBytes(null);
+			//鍙戦�氱煡 String NotifyFriendRequestTopic = "FRN";
+			//publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, addFriendRequest.getTargetUid(), head[0], userId, addFriendRequest.getReason());
+//	    	mScheduledExecutorService.schedule(threadFactory.newThread(new Runnable() {
+//	            @Override
+//	            public void run() {
+//	               exeMessage(IMTopic.NotifyFriendRequestTopic, addFriendRequest.getTargetUid(), head[0], userId, addFriendRequest.getReason());
+//	            }
+//	        }), 100, TimeUnit.MILLISECONDS);
+
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}		
+	}
+	
+	//鍔犳湅鍙嬬殑瀵规柟锛屾帴鍙楄姹�
+	public void handleFriend() throws Exception {
+		//澶�
+		WFCMessage.HandleFriendRequest request = (WFCMessage.HandleFriendRequest) dataPool.getWFCMessage(WFCMessage.HandleFriendRequest.class);
+		
+		//灏�
+		long[] heads = new long[2];
+        WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+        builder.setFromUser(request.getTargetUid());
+        
+        user.handleFriendRequest(user.getId(), request, builder, heads);
+
+        //6.鍙戦�氱煡娑堟伅
+		long messageId = MessageShardingUtil.generateId();
+		long timestamp = System.currentTimeMillis();
+		builder.setMessageId(messageId);
+		builder.setServerTimestamp(timestamp);
+		ChatSpaceType spaceType = ChatSpaceType.pase(builder.build().getConversation().getType());
+		Bucket<?> bucket = Bucket.getInstance(spaceType);
+		bucket.pushOneMessage(builder.build(), UserStore.getById(request.getTargetUid()), false);		 
+		
+		//7.鍙戦棶鍊欒娑堟伅
+		String language = "zh";
+		WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+		contentBuilder.setType(90).setContent(I18n.getString(language, "Above_Greeting_Message"));
+		
+        builder = WFCMessage.Message.newBuilder();
+        builder.setFromUser(request.getTargetUid());
+        builder.setConversation(WFCMessage.Conversation.newBuilder().setTarget(user.getId()).setLine(0).setType(ProtoConstants.ConversationType.ConversationType_Private).build());
+        builder.setContent(contentBuilder);
+        timestamp = System.currentTimeMillis();
+        builder.setServerTimestamp(timestamp);
+
+        messageId = MessageShardingUtil.generateId();
+        builder.setMessageId(messageId);
+        bucket.pushOneMessage(builder.build(), UserStore.getById(request.getTargetUid()), false);	
+		
+		//8.寮�濮嬭亰澶╂秷鎭�
+        contentBuilder.setContent(I18n.getString(language, "Friend_Can_Start_Chat"));
+        builder.setContent(contentBuilder);
+        messageId = MessageShardingUtil.generateId();
+        builder.setMessageId(messageId);
+        timestamp = System.currentTimeMillis();
+        builder.setServerTimestamp(timestamp);
+        bucket.pushOneMessage(builder.build(), UserStore.getById(request.getTargetUid()));
+        
+		//9.self娑堟伅
+        ModuleLoader.getImBusinessScheduler().execute(() -> bucket.getOne(user.getId()).notifyOneFriend(IMTopic.NotifyFriendTopic, request.getTargetUid(), heads[0]));
+        
+		//10.target娑堟伅
+        ModuleLoader.getImBusinessScheduler().execute(() -> bucket.getOne(user.getId()).notifyOneFriend(IMTopic.NotifyFriendTopic, user.getId(), heads[1]));
+		
+		resultPool.setBytes(null);
+	}
+	
+	public void exeMessage(String topic, String receiver, long head, String fromUser, String pushContent) {
+		try {
+            ByteBuf payload = Unpooled.buffer();
+            payload.writeLong(head);
+            MqttPublishMessage publishMsg;
+            publishMsg = notRetainedPublish(topic, MqttQoS.AT_MOST_ONCE, payload);
+            
+			Client client = user.getClient(user.getId());
+			Session sessionC = client.getSession();
+			if (sessionC != null) {
+				Channel channel = sessionC.getChannel();
+				if (publishMsg != null) {
+					channel.writeAndFlush(publishMsg);
+				}
+			}            
+		} catch(Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+    public static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message,
+            int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    }	
+	
+	private ThreadFactory threadFactory = new ThreadFactory() {
+        @Override
+        public Thread newThread(final Runnable r) {
+            return new Thread() {
+                @Override
+                public void run() {
+                    r.run();
+                }
+            };
+        }
+    };
+    
+	public void getUserInfo() {
+		String userId = dataPool.getString("userId");
+		User user = UserStore.getById(userId);
+		if (user == null) {
+			return;
+		}
+		WFCMessage.User.Builder userBuilder = WFCMessage.User.newBuilder();
+		userBuilder.setUid(user.getId());
+		userBuilder.setName(user.getName());
+		userBuilder.setDisplayName(user.getDisplayName());
+		
+		userBuilder.setPortrait(user.getPortrait());
+		userBuilder.setMobile(user.getMobile());
+		String extra = user.getExtra();
+		if (extra != null && !extra.equals("")) {
+			userBuilder.setExtra(extra);
+		} else {
+			userBuilder.setExtra("");
+		}
+		
+		WFCMessage.User wfcUser = userBuilder.build();
+		
+		resultPool.add(wfcUser);
+	}    
+	
+	public void getUser() {
+		try {
+			IMHttpWrapper httpWrapper = dataPool.getHttpWrapper();
+			byte[] bytes = null;
+			
+			if (httpWrapper == null) {
+				if (dataPool.getBody() == null) {
+					logger.debug(dataPool);
+					return;
+				}
+				bytes = dataPool.getBody().getBytes();
+			} else {
+				bytes = httpWrapper.getData().toByteArray();
+			}
+
+			WFCMessage.PullUserRequest request = WFCMessage.PullUserRequest.parseFrom(bytes);
+			
+			List<WFCMessage.UserRequest> requestList = request.getRequestList();
+
+	        WFCMessage.PullUserResult.Builder builder = WFCMessage.PullUserResult.newBuilder();
+	        logger.debug("requestList: " + requestList.size());
+	        for (WFCMessage.UserRequest userRequest: requestList) {
+	        	 String uid = userRequest.getUid();
+	        	 
+	        	 User usr = UserStore.getById(uid);
+	        	 logger.debug("UID====>: " + usr.getId());
+	        	 logger.debug("Mobile====>: " + usr.getMobile());
+	        	 logger.debug("Extra====>: " + usr.getExtra());
+	        	 
+	        	 WFCMessage.UserResult userResult = usr.toWFCUserResult();//DataList.getUser(uid);
+	        	 
+	        	 builder.addResult(userResult);
+	        }
+
+	        byte[] resBytes = builder.build().toByteArray();
+			resultPool.setBytes(resBytes);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public void loadRemoteMessage() throws Exception {
+//		//澶�
+//		WFCMessage.LoadRemoteMessages request = (WFCMessage.LoadRemoteMessages) dataPool.getWFCMessage(WFCMessage.LoadRemoteMessages.class);
+//		
+//		//灏�
+//		WFCMessage.PullMessageResult result = null;
+//		byte[] bytes = result.toByteArray();
+//		
+//		resultPool.setBytes(bytes);
+	}
+	
+	public void getClient() {
+		Client client = session.getClient();
+		resultPool.add(client);
+	}
+	
+	public void getUserSetting() {
+		WFCMessage.GetUserSettingResult.Builder builder = WFCMessage.GetUserSettingResult.newBuilder();
+		
+        byte[] resBytes = builder.build().toByteArray();
+		resultPool.setBytes(ErrorCode.ERROR_CODE_NOT_MODIFIED.getCode(), resBytes);		
+	}
+	
+	public void putUserSetting() throws Exception { 
+		WFCMessage.ModifyUserSettingReq settingRequest = (WFCMessage.ModifyUserSettingReq) dataPool.getWFCMessage(WFCMessage.ModifyUserSettingReq.class);
+		//System.out.println("aaa");
+		//WFCMessage.ModifyUserSettingReq settingRequest = dataPool.getWFCMessage(WFCMessage.ModifyUserSettingReq.class).getClass();
+		//IMHttpWrapper wrapper = dataPool.getHttpWrapper();
+		//byte[] bytes = wrapper.getData().toByteArray();
+		//WFCMessage.ModifyUserSettingReq settingRequest = WFCMessage.ModifyUserSettingReq.parseFrom(bytes);
+		
+		resultPool.setBytes(null);
+	}
+	
+	public void setUserInfo() {
+		
+	}
+	
+	public void getBlacklist() {
+		
+	}
+	
+	public void blackListUser() {
+		long[] head = new long[1];
+		
+		try {
+			//杈撳叆
+			WFCMessage.BlackUserRequest.Builder blackUserBuilder = WFCMessage.BlackUserRequest.newBuilder();
+			blackUserBuilder.setUid(dataPool.getString("targetUid"));
+			blackUserBuilder.setStatus(dataPool.getInteger("status", 0));
+			WFCMessage.BlackUserRequest blackUserRequest = blackUserBuilder.build();
+			
+			//杈撳嚭
+			resultPool.setBytes(null);
+			//鍙戦�氱煡 String NotifyFriendRequestTopic = "FRN";
+			//publisher.publishNotification(IMTopic.NotifyFriendRequestTopic, addFriendRequest.getTargetUid(), head[0], userId, addFriendRequest.getReason());
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}		
+	}
+	
+	public void broadCastMessage() throws Exception {
+		//澶�
+		WFCMessage.Message broadCastMessage = (WFCMessage.Message) dataPool.getWFCMessage(WFCMessage.Message.class);
+		
+		//灏�
+		ByteBuf payload = Unpooled.buffer();
+		long messageId = MessageRecord.newMessageId();
+	    payload.ensureWritable(20).writeLong(messageId).writeLong(10L);
+	    
+	    byte[] resBytes = payload.array();
+	    resultPool.setBytes(resBytes);
+	}
+	
+	public void channelListen() throws Exception {
+		//澶�
+		WFCMessage.ListenChannel listenChannel = (WFCMessage.ListenChannel) dataPool.getWFCMessage(WFCMessage.ListenChannel.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void channelSearch() throws Exception {
+		//澶�
+		WFCMessage.SearchUserRequest listenChannel = (WFCMessage.SearchUserRequest) dataPool.getWFCMessage(WFCMessage.SearchUserRequest.class);
+		
+		//灏�
+		List<WFCMessage.ChannelInfo> users = null;
+        WFCMessage.SearchChannelResult.Builder builder = WFCMessage.SearchChannelResult.newBuilder();
+        builder.addAllChannel(users);
+        builder.setKeyword(listenChannel.getKeyword());
+        byte[] resBytes = builder.build().toByteArray();
+        resultPool.setBytes(resBytes);
+	}
+	
+	public void createChannel() throws Exception {
+		//澶�
+		WFCMessage.ChannelInfo request = (WFCMessage.ChannelInfo) dataPool.getWFCMessage(WFCMessage.ChannelInfo.class);
+		
+		//灏�
+		WFCMessage.ChannelInfo.Builder builder = request.toBuilder();
+        long update = System.currentTimeMillis();
+        request = builder.setUpdateDt(update).build();
+        
+        WFCMessage.ModifyUserSettingReq modifyUserSettingReq = WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingMyChannels).setKey(request.getTargetId()).setValue("1").build();
+        
+        byte[] resBytes = request.getTargetId().getBytes();
+		
+        resultPool.setBytes(resBytes);
+	}
+	
+	public void deleteFriend() throws Exception {
+		long[] head = new long[2];
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void destoryUser() throws Exception {
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		WFCMessage.IDBuf.Builder requestBuilder = request.toBuilder();
+		WFCMessage.IDBuf idBuf = requestBuilder.setId(dataPool.getString("userId")).build();
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void dismissGroup() throws Exception {
+		//澶�
+		WFCMessage.DismissGroupRequest request = (WFCMessage.DismissGroupRequest) dataPool.getWFCMessage(WFCMessage.DismissGroupRequest.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void destoryChannel() throws Exception {
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void kickOffGroup() throws Exception {
+		//澶�
+		WFCMessage.RemoveGroupMemberRequest request = (WFCMessage.RemoveGroupMemberRequest) dataPool.getWFCMessage(WFCMessage.RemoveGroupMemberRequest.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void kickoffPCClient() throws Exception {
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		
+		//灏�
+		resultPool.setBytes(null);		
+	}
+	
+	public void modifyChannel() throws Exception {
+		//澶�
+		WFCMessage.ModifyChannelInfo request = (WFCMessage.ModifyChannelInfo) dataPool.getWFCMessage(WFCMessage.ModifyChannelInfo.class);
+		
+		//灏�
+		resultPool.setBytes(null);			
+	}
+	
+	public void quitChatRoom() throws Exception {
+		//澶�
+		WFCMessage.IDBuf request = (WFCMessage.IDBuf) dataPool.getWFCMessage(WFCMessage.IDBuf.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void setFriendAlias() throws Exception {
+		//澶�
+		WFCMessage.AddFriendRequest request = (WFCMessage.AddFriendRequest) dataPool.getWFCMessage(WFCMessage.AddFriendRequest.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void transferChannel() throws Exception {
+		//澶�
+		WFCMessage.TransferChannel request = (WFCMessage.TransferChannel) dataPool.getWFCMessage(WFCMessage.TransferChannel.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void userSearch() throws Exception {
+		//澶�
+		WFCMessage.SearchUserRequest request = (WFCMessage.SearchUserRequest) dataPool.getWFCMessage(WFCMessage.SearchUserRequest.class);
+		
+		//灏�
+        List<WFCMessage.User> users = user.searchUser(request.getKeyword(), request.getFuzzy(), request.getPage());
+        WFCMessage.SearchUserResult.Builder builder = WFCMessage.SearchUserResult.newBuilder();
+        builder.addAllEntry(users);
+        byte[] bytes = builder.build().toByteArray();
+        
+        resultPool.setBytes(bytes);
+	}
+	
+	public void getToken() {
+		Token token = session.getToken();
+		byte[] value = token.getFullValue();
+		
+		resultPool.add(value);
+	}
+	
+	public static void main(String[] args) throws Exception {
+		String dataStr = "\\344\\275\\240\\344\\273\\254\\345\\267\\262\\347\\273\\217\\346\\210\\220\\344\\270\\272\\345\\245\\275\\345\\217\\213\\344\\272\\206\\357\\274\\214\\347\\216\\260\\345\\234\\250\\345\\217\\257\\344\\273\\245\\345\\274\\200\\345\\247\\213\\350\\201\\212\\345\\244\\251\\344\\272\\206";
+		if (! dataStr.contains("\\")) {
+			System.out.println("1:" + dataStr);;
+		}
+		//涓嶅睘浜庡叓杩涘埗鍐呭鐨勫瓧绗�
+		StringBuilder oldBuffer = new StringBuilder();
+		//灞炰簬鍏繘鍒剁殑鍐呭锛岃浆鎴愬崄鍏繘鍒跺悗缂撳瓨鍦ㄨ繖閲�
+		StringBuilder hexBuffer = new StringBuilder();
+		for (int i = 0; i < dataStr.length(); i ++) {
+			 char c = dataStr.charAt(i);
+			 if (c != '\\') {
+			     oldBuffer.append(c);
+			 }
+			 //鍙嶆枩鏉犲線鍚�3涓负涓�缁勶紝缁勬垚浜嗕竴涓叓杩涘埗鏁般�備緥濡俓20710,鍏跺疄鏄�207缁勬垚浜嗕竴涓叓杩涘埗鏁�
+			 else {
+			       char c1 = dataStr.charAt(i + 1);
+			       char c2 = dataStr.charAt(i + 2);
+			       char c3 = dataStr.charAt(i + 3);
+			       i += 3;
+			       //灏嗗叓杩涘埗杞崲涓哄崄杩涘埗锛屽啀杞崲涓哄崄鍏繘鍒�
+			       String hex = Integer.toHexString((Integer.valueOf("" + c1 + c2 + c3, 8)));
+			       //鍏堢紦瀛樹綇锛岀洿鍒板噾澶熶笁涓瓧鑺�
+			       hexBuffer.append(hex);
+			       String hexString = hexBuffer.toString();
+			       //utf8缂栫爜涓紝涓変釜瀛楄妭涓轰竴涓眽瀛�
+			       if (hexString.length() == 6) {
+			    	   //鍑戝涓変釜瀛楄妭浜嗭紝杞垚姹夊瓧鍚庢斁鍏ldBuffer涓�
+			    	   oldBuffer.append(hexStr2Str(hexString));
+			    	   //鍑戝涓�涓眽瀛椾簡锛屾竻绌虹紦瀛�
+			    	   hexBuffer = new StringBuilder();
+			       }
+			 }
+			}
+			System.out.println("2:" + oldBuffer.toString());
+			System.out.println("3:" + EmojiParser.parseToHtmlDecimal(oldBuffer.toString()));
+			
+//		       String str = "Here is a boy: :boy|type_6:!";
+//		        System.out.println("鍘熷瀛楃涓猴細\n" + str);
+//
+//		        System.out.println("to html锛�");
+//		        String s = EmojiParser.parseToHtmlDecimal(str);
+//		        System.out.println(s);
+//
+//		        System.out.println("杩樺師锛�");
+//		        System.out.println(EmojiParser.parseToUnicode(s));	
+			
+	        String str = "鑻嶅ぉ鍘氬湡\uD83D\uDE01 \uD83D\uDC36 \uD83E\uDD14 \uD83D\uDC7B \uD83D\uDE92";
+	        System.out.println("鍘熷瀛楃涓猴細\n" + str);
+
+	        System.out.println("to aliases 涔嬪悗锛�");
+	        System.out.println(EmojiParser.parseToAliases(str));
+	        System.out.println(EmojiParser.parseToAliases(str, EmojiParser.FitzpatrickAction.PARSE));
+	        System.out.println(EmojiParser.parseToAliases(str, EmojiParser.FitzpatrickAction.REMOVE));
+	        System.out.println(EmojiParser.parseToAliases(str, EmojiParser.FitzpatrickAction.IGNORE));
+	        System.out.println(EmojiParser.parseToAliases(str, EmojiParser.FitzpatrickAction.IGNORE));
+	        System.out.println(EmojiParser.parseToUnicode(str));			
+	}
+	
+	private static String hexStr2Str(String hexStr) {
+		String str = "0123456789abcdef";
+		char[] hexs = hexStr.toCharArray();
+		byte[] bytes = new byte[hexStr.length() / 2];
+		int n;
+		for (int i = 0; i < bytes.length; i++) {
+			 n = str.indexOf(hexs[2 * i]) * 16;
+			 n += str.indexOf(hexs[2 * i + 1]);
+			 bytes[i] = (byte) (n & 0xff);
+		}
+		return new String(bytes, StandardCharsets.UTF_8);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/handler/FriendCircleHandler.java b/IMserver/medeasy/src/chat/handler/FriendCircleHandler.java
new file mode 100644
index 0000000..5fb89a8
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/FriendCircleHandler.java
@@ -0,0 +1,213 @@
+package chat.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import chat.module.friendcircle.CircleObject;
+import chat.module.friendcircle.FriendCircle;
+import chat.server.call.CallObject;
+import chat.user.User;
+import chat.user.UserStore;
+
+public class FriendCircleHandler extends CallObject { 
+
+	public static int PageSize_FriendCircle = 5;
+	
+	@Override
+	protected void publishMethod() {
+		// 鍒嗛〉鏌ヨ鍖荤敓鍦堝垪琛�
+		addOneMethod("getList");
+		
+		// 鍒嗛〉鏌ヨ鍗曚釜鍖荤敓鍙戠殑鍔ㄦ��
+		addOneMethod("getOneUserList");
+		
+		// 鏌ヨ鎸囧畾鏈嬪弸鍦堝唴瀹�
+		addOneMethod("getOneCircleObject");
+		
+		// 鍙戝竷涓�涓湅鍙嬪湀鍐呭
+		addOneMethod("createOneCircleObject");
+		
+		// 鍏虫敞璇ユ湅鍙嬪湀
+		addOneMethod("addOneAttention");
+		
+		// 鏀惰棌 褰撳墠鍐呭
+		addOneMethod("addOneCollect");
+		
+		// 鐐硅禐 褰撳墠鍐呭
+		addOneMethod("addOneThumbsup");
+		
+		// 璇勮 褰撳墠鍐呭
+		addOneMethod("addOneComment");
+		
+		// 杞彂 褰撳墠鍐呭
+		addOneMethod("addOneForword");
+	}
+	
+	// 鍒嗛〉鏌ヨ鍖荤敓鍦堝垪琛�
+	public void getList() {
+		int pageNo = dataPool.getInteger("pageno", 0);
+		List<CircleObject> resultList = FriendCircle.getCircleObjectList(pageNo, PageSize_FriendCircle);
+		
+		resultPool.add("list", resultList);
+	}
+	
+	// 鍒嗛〉鏌ヨ鍗曚釜鍖荤敓鍙戠殑鍔ㄦ��
+	public void getOneUserList() {
+		int pageNo = dataPool.getInteger("pageno", 0);
+		//鏈嬪弸鍦堢敤鎴稩D
+		String ownerId = dataPool.getString("ownerid");
+		
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			resultPool.add(new ArrayList<CircleObject>());
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		List<CircleObject> resultList = friendCircle.getOneUserCircleObjectList(pageNo, PageSize_FriendCircle);
+		
+		resultPool.add("list", resultList);
+	}
+	
+	// 寰楀埌涓�涓湅鍙嬪湀瀵硅薄
+	public void getOneCircleObject() {
+		String ownerId = dataPool.getString("ownerId");
+		String circleObjectId = dataPool.getString("circleObjectId"); 
+		
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		CircleObject result = friendCircle.getOneCircleObject(circleObjectId);
+		
+		resultPool.add(result);
+	}
+	
+	// 鍙戝竷涓�涓湅鍙嬪湀鍐呭
+	public void createOneCircleObject() {
+		String ownerId = dataPool.getString("ownerId");
+		
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		String circleObjectId = friendCircle.createOneCircleObject(dataPool);
+		
+		resultPool.add("circleObjectId", circleObjectId);
+	}
+	
+	//鍏虫敞
+	public void addOneAttention() {
+		String ownerId = dataPool.getString("ownerId");
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		friendCircle.addOneAttention(user);
+	}
+	
+	// 鏀惰棌
+	public void addOneCollect() {
+		String ownerId = dataPool.getString("ownerId");
+		String circleObjectId = dataPool.getString("circleObjectId");
+				
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		CircleObject circelObject = friendCircle.getOneCircleObject(circleObjectId);
+		
+		if (circelObject == null) {
+			return;
+		}
+		
+		circelObject.addOneCollect(user);
+	}
+	
+	// 鐐硅禐
+	public void addOneThumbsup() {
+		String ownerId = dataPool.getString("ownerId");
+		String circleObjectId = dataPool.getString("circleObjectId");
+				
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		CircleObject circelObject = friendCircle.getOneCircleObject(circleObjectId);
+		
+		if (circelObject == null) {
+			return;
+		}
+		
+		circelObject.addOneThumbsup(user);
+	}
+	
+	public void addOneComment() {
+		String ownerId = dataPool.getString("ownerId");
+		String circleObjectId = dataPool.getString("circleObjectId");
+		String parentId = dataPool.getString("parentId");
+		String comment = dataPool.getString("comment");
+		
+		User target = UserStore.getById(ownerId);
+		
+		if (target == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		CircleObject circelObject = friendCircle.getOneCircleObject(circleObjectId);
+		
+		if (circelObject == null) {
+			return;
+		}
+		
+		String commentId = circelObject.addOneComment(user, parentId, comment);
+		
+		resultPool.add("commentId", commentId);
+	}
+	
+	// 杞彂
+	public void addOneForword() {
+		// 褰撳墠鏈嬪弸鍦堢殑鎵�鏈変汉
+		String ownerId = dataPool.getString("ownerId");
+		
+		// 鏈嬪弸鍦堝璞★紙鍝釜鍐呭锛�
+		String circleObjectId = dataPool.getString("circleObjectId");
+		
+		// 杞彂缁欎簡璋�
+		String toId = dataPool.getString("toId");
+				
+		User target = UserStore.getById(ownerId);
+		User to = UserStore.getById(toId);
+		
+		if (target == null || to == null) {
+			return;
+		}
+		
+		FriendCircle friendCircle = target.getFriendCircle();
+		CircleObject circelObject = friendCircle.getOneCircleObject(circleObjectId);
+		
+		if (circelObject == null) {
+			return;
+		}
+		
+		circelObject.addOneForward(user, to);
+	}
+}
diff --git a/IMserver/medeasy/src/chat/handler/FriendshipHandler.java b/IMserver/medeasy/src/chat/handler/FriendshipHandler.java
new file mode 100644
index 0000000..77c3a16
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/FriendshipHandler.java
@@ -0,0 +1,103 @@
+package chat.handler;
+
+import java.util.Date;
+import java.util.List;
+
+import chat.module.PrivateFriendBucket;
+import chat.module.entity.PrivateFriend;
+import chat.module.entity.PublishOperator;
+import chat.module.entity.MessageRecord;
+import chat.server.call.CallObject;
+
+public class FriendshipHandler extends CallObject {
+
+	private static PrivateFriendBucket friendshipBucket;
+	
+	static {
+		friendshipBucket = PrivateFriendBucket.getInstance();
+	}
+	
+	@Override
+	protected void publishMethod() {
+		addOneMethod("add");
+		addOneMethod("delete");
+		addOneMethod("pull");
+		addOneMethod("publish");
+		addOneMethod("setFriendAlias");
+	}
+	
+	protected void add() {
+		String friendId = dataPool.getString("target");
+		
+		//1. add friend ship
+		PrivateFriend friendShip = friendshipBucket.createOne(friendId, user);
+		
+		//2. notify friend
+		friendShip.notify(PublishOperator.Create, user);
+	}
+	
+	protected void delete() {
+		String friendshipId = dataPool.getString("target");
+		
+		PrivateFriend friendship = friendshipBucket.getOne(friendshipId);
+		
+		if (friendship == null) {
+			return;
+		}
+		
+		//1. notify friend
+		friendship.notify(PublishOperator.Destroy, user);
+		
+		//2. destroy
+		friendshipBucket.deleteOne(friendshipId);
+	}
+	
+	protected void pull() {
+		String friendshipId = dataPool.getString("friendshipId");
+		long timeStamp = Long.parseLong(dataPool.getString("timePoint"));
+		
+		PrivateFriend friendship = friendshipBucket.getOne(friendshipId);
+		
+		if (friendship == null) {
+			return;
+		}
+		
+		//1. get message list
+		List<MessageRecord> messageList = friendship.getMessageList(timeStamp);
+		
+		//2. result
+		resultPool.add(messageList);
+	}
+	
+	protected void publish() {
+		String friendshipId = dataPool.getString("friendshipId");
+		MessageRecord record = dataPool.getMessageRecord();
+		
+		PrivateFriend friendship = friendshipBucket.getOne(friendshipId);
+		
+		if (friendship == null) {
+			return;
+		}
+		
+		//1. add to list
+		//friendship.publishOneMessage(record, user, true, null);
+		
+		//2. notify
+		friendship.notify(PublishOperator.PublishMessage, record, user);
+	}
+	
+	protected void setFriendAlias() {
+		String friendshipId = dataPool.getString("friendshipId");
+		String alias = dataPool.getString("alias");
+		
+		PrivateFriend friendship = friendshipBucket.getOne(friendshipId);
+		
+		if (friendship == null) {
+			return;
+		}
+		
+		//1. set alias
+		friendship.setMemberAlias(friendshipId, alias);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/GroupHandler.java b/IMserver/medeasy/src/chat/handler/GroupHandler.java
new file mode 100644
index 0000000..7f1451b
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/GroupHandler.java
@@ -0,0 +1,368 @@
+package chat.handler;
+
+import java.util.List;
+import java.util.concurrent.ThreadFactory;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import chat.message.SendMessageCallback;
+import chat.module.GroupBucket;
+import chat.module.entity.Group;
+import chat.module.entity.GroupType;
+import chat.module.entity.MessageRecord;
+import chat.module.entity.PublishOperator;
+import chat.server.call.CallObject;
+import chat.server.im.IMTopic;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.Client;
+import chat.user.Session;
+import chat.user.User;
+import cn.wildfirechat.proto.WFCMessage;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+
+public class GroupHandler extends CallObject {
+	
+	@Override
+	protected void publishMethod() {
+		addOneMethod("createGroup");
+		addOneMethod("quitGroup");
+		addOneMethod("getInfo");
+		addOneMethod("addMembers");
+		addOneMethod("getMemberList");
+		addOneMethod("setGroupManager");
+		addOneMethod("friendUnread");
+		addOneMethod("transferGroup");
+		
+		addOneMethod("join");
+		addOneMethod("leave");
+		addOneMethod("kickoff");
+		addOneMethod("changeGroupName");
+		addOneMethod("changeMemberAlias");
+		addOneMethod("modifyGroupAlias");
+		addOneMethod("modifyGroup");
+		addOneMethod("pull");
+		addOneMethod("publish");
+	}
+	
+	public void createGroup() throws Exception {
+		WFCMessage.CreateGroupRequest request = dataPool.getWFCMessage(WFCMessage.CreateGroupRequest.class);
+		
+		//1. create
+		WFCMessage.Group wfcGroup = request.getGroup();
+		GroupType type = GroupType.parse(wfcGroup.getGroupInfo().getExtra());
+		
+		GroupBucket groupBucket = GroupBucket.getInstance(type);
+		Group group = groupBucket.getOrCreate(wfcGroup, user);
+		
+		//2.鍙戦�侀�氱煡娑堟伅
+		//WFCMessage.GroupInfo groupInfo = group.createGroupInfo(user.getId(), request.getGroup().getGroupInfo(), request.getGroup().getMembersList());
+		WFCMessage.MessageContent content = group.createGroupMessage(wfcGroup.getGroupInfo(), user.getId());
+		groupBucket.sendGroupNotification(user, request, content, group);
+		
+		//3. return
+		String groupId = group.getId();
+        byte[] data = groupId.getBytes();
+    	resultPool.setBytes(data);
+    	
+    	//3. publish --hefeixia鍘绘帀
+//    	SendMessageCallback callback = new SendMessageCallback();
+//    	callback.setSender(user);
+//    	callback.setMemberList(group.getMemberList());
+//    	callback.setMessage("hello ");
+//    	
+//    	resultPool.setCallback(callback);
+	}
+	
+    public void quitGroup() throws Exception {
+    	//澶�
+    	WFCMessage.QuitGroupRequest request = dataPool.getWFCMessage(WFCMessage.QuitGroupRequest.class);
+    	
+		String groupId = request.getGroupId();
+				
+		Group group = GroupBucket.getGroup(groupId);
+		
+		if (group == null) {
+			return;
+		}
+		
+		group.quit();
+		
+		//2. return
+    	resultPool.setBytes(null);
+    }
+    
+	public void getInfo() throws InvalidProtocolBufferException {
+		//1. 
+		WFCMessage.PullUserRequest request = dataPool.getWFCMessage(WFCMessage.PullUserRequest.class);
+		List<WFCMessage.UserRequest> groupList = request.getRequestList();
+		
+		//2.
+		List<WFCMessage.GroupInfo> friendGroupList = GroupBucket.getGroupList(groupList);
+		
+        WFCMessage.PullGroupInfoResult.Builder builder = WFCMessage.PullGroupInfoResult.newBuilder();
+        builder.addAllInfo(friendGroupList);
+        
+        byte[] resBytes = builder.build().toByteArray();
+		resultPool.setBytes(resBytes);
+	}
+	
+	public void addMembers() throws Exception {
+		WFCMessage.AddGroupMemberRequest request = dataPool.getWFCMessage(WFCMessage.AddGroupMemberRequest.class);
+		
+		//1. add members
+		String groupId = request.getGroupId();
+		Group group = GroupBucket.getGroup(groupId);
+		group.addMembersWfc(groupId, request.getAddedMemberList());
+			
+		//2. return 
+		resultPool.setBytes(null);
+		
+    	//3. 鍙戞秷鎭� 
+    	SendMessageCallback callback = new SendMessageCallback();
+    	callback.setSender(user);
+    	callback.setMemberList(group.getMemberList());
+    	callback.setMessage("hello ");
+    	
+    	resultPool.setCallback(callback);
+	}
+	
+	public void getMemberList() throws InvalidProtocolBufferException {
+		//1. 
+		WFCMessage.PullGroupMemberRequest request = dataPool.getWFCMessage(WFCMessage.PullGroupMemberRequest.class);
+		String groupId = request.getTarget();
+		
+		Group friendGroup = GroupBucket.getGroup(groupId);
+		
+		if (friendGroup == null) {
+			return;
+		}
+		
+		//1. get member list
+		List<WFCMessage.GroupMember> members = friendGroup.getWFCMemberList();
+		
+        WFCMessage.PullGroupMemberResult.Builder builder = WFCMessage.PullGroupMemberResult.newBuilder();
+        builder.addAllMember(members);
+		
+		//2. result
+        byte[] resBytes = builder.build().toByteArray();
+		resultPool.setBytes(resBytes);
+	}
+	
+//	public void addMember() {
+//		String userId = user.getId();
+//		String groupId = dataPool.getString("groupId");
+//		List<String> memberList = dataPool.getList("memberlist");
+//				
+//		Group FriendGroup = GroupBucket.getGroup(groupId);
+//		
+//		if (FriendGroup == null) {
+//			return;
+//		}
+//		
+//		//1. add members
+//		FriendGroup.addMembers(groupId, memberList);
+//		
+//		//2. notify
+//		FriendGroup.notify(PublishOperator.AddMembers, memberList, userId);
+//	}
+	
+//	public void leave() {
+//		String userId = user.getId();
+//		String groupId = dataPool.getString("groupId");
+//		
+//		Group FriendGroup = GroupBucket.getGroup(groupId);
+//		
+//		if (FriendGroup == null) {
+//			return;
+//		}
+//		
+//		//1. notify
+//		FriendGroup.notify(PublishOperator.Leave, userId);
+//		
+//		//2. delete member
+//		FriendGroup.deleteOneMember(userId);
+//	}
+	
+	public void kickoff() throws Exception {
+		String userId = user.getId();
+		String groupId = dataPool.getString("groupId");
+		String memberId = dataPool.getString("memberId");
+		
+		Group FriendGroup = GroupBucket.getGroup(groupId);
+		
+		if (FriendGroup == null) {
+			return;
+		}
+		
+		//1. notify
+		FriendGroup.notify(PublishOperator.KickOff, memberId, userId);
+		
+		//2. delete member
+		FriendGroup.deleteOneMember(memberId);
+	}
+	
+	public void changeGroupName() {
+		String userId = user.getId();
+		String groupId = dataPool.getString("groupId");
+		String groupName = dataPool.getString("groupName");
+		
+		Group FriendGroup = GroupBucket.getGroup(groupId);
+		
+		if (FriendGroup == null) {
+			return;
+		}
+		
+		//1. change group name
+		FriendGroup. setName(groupName);
+		
+		//2. notify
+		FriendGroup.notify(PublishOperator.ChangeName, groupName, userId);
+	}
+	
+	public void changeMemberAlias() {
+		String groupId = dataPool.getString("groupId");
+		String memberId = dataPool.getString("memberId");
+		String alias = dataPool.getString("alias");
+		
+		Group FriendGroup = GroupBucket.getGroup(groupId);
+		
+		if (FriendGroup == null) {
+			return;
+		}
+		
+		//1. change member alias
+		FriendGroup.setMemberAlias(memberId, alias);
+		
+	}
+	
+	protected void pull() {
+		String groupId = dataPool.getString("groupId");
+		long timeStamp = Long.parseLong(dataPool.getString("timePoint"));
+		
+		Group FriendGroup = GroupBucket.getGroup(groupId);
+		
+		if (FriendGroup == null) {
+			return;
+		}
+		
+		//1. get message list
+		List<MessageRecord> messageList = FriendGroup.getMessageList(timeStamp);
+		
+		//2. result
+		resultPool.add(messageList);
+	}
+	
+	protected void publish() {
+		String groupId = dataPool.getString("groupId");
+		MessageRecord record = dataPool.getMessageRecord();
+		
+		Group FriendGroup = GroupBucket.getGroup(groupId);
+		
+		if (FriendGroup == null) {
+			return;
+		}
+		
+		//1. add to message list
+		//FriendGroup.publishOneMessage(record, user, true, null);
+		
+		//2. publish
+		FriendGroup.notify(PublishOperator.PublishMessage, record, user);
+	}
+	
+	public void exeMessage(User user) {
+		try {
+			long messageSeq = MessageRecord.newMessageId();
+	        WFCMessage.NotifyMessage notifyMessage = WFCMessage.NotifyMessage
+									                .newBuilder()
+									                .setType(0)
+									                .setHead(messageSeq)
+									                .build();
+	        ByteBuf payload = Unpooled.buffer();
+	        byte[] byteData = notifyMessage.toByteArray();
+	        payload.ensureWritable(byteData.length).writeBytes(byteData);
+	        MqttPublishMessage publishMsg = notRetainedPublish(IMTopic.NotifyMessageTopic, MqttQoS.AT_MOST_ONCE, payload);
+			
+			Client client = user.getClient(user.getId());
+			Session sessionC = client.getSession();
+			if (sessionC != null) {
+				Channel channel = sessionC.getChannel();
+				if (publishMsg != null) {
+					channel.writeAndFlush(publishMsg);
+				}
+			}			
+		} catch(Exception e) {
+			e.printStackTrace();
+		}
+	}	
+	
+	private ThreadFactory threadFactory = new ThreadFactory() {
+        @Override
+        public Thread newThread(final Runnable r) {
+            return new Thread() {
+                @Override
+                public void run() {
+                    r.run();
+                }
+            };
+        }
+    };
+    
+    public static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message,
+            int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    }
+    
+    public void modifyGroupAlias() throws Exception {
+		//澶�
+    	WFCMessage.ModifyGroupMemberAlias request = (WFCMessage.ModifyGroupMemberAlias) dataPool.getWFCMessage(WFCMessage.ModifyGroupMemberAlias.class);
+    	
+		//灏�
+		resultPool.setBytes(null);	    	
+    }
+    
+    public void modifyGroup() throws Exception {
+    	//澶�
+    	WFCMessage.ModifyGroupInfoRequest request = (WFCMessage.ModifyGroupInfoRequest) dataPool.getWFCMessage(WFCMessage.ModifyGroupInfoRequest.class);
+    	
+    	//灏�
+    	resultPool.setBytes(null);
+    }
+    
+    public void setGroupManager() throws Exception {
+    	//澶�
+    	WFCMessage.SetGroupManagerRequest request = (WFCMessage.SetGroupManagerRequest) dataPool.getWFCMessage(WFCMessage.SetGroupManagerRequest.class);
+
+    	//灏�
+    	resultPool.setBytes(null);
+    }
+    
+    public void friendUnread() throws Exception {
+    	long[] head = new long[1];
+    	//澶�
+    	WFCMessage.Version request = (WFCMessage.Version) dataPool.getWFCMessage(WFCMessage.Version.class);
+
+    	//灏�
+    	resultPool.setBytes(null);    	
+    }
+    
+    public void transferGroup() throws Exception {
+    	//澶�
+    	WFCMessage.TransferGroupRequest request = (WFCMessage.TransferGroupRequest) dataPool.getWFCMessage(WFCMessage.TransferGroupRequest.class);
+
+    	//灏�
+    	resultPool.setBytes(null);      	
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/ManagerNotifyHandler.java b/IMserver/medeasy/src/chat/handler/ManagerNotifyHandler.java
new file mode 100644
index 0000000..d59a51e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/ManagerNotifyHandler.java
@@ -0,0 +1,41 @@
+package chat.handler;
+
+import chat.server.call.CallObject;
+
+public class ManagerNotifyHandler extends CallObject {
+
+	@Override
+	protected void publishMethod() {
+		addOneMethod("createOneUser");
+		addOneMethod("modifyOneUser");
+		addOneMethod("deleteOneUser");
+		addOneMethod("createOneOrder");
+		addOneMethod("modifyOneOrder");
+		addOneMethod("deleteOneOrder");
+	}
+	
+	public void createOneUser() {
+		
+	}
+	
+	public void modifyOneUser() {
+		
+	}
+	
+	public void deleteOneUser() {
+		
+	}
+	
+	public void createOneOrder() {
+		
+	}
+	
+	public void modifyOneOrder() {
+		
+	}
+	
+	public void deleteOneOrder() {
+		
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/handler/MessageHandler.java b/IMserver/medeasy/src/chat/handler/MessageHandler.java
new file mode 100644
index 0000000..670d99c
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/MessageHandler.java
@@ -0,0 +1,13 @@
+package chat.handler;
+
+import chat.server.call.CallObject;
+
+public class MessageHandler extends CallObject {
+
+	@Override
+	protected void publishMethod() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/RobotHandler.java b/IMserver/medeasy/src/chat/handler/RobotHandler.java
new file mode 100644
index 0000000..510dd69
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/RobotHandler.java
@@ -0,0 +1,13 @@
+package chat.handler;
+
+import chat.server.call.CallObject;
+
+public class RobotHandler extends CallObject {
+
+	@Override
+	protected void publishMethod() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/SensitiveHandler.java b/IMserver/medeasy/src/chat/handler/SensitiveHandler.java
new file mode 100644
index 0000000..1d3be78
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/SensitiveHandler.java
@@ -0,0 +1,13 @@
+package chat.handler;
+
+import chat.server.call.CallObject;
+
+public class SensitiveHandler extends CallObject {
+
+	@Override
+	protected void publishMethod() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/SystemHandler.java b/IMserver/medeasy/src/chat/handler/SystemHandler.java
new file mode 100644
index 0000000..02f76c5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/SystemHandler.java
@@ -0,0 +1,236 @@
+package chat.handler;
+
+import java.util.Set;
+
+import chat.consts.MediaServerConfig;
+import chat.consts.ProtoConstants;
+import chat.module.Bucket;
+import chat.module.entity.ChatSpaceType;
+import chat.module.entity.MessageRecord;
+import chat.security.DES;
+import chat.server.call.CallObject;
+import chat.server.call.ResultCode;
+import chat.server.im.ResultPool;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.upload.UploadFile;
+import cn.hutool.core.lang.UUID;
+import cn.wildfirechat.proto.WFCMessage;
+import io.moquette.spi.impl.security.AES;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.FullHttpRequest;
+
+public class SystemHandler extends CallObject {
+	
+	private static final String KEY = "imfile";
+	
+	@Override
+	protected void publishMethod() {
+		addOneMethod("route");
+		addOneMethod("getMediaUploadToken");
+		addOneMethod("getQiniuUploadToken");
+		addOneMethod("uploadFileToServer");
+		addOneMethod("getSetting");
+		addOneMethod("setSetting");
+		addOneMethod("getToken");
+		addOneMethod("modifyMyInfo");
+		addOneMethod("multiCastMessage");
+		addOneMethod("recallMessage");
+		addOneMethod("sendMessage");
+		addOneMethod("uploadDeviceToken");
+	}
+
+	public void route() throws Exception {
+        WFCMessage.RouteResponse response = WFCMessage.RouteResponse.newBuilder().setHost("192.168.31.117").setLongPort(1883).setShortPort(80).build();
+        byte[] resBytes = response.toByteArray();
+		resultPool.setBytes(resBytes);
+	}
+	
+	public void uploadDeviceToken() throws Exception {
+		//澶�
+		WFCMessage.UploadDeviceTokenRequest request = (WFCMessage.UploadDeviceTokenRequest) dataPool.getWFCMessage(WFCMessage.UploadDeviceTokenRequest.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	//IMTopic.SendMessageTopic  MS
+	public void sendMessage() throws Exception {
+		//澶�
+		WFCMessage.Message message = (WFCMessage.Message) dataPool.getWFCMessage(WFCMessage.Message.class);
+		
+		long messageId = MessageRecord.newMessageId();
+		long timeStamp = System.currentTimeMillis();
+		message = message.toBuilder().setFromUser(user.getId()).setMessageId(messageId).setServerTimestamp(timeStamp).build();
+		
+		ChatSpaceType spaceType = ChatSpaceType.pase(message.getConversation().getType());
+		Bucket<?> bucket = Bucket.getInstance(spaceType);
+		bucket.pushOneMessage(message, user);
+       
+		//灏�
+        ByteBuf ackPayload = Unpooled.buffer();
+
+        ackPayload = ackPayload.capacity(20);
+        ackPayload.writeLong(messageId);
+        ackPayload.writeLong(timeStamp);
+        
+	    byte[] resBytes = new byte[ackPayload.readableBytes()];
+	    ackPayload.getBytes(0, resBytes);
+	    
+	    resultPool.setBytes(resBytes);
+	}
+	
+	public int getNotifyReceivers(String userId, WFCMessage.Message.Builder messageBuilder, Set<String> notifyReceivers) throws Exception {
+		int pullType = ProtoConstants.PullType.Pull_Normal;
+		notifyReceivers.add(userId);
+		notifyReceivers.add(messageBuilder.getConversation().getTarget());
+		return pullType;
+	}	
+	
+	public void recallMessage() throws Exception {
+		//澶�
+		WFCMessage.INT64Buf request = (WFCMessage.INT64Buf) dataPool.getWFCMessage(WFCMessage.INT64Buf.class);
+		
+		WFCMessage.INT64Buf.Builder requestB = request.toBuilder();
+		requestB.setId(Long.parseLong(dataPool.getString("messageUid")));
+		requestB.build();
+		//灏�
+		
+		resultPool.setBytes(null);
+	}
+	
+	public void multiCastMessage() throws Exception {
+		//澶�
+		WFCMessage.MultiCastMessage multiCastMessage = (WFCMessage.MultiCastMessage) dataPool.getWFCMessage(WFCMessage.MultiCastMessage.class);
+		
+		//灏�
+		ByteBuf payload = Unpooled.buffer();
+		long messageId = MessageRecord.newMessageId();
+	    payload.ensureWritable(20).writeLong(messageId).writeLong(System.currentTimeMillis());
+	    
+	    byte[] resBytes = payload.array();
+	    resultPool.setBytes(resBytes);
+	}
+	
+	public void modifyMyInfo() throws Exception {
+		//澶�
+		WFCMessage.ModifyMyInfoRequest request = (WFCMessage.ModifyMyInfoRequest) dataPool.getWFCMessage(WFCMessage.ModifyMyInfoRequest.class);
+		
+		//灏�
+		resultPool.setBytes(null);
+	}
+	
+	public void getToken() throws Exception {
+		//澶�
+		WFCMessage.GetTokenRequest request = (WFCMessage.GetTokenRequest) dataPool.getWFCMessage(WFCMessage.GetTokenRequest.class);
+		
+		WFCMessage.GetTokenRequest.Builder requestBuild = request.toBuilder();
+		requestBuild.setUserId(dataPool.getString("userId"));
+		requestBuild.setClientId(dataPool.getString("clientId"));
+		requestBuild.setPlatform(dataPool.getInteger("platform", 0));
+		
+		request = requestBuild.build();
+		
+		//灏�
+		String strToken = "";
+        String result = strToken + "|" + session.getSecret() + "|" + "123456";
+        byte[] bytes = result.getBytes();
+        
+        resultPool.setBytes(bytes);
+	}
+	
+	public void getQiniuUploadToken() throws Exception {
+		String token;
+		WFCMessage.GetUploadTokenResult.Builder resultBuilder = WFCMessage.GetUploadTokenResult.newBuilder();
+		
+        token = getToken(5);
+        String domain = "http://" + MediaServerConfig.SERVER_IP + ":" + MediaServerConfig.HTTP_SERVER_PORT;
+        resultBuilder.setDomain(domain);
+        resultBuilder.setServer(MediaServerConfig.SERVER_IP);
+        resultBuilder.setPort(MediaServerConfig.HTTP_SERVER_PORT);
+        resultBuilder.setToken(token);
+
+        byte[] data = resultBuilder.buildPartial().toByteArray();
+		resultPool.setBytes(data);		
+	}
+	
+	public void getMediaUploadToken() throws Exception {
+		String token;
+		int type;
+		
+		WFCMessage.GetUploadTokenRequest request = (WFCMessage.GetUploadTokenRequest) dataPool.getWFCMessage(WFCMessage.GetUploadTokenRequest.class);
+		type = request.getMediaType();
+		
+		WFCMessage.GetUploadTokenResult.Builder resultBuilder = WFCMessage.GetUploadTokenResult.newBuilder();
+		
+        token = getToken(type);
+        String domain = "http://" + MediaServerConfig.SERVER_IP + ":" + MediaServerConfig.HTTP_SERVER_PORT;
+        resultBuilder.setDomain(domain);
+        resultBuilder.setServer(MediaServerConfig.SERVER_IP);
+        resultBuilder.setPort(MediaServerConfig.HTTP_SERVER_PORT);
+        resultBuilder.setToken(token);
+
+        byte[] data = resultBuilder.buildPartial().toByteArray();
+		resultPool.setBytes(data);
+	}
+	
+	public void uploadFileToServer() throws Exception {
+		FullHttpRequest request = dataPool.getHttpRequest();
+		String requestId = UUID.randomUUID().toString().replace("-", "");
+		
+		String key = UploadFile.multipartUpload(request, requestId);
+		 
+		resultPool.setNeedReturnCode(false);
+		resultPool.add("key", key, false);
+	}
+	
+    public static String getToken(int type) {
+        String signKey = KEY + "|" + (System.currentTimeMillis()) + "|" + type;
+        try {
+            return DES.encryptDES(signKey);
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return null;
+    }
+	
+	public void getSetting() throws Exception {
+		
+	}
+	
+	public void setSetting() throws Exception {
+		
+	}
+	
+    public static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message,
+            int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    }
+	
+	public static void main(String[] args) {
+        WFCMessage.RouteResponse response = WFCMessage.RouteResponse.newBuilder().setHost("192.168.31.117").setLongPort(1883).setShortPort(80).build();
+        byte[] resBytes = response.toByteArray();
+        resBytes = AES.AESEncrypt(resBytes, "31a95a1a-d169-4a26-be4c-ef73088c1b1f");
+
+//		data = Base64.getEncoder().encode(data);
+		
+        ByteBuf buf = Unpooled.buffer();
+        
+        buf.ensureWritable(1).writeByte(ResultCode.Success.getValue());
+        buf.ensureWritable(resBytes.length).writeBytes(resBytes);
+        
+        System.out.println(buf);
+	
+	}
+}
diff --git a/IMserver/medeasy/src/chat/handler/data/DataList.java b/IMserver/medeasy/src/chat/handler/data/DataList.java
new file mode 100644
index 0000000..c6cfd44
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/data/DataList.java
@@ -0,0 +1,143 @@
+package chat.handler.data;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import chat.user.User;
+import chat.user.UserStore;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.Message;
+import cn.wildfirechat.proto.WFCMessage.UserResult;
+
+public class DataList {
+
+	private static List<FriendData> friendList;
+	private static List<WFCMessage.Message> messageList;
+	private static Map<String, WFCMessage.UserResult> userMap;
+	private static WFCMessage.UserResult currentUserInfo;
+	public static long timestamp;
+	
+	static {
+		timestamp = System.currentTimeMillis();
+		
+		//1. friend list
+		friendList = new ArrayList<FriendData>();
+		
+//		friendList.add(new FriendData("user000", "user001", "鏈嬪弸1鍒悕", null, 0, 0, timestamp));
+//		friendList.add(new FriendData("user000", "user002", "鏈嬪弸2鍒悕", null, 0, 0, timestamp));
+//		friendList.add(new FriendData("user000", "user003", "鏈嬪弸3鍒悕", null, 0, 0, timestamp));
+//		friendList.add(new FriendData("user000", "user004", "鏈嬪弸4鍒悕", null, 0, 0, timestamp));
+		
+		//2. message list
+		messageList = new ArrayList<WFCMessage.Message>();
+		
+		WFCMessage.Message message0 = createOneMessage(202101109876543201L, "user001");
+		messageList.add(message0);
+		
+//		WFCMessage.Message message1 = createOneMessage(202101109876543202L, "user001");
+//		messageList.add(message1);
+		
+		WFCMessage.Message message2 = createOneMessage(202101109876543203L, "user002");
+		messageList.add(message2);
+		
+		WFCMessage.Message message3 = createOneMessage(202101109876543204L, "user003");
+		messageList.add(message3);
+		
+		WFCMessage.Message message4 = createOneMessage(202101109876543204L, "user004");
+		messageList.add(message4);
+		
+		//3. user list
+		userMap = new HashMap<String, WFCMessage.UserResult>();
+//		currentUserInfo = createUserInfo("user000", "user000", "usera000", "http://cdn2.wildfirechat.cn/robot.png", "13636388405");
+//		WFCMessage.UserResult user1 = createUserInfo("user001", "user001", "usera001", "http://cdn2.wildfirechat.cn/robot.png", "13600000001");
+//		WFCMessage.UserResult user2 = createUserInfo("user002", "user002", "usera002", "http://cdn2.wildfirechat.cn/robot.png", "13600000002");
+//		WFCMessage.UserResult user3 = createUserInfo("user003", "user003", "usera003", "http://cdn2.wildfirechat.cn/robot.png", "13600000003");
+//		WFCMessage.UserResult user4 = createUserInfo("user004", "user004", "user004", "http://cdn2.wildfirechat.cn/robot.png", "13600000004");
+		
+//		userMap.put("user000", currentUserInfo);
+//		userMap.put("user001", user1);
+//		userMap.put("user002", user2);
+//		userMap.put("user003", user3);
+//		userMap.put("user004", user4);
+	}
+	
+	public static List<FriendData> getFriendList() {
+		return friendList;
+	}
+
+	public static List<WFCMessage.Message> getMessageList() {
+		return messageList;
+	}
+	
+	public static WFCMessage.UserResult getUserInfo() {
+		return currentUserInfo;
+	}
+	
+	private static Message createOneMessage(long messageId, String userId) {
+		WFCMessage.Message message = null;
+		
+		try {
+			WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			
+			builder.setMessageId(messageId);
+			builder.setFromUser(userId);
+			
+	        WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+	        cb.setType(0);
+	        //cb.setTarget("user000");
+	        cb.setTarget("user000");
+	        cb.setLine(0);
+	        builder.setConversation(cb.build());
+	        
+	        WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+	        contentBuilder.setType(1);
+	        String str = "this is " + userId + "say 娴嬭瘯: Hello!!!";
+	        byte[] bytes = str.getBytes();
+	        bytes = Base64.getEncoder().encode(bytes);
+	        //ByteString byteString = ByteString.copyFromUtf8(str);
+	        //contentBuilder.setSearchableContentBytes(byteString);
+	        contentBuilder.setSearchableContent(str);
+	        contentBuilder.setMediaType(0);
+	        contentBuilder.setPersistFlag(0);
+	        contentBuilder.setExpireDuration(0);
+	        contentBuilder.setMentionedType(0);
+	        WFCMessage.MessageContent messageContent = contentBuilder.build();
+	        builder.setContent(messageContent);
+	        
+	        builder.setServerTimestamp(timestamp);
+			
+			message = builder.build();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+		return message;
+	}
+	
+	private static UserResult createUserInfo(String userId, String name, String displayName, String portrait, String mobile) {
+		//1. create user
+		User user = new User(userId);
+		user.setName(name);
+		user.setDisplayName(displayName);
+		user.setPortrait(portrait);
+		user.setMobile(mobile);
+		
+		//2. add to store
+		UserStore.addOne(user);
+
+		//3. to user result
+        WFCMessage.UserResult userResult = user.toWFCUserResult();
+        
+        return userResult;
+	}
+
+	public static UserResult getUser(String uid) {
+		WFCMessage.UserResult user = userMap.get(uid);
+		return user;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/handler/data/FriendData.java b/IMserver/medeasy/src/chat/handler/data/FriendData.java
new file mode 100644
index 0000000..34bfac7
--- /dev/null
+++ b/IMserver/medeasy/src/chat/handler/data/FriendData.java
@@ -0,0 +1,82 @@
+package chat.handler.data;
+
+public class FriendData {
+	
+    private String userId;
+    private String friendUid;
+    private String alias;
+    private String extra;
+    private int state;
+    private int blacked;
+    private long timestamp;
+
+
+    public FriendData(String userId, String friendUid, String alias, String extra, int state, int blacked, long timestamp) {
+        this.userId = userId;
+        this.friendUid = friendUid;
+        this.alias = alias;
+        this.extra = extra;
+        this.state = state;
+        this.blacked = blacked;
+        this.timestamp = timestamp;
+    }
+
+    public FriendData() {
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getFriendUid() {
+        return friendUid;
+    }
+
+    public void setFriendUid(String friendUid) {
+        this.friendUid = friendUid;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+    public String getExtra() {
+        return extra;
+    }
+
+    public void setExtra(String extra) {
+        this.extra = extra;
+    }
+
+    public int getState() {
+        return state;
+    }
+
+    public void setState(int state) {
+        this.state = state;
+    }
+
+    public int getBlacked() {
+        return blacked;
+    }
+
+    public void setBlacked(int blacked) {
+        this.blacked = blacked;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+}
diff --git a/IMserver/medeasy/src/chat/medeasy/HttpClientUtil.java b/IMserver/medeasy/src/chat/medeasy/HttpClientUtil.java
new file mode 100644
index 0000000..35c607e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/medeasy/HttpClientUtil.java
@@ -0,0 +1,91 @@
+package chat.medeasy;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+
+public class HttpClientUtil {
+
+	public static String execHttpClient(String jsonStr, String serverURL, Map<String, String> heads) {
+		boolean result = false;
+		CloseableHttpResponse response = null;
+		CloseableHttpClient httpClient = null;
+		HttpPost httpPost = null;
+		String responseContent = "";
+		
+		try {
+			 httpClient = HttpClientBuilder.create().build();
+			 httpPost = new HttpPost(serverURL);
+			 if (heads != null) {
+				 for (String head : heads.keySet()) {
+					  httpPost.addHeader(head, heads.get(head));
+				 }
+			 }
+			 httpPost.setEntity(new StringEntity(jsonStr, "UTF-8"));
+			 response = httpClient.execute(httpPost);
+			 HttpEntity entity = response.getEntity();
+			 responseContent = EntityUtils.toString(entity);
+			 response.close();
+			 httpClient.close();
+		} catch(Exception e) {
+			 e.printStackTrace();
+		} finally {
+			close(response, httpClient);
+		}
+		
+		return responseContent;
+	}
+	
+	private static void close(Closeable... closeables) {
+		if (closeables != null && closeables.length > 0) {
+			try {
+				for (Closeable closeable : closeables) {
+					if (closeable != null) {
+						closeable.close();
+					}
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}		
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/IMserver/medeasy/src/chat/message/Callback.java b/IMserver/medeasy/src/chat/message/Callback.java
new file mode 100644
index 0000000..2563374
--- /dev/null
+++ b/IMserver/medeasy/src/chat/message/Callback.java
@@ -0,0 +1,10 @@
+package chat.message;
+
+public class Callback {
+
+	public void exec() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/message/MessageRunner.java b/IMserver/medeasy/src/chat/message/MessageRunner.java
new file mode 100644
index 0000000..e91a86f
--- /dev/null
+++ b/IMserver/medeasy/src/chat/message/MessageRunner.java
@@ -0,0 +1,61 @@
+package chat.message;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MessageRunner {
+
+	private static final Logger LOG = LoggerFactory.getLogger(MessageRunner.class);
+	//private ScheduledExecutorService mScheduledExecutorService = Executors.newScheduledThreadPool(10);
+	private ScheduledExecutorService executor;
+	private final AtomicInteger runCounter;
+	
+	public MessageRunner(ScheduledExecutorService executor) {
+		this.runCounter = new AtomicInteger();
+		this.executor = executor;
+	}
+	
+//	private ThreadFactory threadFactory = new ThreadFactory() {
+//        @Override
+//        public Thread newThread(final Runnable r) {
+//            return new Thread() {
+//                @Override
+//                public void run() {
+//                    r.run();
+//                }
+//            };
+//        }
+//    };
+    
+    public void execute(Runnable task) {
+    	int startCount = runCounter.incrementAndGet();
+    	LOG.debug("Submit task and current task count {}", startCount);
+    	final long startTime = System.currentTimeMillis();
+    	executor.execute(() -> {
+    		try {
+    			 task.run();
+    		} finally {
+    			 int endCount = runCounter.decrementAndGet();
+    			 LOG.debug("Finish task and current task count {} use time {}", endCount, System.currentTimeMillis()-startTime);
+    		}
+    	});
+    }
+    
+    public void shutdown() {
+    	executor.isShutdown();
+    }
+	
+//	public void publishToMembers(MessageRecord message, List<Member> memberList, User sender) {
+//    	mScheduledExecutorService.schedule(threadFactory.newThread(new Runnable() {
+//            @Override
+//            public void run() {
+//               exeMessage(user);
+//            }
+//        }), 100, TimeUnit.MILLISECONDS);
+//	}
+}
diff --git a/IMserver/medeasy/src/chat/message/MessageServer.java b/IMserver/medeasy/src/chat/message/MessageServer.java
new file mode 100644
index 0000000..ba97163
--- /dev/null
+++ b/IMserver/medeasy/src/chat/message/MessageServer.java
@@ -0,0 +1,50 @@
+package chat.message;
+
+import chat.module.entity.MessageRelation;
+import chat.persist.Message;
+import cn.wildfirechat.proto.WFCMessage;
+
+public class MessageServer {
+
+	public WFCMessage.Message createOneMessage(Message message, MessageRelation messageRelation) {
+		WFCMessage.Message messageWFC = null;
+		
+		try {
+			 WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			 builder.setMessageId(message.getMessageid());
+			 builder.setFromUser(message.getSenderid());
+			 
+			 WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+			 cb.setType(messageRelation.getType());
+			 cb.setTarget(messageRelation.getTargetid());
+			 cb.setLine(messageRelation.getLine());
+			 builder.setConversation(cb.build());
+			 
+			 WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+			 contentBuilder.setType(message.getType());
+			 contentBuilder.setSearchableContent(message.getContent());
+			 contentBuilder.setMediaType(0);
+			 contentBuilder.setPersistFlag(message.getPersistflag());
+	         contentBuilder.setExpireDuration(0);
+	         contentBuilder.setMentionedType(0);
+	         
+	         WFCMessage.MessageContent messageContent = contentBuilder.build();
+	         
+	         builder.setContent(messageContent);
+	         
+	         messageWFC = builder.build();
+			 
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+		return messageWFC;
+	}
+}
+
+
+
+
+
+
+
+
diff --git a/IMserver/medeasy/src/chat/message/MessagesPublisher.java b/IMserver/medeasy/src/chat/message/MessagesPublisher.java
new file mode 100644
index 0000000..1afa820
--- /dev/null
+++ b/IMserver/medeasy/src/chat/message/MessagesPublisher.java
@@ -0,0 +1,134 @@
+package chat.message;
+
+import static chat.consts.ProtoConstants.PersistFlag.Transparent;
+
+import java.util.Collection;
+import java.util.List;
+
+import chat.consts.ProtoConstants;
+import chat.module.PrivateFriendBucket;
+import chat.module.entity.MessageContainer;
+import chat.module.entity.PrivateFriend;
+import chat.server.im.IMTopic;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.Client;
+import chat.user.Session;
+import chat.user.UserStore;
+import chat.util.MessageShardingUtil;
+import cn.wildfirechat.proto.WFCMessage;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+
+public class MessagesPublisher {
+
+	public void publish2Receivers(WFCMessage.Message messageT, Collection<String> receivers, int pullType) {
+		String sender = messageT.getFromUser();
+		int conversationType = messageT.getConversation().getType();
+		String target = messageT.getConversation().getTarget();
+		int line = messageT.getConversation().getLine();
+		long messageId = messageT.getMessageId();
+		int messageContentType = messageT.getContent().getType();
+		MessageContainer messageContainer;
+		
+		String pushContent;
+        if (messageT.getContent().getPersistFlag() == Transparent) {
+            pushContent = null;
+        } else {
+        	if (messageContentType == ProtoConstants.ContentType.Text) {
+        		pushContent = messageT.getContent().getPushContent();
+        	}
+        }
+
+		String pushData = messageT.getContent().getPushData();
+		
+		long serverTime = messageT.getServerTimestamp();
+		int mentionType = messageT.getContent().getMentionedType();
+		List<String> mentionTargets = messageT.getContent().getMentionedTargetList();
+		int persistFlag = messageT.getContent().getPersistFlag();
+		WFCMessage.Message message = null;
+		
+		if (persistFlag == Transparent) {
+			publishTransparentMessage2Receivers(messageT, receivers, pullType);
+			return;
+		}
+		
+		try {
+			for (String usr : receivers) {
+				 if (usr.equals(sender)) {
+					 continue;
+				 }
+				 
+				 long messageSeq = MessageShardingUtil.generateId();
+				 
+				 //鏍规嵁sender銆乼argetId 瀹氫綅ChatSpaceType, 淇濆瓨message鏁版嵁
+				 if(messageT.getConversation().getType() == 0) {
+					//PrivateFriendBucket.getInstance().saveMessage(messageT, messageSeq);
+				 }
+				 //缇ょ粍鍙戞秷鎭�
+				 else if (messageT.getConversation().getType() == 1) {
+				 }
+				 
+				 if (!usr.equals(sender)) {
+                     WFCMessage.NotifyMessage notifyMessage = WFCMessage.NotifyMessage
+								                             .newBuilder()
+								                             .setType(pullType)
+								                             .setHead(messageSeq)
+								                             .build();
+         	         ByteBuf payload = Unpooled.buffer();
+        	         byte[] byteData = notifyMessage.toByteArray();
+        	         
+        	         payload.ensureWritable(byteData.length).writeBytes(byteData);
+        	         MqttPublishMessage publishMsg;
+        	         publishMsg = notRetainedPublish(IMTopic.NotifyMessageTopic, MqttQoS.AT_MOST_ONCE, payload);
+        			 
+        			 Client client = UserStore.getById(usr).getClient(usr);
+        			 
+        			 Session sessionC = client.getSession();
+        			 if (sessionC != null) {
+        			 	 Channel channel = sessionC.getChannel();
+        			 	 if (publishMsg != null) {
+        			 	 	 channel.writeAndFlush(publishMsg);
+        			 	 }
+        			 }
+				 }
+			}
+		} catch(Exception e) {
+			e.printStackTrace();
+		}		
+	}
+	
+    private void publishTransparentMessage2Receivers(WFCMessage.Message message, Collection<String> receivers, int pullType) {
+        for (String user : receivers) {
+	         ByteBuf payload = Unpooled.buffer();
+	         byte[] byteData = message.toByteArray();
+	         payload.ensureWritable(byteData.length).writeBytes(byteData);
+	         MqttPublishMessage publishMsg;
+	         publishMsg = notRetainedPublish(IMTopic.SendMessageTopic, MqttQoS.AT_MOST_ONCE, payload);
+ 			
+	         Client client = UserStore.getById(user).getClient(user);
+ 			
+ 			 Session sessionC = client.getSession();
+ 			 if (sessionC != null) {
+ 				 Channel channel = sessionC.getChannel();
+ 				 if (publishMsg != null) {
+ 					 channel.writeAndFlush(publishMsg);
+ 				 }
+ 			 }	         
+        }
+    }
+    
+    private static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message, int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    }    
+}
diff --git a/IMserver/medeasy/src/chat/message/SendMessageCallback.java b/IMserver/medeasy/src/chat/message/SendMessageCallback.java
new file mode 100644
index 0000000..f19d231
--- /dev/null
+++ b/IMserver/medeasy/src/chat/message/SendMessageCallback.java
@@ -0,0 +1,25 @@
+package chat.message;
+
+import java.util.List;
+
+import chat.module.entity.Member;
+import chat.user.User;
+
+public class SendMessageCallback {
+
+	public void setSender(User user) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void setMemberList(List<Member> memberList) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void setMessage(String string) {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/Bucket.java b/IMserver/medeasy/src/chat/module/Bucket.java
new file mode 100644
index 0000000..e699c95
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/Bucket.java
@@ -0,0 +1,249 @@
+package chat.module;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import chat.consts.ProtoConstants;
+import chat.module.entity.ChatSpaceType;
+import chat.module.entity.Group;
+import chat.module.entity.Member;
+import chat.module.entity.MessageContainer;
+import chat.module.entity.MessageRecord;
+import chat.server.im.IMTopic;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.Client;
+import chat.user.Session;
+import chat.user.User;
+import chat.user.UserStore;
+import chat.util.MessageShardingUtil;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.Message;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+
+import static chat.consts.ProtoConstants.PersistFlag.Transparent;
+
+public class Bucket<T extends MessageContainer> {
+	
+	private ConcurrentMapList<T> itemMap;
+	private static int pullType;
+	
+	public Bucket() {
+		itemMap = new ConcurrentMapList<T>();
+	}
+
+	public static Bucket<?> getInstance(ChatSpaceType spaceType) {
+		if (ChatSpaceType.Private == spaceType) {
+			pullType = ProtoConstants.PullType.Pull_Normal;
+			return PrivateFriendBucket.getInstance();
+		}
+		else if (ChatSpaceType.Group == spaceType) {
+			pullType = ProtoConstants.PullType.Pull_Normal;
+			return GroupBucket.getInstance();
+		}
+		return null;
+	}
+	
+	public void sendGroupNotification(User user, WFCMessage.CreateGroupRequest request, WFCMessage.MessageContent content, Group group) {
+		String targetId = group.getId();
+		List<Integer> lines = request.getToLineList();
+		
+        if (lines == null) {
+            lines = new ArrayList<>();
+        } else {
+            lines = new ArrayList<>(lines);
+        }
+
+        if (lines.isEmpty()) {
+            lines.add(0);
+        }
+
+        for (int line : lines) {
+            long timestamp = System.currentTimeMillis();
+            WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder().setContent(content).setServerTimestamp(timestamp);
+            builder.setConversation(builder.getConversationBuilder().setType(ProtoConstants.ConversationType.ConversationType_Group).setTarget(targetId).setLine(line));
+            builder.setFromUser(user.getId());
+            try {
+                 long messageId = MessageShardingUtil.generateId();
+                 builder.setMessageId(messageId);
+                 pushOneMessage(builder.build(), user, request);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }		
+	}
+	
+	public void pushOneMessage(Message message, User user) throws Exception {
+        ModuleLoader.getImBusinessScheduler().execute(() -> doPushOneMessage(message, user, null, true));
+	}
+	
+	public void pushOneMessage(Message message, User user, boolean isExceptUser) throws Exception {
+        ModuleLoader.getImBusinessScheduler().execute(() -> doPushOneMessage(message, user, null, isExceptUser));
+	}	
+	
+	public void pushOneMessage(Message message, User user, WFCMessage.CreateGroupRequest request) throws Exception {
+		ModuleLoader.getImBusinessScheduler().execute(() -> doPushOneMessage(message, user, request, true));
+	}
+
+	public void doPushOneMessage(Message message, User user, WFCMessage.CreateGroupRequest request, boolean isExceptUser) {
+		//String containerId = getMessageContainerID(message);
+		//1.寰楀埌messageContainer  濡傛灉鏄鑱�......,濡傛灉鏄兢鑱�.....
+		
+		Set<String> notifyReceivers = new LinkedHashSet<String>();
+		WFCMessage.Message.Builder messageBuilder = message.toBuilder();
+		
+		int pullType = 0;
+		if (request == null) {
+			pullType = getNotifyReceivers(user.getId(), messageBuilder, notifyReceivers);
+		}
+		else {//鏄兢缁勭殑娑堟伅
+			pullType = getGroupNotifyReceiver(request.getGroup().getMembersList(), notifyReceivers);
+		}
+		
+        if (message.getContent().getPersistFlag() == Transparent) {
+            notifyReceivers.remove(messageBuilder.getFromUser());
+        }
+		
+		if (message.getContent().getPersistFlag() == Transparent) {
+			publishTransparentMessage2Receivers(message, notifyReceivers, pullType);
+			return;
+		}
+		
+		MessageContainer container = getMessageContainerID(message);
+		
+		if (container == null) {
+			return;
+		}
+		
+		String userId = user.getId();
+		String spaceCode = container.getOneMember(userId).getSpacecode();
+		String spaceId = container.getOneMember(userId).getSpaceid();
+		try {
+			 MessageRecord record = MessageRecord.getInstance(spaceCode, spaceId, message);
+			 container.addOneMessage(pullType, record, user, message, isExceptUser);
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+	
+    private void publishTransparentMessage2Receivers(WFCMessage.Message message, Collection<String> receivers, int pullType) {
+        for (String user : receivers) {
+	         ByteBuf payload = Unpooled.buffer();
+	         byte[] byteData = message.toByteArray();
+	         payload.ensureWritable(byteData.length).writeBytes(byteData);
+	         MqttPublishMessage publishMsg;
+	         publishMsg = notRetainedPublish(IMTopic.SendMessageTopic, MqttQoS.AT_MOST_ONCE, payload);
+ 			
+	         Client client = UserStore.getById(user).getClient(user);
+ 			
+ 			 Session sessionC = client.getSession();
+ 			 if (sessionC != null) {
+ 				 Channel channel = sessionC.getChannel();
+ 				 if (publishMsg != null) {
+ 					 channel.writeAndFlush(publishMsg);
+ 				 }
+ 			 }	         
+        }
+    }
+    
+    private static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message, int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    } 
+    
+    public int getGroupNotifyReceiver(List<WFCMessage.GroupMember> members, Set<String> notifyReceivers) {
+    	int pullType = ProtoConstants.PullType.Pull_Normal;
+    	for (WFCMessage.GroupMember member : members) {
+    		 notifyReceivers.add(member.getMemberId());
+    	}
+    	
+    	return pullType;
+    }
+	
+	public int getNotifyReceivers(String userId, WFCMessage.Message.Builder messageBuilder, Set<String> notifyReceivers) {
+		int pullType = ProtoConstants.PullType.Pull_Normal;
+		if (ChatSpaceType.Group == ChatSpaceType.pase(messageBuilder.getConversation().getType())) {
+			Group friendGroup = GroupBucket.getGroup(messageBuilder.getConversation().getTarget());
+			for(Member member : friendGroup.getMemberList()) {
+				notifyReceivers.add(member.getUserId());
+			}
+		}
+		else if (ChatSpaceType.Private == ChatSpaceType.pase(messageBuilder.getConversation().getType())){
+			notifyReceivers.add(userId);
+			notifyReceivers.add(messageBuilder.getConversation().getTarget());			
+		}
+
+		return pullType;
+	}
+	
+	private MessageContainer getMessageContainerID(Message message) {
+		MessageContainer msgContainer = null;
+		
+		if (message.getConversation().getType() == 0) {
+			//鍙栧嚭鎵�鏈夌鏈夌殑MeessageContainer锛屾牴鎹汉鏉ユ煡鎵惧叿浣撶殑绉佽亰id(鍙互鎯宠薄涓轰竴涓壒娈婄殑缇ょ粍锛屽彧鏈変簩涓汉)
+			//闇�瑕佹瘮杈冨彂閫佽�呬笌鎺ユ敹鑰�
+			for (MessageContainer messageContainer : getAll()) {
+				 if (messageContainer.getOneMember(message.getFromUser()) != null
+				     && messageContainer.getOneMember(message.getConversation().getTarget()) != null) {
+					 msgContainer = messageContainer;
+					 break;
+				 }
+			}
+		}
+		else if (message.getConversation().getType() == 1) {
+			msgContainer = GroupBucket.getGroup(message.getConversation().getTarget());//itemMap.get(message.getConversation().getTarget());
+		}
+		
+		return msgContainer;
+	}
+
+	public T createOne(String tableName, T one) throws Exception {
+		DataObject dataObject = DataObject.getInstance(tableName);
+		
+		Entity entity = dataObject.newEntity();
+		one.pushTo(entity);
+			
+		dataObject.insertToDataBase(entity);
+		return one;
+	}
+	
+	public void addOne(String key, T item) {
+		itemMap.add(key, item);
+	}
+	
+	public T getOne(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		return itemMap.get(key);
+	}
+	
+	public T deleteOne(String key) {
+		return itemMap.delete(key);
+	}
+
+	public List<T> getAll() {
+		return itemMap.getList();
+	}
+	
+	public int size() {
+		return itemMap.size();
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/ChannelBucket.java b/IMserver/medeasy/src/chat/module/ChannelBucket.java
new file mode 100644
index 0000000..e2b75be
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/ChannelBucket.java
@@ -0,0 +1,27 @@
+package chat.module;
+
+import chat.module.entity.Channel;
+import chat.user.User;
+
+public class ChannelBucket extends Bucket<Channel> {
+
+	private static ChannelBucket instance;
+	
+	public static synchronized ChannelBucket getInstance() {
+		if (instance == null) {
+			instance = new ChannelBucket();
+		}
+		
+		return instance;
+	}
+	
+//	public Channel createOne(String name, User sender) {
+//		Channel channel = new Channel(name, sender);
+//		String channelId = channel.getId();
+//		
+//		addOne(channelId, channel);
+//		
+//		return channel;
+//	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/ChatroomBucket.java b/IMserver/medeasy/src/chat/module/ChatroomBucket.java
new file mode 100644
index 0000000..5f8c44b
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/ChatroomBucket.java
@@ -0,0 +1,33 @@
+package chat.module;
+
+import chat.module.entity.ChatRoom;
+import chat.user.User;
+
+public class ChatroomBucket extends Bucket<ChatRoom> {
+	
+	private static ChatroomBucket instance;
+	
+	private ChatroomBucket() {
+		
+	}
+	
+	public static synchronized ChatroomBucket getInstance() {
+		if (instance == null) {
+			instance = new ChatroomBucket();
+		}
+		
+		return instance;
+	}
+	
+//	public ChatRoom createOne(String name, User sender) {
+//		ChatRoom chatroom = new ChatRoom(name, sender);
+//		String key = chatroom.getId();
+//		
+//		addOne(key, chatroom);
+//		
+//		return chatroom;
+//	}
+
+
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/ConcurrentMapList.java b/IMserver/medeasy/src/chat/module/ConcurrentMapList.java
new file mode 100644
index 0000000..d7992c8
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/ConcurrentMapList.java
@@ -0,0 +1,210 @@
+package chat.module;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import chat.module.entity.FriendShip;
+import frame.util.ContentBuilder;
+
+public class ConcurrentMapList<T> implements Iterable<T> {
+
+	protected List<T> itemList;
+	protected Map<String, T> itemMap;
+	protected Map<String, Integer> indexMap;
+	
+	
+	public ConcurrentMapList() {
+		itemList = new ArrayList<T>();
+		itemMap = new HashMap<String, T>();
+	}
+	
+	public void addAll(Map<String, T> map) {
+		synchronized (this) {
+			Set<String> keys = map.keySet();
+			
+			for (String key: keys) {
+				add(key, map.get(key));
+			}
+		}
+	}
+	
+	public void add(String key, T item) {
+		if (key == null) {
+			return;
+		}
+		
+		synchronized (this) {
+			key = key.toLowerCase();
+			itemMap.put(key, item);
+			itemList.add(item);
+		}
+	}
+	
+	public void addMapList(String key, T items) {
+		if (key == null) {
+			return;
+		}
+		synchronized (this) {
+			key = key.toLowerCase();
+			itemMap.put(key, items);
+		}
+	}
+
+	public void set(String key, T item) {
+		if (key == null) {
+			return;
+		}
+		
+		synchronized (this) {
+			if (indexMap == null) {
+				indexMap = new HashMap<String, Integer>();
+			}
+			
+			key = key.toLowerCase();
+			
+			if (!itemMap.containsKey(key)) {
+				itemMap.put(key, item);
+				indexMap.put(key, itemList.size());
+				itemList.add(item);
+			}
+			else {
+				Integer idx = indexMap.get(key);
+				itemList.set(idx, item);
+			}
+		}
+	}
+	
+	public T get(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		synchronized (this) {
+			key = key.toLowerCase();
+			return itemMap.get(key);
+		}
+	}
+	
+	public T get(int idx) {
+		synchronized (this) {
+			return itemList.get(idx);
+		}
+	}
+	
+	public T delete(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		synchronized (this) {
+			T obj = itemMap.get(key.toLowerCase());
+			
+			if (obj != null) {
+				itemMap.remove(key);
+				itemList.remove(obj);
+			}
+			
+			return obj;
+		}
+	}
+	
+	public List<T> getList() {
+		synchronized (this) {
+			return itemList;
+		}
+	}
+	
+	public Set<String> getKeySet() {
+		synchronized (this) {
+			return itemMap.keySet();
+		}
+	}	
+
+	public boolean isEmpty() {
+		return itemList.isEmpty();
+	}
+	
+	public int size() {
+		return itemList.size();
+	}
+	
+	public int mapSize() {
+		return itemMap.size();
+	}
+	
+	public Iterator<T> iterator() {
+		synchronized (this) {
+			return itemList.iterator();
+		}
+	}
+
+	public void clear() {
+		itemList.clear();
+		itemMap.clear();
+	}
+	
+	public String toString(String separator) {
+		ContentBuilder builder = new ContentBuilder(separator);
+		
+		for (String key: itemMap.keySet()) {
+			builder.append(key);
+		}
+		
+		return builder.toString();
+	}
+	
+	public Set<String> keySet() {
+		return itemMap.keySet();
+	}
+
+	public boolean equals(ConcurrentMapList<T> another) {
+		if (another == null) {
+			return false;
+		}
+		
+		if (this == another) {
+			return true;
+		}
+		
+		Set<String> keys = itemMap.keySet();
+		for (String key: keys) {
+			if (!another.contains(key)) {
+				return false;
+			}
+		}
+		
+		Set<String> anotherKeys = another.itemMap.keySet();
+		for (String anotherKey: anotherKeys) {
+			if (!contains(anotherKey)) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+
+	public boolean contains(String key) {
+		if (key == null) {
+			return false;
+		}
+		
+		synchronized (this) {
+			key = key.toLowerCase();
+			return itemMap.containsKey(key);
+		}
+	}
+
+	public Object[] toArray() {
+		return itemList.toArray();
+	}
+
+	@SuppressWarnings("hiding")
+	public <T> T[] toArray(T[] a) {
+		return itemList.toArray(a);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/FriendRequstBucket.java b/IMserver/medeasy/src/chat/module/FriendRequstBucket.java
new file mode 100644
index 0000000..2ac9ab4
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/FriendRequstBucket.java
@@ -0,0 +1,78 @@
+package chat.module;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import chat.module.entity.Group;
+import chat.module.entity.FriendRequest;
+import chat.module.entity.Member;
+import chat.module.entity.MessageRecord;
+import chat.user.User;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.UserRequest;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+
+public class FriendRequstBucket extends Bucket<FriendRequest> {
+
+	private static FriendRequstBucket instance;
+	private static final Logger LOG = LoggerFactory.getLogger(FriendRequstBucket.class);
+	
+	public static synchronized FriendRequstBucket getInstance() {
+		if (instance == null) {
+			instance = new FriendRequstBucket();
+		}
+		
+		return instance;
+	}
+	
+    public static String getUUID() {
+        UUID uuid = UUID.randomUUID();
+        String str = uuid.toString();
+        str = str.replace("-", "");
+        return str;
+    }
+	
+	public void createFriendRequest(String userId, WFCMessage.AddFriendRequest request, long[] head) throws Exception {
+		//1. get group from cache
+		FriendRequest friendRequest = getOne(userId);
+		
+		//2. create new group
+		if (friendRequest == null) {
+			friendRequest = new FriendRequest(userId, request.getTargetUid());
+			friendRequest.load(request);
+			
+			createOneFriendRequest(friendRequest);
+			addOne(userId, friendRequest);
+		}
+		
+		//3. create hello message
+		//MessageRecord record = MessageRecord.getTextInstance(sender.getName() + "鎷変綘鍏ョ兢", sender);
+		//friendGroup.addOneMessage(record, sender);
+		
+		//4. send message to members
+//		friendGroup.publishOneMessage(record, sender, true, content);
+
+		//5. return
+	}
+
+    private void createOneFriendRequest(FriendRequest friendRequest) throws Exception {
+    	DataObject dataObject; 
+    	Entity entity;
+    	
+    	//1. insert group
+		dataObject = DataObject.getInstance("friend_request");
+		
+		entity = dataObject.newEntity();
+		friendRequest.pushTo(entity);
+			
+		dataObject.insertToDataBase(entity);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/GroupBucket.java b/IMserver/medeasy/src/chat/module/GroupBucket.java
new file mode 100644
index 0000000..c71d670
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/GroupBucket.java
@@ -0,0 +1,260 @@
+package chat.module;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import chat.consts.ProtoConstants;
+import chat.module.entity.Group;
+import chat.module.entity.GroupType;
+import chat.module.entity.Member;
+import chat.module.entity.MessageRecord;
+import chat.user.User;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.GroupInfo;
+import cn.wildfirechat.proto.WFCMessage.UserRequest;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+
+public class GroupBucket extends Bucket<Group> {
+
+	protected static final Logger logger; 
+	private static GroupBucket groupDoctorBucket;
+	private static GroupBucket groupPatientBucket;
+	private static GroupBucket groupFriendBucket;
+	private static GroupBucket allGroupBucket;
+	private static ConcurrentMapList<Group> allGroups;
+	private GroupType groupType;
+	private static int pullType;
+	
+	static {
+		logger = Logger.getLogger(GroupBucket.class);
+		allGroupBucket = new GroupBucket();
+		groupDoctorBucket = new GroupBucket(GroupType.Doctor);
+		groupPatientBucket = new GroupBucket(GroupType.Patient);
+		groupFriendBucket = new GroupBucket(GroupType.Friend);
+		allGroups = new ConcurrentMapList<Group>();
+		pullType = ProtoConstants.PullType.Pull_Normal;
+	}
+	
+	public static synchronized GroupBucket getInstance() {
+		if (allGroupBucket == null) {
+			allGroupBucket = new GroupBucket();
+		}
+		
+		return allGroupBucket;		
+	}
+	
+	public GroupBucket() {}
+	
+	public static synchronized GroupBucket getInstance(GroupType type) {
+		if (GroupType.Doctor == type) {
+			return groupDoctorBucket;
+		}
+		else if (GroupType.Patient == type) {
+			return groupPatientBucket;
+		}
+		else if (GroupType.Friend == type) {
+			return groupFriendBucket;
+		}
+		
+		return null;
+	}
+	
+	public GroupBucket(GroupType groupType) {
+		this.groupType = groupType;
+	}
+
+	public static void load(GroupType type, Entity entity) {
+		Group group = new Group();
+		group.load(entity);
+		
+		if (GroupType.Doctor == type) {
+			groupDoctorBucket.addOne(group.getId(), group);
+		}
+		else if (GroupType.Patient == type) {
+			groupPatientBucket.addOne(group.getId(), group);
+		}
+		else if (GroupType.Friend == type) {
+			groupFriendBucket.addOne(group.getId(), group);
+		}
+		
+		allGroups.add(group.getId(), group);
+		allGroupBucket.addOne(group.getId(), group);
+	}
+	
+    public void addGroupMember(WFCMessage.AddGroupMemberRequest addGroupMemberRequest) throws Exception {
+    	String groupId = addGroupMemberRequest.getGroupId();
+    	Group friendGroup = getOne(groupId);
+    	
+    	//1.涓嶅瓨鍦ㄧ兢缁勶紝鍒欑洿鎺ラ��鍑�
+    	if (friendGroup == null) {
+    		return;
+    	}
+    	
+    	//2.瀛樺湪缇ょ粍锛屽垯灏嗘柊澧炲姞鐨勭粰鍛樺鍔犲埌缇ょ粍涓�
+		friendGroup = new Group(groupId, "", "GroupDoctor");
+		friendGroup.loadMember(addGroupMemberRequest);
+		
+		addFriendGroupMembers(friendGroup);
+		//鏇存崲缇ょ粍鐨勭粍鍛�
+		refreshOne(addGroupMemberRequest);
+    }
+    
+	//灏唃roupId锛屽搴旂殑缁勬垚鍛樿繘琛屾洿鏂�
+	public void refreshOne(WFCMessage.AddGroupMemberRequest addGroupMemberRequest) {
+		Group existFriendGroup = getOne(addGroupMemberRequest.getGroupId());
+    	if (existFriendGroup == null) {
+    		return;
+    	}
+    	List<WFCMessage.GroupMember> wfcMemberList = existFriendGroup.getWFCMemberList();
+    	wfcMemberList.addAll(addGroupMemberRequest.getAddedMemberList());
+    	
+    	deleteOne(addGroupMemberRequest.getGroupId());
+    	
+    	addOne(addGroupMemberRequest.getGroupId(), existFriendGroup);
+	}
+	
+	public void createGroup() throws Exception {
+		
+	}
+	
+	public Group getOrCreate(WFCMessage.Group group, User sender) throws Exception {
+		WFCMessage.GroupInfo groupInfo = group.getGroupInfo();
+		String groupId = groupInfo.getTargetId();
+		
+		//1. get group from cache
+		Group friendGroup = getOne(groupId);
+		
+		//2. create new group
+		if (friendGroup == null) {
+			if (groupId == null || ("").equals(groupId)) {
+				groupId = ID.newValue();
+			}
+			
+			friendGroup = new Group(groupId, sender.getId(), "GroupDoctor");
+			friendGroup.load(groupId, group, sender);
+			createOneFriendGroup(friendGroup);
+			addOne(groupId, friendGroup);
+		}
+		
+		//3. create hello message
+//		MessageRecord record = MessageRecord.getTextInstance(sender.getName() + "鎷変綘鍏ョ兢", sender);
+//		friendGroup.addOneMessage(ProtoConstants.PullType.Pull_Normal, record, sender, null);
+		
+		//4. send message to members
+//		friendGroup.publishOneMessage(record, sender, true, content);
+
+		//5. return
+        return friendGroup;
+	}
+
+	public List<WFCMessage.GroupInfo> getList(List<UserRequest> groupList) {
+		List<WFCMessage.GroupInfo> result = new ArrayList<WFCMessage.GroupInfo>();
+		
+		for (UserRequest user: groupList) {
+			String id = user.getUid();
+			Group group = getOne(id);
+			
+			if (group != null) {
+				result.add(group.toWFCMessage());
+			}
+		}
+		
+		return result;
+	}
+
+	public static Group getGroup(String groupId) {
+		return allGroups.get(groupId);
+	}
+
+	public static List<GroupInfo> getGroupList(List<UserRequest> groupList) {
+		List<WFCMessage.GroupInfo> result = new ArrayList<WFCMessage.GroupInfo>();
+		
+		for (UserRequest groupRquest: groupList) {
+			String id = groupRquest.getUid();
+			Group group = allGroups.get(id);
+			
+			if (group != null) {
+				result.add(group.toWFCMessage());
+			}
+		}
+		
+		return result;
+	}
+	
+	private void addFriendGroupMembers(Group friendGroup) throws Exception {
+		DataObject dataObject;
+		Entity entity;
+		
+		//1. insert group members
+		List<Member> memberList = friendGroup.getMemberList();
+		
+		dataObject = DataObject.getInstance("friendgroupmember");
+		
+		for (Member member: memberList) {
+			 entity = dataObject.newEntity();
+			 member.pushTo(entity);
+			 dataObject.insertToDataBase(entity);			 
+		}
+		
+	}
+	
+    private void createOneFriendGroup(Group friendGroup) throws Exception {
+    	DataObject dataObject; 
+    	Entity entity;
+    	
+    	//1. insert group
+		dataObject = DataObject.getInstance("chatspace");
+		
+		entity = dataObject.newEntity();
+		friendGroup.pushTo(entity);
+		
+		allGroups.add(friendGroup.getId(), friendGroup);
+		
+		if (friendGroup.getTypecode().equals("GroupDoctor")) {
+			groupDoctorBucket.addOne(friendGroup.getId(), friendGroup);
+		}
+		else if (friendGroup.getTypecode().equals("GroupFriend")) {
+			groupFriendBucket.addOne(friendGroup.getId(), friendGroup);
+		}
+			
+		dataObject.insertToDataBase(entity);
+		
+		//2. insert members
+		List<Member> memberList = friendGroup.getMemberList();
+		
+		dataObject = DataObject.getInstance("member");
+		
+		for (Member member: memberList) {
+			 entity = dataObject.newEntity();
+			 member.pushTo(entity);
+			 dataObject.insertToDataBase(entity);
+		}
+	}
+
+	@Override
+	public String toString() {
+		return groupType + ", size: " + size();
+	}
+
+	public static int getPullType() {
+		return pullType;
+	}
+
+	public static void setPullType(int pullType) {
+		GroupBucket.pullType = pullType;
+	}
+
+	public static ConcurrentMapList<Group> getAllGroups() {
+		return allGroups;
+	}
+
+	public static void setAllGroups(ConcurrentMapList<Group> allGroups) {
+		GroupBucket.allGroups = allGroups;
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/module/ModuleLoader.java b/IMserver/medeasy/src/chat/module/ModuleLoader.java
new file mode 100644
index 0000000..9ca5e10
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/ModuleLoader.java
@@ -0,0 +1,361 @@
+package chat.module;
+
+import java.sql.Connection;
+import java.util.concurrent.Executors;
+
+import org.apache.log4j.Logger;
+
+import chat.message.MessageRunner;
+import chat.message.MessagesPublisher;
+import chat.module.entity.ChatSpaceType;
+import chat.module.entity.FriendShip;
+import chat.module.entity.GroupType;
+import chat.module.entity.MessageContainer;
+import chat.module.friendcircle.FriendCircle;
+import chat.user.ClientStore;
+import chat.user.NotifyStore;
+import chat.user.User;
+import chat.user.UserStore;
+import chat.util.DBUtil;
+import frame.object.data.Entity;
+import frame.object.data.EntitySet;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+
+public class ModuleLoader {
+	
+	private static Logger logger;
+	private static PrivateFriendBucket privateFriendBucket;
+	private static String cachedSpaceId;
+	private static MessageContainer cachedContainer;
+	private static String cachedUserId;
+	private static User cachedUser;
+	public static Connection connDB;
+	private static MessageRunner imBusinessScheduler;
+	private static MessagesPublisher messagePublisher;
+	
+	static {
+		logger = Logger.getLogger(ModuleLoader.class);
+		
+		privateFriendBucket = PrivateFriendBucket.getInstance();
+	}
+
+	public static PrivateFriendBucket getPrivateFriendBucket() {
+		return privateFriendBucket;
+	}
+
+	public static void setPrivateFriendBucket(PrivateFriendBucket privateFriendBucket) {
+		ModuleLoader.privateFriendBucket = privateFriendBucket;
+	}
+
+	public static void load() throws Exception {
+		//1.
+		loadUser();
+		loadClient();
+		loadNotify();
+		
+		//2.缇ょ粍
+		loadChatSpace();
+		
+		//3.缇ょ粍鎴愬憳
+		loadMember();
+		
+		//4.缇ょ粍娑堟伅 
+		loadMessage();
+		
+		//5. 缇ょ粍娑堟伅鍏崇郴
+		loadMessageRelation();
+		
+		//6.鍔犲ソ鍙嬪叧绯�
+		LoadFriendShip();
+		
+		//7.鍔犳湅鍙嬪湀
+		LoadFriendCircle();
+		
+		//8.鍔犳暟鎹簱杩炴帴
+		connDB = LoadDBConn();
+		
+		//9.鍔犺浇鎵ц绾跨▼姹�
+		int threadNum = Runtime.getRuntime().availableProcessors() * 2;
+		imBusinessScheduler = new MessageRunner(Executors.newScheduledThreadPool(threadNum));	
+		
+		//10.瀹炰緥鍖栨秷鎭彂閫�
+		messagePublisher = new MessagesPublisher();
+	}
+	
+	private static Connection LoadDBConn() throws Exception {
+		DBUtil dbUtil = new DBUtil();
+		Connection conn = dbUtil.getConnection();
+		return conn;
+	}
+
+	private static void loadUser() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("usr");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		int cnt = 0;
+		for (Entity entity: entitySet) {
+			 UserStore.loadOne(entity);
+			 cnt++;
+		}
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("load user: " + cnt);
+		}
+	}
+
+	private static void loadClient() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("client");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		int cnt = 0;
+		for (Entity entity: entitySet) {
+			 ClientStore.loadOne(entity);
+			 cnt++;
+		}
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("load client: " + cnt);
+		}		
+	}
+	
+	private static void loadNotify() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("notify");
+		namedSQL.setFilter("isread = 'F' ");
+		
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		int cnt = 0;
+		for (Entity entity: entitySet) {
+			 NotifyStore.loadOne(entity);
+			 cnt++;
+		}
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("load client: " + cnt);
+		}
+	}
+
+	private static void loadChatSpace() throws Exception {
+		int cnt = 0; 
+		ChatSpaceType spaceType;
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("chatSpace");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		for (Entity entity: entitySet) {
+			spaceType = ChatSpaceType.pase(entity.getString("typeCode"));
+			
+			if (ChatSpaceType.Private == spaceType) {//绉佽亰
+				privateFriendBucket.load(entity);				
+			}
+			else if (ChatSpaceType.GroupDoctor == spaceType) {//鍖荤敓缇�
+				GroupBucket.load(GroupType.Doctor, entity);
+			}
+			else if (ChatSpaceType.GroupPatient == spaceType) {//鎮h�呯兢
+				GroupBucket.load(GroupType.Patient, entity);
+			}
+			else if (ChatSpaceType.GroupFriend == spaceType) {//鏈嬪弸缇�
+				GroupBucket.load(GroupType.Friend, entity);
+			}
+			else if (ChatSpaceType.Assistant == spaceType) {//鍖诲姪
+				
+			}
+			else if (ChatSpaceType.Channel == spaceType) {//棰戦亾
+				
+			}
+			else if (ChatSpaceType.ChatRoom == spaceType) {//鑱婂ぉ瀹�
+				
+			}
+			else if (ChatSpaceType.FriendCircle == spaceType) {//鏈嬪弸鍦�
+				
+			}
+
+			cnt++;
+		}
+		
+		if (logger.isDebugEnabled()) {
+			logger.debug("load chat space: " + cnt);
+		}	
+	}
+	
+	private static void loadMember() throws Exception {
+		//1.绉佽亰
+		doLoadMember(ChatSpaceType.Private, privateFriendBucket);
+		//2.鍖荤敓缇ょ粍
+		doLoadMember(ChatSpaceType.GroupDoctor, GroupBucket.getInstance(GroupType.Doctor));
+		//3.鎮h�呯兢缁�
+		doLoadMember(ChatSpaceType.GroupPatient, GroupBucket.getInstance(GroupType.Patient));
+		//4.鏈嬪弸缇ょ粍
+		doLoadMember(ChatSpaceType.GroupFriend, GroupBucket.getInstance(GroupType.Friend));
+	}
+	
+	private static void doLoadMember(ChatSpaceType spaceType, Bucket<?> spaceBucket) throws Exception {
+		String spaceId; 
+		MessageContainer messageContainer;
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("member").setOrderBy("spaceid");
+		namedSQL.setFilter("spacecode = '" + spaceType + "' ");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		for (Entity entity: entitySet) {
+			 spaceId = entity.getString("spaceid");
+			 messageContainer = getMessageContainer(spaceBucket, spaceId);
+			 messageContainer.loadOneMember(entity);
+		}
+	}
+
+	private static void loadMessage() throws Exception {
+		doLoadMessage(ChatSpaceType.Private, privateFriendBucket);
+		doLoadMessage(ChatSpaceType.GroupDoctor, GroupBucket.getInstance(GroupType.Doctor));
+		doLoadMessage(ChatSpaceType.GroupPatient, GroupBucket.getInstance(GroupType.Patient));
+		doLoadMessage(ChatSpaceType.GroupFriend, GroupBucket.getInstance(GroupType.Friend));
+	}
+	
+	private static void doLoadMessage(ChatSpaceType spaceType, Bucket<?> spaceBucket) throws Exception {
+		String spaceId; 
+		MessageContainer messageContainer;
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("message").setOrderBy("spaceid, createtime asc");
+		namedSQL.setFilter("TO_DAYS(NOW()) - TO_DAYS(createtime) >= 0 and spacecode = '" + spaceType + "' ");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		for (Entity entity: entitySet) {
+			 spaceId = entity.getString("spaceid");
+			 messageContainer = getMessageContainer(spaceBucket, spaceId);
+			 messageContainer.loadOneMessage(entity);
+		}
+	}
+
+	//娑堟伅鍏崇郴  Private, GroupDoctor, GroupPatient, GroupFriend, Assistant, Channel, ChatRoom, FriendCircle, Unknown;
+	private static void loadMessageRelation() throws Exception {
+		//1.绉佽亰
+		doLoadMessageRelation(ChatSpaceType.Private, privateFriendBucket);
+		//2.鍖荤敓缇ょ粍
+		doLoadMessageRelation(ChatSpaceType.GroupDoctor, GroupBucket.getInstance(GroupType.Doctor));
+		//3.鎮h�呯兢缁�
+		doLoadMessageRelation(ChatSpaceType.GroupPatient, GroupBucket.getInstance(GroupType.Patient));
+		//4.鏈嬪弸缇ょ粍
+		doLoadMessageRelation(ChatSpaceType.GroupFriend, GroupBucket.getInstance(GroupType.Friend));		
+	}
+	
+	private static void doLoadMessageRelation(ChatSpaceType spaceType, Bucket<?> spaceBucket) throws Exception {
+		String spaceId;
+		MessageContainer messageContainer;
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("messagerelation").setOrderBy("spaceid, receivetime asc");
+		namedSQL.setFilter("TO_DAYS(NOW()) - TO_DAYS(receivetime) >=0 and spacecode = '" + spaceType + "' ");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		for (Entity entity : entitySet) {
+			 spaceId = entity.getString("spaceid");
+			 
+			if (spaceId == null) {
+				continue;
+			}
+				
+			messageContainer = getMessageContainer(spaceBucket, spaceId);
+			messageContainer.loadOneMessageRelation(entity);
+		}		
+	}
+	
+	private static void LoadFriendShip() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getActiveFriendship");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		User user, friend; 
+		FriendShip friendShip;
+		
+		for (Entity entity : entitySet) {
+			//1. 
+			user = getUser(entity.getString("userId"));
+			//friend = UserStore.getById(entity.getString("friendId"));
+			friend = getUser(entity.getString("friendId"));
+
+			if (user == null || friend == null) {
+				continue;
+			}
+			
+			//濡傛灉锛屾湅鍙嬪叧绯昏繕澶勪簬瀹¤鐘舵�侊紝閭d箞锛屽皢淇℃伅鍔犲叆鍒版湅鍙嬫帹閫乴ist涓�
+			if ("apply".equals(entity.getString("statuscode"))) {
+				friendShip = new FriendShip();
+				friendShip.load(entity);
+				user.addOnePushFriendShip(user.getId(), friendShip);
+				continue;
+			}
+
+			friendShip = new FriendShip();
+			friendShip.load(entity);
+			//user.addOneFrieldShip(friend.getId(), friendShip);
+			user.addOneFrieldShip(user.getId(), friendShip);
+			
+			friendShip = friendShip.getReverseInstance();
+			friend.addOneFrieldShip(friendShip.getUserid(), friendShip);
+		}	
+	}
+	
+	private static void LoadFriendCircle() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getEntitySet");
+		namedSQL.setTableName("friendcircle").setOrderBy("senderid, createtime asc");
+		EntitySet entitySet = SQLRunner.getEntitySet(namedSQL);
+		
+		String userId; User user; 
+		FriendCircle friendCircle;
+		
+		for (Entity entity : entitySet) {
+			userId = entity.getString("senderid");
+			user = UserStore.getCachedById(userId);
+			
+			if (user == null) {
+				continue;
+			}
+			
+			friendCircle = user.getFriendCircle();
+			friendCircle.loadOneCricleObject(entity);
+		}				
+	}	
+	
+	private static MessageContainer getMessageContainer(Bucket<?> spaceBucket, String spaceId) {
+		if (spaceId.equals(cachedSpaceId)) {
+			return cachedContainer;
+		}
+
+		cachedSpaceId = spaceId;
+		cachedContainer = spaceBucket.getOne(cachedSpaceId);
+		return cachedContainer;
+	}
+	
+	private static User getUser(String userId) {
+		if (userId.equals(cachedUserId)) {
+			return cachedUser;
+		}
+
+		cachedUserId = userId;
+		cachedUser = UserStore.getById(cachedUserId);
+		return cachedUser;
+	}
+
+	public static MessageRunner getImBusinessScheduler() {
+		return imBusinessScheduler;
+	}
+
+	public static void setImBusinessScheduler(MessageRunner imBusinessScheduler) {
+		ModuleLoader.imBusinessScheduler = imBusinessScheduler;
+	}
+
+	public static MessagesPublisher getMessagePublisher() {
+		return messagePublisher;
+	}
+
+	public static void setMessagePublisher(MessagesPublisher messagePublisher) {
+		ModuleLoader.messagePublisher = messagePublisher;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/PrivateFriendBucket.java b/IMserver/medeasy/src/chat/module/PrivateFriendBucket.java
new file mode 100644
index 0000000..88281c0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/PrivateFriendBucket.java
@@ -0,0 +1,43 @@
+package chat.module;
+
+import chat.consts.ProtoConstants;
+import chat.module.entity.ChatSpaceType;
+import chat.module.entity.Member;
+import chat.module.entity.MessageRecord;
+import chat.module.entity.MessageRelation;
+import chat.module.entity.PrivateFriend;
+import chat.user.User;
+import chat.user.UserStore;
+import cn.wildfirechat.proto.WFCMessage.Message;
+import frame.object.data.Entity;
+
+public class PrivateFriendBucket extends Bucket<PrivateFriend> {
+
+	private static PrivateFriendBucket instance;
+
+	public static synchronized PrivateFriendBucket getInstance() {
+		if (instance == null) {
+			instance = new PrivateFriendBucket();
+		}
+		
+		return instance;
+	}
+	
+	public PrivateFriend createOne(String name, User sender) {
+		PrivateFriend friendship = new PrivateFriend(name, sender);
+		String key = friendship.getId();
+		
+		addOne(key, friendship);
+		
+		return friendship;
+	}
+
+	public void load(Entity entity) {
+		// TODO Auto-generated method stub
+		PrivateFriend privateFriend = new PrivateFriend();
+		privateFriend.load(entity);
+
+		addOne(privateFriend.getId(), privateFriend);		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/RelationshipBucket.java b/IMserver/medeasy/src/chat/module/RelationshipBucket.java
new file mode 100644
index 0000000..22e6147
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/RelationshipBucket.java
@@ -0,0 +1,38 @@
+package chat.module;
+
+import chat.module.entity.FriendShip;
+import chat.module.entity.PublishOperator;
+import chat.user.User;
+import frame.object.data.Entity;
+
+public class RelationshipBucket {
+
+	private static RelationshipBucket instance;
+	protected ConcurrentMapList<FriendShip> friendShipList;
+	
+	
+	private RelationshipBucket() {
+		
+	}
+	
+	public static synchronized RelationshipBucket getInstance() {
+		if (instance == null) {
+			instance = new RelationshipBucket();
+		}
+		
+		return instance;
+	}
+	
+	public void loadOne(Entity entity) {
+		FriendShip friendShip = new FriendShip();
+		friendShip.load(entity);
+		
+		friendShipList.add(friendShip.getFriendid(), friendShip);
+	}
+
+	public void notify(PublishOperator operator, User sender) {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/UserMessageList.java b/IMserver/medeasy/src/chat/module/UserMessageList.java
new file mode 100644
index 0000000..729aa3e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/UserMessageList.java
@@ -0,0 +1,33 @@
+package chat.module;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import chat.module.entity.MessageRelation;
+
+public class UserMessageList {
+
+	private List<MessageRelation> messageList;
+	private int pos;
+	
+	public UserMessageList() {
+		messageList = new ArrayList<MessageRelation>();
+	}
+
+	public List<MessageRelation> getMessageList() {
+		return messageList;
+	}
+
+	public void setMessageList(List<MessageRelation> messageList) {
+		this.messageList = messageList;
+	}
+
+	public int getPos() {
+		return pos;
+	}
+
+	public void setPos(int pos) {
+		this.pos = pos;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/Channel.java b/IMserver/medeasy/src/chat/module/entity/Channel.java
new file mode 100644
index 0000000..66875b4
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/Channel.java
@@ -0,0 +1,19 @@
+package chat.module.entity;
+
+import chat.user.User;
+import frame.object.data.Entity;
+
+public class Channel extends MessageContainer {
+	
+	public Channel(String name, User creator) {
+		super(name, creator);
+	}
+
+	@Override
+	public void pushTo(Entity entity) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/ChatRoom.java b/IMserver/medeasy/src/chat/module/entity/ChatRoom.java
new file mode 100644
index 0000000..21acfd5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/ChatRoom.java
@@ -0,0 +1,19 @@
+package chat.module.entity;
+
+import chat.user.User;
+import frame.object.data.Entity;
+
+public class ChatRoom extends MessageContainer {
+
+	
+	public ChatRoom(String name, User creator) {
+		super(name, creator);
+	}
+
+	@Override
+	public void pushTo(Entity entity) throws Exception {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/ChatSpaceType.java b/IMserver/medeasy/src/chat/module/entity/ChatSpaceType.java
new file mode 100644
index 0000000..74e9672
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/ChatSpaceType.java
@@ -0,0 +1,89 @@
+package chat.module.entity;
+
+public enum ChatSpaceType {
+
+	Private, Group, GroupDoctor, GroupPatient, GroupFriend, Assistant, Channel, ChatRoom, FriendCircle, Unknown;
+	
+	
+	public static ChatSpaceType pase(String value) {
+		if (value == null) {
+			return Unknown;
+		}
+		
+		value = value.toLowerCase();
+		
+		if ("private".equals(value)) {
+			return Private;
+		}
+		else if ("group".equals(value)) {
+			return Group;
+		}
+		else if ("groupdoctor".equals(value)) {
+			return GroupDoctor;
+		}
+		else if ("grouppatient".equals(value)) {
+			return GroupPatient;
+		}		
+		else if ("groupfriend".equals(value)) {
+			return GroupFriend;
+		}
+		else if ("assistant".equals(value)) {
+			return Assistant;
+		}
+		else if ("channel".equals(value)) {
+			return Channel;
+		}
+		else if ("chatroom".equals(value)) {
+			return ChatRoom;
+		}
+		else if ("friendcircle".equals(value)) {
+			return FriendCircle;
+		}
+		
+		return Unknown;
+	}
+
+	public static ChatSpaceType pase(int type) {
+		// TODO Auto-generated method stub
+		if (type == 0) {
+			return Private;
+		}
+		else if (type == 1) {
+			return Group;
+		}
+		return Unknown;
+	}
+	
+	public int toInt() {
+		if (Private == this) {
+			return 0;
+		}
+		else if (Group == this) {
+			return 1;
+		}
+		else if (GroupDoctor == this) {
+			return 2;
+		}
+		else if (GroupPatient == this) {
+			return 3;
+		}		
+		else if (GroupFriend == this) {
+			return 4;
+		}
+		else if (Assistant == this) {
+			return 5;
+		}
+		else if (Channel == this) {
+			return 6;
+		}
+		else if (ChatRoom == this) {
+			return 7;
+		}
+		else if (FriendCircle == this) {
+			return 8;
+		}
+		
+		return -1;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/FriendRequest.java b/IMserver/medeasy/src/chat/module/entity/FriendRequest.java
new file mode 100644
index 0000000..ed4afea
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/FriendRequest.java
@@ -0,0 +1,48 @@
+package chat.module.entity;
+
+import cn.wildfirechat.proto.ProtoConstants;
+import cn.wildfirechat.proto.WFCMessage;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+public class FriendRequest extends MessageContainer {
+
+	private String id;
+	private String uid;
+	private String friendId;
+	private String reason;
+	private int status;
+	private long dt;
+	private boolean from_read_status;
+	private boolean to_read_status;
+	
+	public FriendRequest(String uid, String friendId) {
+		super(null, null);
+		this.id = ID.newValue();
+		this.uid = uid;
+		this.friendId = friendId;
+		this.dt = System.currentTimeMillis();
+	}
+	
+	public void load(WFCMessage.AddFriendRequest addFriendRequest) {
+		//1. load group info
+		this.reason = addFriendRequest.getReason();
+		this.status = ProtoConstants.FriendRequestStatus.RequestStatus_Sent;
+		this.to_read_status = false;
+		this.dt = System.currentTimeMillis();
+	}	
+	
+	@Override
+	public void pushTo(Entity entity) throws Exception {
+		// TODO Auto-generated method stub
+		entity.set("id", id);
+		entity.set("uid", uid);
+		entity.set("friendId", friendId);
+		entity.set("reason", reason);
+		entity.set("status", status);
+		entity.set("dt", dt);
+		entity.set("from_read_status", from_read_status);
+		entity.set("to_read_status", to_read_status);		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/FriendShip.java b/IMserver/medeasy/src/chat/module/entity/FriendShip.java
new file mode 100644
index 0000000..5c7ff46
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/FriendShip.java
@@ -0,0 +1,125 @@
+package chat.module.entity;
+
+import chat.user.User;
+import cn.wildfirechat.proto.WFCMessage;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+
+public class FriendShip {
+
+	private String id;
+	private String userid;
+	private String friendid;
+	private String statuscode;
+	//private FriendshipStatus status;
+	private String verifytext;
+	private long timestamp;
+	private FriendShip reverseInstance;
+	private WFCMessage.FriendRequest friendRequest;
+	
+	public FriendShip() {}
+	
+	public FriendShip(User user, String friendId, String status) {
+		this.id = ID.newValue();
+		this.userid = user.getId();
+		this.friendid = friendId;
+		this.statuscode = status;
+		this.verifytext = "鎴戞槸" + user.getName();
+		this.timestamp = System.currentTimeMillis();
+	}
+	
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		userid = entity.getString("userid");
+		friendid = entity.getString("friendid");
+		//status = FriendshipStatus.parse(entity.getString("statuscode"));
+		statuscode = entity.getString("statuscode");
+		verifytext = entity.getString("verifytext");
+		timestamp = Long.parseLong(entity.getString("timestamp"));
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("userid", userid);
+		entity.set("friendid", friendid);
+		entity.set("statuscode", statuscode);
+		entity.set("verifytext", verifytext);
+		entity.set("timestamp", timestamp);
+	}
+	
+	public void addFriendShipToDataBase() {
+		try {
+			 DataObject dataObject = DataObject.getInstance("friendship");
+			
+			 Entity entity = dataObject.newEntity();
+			 pushTo(entity);
+				
+			 dataObject.insertToDataBase(entity);			
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+
+	public void updateFriendShipToDataBase(String status) {
+		try {
+			 DataObject dataObject = DataObject.getInstance("friendship");
+			 
+			 Entity entity = dataObject.newEntity();
+			 pushTo(entity);
+			 entity.set("statuscode", status);
+			 
+			 dataObject.updateToDataBase(entity);		
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+
+	public synchronized FriendShip getReverseInstance() {
+		if (reverseInstance != null) {
+			return reverseInstance;
+		}
+		
+		reverseInstance = new FriendShip();
+		
+		reverseInstance.id = this.id;
+		reverseInstance.userid = this.friendid;
+		reverseInstance.friendid = this.userid;
+		reverseInstance.statuscode = this.statuscode;
+		reverseInstance.verifytext = this.verifytext;
+		reverseInstance.timestamp = this.timestamp;
+		
+		return reverseInstance;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public String getUserid() {
+		return userid;
+	}
+
+	public String getFriendid() {
+		return friendid;
+	}
+
+	public String getVerifytext() {
+		return verifytext;
+	}
+
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	public WFCMessage.FriendRequest getFriendRequest() {
+		return friendRequest;
+	}
+
+	public void setFriendRequest(WFCMessage.FriendRequest friendRequest) {
+		this.friendRequest = friendRequest;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/FriendshipStatus.java b/IMserver/medeasy/src/chat/module/entity/FriendshipStatus.java
new file mode 100644
index 0000000..ad553c0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/FriendshipStatus.java
@@ -0,0 +1,12 @@
+package chat.module.entity;
+
+public enum FriendshipStatus {
+
+	Apply, Open, Close, Blacked;
+
+	public static FriendshipStatus parse(String string) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/Group.java b/IMserver/medeasy/src/chat/module/entity/Group.java
new file mode 100644
index 0000000..4945dea
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/Group.java
@@ -0,0 +1,229 @@
+package chat.module.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import chat.user.User;
+import cn.wildfirechat.proto.WFCMessage;
+
+import cn.wildfirechat.proto.WFCMessage.GroupInfo;
+import cn.wildfirechat.proto.WFCMessage.GroupMember;
+import cn.wildfirechat.proto.WFCMessage.MessageContent;
+import frame.object.data.Entity;
+
+public class Group extends MessageContainer {
+
+	private String id;
+	private String typecode;
+	private String name;
+	private String statuscode;
+	private String portrait;
+	private String ownerid;
+	private long timestamp;
+	
+	private List<Member> memberList;
+
+	private WFCMessage.GroupInfo groupInfo;
+	private List<WFCMessage.GroupMember> wfcMemberList;
+	
+	public Group() {
+		super();
+	}
+	
+	public Group(String id, String ownerId, String typeCode) {
+		super(null, null);
+		this.id = id;
+		this.ownerid = ownerId;
+		this.timestamp = System.currentTimeMillis();
+		this.statuscode = "Open";
+		this.typecode = typeCode;
+		this.wfcMemberList = new ArrayList<WFCMessage.GroupMember>();
+	}
+	
+
+	public GroupInfo createGroupInfo(String fromUser, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList) {
+		// TODO Auto-generated method stub
+		long dt = System.currentTimeMillis();
+        groupInfo = groupInfo.toBuilder()
+	                .setTargetId(id)
+	                .setName(groupInfo.getName())
+	                .setPortrait(groupInfo.getPortrait())
+	                .setType(groupInfo.getType())
+	                .setExtra(groupInfo.getExtra())
+	                .setUpdateDt(dt)
+	                .setMemberUpdateDt(dt)
+	                .setMemberCount(memberList.size())
+	                .setOwner(fromUser)
+	                .build();
+        return groupInfo;
+	}
+
+	public Group(String name, User sender) {
+		super(name, sender);
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getTypecode() {
+		return typecode;
+	}
+
+	public void setTypecode(String typecode) {
+		this.typecode = typecode;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getStatuscode() {
+		return statuscode;
+	}
+
+	public void setStatuscode(String statuscode) {
+		this.statuscode = statuscode;
+	}
+
+	public String getPortrait() {
+		return portrait;
+	}
+
+	public void setPortrait(String portrait) {
+		this.portrait = portrait;
+	}
+
+	public String getOwnerid() {
+		return ownerid;
+	}
+
+	public void setOwnerid(String ownerid) {
+		this.ownerid = ownerid;
+	}
+
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public void load(String groupId, WFCMessage.Group group, User sender) {
+		//1. load group info
+		WFCMessage.GroupInfo groupInfo = group.getGroupInfo();
+		loadGroupInfo(groupId, groupInfo);
+		
+		//2. load members
+		List<GroupMember> memberList = group.getMembersList();
+		loadGroupMembers(groupId, memberList, sender);
+		//
+		clearWFCMemberList();
+	}
+	
+	public void loadMember(WFCMessage.AddGroupMemberRequest addGroupMemberRequest) {
+		List<GroupMember> memberList = addGroupMemberRequest.getAddedMemberList();
+		loadGroupMembers(addGroupMemberRequest.getGroupId(), memberList, null);
+		
+		clearWFCMemberList();
+	}
+	
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		typecode = entity.getString("typecode");
+		name = entity.getString("name");
+		statuscode = entity.getString("statuscode");
+		portrait = entity.getString("portrait");
+		ownerid = entity.getString("ownerid");
+		timestamp = Long.parseLong(entity.getString("timestamp"));
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("typecode", typecode);//绌�
+		entity.set("name", name);
+		entity.set("statuscode", statuscode);
+		entity.set("portrait", portrait);
+		entity.set("ownerid", ownerid);
+		entity.set("timestamp", timestamp);
+	}
+	
+	public WFCMessage.GroupInfo toWFCMessage() {
+		if (groupInfo != null) {
+			return groupInfo;
+		}
+		
+		WFCMessage.GroupInfo.Builder builder = WFCMessage.GroupInfo.newBuilder();
+		builder.setTargetId(id);
+		builder.setName(name);
+		builder.setPortrait(portrait);
+		builder.setOwner(ownerid);
+		builder.setType(0);
+		groupInfo = builder.build();
+		
+		return groupInfo;
+	}
+	
+	private void loadGroupInfo(String groupId, GroupInfo groupInfo) {
+		id = groupId;
+		name = groupInfo.getName();
+		portrait = groupInfo.getPortrait();
+		//ownerId = groupInfo.getOwner();
+		//type = groupInfo.getType();
+		//count = getMemberCount();
+	}
+
+	private void loadGroupMembers(String groupId, List<GroupMember> memberList, User sender) {
+		for (WFCMessage.GroupMember groupMember: memberList) {
+			 Member member = new Member(groupId, typecode);
+			 member.load(groupMember);
+			 
+			 //灏嗙兢缁勫垱寤鸿�呯殑roletype璁剧疆涓�2
+			 if (sender != null) {
+				 if (groupMember.getMemberId().equals(sender.getId())) {
+					 member.setRolecode(2);
+				 }				 
+			 }
+			
+			 addOneMember(member);
+		}
+	}
+
+	public List<WFCMessage.GroupMember> getWFCMemberList() {
+		if (wfcMemberList != null) {
+			return wfcMemberList;
+		}
+		
+		List<Member> memberList = getMemberList();
+		
+		for (Member member: memberList) {
+			WFCMessage.GroupMember groupMember = member.toWFCMember();
+			wfcMemberList.add(groupMember);
+		}
+		
+		return wfcMemberList;
+	}
+	
+	private void clearWFCMemberList() {
+		if (wfcMemberList == null) {
+			return;
+		}
+		
+		wfcMemberList.clear();
+	}
+
+	public void quit() {
+		// TODO Auto-generated method stub
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/GroupType.java b/IMserver/medeasy/src/chat/module/entity/GroupType.java
new file mode 100644
index 0000000..42cf6a3
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/GroupType.java
@@ -0,0 +1,12 @@
+package chat.module.entity;
+
+public enum GroupType {
+
+	Doctor, Patient, Friend;
+
+	public static GroupType parse(String extra) {
+		// TODO Auto-generated method stub
+		return Doctor;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/Member.java b/IMserver/medeasy/src/chat/module/entity/Member.java
new file mode 100644
index 0000000..b552583
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/Member.java
@@ -0,0 +1,136 @@
+package chat.module.entity;
+
+import chat.user.User;
+import chat.user.UserStore;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.GroupMember;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+public class Member {
+
+	private String id;
+	private String spaceid;
+	private String spacecode;
+	private String userid;
+	private String alias;
+	private String statuscode;
+	private int rolecode;
+	private long timestamp;
+	private String ismute;	
+	private String isforbidden;
+	
+	private User user;
+	private WFCMessage.GroupMember wfcMember;
+	
+	public Member(String containerId, String typecode) {
+		this.id = ID.newValue();
+		this.spaceid = containerId;
+		this.spacecode = typecode;
+		this.timestamp = System.currentTimeMillis();
+	}
+	
+	public Member(String spaceId, User user) {
+		this.id = ID.newValue();
+		this.spaceid = spaceId;
+		this.spacecode = "Private";
+		this.userid = user.getId();
+		this.alias = user.getName();
+		this.statuscode = "Open";
+		this.rolecode = 0;
+		this.timestamp = System.currentTimeMillis();
+		this.ismute = "F";
+		this.isforbidden = "F";
+	}
+	
+	public void load(Entity entity) throws Exception {
+		id = entity.getString("id");
+		spaceid = entity.getString("spaceid");
+		spacecode = entity.getString("spacecode");
+		userid = entity.getString("userid");
+		alias = entity.getString("alias");
+		statuscode = entity.getString("statuscode");
+		rolecode = entity.getInteger("rolecode");
+		timestamp = Long.parseLong(entity.getString("timestamp"));
+		ismute = entity.getString("ismute");
+		isforbidden = entity.getString("isforbidden");
+	}	
+
+	public void load(GroupMember groupMember) {
+		alias = groupMember.getAlias();
+		userid = groupMember.getMemberId();
+		rolecode = groupMember.getType();
+	}
+
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("spaceid", spaceid);
+		entity.set("spacecode", spacecode);
+		entity.set("userid", userid);
+		entity.set("alias", alias);
+		entity.set("statuscode", "Open");
+		entity.set("rolecode", rolecode);
+		entity.set("timestamp", timestamp);
+		entity.set("ismute", ismute);
+		entity.set("isforbidden", isforbidden);
+	}
+
+	public User getUser() {
+		return UserStore.getById(userid);
+	}
+
+	public String getAlias() {
+		return alias;
+	}
+
+	public WFCMessage.GroupMember toWFCMember() {
+		if (wfcMember != null) {
+			synchronized (this) {
+				if (wfcMember != null) {
+					return wfcMember;
+				}
+			}
+		}
+		
+		WFCMessage.GroupMember.Builder builder = WFCMessage.GroupMember.newBuilder();
+		
+		builder.setAlias(alias);
+		builder.setMemberId(userid);
+		builder.setType(rolecode);
+		
+		return wfcMember;
+	}
+	
+	public String getId() {
+		return id;
+	}
+
+	public String getUserId() {
+		return userid;
+	}
+
+	public String getSpaceid() {
+		return spaceid;
+	}
+
+	public void setSpaceid(String spaceid) {
+		this.spaceid = spaceid;
+	}
+
+	public String getSpacecode() {
+		return spacecode;
+	}
+
+	public void setSpacecode(String spacecode) {
+		this.spacecode = spacecode;
+	}
+
+	public int getRolecode() {
+		return rolecode;
+	}
+
+	public void setRolecode(int rolecode) {
+		this.rolecode = rolecode;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/MessageContainer.java b/IMserver/medeasy/src/chat/module/entity/MessageContainer.java
new file mode 100644
index 0000000..f99adc1
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/MessageContainer.java
@@ -0,0 +1,579 @@
+package chat.module.entity;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.protobuf.ByteString;
+
+import chat.module.ConcurrentMapList;
+import chat.server.im.IMTopic;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.Client;
+import chat.user.Session;
+import chat.user.User;
+import chat.user.UserStore;
+import cn.wildfirechat.pojos.GroupNotificationBinaryContent;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.GroupInfo;
+import cn.wildfirechat.proto.WFCMessage.Message;
+import cn.wildfirechat.proto.WFCMessage.MessageContent;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import chat.persist.*;
+
+public abstract class MessageContainer {
+	
+	protected ConcurrentMapList<MessageRecord> messageList;
+	protected ConcurrentMapList<Member> memberList;
+	protected ConcurrentMapList<MessageRelation> messageRelationList;
+	private static Map<String, MessageRecord> allLoadedMessageMap;
+	
+	static {
+		allLoadedMessageMap = new HashMap<String, MessageRecord>();
+	}
+	
+	public MessageContainer() {
+		messageList = new ConcurrentMapList<MessageRecord>();
+		memberList = new ConcurrentMapList<Member>();
+		messageRelationList = new ConcurrentMapList<MessageRelation>();
+	}
+	
+	public MessageContainer(String name, User creator) {
+		this();
+	}
+
+	public void loadOneMember(Entity entity) throws Exception {
+		String id = entity.getString("id");
+		Member member = new Member(id, "");
+		member.load(entity);
+		
+		memberList.add(member.getUserId(), member);		
+	}	
+
+	public void loadOneMessage(Entity entity) throws Exception {
+		MessageRecord messageRecord = new MessageRecord();
+		messageRecord.load(entity);
+		
+		String id = messageRecord.getId();
+		
+		messageList.add(id, messageRecord);
+		allLoadedMessageMap.put(id, messageRecord);
+	}
+	
+	public void loadOneMessageRelation(Entity entity) throws Exception {
+		MessageRelation messageRelation = new MessageRelation();
+		messageRelation.load(entity);
+		
+		//1.灏嗘秷鎭叧绯诲彇鍑�
+		messageRelationList.add(messageRelation.getId(), messageRelation);	
+		
+		//2.鍙栧嚭鎵�鏈夋病鏈夊彂鐨勬秷鎭�
+		String userId  = messageRelation.getTargetid();
+		User user = UserStore.getById(userId);
+		user.addOneUnreceivedMessage(messageRelation);
+	}
+	
+	public abstract void pushTo(Entity entity) throws Exception;
+	
+	public List<Member> getMemberList() {
+		return memberList.getList();
+	}
+	
+	public int getMemberCount() {
+		return memberList.getList().size();
+	}
+	
+	public static List<WFCMessage.Message> getMessageList(MessageRecord messageRecord, User user) {
+		List<WFCMessage.Message> messageList = new ArrayList<WFCMessage.Message>();
+		
+		WFCMessage.Message message = null;
+		
+		try {
+			WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			
+			builder.setMessageId(messageRecord.getMessageid());
+			builder.setFromUser(messageRecord.getSenderId());
+			
+	        WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+	        cb.setType(0);
+	        cb.setTarget(user.getId());
+	        cb.setLine(0);
+	        builder.setConversation(cb.build());
+	        
+	        WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+	        contentBuilder.setType(1);
+	        String str = messageRecord.getContent();
+	        byte[] bytes = str.getBytes();
+	        bytes = Base64.getEncoder().encode(bytes);
+	        contentBuilder.setSearchableContent(str);
+	        contentBuilder.setMediaType(0);
+	        contentBuilder.setPersistFlag(0);
+	        contentBuilder.setExpireDuration(0);
+	        contentBuilder.setMentionedType(0);
+	        WFCMessage.MessageContent messageContent = contentBuilder.build();
+	        builder.setContent(messageContent);
+	        
+	        builder.setServerTimestamp(System.currentTimeMillis());
+			
+			message = builder.build();
+			
+			messageList.add(message);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}		
+		
+		return messageList; 
+	}
+	
+	public void addMembers(String parentId, List<String> userList) throws Exception {
+		for (String userId: userList) {
+			 User user = User.getInstance(userId);
+			 Member member = new Member(parentId, "");
+			 String key = user.getId();
+			
+			 addOneMemberToDataBase(member);
+			 memberList.add(key, member);
+		}
+	}
+	
+	public void addInitMembers(String spaceId, List<String> userList) throws Exception {
+		for (String userId: userList) {
+			 User user = User.getInstance(userId);
+			 Member member = new Member(spaceId, user);
+			 String key = user.getId();
+			
+			 addOneMemberToDataBase(member);
+			 memberList.add(key, member);
+		}		
+	}
+	
+	public void addMembersWfc(String parentId, List<WFCMessage.GroupMember> membersList) throws Exception {
+		for (WFCMessage.GroupMember groupMember : membersList) {
+			User user = User.getInstance(groupMember.getMemberId());
+			Member member = new Member(parentId, "");
+			String key = user.getId();
+			
+			addOneMemberToDataBase(member);
+			memberList.add(key, member);
+		}
+	}	
+	
+	public void kickOffMembers(List<String> userList) throws Exception {
+		for (String userId: userList) {
+			Member member = memberList.get(userId);
+			
+			if (member == null) {
+				continue;
+			}
+			
+			removeOneMemberToDataBase(member);
+			memberList.delete(userId);
+		}
+	}
+	
+	public void addOneMember(Member member) {
+		String key = member.getUserId();
+		memberList.add(key, member);		
+	}
+
+	public void deleteOneMember(String userId) throws Exception {
+		Member member = memberList.get(userId);
+		
+		if (member == null) {
+			return;
+		}
+		
+		removeOneMemberToDataBase(member);
+		memberList.delete(userId);		
+	}
+	
+	public void join(String parentId, User user) {
+		Member member = new Member(parentId, "");
+		String key = user.getId();
+		
+		memberList.add(key, member);
+	}
+	
+	public void leave(User user) {
+		String key = user.getId();
+		memberList.delete(key);
+	}
+	
+	public Member getOneMember(String userId) {
+		return memberList.get(userId);
+	}
+	
+	public List<MessageRecord> getMessageList(long timestamp) {
+		List<MessageRecord> result = new ArrayList<MessageRecord>();
+		
+		List<MessageRecord> list = messageList.getList();
+		int max = list.size() - 1; MessageRecord record;
+		
+		for (int i = max; i >= 0; i--) {
+			record = list.get(i);
+			
+			if (record.isFreshThan(timestamp)) {
+				result.add(record);
+			}
+			else {
+				break;
+			}
+		}
+		
+		return result;
+	}
+	
+	public void addOneMessage(int pullType, MessageRecord record, User sender, Message message, boolean isExceptUser) throws Exception {
+		//1. set sender
+		record.setSender(sender);
+		
+		//2. insert to database		
+		insertOneMessage(record);
+		
+		//3. add to bucket
+		messageList.add(record.getId(), record);
+		
+		//4. send notify to target
+		publishOneNotify(pullType, record, sender, message, isExceptUser);
+	}
+	
+	public void publishOneNotify(int pullType, MessageRecord record, User sender, Message message, boolean isExceptUser) throws Exception {
+		int line = 0; 
+		String userId = sender.getId();
+		
+		for (Member member: memberList) {
+			//0. 鍓旈櫎鑷繁
+			if (userId.equals(member.getUserId()) && message.getContent().getType() != 104 && isExceptUser) {
+				continue;
+			}
+			
+			//1. add message relation
+			MessageRelation relation = MessageRelation.getInstance(line, member.getUserId(), record, message);
+			addOneMessageRelations(relation);
+			
+			if (message.getContent().getType() == 3) {
+				relation.getMessageRecord().setMessage(createOneMessage(relation.getMessageRecord(), message));
+			} else {
+				relation.getMessageRecord().setMessage(createOneMessage(relation.getMessageRecord(), relation, message));
+			}
+
+			//2. 灏嗘秷鎭寕鍒扮洰鏍囩敤鎴蜂笅闈�
+			User user = member.getUser();
+			user.pushOneMessageRelation(relation);
+			
+			//3. try to notify to user
+		    notifyOneClient(pullType, member.getUserId(), isExceptUser);
+		}
+	}
+	
+
+	public MessageContent createGroupMessage(GroupInfo groupInfo, String fromUser) {
+		// TODO Auto-generated method stub
+		WFCMessage.MessageContent content = new GroupNotificationBinaryContent(groupInfo.getTargetId(), fromUser, groupInfo.getName(), "").getCreateGroupNotifyContent();
+		return content;
+	}
+	
+	public WFCMessage.Message createOneMessage(MessageRecord message, Message messageSrc) {
+		WFCMessage.Message messageWFC = null;
+		
+		try {
+			 WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			 builder.setMessageId(message.getMessageid());
+			 builder.setServerTimestamp(message.getTimestamp());
+			 builder.setFromUser(messageSrc.getFromUser());
+			 
+			 WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+			 cb.setType(messageSrc.getConversation().getType());
+			 cb.setTarget(messageSrc.getConversation().getTarget());
+			 cb.setLine(messageSrc.getConversation().getLine());
+			 builder.setConversation(cb.build());
+			 
+			 WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+			 contentBuilder.setType(message.getType());
+			 if (message.getType() == 104) {
+				 contentBuilder.setData(ByteString.copyFrom(message.getContent().getBytes()));
+			 }
+			 else if (message.getType() == 90) {
+				 contentBuilder.setContent(messageSrc.getContent().getContent());
+				 System.out.println(message.getContent());
+			 }
+			 else if (message.getType() == 3) {
+				 contentBuilder.setType(messageSrc.getContent().getType());
+				 contentBuilder.setSearchableContent(messageSrc.getContent().getSearchableContent());
+				 contentBuilder.setContent(messageSrc.getContent().getContent());
+				 contentBuilder.setData(messageSrc.getContent().getData());
+				 contentBuilder.setMediaType(messageSrc.getContent().getMediaType());
+				 contentBuilder.setRemoteMediaUrl(messageSrc.getContent().getRemoteMediaUrl());
+				 contentBuilder.setPersistFlag(messageSrc.getContent().getPersistFlag());
+			 }
+			 else {
+				contentBuilder.setSearchableContent(message.getContent());
+				contentBuilder.setMediaType(0);
+				contentBuilder.setPersistFlag(message.getPersistflag());
+		        contentBuilder.setExpireDuration(0);
+		        contentBuilder.setMentionedType(0);				 
+			 }
+	         
+	         WFCMessage.MessageContent messageContent = contentBuilder.build();
+	         
+	         builder.setContent(messageContent);
+	         
+	         messageWFC = builder.build();
+			 
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+		return messageWFC;		
+	}
+	
+	public WFCMessage.Message createOneMessage(MessageRecord message, MessageRelation messageRelation, WFCMessage.Message messageSend) {
+		WFCMessage.Message messageWFC = null;
+		
+		try {
+			 WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			 builder.setMessageId(message.getMessageid());
+			 builder.setServerTimestamp(message.getTimestamp());
+			 if (message.getSenderId().equals(messageRelation.getTargetid())) {
+				 builder.setFromUser(messageSend.getConversation().getTarget());
+			 } 
+			 else {
+				 builder.setFromUser(message.getSenderId());
+			 }
+			 
+			 WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+			 cb.setType(messageRelation.getType());
+			 cb.setTarget(messageRelation.getTargetid());		 
+			 cb.setLine(messageRelation.getLine());
+			 builder.setConversation(cb.build());
+			 
+			 WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+			 contentBuilder.setType(message.getType());
+			 if (message.getType() == 104) {
+				 contentBuilder.setData(ByteString.copyFrom(message.getContent().getBytes()));
+			 }
+			 else if (message.getType() == 90) {
+				 contentBuilder.setContent(message.getContent());
+			 }
+			 else {
+				contentBuilder.setSearchableContent(message.getContent());
+				contentBuilder.setMediaType(0);
+				contentBuilder.setPersistFlag(message.getPersistflag());
+		        contentBuilder.setExpireDuration(0);
+		        contentBuilder.setMentionedType(0);				 
+			 }
+	         
+	         WFCMessage.MessageContent messageContent = contentBuilder.build();
+	         
+	         builder.setContent(messageContent);
+	         
+	         messageWFC = builder.build();
+			 
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+		return messageWFC;
+	}	
+	
+	public void addOneMessageRelations(MessageRelation relation) throws Exception {
+		//1. insert to database
+		relation.insertToDataBase(relation);
+		
+		//2. add to bucket
+		messageRelationList.add(relation.getId(), relation);
+	}	
+
+	public void setMemberAlias(String memberId, String alias) {
+		Member member = memberList.get(memberId);
+		
+		if (member == null) {
+			return;
+		}
+		
+//		member.set
+		
+//		Friendship friendShip = mapList.get(key);
+//		friendShip.setAlias(friendId, alias);
+	}
+	
+	public void notify(PublishOperator operator, String senderId) {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	public void notify(PublishOperator operator, Object data, String senderId) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void notify(PublishOperator operator, MessageRecord record, String senderId) {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	public void notify(PublishOperator operator, User sender) {
+		// TODO Auto-generated method stub
+	}
+
+	public void notify(PublishOperator operator, MessageRecord record, User sender) {
+		// TODO Auto-generated method stub
+	}
+	
+	public boolean existsDeleteRight(String senderId) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+	
+	private static int insertOneMessage(MessageRecord message) throws Exception {
+		DataObject dataObject = DataObject.getInstance("message");
+		
+		Entity entity = dataObject.newEntity();		
+		message.pushTo(entity);
+			
+		return dataObject.insertToDataBase(entity);
+	}
+	
+	//鍚戞坊鍔犲ソ鍙嬬殑璐﹀彿锛屽彂閫佹秷鎭�
+	public void notifyOneFriend(String topic, String receiver, long head) {
+		MqttPublishMessage publishMsg;
+		ByteBuf payload = Unpooled.buffer();
+		try {
+			 payload.writeLong(head);
+			 publishMsg = notRetainedPublish(topic, MqttQoS.AT_MOST_ONCE, payload);
+			 
+			 Client client = UserStore.getById(receiver).getClient(receiver);
+			 
+			 if (client == null) {
+				 return;
+			 }
+			 Session sessionC = client.getSession();
+			 if (sessionC != null) {
+			 	Channel channel = sessionC.getChannel();
+			 	if (publishMsg != null) {
+			 	    channel.writeAndFlush(publishMsg);
+			 	}
+			 }			 
+		} catch (Exception e) {
+			 e.printStackTrace();
+		}
+	}	
+	
+	//鍚戞坊鍔犲ソ鍙嬬殑璐﹀彿锛屽彂閫佹秷鎭�
+	public void notifyOneFriendRequest(String topic, WFCMessage.AddFriendRequest request, long head, String fromUser) {
+		MqttPublishMessage publishMsg;
+		ByteBuf payload = Unpooled.buffer();
+		String receiver = request.getTargetUid();
+		//String pushContent = request.getReason();
+		try {
+			 payload.writeLong(head);
+			 publishMsg = notRetainedPublish(topic, MqttQoS.AT_MOST_ONCE, payload);
+			 
+			 Client client = UserStore.getById(receiver).getClient(receiver);
+			 
+			 if (client == null) {
+				 return;
+			 }
+			 Session sessionC = client.getSession();
+			 if (sessionC != null) {
+			 	Channel channel = sessionC.getChannel();
+			 	if (publishMsg != null) {
+			 	    channel.writeAndFlush(publishMsg);
+			 	}
+			 }			 
+		} catch (Exception e) {
+			 e.printStackTrace();
+		}
+	}
+	
+	protected boolean notifyOneClient(int pullType, String targetId, boolean isExceptUser) {
+		boolean result = false;
+		try {
+			 long messageSeq = System.currentTimeMillis();
+	         WFCMessage.NotifyMessage notifyMessage = WFCMessage.NotifyMessage
+									                 .newBuilder()
+									                 .setType(pullType)
+									                 .setHead(messageSeq)
+									                 .build();
+			 ByteBuf payload = Unpooled.buffer();
+			 byte[] byteData = notifyMessage.toByteArray();
+			 
+			 payload.ensureWritable(byteData.length).writeBytes(byteData);
+			 MqttPublishMessage publishMsg;
+			 publishMsg = notRetainedPublish(IMTopic.NotifyMessageTopic, MqttQoS.AT_MOST_ONCE, payload);
+			 
+			 Client client = UserStore.getById(targetId).getClient(targetId);
+			 
+			 if (client == null) {
+				 return false;
+			 }
+			 Session sessionC = client.getSession();
+			 if (sessionC != null) {
+			 	Channel channel = sessionC.getChannel();
+			 	if (publishMsg != null) {
+			 	    channel.writeAndFlush(publishMsg);
+			 	}
+			 }
+			 result = true;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return result;
+	}
+	
+	private void addOneMemberToDataBase(Member member) throws Exception {
+		DataObject dataObject = DataObject.getInstance("member");
+		
+		Entity entity = dataObject.newEntity();
+		member.pushTo(entity);
+			
+		dataObject.insertToDataBase(entity);
+	}
+
+	private void removeOneMemberToDataBase(Member member) throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("removeOneMember");
+		namedSQL.setParam("memberId", member.getId());
+		SQLRunner.execSQL(namedSQL);
+	}
+
+	public void saveMessage(String usr, Message messageT) {
+		// TODO Auto-generated method stub
+	}
+
+	public void saveMessageRelation(String usr, Message messageT) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public static MessageRecord getLoadedMessage(String parentid) {
+		if (parentid == null) {
+			return null;
+		}
+		
+		return allLoadedMessageMap.get(parentid);
+	}
+	
+    private static MqttPublishMessage notRetainedPublish(String topic, MqttQoS qos, ByteBuf message) {
+        return notRetainedPublishWithMessageId(topic, qos, message, 0);
+    }
+
+    private static MqttPublishMessage notRetainedPublishWithMessageId(String topic, MqttQoS qos, ByteBuf message, int messageId) {
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBLISH, false, qos, false, 0);
+        MqttPublishVariableHeader varHeader = new MqttPublishVariableHeader(topic, messageId);
+        return new MqttPublishMessage(fixedHeader, varHeader, message);
+    }	
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/MessageRecord.java b/IMserver/medeasy/src/chat/module/entity/MessageRecord.java
new file mode 100644
index 0000000..29cb2df
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/MessageRecord.java
@@ -0,0 +1,328 @@
+package chat.module.entity;
+
+import chat.consts.ProtoConstants;
+import chat.server.call.ResultCode;
+import chat.server.moquette.message.ModifiedMqttPubAckMessage;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageIdVariableHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.User;
+import chat.user.UserStore;
+import chat.util.ByteStrToStr;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.Message;
+
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+
+public class MessageRecord {
+
+	private String id;
+	private String spaceid;
+	private String spacecode;
+	private String typecode;
+	private int type;
+	private String path;
+	private String content;
+	private int persistflag;
+	private String senderid;
+	private long messageid;
+	private String statuscode;
+	private long timestamp;
+	private String parentid;
+	private int level;
+	
+	private User sender;
+	private WFCMessage.Message message;
+	
+	public MessageRecord() {
+		timestamp = System.currentTimeMillis();
+	}
+	
+	public static MessageRecord getInstance(String spaceCode, String spaceId, Message message) throws Exception {
+		MessageRecord result = new MessageRecord();
+		
+		result.id = ID.newValue();
+		
+		if (message.getContent().getType() == 1) {
+			result.typecode = "text";
+		}
+		else if (message.getContent().getType() == 2) {
+			result.typecode = "voice";
+		}
+		else if (message.getContent().getType() == 3) {
+			result.typecode = "image";
+		}
+		else if (message.getContent().getType() == 4) {
+			result.typecode = "location";
+		}
+		else if (message.getContent().getType() == 5) {
+			result.typecode = "file";
+		}
+		else if (message.getContent().getType() == 6) {
+			result.typecode = "video";
+		}
+		else if (message.getContent().getType() == 7) {
+			result.typecode = "sticker";
+		}
+		else if (message.getContent().getType() == 8) {
+			result.typecode = "richmedia";
+		}
+		else if (message.getContent().getType() == 104) {
+			result.typecode = "groupNotiy";
+		}
+		else if (message.getContent().getType() == 90) {
+			result.typecode = "newFriendNotify";
+		}
+		
+		result.type = message.getContent().getType();
+		result.spaceid = spaceId;
+		result.spacecode = spaceCode;
+
+		if (message.getContent().getType() == 90) {
+			result.content = message.getContent().getContent();
+		}
+		else if (message.getContent().getSearchableContent() == null || ("").equals(message.getContent().getSearchableContent())) {
+			result.content = ByteStrToStr.transformStr(message.getContent().getData());
+		}
+		else {
+			result.content = message.getContent().getSearchableContent();
+		}
+		
+		result.persistflag = message.getContent().getPersistFlag();
+		result.senderid = message.getFromUser();
+		result.messageid = message.getMessageId();
+		result.statuscode = "send";
+		result.timestamp = System.currentTimeMillis();
+		result.sender = UserStore.getById(message.getFromUser());
+		
+		return result;
+	}
+	
+	public static MessageRecord getTextInstance(String content, User sender) throws Exception {
+		MessageRecord result = new MessageRecord();
+		
+		result.id = ID.newValue();
+		result.messageid = newMessageId();
+		result.sender = sender;
+		result.senderid = sender.getId();
+		result.content = content;
+		
+		return result;
+	}
+
+	public static MessageRecord getImageInstance(String content) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void load(Entity entity) throws Exception {
+		// TODO Auto-generated method stub
+		id = entity.getString("id");
+		spaceid = entity.getString("spaceid");
+		spacecode = entity.getString("spacecode");
+		typecode = entity.getString("typecode");
+		type = entity.getInteger("type");
+		content = entity.getString("content");
+		path = entity.getString("path");
+		persistflag = entity.getInteger("persistflag");
+		senderid = entity.getString("senderid");
+		messageid = Long.parseLong(entity.getString("messageid"));
+		statuscode = entity.getString("statuscode");
+		timestamp = Long.parseLong(entity.getString("timestamp"));
+		parentid = entity.getString("parentid");
+		level = entity.getInteger("level");
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("spaceid", spaceid);
+		entity.set("spacecode", spacecode);
+		entity.set("content", content);
+		entity.set("typecode", typecode);
+		entity.set("type", type);
+		entity.set("content", content);
+		entity.set("path", path);
+		entity.set("persistflag", persistflag);
+		entity.set("senderid", senderid);
+		entity.set("content", content);
+		entity.set("messageid", messageid);
+		entity.set("statuscode", statuscode);
+		entity.set("timestamp", timestamp);
+		entity.set("parentid", parentid);
+		entity.set("level", level);
+	}
+	
+	public MqttMessage toMqttMessage(String targetId, WFCMessage.MessageContent content) {
+		WFCMessage.Message wfcMessage = toWFCMessage(targetId, content);
+		
+		byte[] bytes = wfcMessage.toByteArray();
+		
+        ByteBuf buf = Unpooled.buffer();
+        buf.ensureWritable(1).writeByte(ResultCode.Success.getValue());
+        buf.ensureWritable(bytes.length).writeBytes(bytes);
+
+        MqttMessageIdVariableHeader header = MqttMessageIdVariableHeader.from(Integer.parseInt(String.valueOf(messageid)));
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBACK, false, MqttQoS.AT_MOST_ONCE, false, 0);
+        ModifiedMqttPubAckMessage mqttMessage = new ModifiedMqttPubAckMessage(fixedHeader, header, buf);
+
+		return mqttMessage;
+	}
+	
+	public Message toWFCMessage(String targetId, WFCMessage.MessageContent contentMessage) {
+		WFCMessage.Message message = null;
+		
+		try {
+			WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			if (contentMessage != null) {
+				long timestamp = System.currentTimeMillis();
+				builder = WFCMessage.Message.newBuilder().setContent(contentMessage).setServerTimestamp(timestamp);
+	            builder.setConversation(builder.getConversationBuilder().setType(ProtoConstants.ConversationType.ConversationType_Group).setTarget(targetId).setLine(0));
+	            builder.setFromUser("user000");
+                long messageId = newMessageId();
+                builder.setMessageId(messageId);
+			} else {
+				builder = WFCMessage.Message.newBuilder();
+				builder.setMessageId(messageid);
+				builder.setFromUser(senderid);
+		        WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+		        cb.setType(0);
+		        cb.setTarget(targetId);
+		        cb.setLine(0);
+		        builder.setConversation(cb.build());				
+			}
+			
+	        WFCMessage.MessageContent.Builder contentBuilder = null;
+	        if (contentMessage == null) {
+		        contentBuilder = WFCMessage.MessageContent.newBuilder();
+		        contentBuilder.setType(1);
+		        contentBuilder.setSearchableContent(content);
+		        contentBuilder.setMediaType(0);
+		        contentBuilder.setPersistFlag(0);
+		        contentBuilder.setExpireDuration(0);
+		        contentBuilder.setMentionedType(0);	  
+		        WFCMessage.MessageContent messageContent = contentBuilder.build();
+		        
+		        builder.setContent(messageContent);
+		        builder.setServerTimestamp(System.currentTimeMillis());
+	        }
+			
+			message = builder.build();
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}		
+			
+		return message;
+	}
+
+	public String getSenderId() {
+		return senderid;
+	}
+
+	public String getContent() {
+		return content;
+	}
+
+	public void setSender(User sender) {
+		if (sender == null) {
+			this.sender = null;
+			this.senderid = null;
+			return;
+		}
+		
+		this.sender = sender;
+		this.senderid = sender.getId();
+	}
+	
+	public WFCMessage.Message getWFCMessage() {
+		return message;
+	}
+
+	public static int newMessageId() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("nextval");
+		namedSQL.setParam("name", "messageId");
+		
+		int result = SQLRunner.getInteger(namedSQL);
+		return result;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public boolean isFreshThan(long timestamp) {
+		return this.timestamp > timestamp;
+	}
+	
+	public long getMessageid() {
+		return messageid;
+	}
+
+	public void setMessageid(long messageid) {
+		this.messageid = messageid;
+	}
+
+	public WFCMessage.Message getMessage() {
+		return message;
+	}
+
+	public void setMessage(WFCMessage.Message message) {
+		this.message = message;
+	}
+
+	public String getTypecode() {
+		return typecode;
+	}
+
+	public void setTypecode(String typecode) {
+		this.typecode = typecode;
+	}
+
+	public int getPersistflag() {
+		return persistflag;
+	}
+
+	public void setPersistflag(int persistflag) {
+		this.persistflag = persistflag;
+	}
+
+	public int getType() {
+		return type;
+	}
+
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public String getSpacecode() {
+		return spacecode;
+	}
+
+	public void setSpacecode(String spacecode) {
+		this.spacecode = spacecode;
+	}
+
+	public String getSpaceid() {
+		return spaceid;
+	}
+
+	public void setSpaceid(String spaceid) {
+		this.spaceid = spaceid;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/MessageRelation.java b/IMserver/medeasy/src/chat/module/entity/MessageRelation.java
new file mode 100644
index 0000000..bd4badc
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/MessageRelation.java
@@ -0,0 +1,158 @@
+package chat.module.entity;
+
+import java.nio.charset.StandardCharsets;
+
+import cn.wildfirechat.proto.WFCMessage.Message;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+public class MessageRelation {
+
+	private String id;
+	private String spaceid;
+	private String spacecode;
+	private String parentid;
+	private String targetid;
+	private int type;
+	private int line;
+	private String statuscode;
+	private MessageRecord messageRecord;
+	
+	public MessageRelation() {}
+
+	public static MessageRelation getInstance(int line, String targetId, MessageRecord record, Message message) {
+		MessageRelation result = new MessageRelation();
+		
+		result.id = ID.newValue();	
+		result.parentid = record.getId();
+		if (message == null) {
+			result.targetid = targetId;
+		}
+		else if (message.getConversation().getType() == 1) {//缇ょ粍
+			result.targetid = message.getConversation().getTarget();
+		}
+		else if (message.getConversation().getType() == 0) {//绉佽亰
+			result.targetid = targetId;
+		}
+		result.type = message.getConversation().getType();
+		//result.targetid = targetId;
+		result.line = line;
+		result.statuscode = "unreceived";
+		result.messageRecord = record;
+		result.spaceid = record.getSpaceid();
+		result.spacecode = record.getSpacecode();
+		
+		return result;
+	}
+	
+	public static MessageRelation getImageInstance(String content) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+	public int insertToDataBase(MessageRelation relation) throws Exception {
+		DataObject dataObject = DataObject.getInstance("messagerelation");
+		
+		Entity entity = dataObject.newEntity();
+		relation.pushTo(entity);
+			
+		return dataObject.insertToDataBase(entity);
+	}
+	
+	public int updateStatusToDataBase(MessageRelation relation, String status) throws Exception {
+		DataObject dataObject = DataObject.getInstance("messagerelation");
+		
+		Entity entity = dataObject.newEntity();
+		relation.pushTo(entity);
+		
+		entity.set("statuscode", status);
+			
+		return dataObject.updateToDataBase(entity);
+	}
+
+	public void load(Entity entity) throws Exception {
+		id = entity.getString("id");
+		spaceid = entity.getString("spaceid");
+		spacecode = entity.getString("spacecode");
+		parentid = entity.getString("parentid");
+		targetid = entity.getString("targetid");
+		type = entity.getInteger("type");
+		line = entity.getInteger("line");
+		statuscode = entity.getString("statuscode");
+		
+		messageRecord = MessageContainer.getLoadedMessage(parentid);
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("spaceid", spaceid);
+		entity.set("spacecode", spacecode);
+		entity.set("parentid", parentid);
+		entity.set("targetid", targetid);
+		entity.set("type", type);
+		entity.set("line", line);
+		entity.set("statuscode", statuscode);
+	}
+	
+	public MessageRecord getMessageRecord() {
+		return messageRecord;
+	}
+
+	public void setMessageRecord(MessageRecord messageRecord) {
+		this.messageRecord = messageRecord;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public String getTargetid() {
+		return targetid;
+	}
+
+	public void setTargetid(String targetid) {
+		this.targetid = targetid;
+	}
+
+	public String getStatuscode() {
+		return statuscode;
+	}
+
+	public void setStatuscode(String statuscode) {
+		this.statuscode = statuscode;
+	}
+
+	public int getType() {
+		return type;
+	}
+
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	public int getLine() {
+		return line;
+	}
+
+	public void setLine(int line) {
+		this.line = line;
+	}
+
+	public String getSpaceid() {
+		return spaceid;
+	}
+
+	public void setSpaceid(String spaceid) {
+		this.spaceid = spaceid;
+	}
+
+	public String getSpacecode() {
+		return spacecode;
+	}
+
+	public void setSpacecode(String spacecode) {
+		this.spacecode = spacecode;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/MessageType.java b/IMserver/medeasy/src/chat/module/entity/MessageType.java
new file mode 100644
index 0000000..11902bb
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/MessageType.java
@@ -0,0 +1,44 @@
+package chat.module.entity;
+
+public enum MessageType {
+	unreceived(0), 
+	received(1),
+	Unknown(2);
+	
+	private final int value;
+	
+	MessageType(int value) {
+		this.value = value;
+	}
+	
+	public int value() {
+		return value;
+	}
+	
+	public static MessageType parse(String value) {
+		if (value == null) {
+			return Unknown;
+		}
+		
+		value = value.toLowerCase();
+		
+		if ("unreceived".equals(value)) {
+			return unreceived;
+		}
+		else if ("received".equals(value)) {
+			return received;
+		}
+		
+		return Unknown;
+	}
+	
+	public static MessageType valueOf(int value) {
+		for (MessageType qt : values()) {
+			 if (qt.value == value) {
+				 return qt;
+			 }
+		}
+		throw new IllegalArgumentException("invalid MessageType: " + value);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/Notify.java b/IMserver/medeasy/src/chat/module/entity/Notify.java
new file mode 100644
index 0000000..9ee1622
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/Notify.java
@@ -0,0 +1,136 @@
+package chat.module.entity;
+
+import java.util.Date;
+
+import chat.user.NotifySubject;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+
+public class Notify {
+
+	private String id;
+	private String sender;
+	private String bizid;
+	private String roletype;
+	private String target;
+	private String type;
+	private String msgtitle;
+	private String msgcontent;
+	private Date msgtime;
+	private String isread;
+	
+	private NotifySubject notifyContent;
+	
+	public static boolean saveNotify(Notify notify) {
+		try {
+			 DataObject dataObject = DataObject.getInstance("notify");
+			
+			 Entity entity = dataObject.newEntity();
+			 notify.pushTo(entity);
+			 dataObject.insertToDataBase(entity);
+			 return true;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("sender", sender);
+		entity.set("target", target);
+		entity.set("type", type);
+		entity.set("msgtitle", msgtitle);
+		entity.set("msgcontent", msgcontent);
+		entity.set("msgtime", msgtime);
+		entity.set("isread", isread);
+	}
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getSender() {
+		return sender;
+	}
+	
+	public void setSender(String sender) {
+		this.sender = sender;
+	}
+	
+	public String getTarget() {
+		return target;
+	}
+	
+	public void setTarget(String target) {
+		this.target = target;
+	}
+	
+	public String getType() {
+		return type;
+	}
+	
+	public void setType(String type) {
+		this.type = type;
+	}
+	
+	public String getMsgtitle() {
+		return msgtitle;
+	}
+	
+	public void setMsgtitle(String msgtitle) {
+		this.msgtitle = msgtitle;
+	}
+	
+	public String getMsgcontent() {
+		return msgcontent;
+	}
+	
+	public void setMsgcontent(String msgcontent) {
+		this.msgcontent = msgcontent;
+	}
+
+	public Date getMsgtime() {
+		return msgtime;
+	}
+
+	public void setMsgtime(Date msgtime) {
+		this.msgtime = msgtime;
+	}
+
+	public String getIsread() {
+		return isread;
+	}
+	
+	public void setIsread(String isread) {
+		this.isread = isread;
+	}
+	
+	public String getBizid() {
+		return bizid;
+	}
+
+	public void setBizid(String bizid) {
+		this.bizid = bizid;
+	}
+
+	public String getRoletype() {
+		return roletype;
+	}
+
+	public void setRoletype(String roletype) {
+		this.roletype = roletype;
+	}
+
+	public NotifySubject getNotifyContent() {
+		return notifyContent;
+	}
+
+	public void setNotifyContent(NotifySubject notifyContent) {
+		this.notifyContent = notifyContent;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/PrivateFriend.java b/IMserver/medeasy/src/chat/module/entity/PrivateFriend.java
new file mode 100644
index 0000000..35ed89e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/PrivateFriend.java
@@ -0,0 +1,129 @@
+package chat.module.entity;
+
+import java.util.List;
+
+import chat.module.ModuleLoader;
+import chat.user.User;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+
+public class PrivateFriend extends MessageContainer {
+
+	private String id;
+	private String typecode;
+	private String name;
+	private String statuscode;
+	private String portrait;
+	private String ownerid;
+	private long timestamp;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTypecode() {
+		return typecode;
+	}
+	
+	public void setTypecode(String typecode) {
+		this.typecode = typecode;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getStatuscode() {
+		return statuscode;
+	}
+	
+	public void setStatuscode(String statuscode) {
+		this.statuscode = statuscode;
+	}
+	
+	public String getPortrait() {
+		return portrait;
+	}
+	
+	public void setPortrait(String portrait) {
+		this.portrait = portrait;
+	}
+	
+	public String getOwnerid() {
+		return ownerid;
+	}
+	
+	public void setOwnerid(String ownerid) {
+		this.ownerid = ownerid;
+	}
+	
+	public long getTimestamp() {
+		return timestamp;
+	}
+	
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+	
+	public PrivateFriend() {
+		super();
+	}
+	
+	public void createPrivateFriend() {
+    	DataObject dataObject; 
+    	Entity entity;
+    	try {
+        	 //1. insert group
+    		 dataObject = DataObject.getInstance("chatspace");
+    		
+    		 entity = dataObject.newEntity();
+    		 pushTo(entity);
+    			
+    		 dataObject.insertToDataBase(entity); 
+    		 
+    	} catch(Exception e) {
+    		 e.printStackTrace();
+    	}
+		
+	}
+	
+	public PrivateFriend(String name, User sender) {
+		super(name, sender);
+		this.id = ID.newValue();
+		this.typecode = "Private";
+		this.name = name;
+		this.statuscode = "Open";
+		this.ownerid = sender.getId();
+		this.timestamp = System.currentTimeMillis();
+	}
+
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		typecode = entity.getString("typecode");
+		name = entity.getString("name");
+		statuscode = entity.getString("statuscode");
+		portrait = entity.getString("portrait");
+		ownerid = entity.getString("ownerid");
+		timestamp = Long.parseLong(entity.getString("timestamp"));
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("typecode", typecode);
+		entity.set("name", name);
+		entity.set("statuscode", statuscode);
+		entity.set("portrait", portrait);
+		entity.set("ownerid", ownerid);
+		entity.set("timestamp", timestamp);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/PublishOperator.java b/IMserver/medeasy/src/chat/module/entity/PublishOperator.java
new file mode 100644
index 0000000..9a6c914
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/PublishOperator.java
@@ -0,0 +1,8 @@
+package chat.module.entity;
+
+public enum PublishOperator {
+
+	Create, Destroy, AddMembers, Join, Leave, KickOff, 
+	PublishMessage, ChangeName, ChangeMemberAlias, Online; 
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/entity/Subscriber.java b/IMserver/medeasy/src/chat/module/entity/Subscriber.java
new file mode 100644
index 0000000..244ed77
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/entity/Subscriber.java
@@ -0,0 +1,40 @@
+package chat.module.entity;
+
+import java.util.Date;
+
+import chat.user.User;
+
+public class Subscriber {
+
+	private String channelId;
+	private User user;
+	private Date beginTime;
+	
+	public Subscriber(String channelId) {
+		this.channelId = channelId;
+	}
+
+	public String getChannelId() {
+		return channelId;
+	}
+
+	public User getUser() {
+		return user;
+	}
+
+	public Date getBeginTime() {
+		return beginTime;
+	}
+
+	public void notify(PublishOperator operator, User sender) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void notify(PublishOperator operator, MessageRecord record, User sender) {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/CircleObject.java b/IMserver/medeasy/src/chat/module/friendcircle/CircleObject.java
new file mode 100644
index 0000000..e76df94
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/CircleObject.java
@@ -0,0 +1,239 @@
+package chat.module.friendcircle;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import chat.server.im.DataPool;
+import chat.user.User;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.util.MapList;
+
+
+public class CircleObject implements IJsonProvider {
+
+	private String id;
+	private FriendCircle root;
+	private String ownerId;
+	private String doctorId;
+	private String location;
+	private LabeList labelList;
+	private String content;
+	private String media;
+	private MediaType mediaType;
+	private int cnt_collection;
+	private int cnt_thumbsup;
+	private int cnt_comment;
+	private int cnt_forward;
+	private MapList<User> collectionList;
+	private MapList<User> thumbsupList;
+	private MapList<Comment> commentList;
+	private MapList<Forward> forwardList;
+	
+	
+	public CircleObject(FriendCircle root) {
+		labelList = new LabeList();
+		collectionList = new MapList<User>();
+		thumbsupList = new MapList<User>();
+		commentList = new MapList<Comment>();
+		forwardList = new MapList<Forward>();
+		this.root = root;
+	}
+
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		
+		ownerId = entity.getString("senderId");
+		doctorId = entity.getString("doctorId");
+		location = entity.getString("region");
+		labelList.load(entity.getString("dieaselabel"));
+		content = entity.getString("content");
+		mediaType = MediaType.parse(entity.getInteger("type", 2));
+		media = entity.getString("medias");
+		
+		cnt_collection = entity.getInteger("cnt_collection", 0);
+		cnt_thumbsup = entity.getInteger("cnt_thumbsup", 0);
+		cnt_comment = entity.getInteger("cnt_comment", 0);
+		cnt_forward = entity.getInteger("cnt_forward", 0);
+	}
+
+	public void load(DataPool dataPool) {
+		location = dataPool.getString("region");
+		labelList.load(dataPool.getString("dieaselabel"));
+		content = dataPool.getString("content");
+		mediaType = MediaType.parse(dataPool.getString("type"));
+		media = dataPool.getString("media");
+	}
+
+	// 鏀惰棌
+	public void addOneCollect(User one) {
+		if (one == null) {
+			return;
+		}
+		
+		String key = one.getId();
+		User user = collectionList.get(key);
+		
+		if (user == null) {
+			insertOneCollectionToDB(one);
+			collectionList.add(key, one);
+		}
+	}
+	
+	// 鐐硅禐
+	public void addOneThumbsup(User one) {
+		if (one == null) {
+			return;
+		}
+		
+		String key = one.getId();
+		User user = thumbsupList.get(key);
+		
+		if (user == null) {
+			insertOneThumbsupToDB(one);
+			thumbsupList.add(key, one);
+		}
+	}
+
+	public String addOneComment(User user, String parentId, String comment) {
+		if (parentId != null) {
+			return addOneLevelComment(user, comment);
+		}
+		
+		return addTowLevelComment(user, parentId, comment);
+	}
+	
+	// 娣诲姞涓�绾ц瘎璁�
+	public String addOneLevelComment(User one, String content) {
+		if (one == null) {
+			return null;
+		}
+		
+		String id = ID.newValue();
+		
+		Comment comment = new Comment(one);
+		comment.setId(id);
+		comment.setContent(content);
+		
+		insertOneCommentToDB(comment);
+		commentList.add(id, comment);
+		
+		return id;
+	}
+
+	// 娣诲姞浜岀骇璇勮
+	public String addTowLevelComment(User one, String parentId, String content) {
+		if (one == null) {
+			return null;
+		}
+		
+		Comment comment = commentList.get(parentId);
+		
+		if (comment == null) {
+			return null;
+		}
+				
+		insertOneCommentToDB(comment);
+		return comment.addOneSubComment(one, content);
+	}
+	
+	// 杞彂
+	public void addOneForward(User sender, User to) {
+		if (sender == null || to == null) {
+			return;
+		}
+		
+		Forward forward = new Forward(sender, to);
+		String key = forward.getKey();
+		
+		forward = forwardList.get(key);
+		
+		if (forward == null) {
+			insertOneForwardToDB(forward);
+			forwardList.add(key, forward);
+		}
+	}
+
+	public void insertToDB() {
+		// TODO Auto-generated method stub
+		
+	}
+	
+	private void insertOneCollectionToDB(User one) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void insertOneThumbsupToDB(User one) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void insertOneCommentToDB(Comment comment) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void insertOneForwardToDB(Forward forward) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		writer.write("contentId", id);
+		writer.write("ownerId", ownerId);
+		writer.write("doctorId", doctorId);
+		writer.write("avatar", "https://yishiwuyou.oss-cn-shanghai.aliyuncs.com/avatar/2020/12/18/6e546ce5fbbc4482ae9e.png");
+		writer.write("mediaType", mediaType.toIntCode());
+		
+		if (MediaType.Vedio == mediaType) {
+			writer.write("media", media);
+			writer.writeNull("image");
+		}
+		else if (MediaType.Image == mediaType) {
+			writer.write("image", media);
+			writer.writeNull("media");
+		}
+		
+		writer.write("location", location);
+		writer.write("labelList", labelList.getValue());
+		writer.write("isAattention", root.isAttention());
+		writer.write("cnt_collection", cnt_collection + collectionList.size());
+		writer.write("cnt_thumbsup", cnt_thumbsup + thumbsupList.size());
+		writer.write("cnt_comment", cnt_comment + commentList.size());
+		writer.write("cnt_forward", cnt_forward + forwardList.size());		
+		writer.write("content", content);
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getOwnerId() {
+		return ownerId;
+	}
+
+	public void setOwnerId(String userId) {
+		this.ownerId = userId;
+	}
+
+	public String getDoctorId() {
+		return doctorId;
+	}
+
+	public void setDoctorId(String doctorId) {
+		this.doctorId = doctorId;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/Comment.java b/IMserver/medeasy/src/chat/module/friendcircle/Comment.java
new file mode 100644
index 0000000..53f7502
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/Comment.java
@@ -0,0 +1,85 @@
+package chat.module.friendcircle;
+
+import chat.user.User;
+import frame.object.data.ID;
+import frame.util.MapList;
+
+public class Comment {
+
+	private String id;
+	private User owner;
+	private int level;
+	private String content;
+	private CircleObject circleObject;
+	private Comment parent;
+	private MapList<Comment> subComentList;
+	
+	
+	public Comment(User owner) {
+		subComentList = new MapList<Comment>();
+		this.owner = owner;
+	}
+	
+	public String addOneSubComment(User owner, String content) {
+		String id = ID.newValue();
+		
+		Comment comment = new Comment(owner);
+		comment.setId(id);
+		comment.setLevel(2);
+		comment.setParent(parent);
+		comment.setContent(content);
+		
+		subComentList.add(id, comment);
+		
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public void setParent(Comment parent) {
+		this.parent = parent;
+	}
+
+	public void setLevel(int level) {
+		this.level = level;
+	}
+
+	public User getOwner() {
+		return owner;
+	}
+
+	public int getLevel() {
+		return level;
+	}
+
+	public String getContent() {
+		return content;
+	}
+
+	public CircleObject getCircleObject() {
+		return circleObject;
+	}
+
+	public Comment getParent() {
+		return parent;
+	}
+
+	public String getParentId() {
+		if (parent == null) {
+			return null;
+		}
+		
+		return parent.getId();
+	}
+
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	public String getId() {
+		return id;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/CommentList.java b/IMserver/medeasy/src/chat/module/friendcircle/CommentList.java
new file mode 100644
index 0000000..97fc0fa
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/CommentList.java
@@ -0,0 +1,42 @@
+package chat.module.friendcircle;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import frame.util.MapList;
+
+public class CommentList implements IJsonProvider {
+	
+	private CircleObject circleObject;
+	private MapList<Comment> commentList;
+	private Comment current;
+	
+	
+	public CommentList(CircleObject circleObject) {
+		this.circleObject = circleObject;
+	}
+
+	public int size() {
+		return commentList.size();
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginArray();
+		
+		for (Comment comment: commentList) {
+			current = comment;
+			writeJSONData(writer);
+		}
+
+		writer.endArray();
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		writer.write("circleObjectId", circleObject.getId());
+		writer.write("level", current.getLevel());
+		writer.write("parentId", current.getParentId());
+		writer.write("circleObjectId", current.getContent());
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/Forward.java b/IMserver/medeasy/src/chat/module/friendcircle/Forward.java
new file mode 100644
index 0000000..2c88ada
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/Forward.java
@@ -0,0 +1,34 @@
+package chat.module.friendcircle;
+
+import chat.user.User;
+
+public class Forward {
+
+	private String key;
+	private User sender;
+	private User to;
+	
+	
+	public Forward(User sender, User to) {
+		this.sender  = sender;
+		this.to = to;
+		this.key = createKey();
+	}
+	
+	private String createKey() {
+		return sender.getId() + "-" + to.getId();
+	}
+
+	public String getKey() {
+		return key;
+	}
+
+	public User getSender() {
+		return sender;
+	}
+
+	public User getTo() {
+		return to;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/FriendCircle.java b/IMserver/medeasy/src/chat/module/friendcircle/FriendCircle.java
new file mode 100644
index 0000000..08f8c8a
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/FriendCircle.java
@@ -0,0 +1,115 @@
+package chat.module.friendcircle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import chat.module.ConcurrentMapList;
+import chat.server.im.DataPool;
+import chat.user.User;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.util.MapList;
+
+public class FriendCircle {
+
+	private static ConcurrentMapList<CircleObject> allList;
+	private ConcurrentMapList<CircleObject> itemList;
+	private MapList<User> attentionList;
+	private boolean attention;
+	
+	static {
+		allList = new ConcurrentMapList<CircleObject>();
+	}
+	
+	public FriendCircle() {
+		itemList = new ConcurrentMapList<CircleObject>();
+    	attentionList = new MapList<User>();
+	}
+	
+	public void loadOneCricleObject(Entity entity) throws Exception {
+		CircleObject circleObject = new CircleObject(this);
+		circleObject.load(entity);
+		
+		String id = circleObject.getId();
+		itemList.add(id, circleObject);
+		
+		String ownerId = circleObject.getOwnerId();
+		if (!allList.contains(ownerId)) {
+			allList.add(id, circleObject);
+		}
+	}
+
+	public String createOneCircleObject(DataPool dataPool) {
+		String id = ID.newValue();
+		
+		CircleObject result = new CircleObject(this);
+		result.setId(id);
+		result.load(dataPool);
+		
+		result.insertToDB();
+		itemList.add(id, result);
+		
+		return id;
+	}
+	
+	public static List<CircleObject> getCircleObjectList(int pageNo, int pageSize) {
+		List<CircleObject> result = new ArrayList<CircleObject>();
+		
+		int begin = pageNo * pageSize;
+		int end = Math.min((begin + pageSize), allList.size());
+		
+		CircleObject object;
+		
+		for (int i = begin; i < end; i++) {
+			object = allList.get(i);
+			result.add(object);
+		}
+		
+		return result;
+	}
+	
+	public List<CircleObject> getOneUserCircleObjectList(int pageNo, int pageSize) {
+		List<CircleObject> result = new ArrayList<CircleObject>();
+		
+		int begin = pageNo * pageSize;
+		int end = Math.min((begin + pageSize), itemList.size());
+		
+		CircleObject object;
+		
+		for (int i = begin; i < end; i++) {
+			object = itemList.get(i);
+			result.add(object);
+		}
+		
+		return result;
+	}
+
+	public CircleObject getOneCircleObjectList(String circleObjectId) {
+		return itemList.get(circleObjectId);
+	}
+	
+	public boolean isAttention() {
+		return attention;
+	}
+
+	public void setAttention(boolean attention) {
+		this.attention = attention;
+	}
+
+	public void addOneAttention(User user) {
+		if (user == null) {
+			return;
+		}
+		
+		String userId = user.getId();
+		
+		if (!attentionList.contains(userId)) {
+			attentionList.add(userId, user);
+		}
+	}
+
+	public CircleObject getOneCircleObject(String circleObjectId) {
+		return itemList.get(circleObjectId);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/FriendCircleLoader.java b/IMserver/medeasy/src/chat/module/friendcircle/FriendCircleLoader.java
new file mode 100644
index 0000000..b23a9f9
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/FriendCircleLoader.java
@@ -0,0 +1,6 @@
+package chat.module.friendcircle;
+
+public class FriendCircleLoader {
+
+	
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/LabeList.java b/IMserver/medeasy/src/chat/module/friendcircle/LabeList.java
new file mode 100644
index 0000000..4133976
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/LabeList.java
@@ -0,0 +1,70 @@
+package chat.module.friendcircle;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import frame.util.ContentBuilder;
+
+public class LabeList {
+
+	public static String Spliter = "#";
+	private Set<String> items;
+	private String value;
+	
+	
+	public LabeList() {
+		items = new HashSet<String>();
+		value = null;
+	}
+	
+	public void addone(String label) {
+		if (label == null) {
+			return;
+		}
+		
+		items.add(label);
+		value = null;
+	}
+
+	public synchronized String getValue() {
+		if (value == null) {
+			value = createValue();
+		}
+		
+		return value;
+	}
+
+	private String createValue() {
+		if (items.isEmpty()) {
+			return "";
+		}
+		
+		ContentBuilder builder = new ContentBuilder(Spliter);
+		
+		for (String label: items) {
+			builder.append(label);
+		}
+		
+		return Spliter + builder.toString();
+	}
+
+	public void load(String value) {
+		if (value == null) {
+			return;
+		}
+		
+		value = value.trim();
+		
+		String[] segments = value.split("#");
+		
+		for (String segment: segments) {
+			segment = segment.trim();
+			
+			if ("".equals(segment)) {
+				continue;
+			}
+			
+			items.add(segment);
+		}
+	}
+}
diff --git a/IMserver/medeasy/src/chat/module/friendcircle/MediaType.java b/IMserver/medeasy/src/chat/module/friendcircle/MediaType.java
new file mode 100644
index 0000000..f512550
--- /dev/null
+++ b/IMserver/medeasy/src/chat/module/friendcircle/MediaType.java
@@ -0,0 +1,51 @@
+package chat.module.friendcircle;
+
+public enum MediaType {
+
+	Vedio, Image, Unknown;
+
+	public static MediaType parse(String code) {
+		if (code == null) {
+			return Unknown;
+		}
+		
+		code = code.toLowerCase();
+		
+		if ("vedio".equals(code)) {
+			return Vedio;
+		}
+		else if ("image".equals(code)) {
+			return Image;
+		}
+		
+		return Unknown;
+	}
+
+	public static MediaType parse(Integer type) {
+		if (type == null) {
+			return Unknown;
+		}
+		
+		if (type == 1) {
+			return Image;
+		}
+		else if (type == 2) {
+			return Vedio;
+		}
+		
+		return Unknown;
+	}
+
+	public int toIntCode() {
+		if (Image == this) {
+			return 1;
+		}
+		else if (Vedio == this) {
+			return 2;
+		}
+		else {
+			return -1;
+		}
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/persist/Message.java b/IMserver/medeasy/src/chat/persist/Message.java
new file mode 100644
index 0000000..a9d78a5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/persist/Message.java
@@ -0,0 +1,149 @@
+package chat.persist;
+
+public class Message {
+
+	private String id;
+	private String spaceid;
+	private String spacecode;
+	private String typecode;
+	private int type;
+	private String path;
+	private String content;
+	private int persistflag;
+	private String senderid;
+	private long messageid;
+	private String statuscode;
+	private long timestamp;
+	private String parentid;
+	private int level;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getSpaceid() {
+		return spaceid;
+	}
+	
+	public void setSpaceid(String spaceid) {
+		this.spaceid = spaceid;
+	}
+	
+	public String getSpacecode() {
+		return spacecode;
+	}
+	
+	public void setSpacecode(String spacecode) {
+		this.spacecode = spacecode;
+	}
+	
+	public String getTypecode() {
+		return typecode;
+	}
+	
+	public void setTypecode(String typecode) {
+		this.typecode = typecode;
+	}
+	
+	public String getPath() {
+		return path;
+	}
+	
+	public void setPath(String path) {
+		this.path = path;
+	}
+	
+	public String getContent() {
+		return content;
+	}
+	
+	public void setContent(String content) {
+		this.content = content;
+	}
+	
+	public int getType() {
+		return type;
+	}
+
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	public int getPersistflag() {
+		return persistflag;
+	}
+
+	public void setPersistflag(int persistflag) {
+		this.persistflag = persistflag;
+	}
+
+	public String getSenderid() {
+		return senderid;
+	}
+	
+	public void setSenderid(String senderid) {
+		this.senderid = senderid;
+	}
+	
+	public long getMessageid() {
+		return messageid;
+	}
+	
+	public void setMessageid(long messageid) {
+		this.messageid = messageid;
+	}
+	
+	public String getStatuscode() {
+		return statuscode;
+	}
+	
+	public void setStatuscode(String statuscode) {
+		this.statuscode = statuscode;
+	}
+	
+	public long getTimestamp() {
+		return timestamp;
+	}
+	
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+	
+	public String getParentid() {
+		return parentid;
+	}
+	
+	public void setParentid(String parentid) {
+		this.parentid = parentid;
+	}
+	
+	public int getLevel() {
+		return level;
+	}
+	
+	public void setLevel(int level) {
+		this.level = level;
+	}
+	
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/IMserver/medeasy/src/chat/persist/MessageDetail.java b/IMserver/medeasy/src/chat/persist/MessageDetail.java
new file mode 100644
index 0000000..193d464
--- /dev/null
+++ b/IMserver/medeasy/src/chat/persist/MessageDetail.java
@@ -0,0 +1,78 @@
+package chat.persist;
+
+public class MessageDetail {
+	
+	private String id;
+	private String spaceid;
+	private String spacecode;
+	private String parentid;
+	private String targetid;
+	private int type;
+	private int line;
+	private String statuscode;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getSpaceid() {
+		return spaceid;
+	}
+	
+	public void setSpaceid(String spaceid) {
+		this.spaceid = spaceid;
+	}
+	
+	public String getSpacecode() {
+		return spacecode;
+	}
+	
+	public void setSpacecode(String spacecode) {
+		this.spacecode = spacecode;
+	}
+	
+	public String getParentid() {
+		return parentid;
+	}
+	
+	public void setParentid(String parentid) {
+		this.parentid = parentid;
+	}
+	
+	public String getTargetid() {
+		return targetid;
+	}
+	
+	public void setTargetid(String targetid) {
+		this.targetid = targetid;
+	}
+	
+	public int getType() {
+		return type;
+	}
+
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	public int getLine() {
+		return line;
+	}
+
+	public void setLine(int line) {
+		this.line = line;
+	}
+
+	public String getStatuscode() {
+		return statuscode;
+	}
+	
+	public void setStatuscode(String statuscode) {
+		this.statuscode = statuscode;
+	}
+
+}
\ No newline at end of file
diff --git a/IMserver/medeasy/src/chat/persistence/MemoryMessagesStore.java b/IMserver/medeasy/src/chat/persistence/MemoryMessagesStore.java
new file mode 100644
index 0000000..173728a
--- /dev/null
+++ b/IMserver/medeasy/src/chat/persistence/MemoryMessagesStore.java
@@ -0,0 +1,33 @@
+package chat.persistence;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import chat.module.FriendRequstBucket;
+
+public class MemoryMessagesStore {
+	
+    private ReadWriteLock mLock = new ReentrantReadWriteLock();
+    private static FriendRequstBucket friendRequstBucket;
+    
+    private Lock mReadLock = mLock.readLock();
+    private Lock mWriteLock = mLock.writeLock();
+	
+    public long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String user, long messageId) {
+        // messageId鏄叏灞�鐨勶紝messageSeq鏄窡涓汉鐩稿叧鐨勶紝鐞嗚涓妋essageId鐨勫闀挎暟搴﹁繙杩滃ぇ浜巗eq銆�
+        // 鑰冭檻鍒颁竴绉嶆儏鍐碉紝褰撴湇鍔″櫒鍙戠敓鍙樺寲锛岀敤鎴峰彂鐢熻縼绉诲悗锛宮essageSeq杩橀渶瑕佷繚鎸佹湁搴忋�� 瑕佷箞鎶奡eq鎸佷箙鍖栵紝瑕佷箞鍦ㄨ縼绉诲悗Seq鍙栦竴涓偗瀹氭瘮浠ュ墠鏇村ぇ鐨勬暟瀛楋紙杩欎釜鏁板瓧灏辨槸messageId锛�
+        // 杩欓噷閫夋嫨浣跨敤鍚庨潰涓�绉嶆儏鍐�
+        long messageSeq = 0;
+
+        mWriteLock.lock();
+        try {
+        	 
+        } finally {
+            mWriteLock.unlock();
+        }
+
+        //databaseStore.persistUserMessage(user, messageId, messageSeq);
+        return messageSeq;
+    }
+}
diff --git a/IMserver/medeasy/src/chat/redis/RedisUtil.java b/IMserver/medeasy/src/chat/redis/RedisUtil.java
new file mode 100644
index 0000000..9593df5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/redis/RedisUtil.java
@@ -0,0 +1,24 @@
+package chat.redis;
+
+import redis.clients.jedis.Jedis;
+
+public class RedisUtil {
+
+	public static boolean createRedisKey(String key, String jsonStr) {
+		boolean result = false;
+		try {
+	         Jedis jedis = new Jedis("139.196.115.152");
+	         jedis.auth("uThyLr0gKTCf"); 
+	         if (jedis.exists(key))
+	        	 jedis.del(key);
+	         jedis.set(key, jsonStr);
+	         jedis.expire(key, 2592000);
+	         jedis.close();
+	         result = true;
+		} catch (Exception e) {
+			 result = false;
+			 e.printStackTrace();
+		}
+		return result;
+	}
+}
diff --git a/IMserver/medeasy/src/chat/security/AES.java b/IMserver/medeasy/src/chat/security/AES.java
new file mode 100644
index 0000000..204f869
--- /dev/null
+++ b/IMserver/medeasy/src/chat/security/AES.java
@@ -0,0 +1,165 @@
+package chat.security;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AES {
+    private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
+    public static void init(byte[] secret) {
+        if (secret != null && secret.length == 16) {
+            aes_key = new byte[16];
+            for (int i = 0; i < 16; i++) {
+                aes_key[i] = secret[i];
+            }
+        } else {
+            System.out.println("Error int key error, secret incorrect");
+        }
+    }
+
+    public static byte[] AESEncrypt(String sSrc, String userKey) {
+        return AESEncrypt(sSrc.getBytes(), userKey);
+    }
+
+    public static byte[] AESEncrypt(byte[] tobeencrypdata, byte[] aesKey) {
+        if (aesKey == null) {
+            System.out.print("Key涓虹┖null");
+            return null;
+        }
+        // 鍒ゆ柇Key鏄惁涓�16浣�
+        if (aesKey.length != 16) {
+            System.out.print("Key闀垮害涓嶆槸16浣�");
+            return null;
+        }
+
+
+        try {
+            SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"绠楁硶/妯″紡/琛ョ爜鏂瑰紡"
+            IvParameterSpec iv = new IvParameterSpec(aesKey);//浣跨敤CBC妯″紡锛岄渶瑕佷竴涓悜閲廼v锛屽彲澧炲姞鍔犲瘑绠楁硶鐨勫己搴�
+            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
+
+            //2018.1.1 0:0:0 浠ユ潵鐨勫皬鏃舵暟
+            int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
+
+            byte[] tobeencrypdatawithtime = new byte[tobeencrypdata.length + 4];
+            byte byte0 = (byte)(curhour & 0xFF);
+            tobeencrypdatawithtime[0] = byte0;
+
+            byte byte1 = (byte)((curhour & 0xFF00) >> 8);
+            tobeencrypdatawithtime[1] = byte1;
+
+            byte byte2 = (byte)((curhour & 0xFF0000) >> 16);
+            tobeencrypdatawithtime[2] = byte2;
+
+            byte byte3 = (byte)((curhour & 0xFF) >> 24);
+            tobeencrypdatawithtime[3] = byte3;
+
+            System.arraycopy(tobeencrypdata, 0, tobeencrypdatawithtime, 4, tobeencrypdata.length);
+
+
+            byte[] encrypted = cipher.doFinal(tobeencrypdatawithtime);
+            return encrypted;
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (NoSuchPaddingException e) {
+            e.printStackTrace();
+        } catch (InvalidKeyException e) {
+            e.printStackTrace();
+        } catch (InvalidAlgorithmParameterException e) {
+            e.printStackTrace();
+        } catch (IllegalBlockSizeException e) {
+            e.printStackTrace();
+        } catch (BadPaddingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static byte[] AESEncrypt(byte[] tobeencrypdata, String userKey) {
+        byte[] aesKey = aes_key;
+        if (userKey != null && !userKey.isEmpty()) {
+            aesKey = convertUserKey(userKey);
+        }
+        return AESEncrypt(tobeencrypdata, aesKey);
+    }
+
+    public static int getUnsignedByte (byte data){      //灏哾ata瀛楄妭鍨嬫暟鎹浆鎹负0~255 (0xFF 鍗矪YTE)銆�
+        return data&0x0FF ;
+    }
+
+    private static byte[] convertUserKey(String userKey) {
+        byte[] key = new byte[16];
+        for (int i = 0; i < 16; i++) {
+            key[i] = (byte) (userKey.charAt(i) & 0xFF);
+        }
+        return key;
+    }
+    public static byte[] AESDecrypt(byte[] sSrc, String userKey, boolean checkTime) {
+        byte[] aesKey = aes_key;
+        if (userKey != null && !userKey.isEmpty()) {
+            aesKey = convertUserKey(userKey);
+        }
+        return AESDecrypt(sSrc, aesKey, checkTime);
+    }
+
+    public static byte[] AESDecrypt(byte[] sSrc, byte[] aesKey, boolean checkTime) {
+        try {
+
+            // 鍒ゆ柇Key鏄惁姝g‘
+            if (aesKey == null) {
+                aesKey = aes_key;
+            }
+            // 鍒ゆ柇Key鏄惁涓�16浣�
+            if (aesKey.length != 16) {
+                System.out.print("Key闀垮害涓嶆槸16浣�");
+                return null;
+            }
+
+            SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+            IvParameterSpec iv = new IvParameterSpec(aesKey);
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+            try {
+                byte[] original = cipher.doFinal(sSrc);
+                int hours = 0;
+
+                if (original.length > 4) {
+                    hours += getUnsignedByte(original[3]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[2]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[1]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[0]);
+
+                    //2018.1.1 0:0:0 浠ユ潵鐨勫皬鏃舵暟
+                    int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
+
+                    if (curhour - hours > 24 && checkTime) {
+                        return null;
+                    }
+                    byte[] neworiginal = new byte[original.length - 4];
+                    System.arraycopy(original, 4, neworiginal, 0, neworiginal.length);
+                    return neworiginal;
+                }
+                return null;
+            } catch (Exception e) {
+                System.out.println(e.toString());
+                return null;
+            }
+        } catch (Exception ex) {
+            System.out.println(ex.toString());
+            return null;
+        }
+    }
+}
diff --git a/IMserver/medeasy/src/chat/security/DES.java b/IMserver/medeasy/src/chat/security/DES.java
new file mode 100644
index 0000000..dd75177
--- /dev/null
+++ b/IMserver/medeasy/src/chat/security/DES.java
@@ -0,0 +1,218 @@
+package chat.security;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Base64;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class DES {
+	
+	private static final String Encrypt_Password = "abcdefgh";
+    private static byte[] iv = { 1, 2, 3, 4, 5, 6, 7, 8 };
+    private static byte[] aes_key= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
+    
+    public static String decryptDES(String decryptString) throws Exception {
+        byte[] byteMi = Base64.getDecoder().decode(decryptString);
+        IvParameterSpec zeroIv = new IvParameterSpec(iv);
+        SecretKeySpec key = new SecretKeySpec(Encrypt_Password.getBytes(), "DES");
+        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+        cipher.init(Cipher.DECRYPT_MODE, key, zeroIv);
+        byte decryptedData[] = cipher.doFinal(byteMi);
+
+        return new String(decryptedData);
+    }
+    
+    public static void init(byte[] secret) {
+        if (secret != null && secret.length == 16) {
+            aes_key = new byte[16];
+            for (int i = 0; i < 16; i++) {
+                aes_key[i] = secret[i];
+            }
+        } else {
+            System.out.println("Error int key error, secret incorrect");
+        }
+    }
+    
+    public static String encryptDES(String encryptString) throws Exception {
+        IvParameterSpec zeroIv = new IvParameterSpec(iv);
+        SecretKeySpec key = new SecretKeySpec(Encrypt_Password.getBytes(), "DES");
+        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
+        byte[] encryptedData = cipher.doFinal(encryptString.getBytes());
+        return new String(Base64.getEncoder().encode(encryptedData));
+    }
+
+	public static byte[] encrypt(byte[] datasource) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
+		SecureRandom random = new SecureRandom();
+		DESKeySpec desKey = new DESKeySpec(Encrypt_Password.getBytes());
+		// 鍒涘缓涓�涓瘑鍖欏伐鍘傦紝鐒跺悗鐢ㄥ畠鎶奃ESKeySpec杞崲鎴�
+		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+		SecretKey securekey = keyFactory.generateSecret(desKey);
+		// Cipher瀵硅薄瀹為檯瀹屾垚鍔犲瘑鎿嶄綔
+		Cipher cipher = Cipher.getInstance("DES");
+		// 鐢ㄥ瘑鍖欏垵濮嬪寲Cipher瀵硅薄
+		cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
+		// 鐜板湪锛岃幏鍙栨暟鎹苟鍔犲瘑
+		// 姝e紡鎵ц鍔犲瘑鎿嶄綔
+		return cipher.doFinal(datasource);
+	}
+
+	public static byte[] decrypt(byte[] src) throws Exception {
+		// DES绠楁硶瑕佹眰鏈変竴涓彲淇′换鐨勯殢鏈烘暟婧�
+		SecureRandom random = new SecureRandom();
+		// 鍒涘缓涓�涓狣ESKeySpec瀵硅薄
+		DESKeySpec desKey = new DESKeySpec(Encrypt_Password.getBytes());
+		// 鍒涘缓涓�涓瘑鍖欏伐鍘�
+		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+		// 灏咲ESKeySpec瀵硅薄杞崲鎴怱ecretKey瀵硅薄
+		SecretKey securekey = keyFactory.generateSecret(desKey);
+		// Cipher瀵硅薄瀹為檯瀹屾垚瑙e瘑鎿嶄綔
+		Cipher cipher = Cipher.getInstance("DES");
+		// 鐢ㄥ瘑鍖欏垵濮嬪寲Cipher瀵硅薄
+		cipher.init(Cipher.DECRYPT_MODE, securekey, random);
+		// 鐪熸寮�濮嬭В瀵嗘搷浣�
+		return cipher.doFinal(src);
+	}
+	
+    public static byte[] AESEncrypt(String sSrc, String userKey) {
+        return AESEncrypt(sSrc.getBytes(), userKey);
+    }
+
+    public static byte[] AESEncrypt(byte[] tobeencrypdata, byte[] aesKey) {
+        if (aesKey == null) {
+            System.out.print("Key涓虹┖null");
+            return null;
+        }
+
+        if (aesKey.length != 16) {
+            System.out.print("Key闀垮害涓嶆槸16浣�");
+            return null;
+        }
+
+        try {
+            SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"绠楁硶/妯″紡/琛ョ爜鏂瑰紡"
+            IvParameterSpec iv = new IvParameterSpec(aesKey);//浣跨敤CBC妯″紡锛岄渶瑕佷竴涓悜閲廼v锛屽彲澧炲姞鍔犲瘑绠楁硶鐨勫己搴�
+            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
+
+            //2018.1.1 0:0:0 浠ユ潵鐨勫皬鏃舵暟
+            int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
+
+            byte[] tobeencrypdatawithtime = new byte[tobeencrypdata.length + 4];
+            byte byte0 = (byte)(curhour & 0xFF);
+            tobeencrypdatawithtime[0] = byte0;
+
+            byte byte1 = (byte)((curhour & 0xFF00) >> 8);
+            tobeencrypdatawithtime[1] = byte1;
+
+            byte byte2 = (byte)((curhour & 0xFF0000) >> 16);
+            tobeencrypdatawithtime[2] = byte2;
+
+            byte byte3 = (byte)((curhour & 0xFF) >> 24);
+            tobeencrypdatawithtime[3] = byte3;
+
+            System.arraycopy(tobeencrypdata, 0, tobeencrypdatawithtime, 4, tobeencrypdata.length);
+
+
+            byte[] encrypted = cipher.doFinal(tobeencrypdatawithtime);
+            return encrypted;
+        } 
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+        
+        return null;
+    }
+    public static byte[] AESEncrypt(byte[] tobeencrypdata, String userKey) {
+        byte[] aesKey = aes_key;
+        if (userKey != null && !userKey.isEmpty()) {
+            aesKey = convertUserKey(userKey);
+        }
+        return AESEncrypt(tobeencrypdata, aesKey);
+    }
+
+    public static int getUnsignedByte (byte data){      //灏哾ata瀛楄妭鍨嬫暟鎹浆鎹负0~255 (0xFF 鍗矪YTE)銆�
+        return data&0x0FF ;
+    }
+
+    private static byte[] convertUserKey(String userKey) {
+        byte[] key = new byte[16];
+        for (int i = 0; i < 16; i++) {
+            key[i] = (byte) (userKey.charAt(i) & 0xFF);
+        }
+        return key;
+    }
+
+    public static byte[] AESDecrypt(byte[] sSrc, String userKey, boolean checkTime) {
+        try {
+
+            byte[] aesKey = aes_key;
+            if (userKey != null && !userKey.isEmpty()) {
+                aesKey = convertUserKey(userKey);
+            }
+            // 鍒ゆ柇Key鏄惁姝g‘
+            if (aesKey == null) {
+                System.out.print("Key涓虹┖null");
+                return null;
+            }
+            // 鍒ゆ柇Key鏄惁涓�16浣�
+            if (aesKey.length != 16) {
+                System.out.print("Key闀垮害涓嶆槸16浣�");
+                return null;
+            }
+
+            SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+            IvParameterSpec iv = new IvParameterSpec(aesKey);
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+            try {
+                byte[] original = cipher.doFinal(sSrc);
+                int hours = 0;
+
+                if (original.length > 4) {
+                    hours += getUnsignedByte(original[3]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[2]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[1]);
+                    hours <<= 8;
+
+                    hours += getUnsignedByte(original[0]);
+
+                    //2018.1.1 0:0:0 浠ユ潵鐨勫皬鏃舵暟
+                    int curhour = (int) ((System.currentTimeMillis()/1000 - 1514736000)/3600);
+
+                    if (curhour - hours > 24 && checkTime) {
+                        return null;
+                    }
+                    byte[] neworiginal = new byte[original.length - 4];
+                    System.arraycopy(original, 4, neworiginal, 0, neworiginal.length);
+                    return neworiginal;
+                }
+                
+                return null;
+            } 
+            catch (Exception e) {
+                System.out.println(e.toString());
+                return null;
+            }
+        } 
+        catch (Exception ex) {
+            System.out.println(ex.toString());
+            return null;
+        }
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/AppDispatcher.java b/IMserver/medeasy/src/chat/server/AppDispatcher.java
new file mode 100644
index 0000000..c2d9094
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/AppDispatcher.java
@@ -0,0 +1,166 @@
+package chat.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import chat.server.call.JSONObject;
+
+
+public class AppDispatcher implements Filter {
+
+	private static Logger logger;
+	private static AppDispatcher instance;
+	
+	private static String contextPath;
+	private static int contextLength;
+	private static Set<String> resourceSet;
+
+	
+	static {
+		logger = Logger.getLogger(AppDispatcher.class);
+	}
+
+	public AppDispatcher() {
+		instance = this;
+		initResourceList(); 
+	}
+
+	public synchronized static AppDispatcher getInstance() {
+		if (instance == null) {
+			instance = new AppDispatcher();
+		}
+
+		return instance;
+	}
+
+	public void init(FilterConfig filterConfig) throws ServletException {
+		ServletContext servletContext = filterConfig.getServletContext();
+
+		contextPath = servletContext.getContextPath();
+		contextLength = contextPath.length();
+	}
+
+	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
+		HttpServletRequest request = (HttpServletRequest) req;
+		HttpServletResponse response = (HttpServletResponse) res;
+		
+		request.setCharacterEncoding("utf-8");
+
+		try {
+			String uri = request.getRequestURI();
+			
+			logger.debug("filter request URI:" + uri); 
+			
+			uri = uri.substring(contextLength);
+			
+			int pos_root = uri.lastIndexOf("/root/");
+			uri = pos_root >= 0 ? uri.substring(pos_root + 5) : uri;
+			
+			try {
+				uri = URLDecoder.decode(uri, "UTF-8");
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			
+			//1.
+			String suffix = getSuffix(uri);
+			
+			if (resourceSet.contains(suffix)) {
+				RequestDispatcher dispatcher = request.getRequestDispatcher(uri);
+				dispatcher.forward(request, response);
+				return;
+			}
+			
+			//2.
+//			RequestParams dataPool = new RequestParams(request);
+//			HttpResultPool resultPool = new HttpResultPool(response);
+			
+//			console.receive(uri, dataPool, resultPool);
+//			writeResultPool(response, resultPool);
+			return;
+		}
+		catch (Exception e) {
+			String error = printStackToString(e);
+			logger.error("dispatch error:" + e.getMessage());
+			logger.error(error);
+			writeError(request, response, error);
+		}
+	}
+	
+	private void writeError(HttpServletRequest request, HttpServletResponse response, String error) throws IOException {
+		PrintWriter writer = response.getWriter();
+		
+		JSONObject json = new JSONObject();
+		json.beginObject();
+		json.addValue("success", false);
+		json.addValue("errorcode", "ServerError");
+		json.addValue("errorMessage", encode(error));
+		json.endObject();
+		writer.print(json.toString());
+			
+		writer.flush();	
+	}
+
+	public void destroy() {
+
+	}
+
+	private String printStackToString(Exception e) {
+		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+		PrintStream printStream = new PrintStream(outStream);
+		e.printStackTrace(printStream);
+
+		return outStream.toString();
+	}
+	
+	private String encode(String value) throws UnsupportedEncodingException {
+		return URLEncoder.encode(value, "UTF-8");
+	}
+	
+	private void initResourceList() {
+		resourceSet = new HashSet<String>();
+		resourceSet.add(".html");
+		resourceSet.add(".css");
+		resourceSet.add(".js");
+		resourceSet.add(".png");
+		resourceSet.add(".jpg");
+		resourceSet.add(".bmp");
+		resourceSet.add(".icon");
+	}
+	
+	private String getSuffix(String uri) {
+		String result = null;
+		
+		int pos = uri.lastIndexOf(".");
+		
+		if (pos <= 0) {
+			return result;
+		}
+		
+		result = uri.substring(pos);
+		result = result.toLowerCase();
+		
+		return result;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/Configer.java b/IMserver/medeasy/src/chat/server/Configer.java
new file mode 100644
index 0000000..8da2742
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/Configer.java
@@ -0,0 +1,201 @@
+package chat.server;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import frame.variant.translator.Translator;
+
+public class Configer {
+
+	private static Configer instance;
+	private static Object lock = new Object();
+	
+	private Map<String, String> params;
+	private String Path_Application;
+	private String Path_WebInfo;
+	private String Path_Config;
+	private String Path_SQL;
+
+	private Configer() {
+		params = new HashMap<String, String>();
+	}
+	
+	public static Configer getInstance() {
+		if (instance == null) {
+			synchronized (lock) {
+				if (instance == null) {
+					instance = new Configer();
+				}
+			}
+		}
+		
+		return instance;
+	}
+	
+	public static void init(ServletContext servletContext) {
+		try {
+			getInstance();
+			
+			instance.params = new HashMap<String, String>();
+
+			instance.Path_Application = servletContext.getRealPath("").replace("\\", "/");
+			instance.Path_WebInfo = servletContext.getRealPath("/WEB-INF").replace("\\", "/");
+			instance.Path_Config = instance.Path_WebInfo + "/config/";
+			instance.Path_SQL = instance.Path_WebInfo + "/sql/";
+			
+			instance.load();
+		}
+		catch(Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void load() throws Exception {
+		File file = new File(Path_Config + "/wildfirechat.conf");
+		
+		Reader reader = new FileReader(file);
+        BufferedReader br = new BufferedReader(reader);
+        
+        try {
+        	String line;
+        	
+            while ((line = br.readLine()) != null) {
+            	line = line.trim();
+                
+                if (line.startsWith("#")) {
+                	continue;
+                }
+
+                loadOneLine(line);
+            }
+        } 
+        finally {
+        	reader.close();
+        }
+	}
+
+	private void loadOneLine(String line) {
+		if (line == null) {
+			return;
+		}
+		
+		line = line.trim();
+		
+        int delimiterIdx = line.indexOf(' ');
+        
+        if (delimiterIdx <= 0) {
+        	return;
+        }
+        
+        String key = line.substring(0, delimiterIdx).trim();
+        String value = line.substring(delimiterIdx).trim();
+        
+        params.put(key, value);
+	}
+
+	public static String getPath_WebInfo() {
+		return instance.Path_WebInfo;
+	}
+
+	public static String getPath_Config() {
+		return instance.Path_Config;
+	}
+
+	public static String getPath_TimerConfig() {
+		return instance.Path_Config + "timer.properties";
+	}
+
+	public static String getWebserviceURI() {
+		return "http://www.jydatas.com/";
+	}
+
+	public static String getPath_Application() {
+		return instance.Path_Application;
+	}
+	
+	public static String getPath_Application(String subpath) {
+		if (subpath == null) {
+			return instance.Path_Application;
+		}
+		
+		subpath = subpath.replace("\\", "/");
+		
+		if ('/' != subpath.charAt(0)) {
+			subpath = "/" + subpath;
+		}
+		
+		if ('/' != subpath.charAt(subpath.length() - 1)) {
+			subpath = subpath + "/";
+		}
+		
+		return instance.Path_Application + subpath;
+	}
+
+	public static String getPath_LoggerConfig() {
+		return instance.Path_Config + "log4j.properties";
+	}
+
+	public static String getPath_SQLConfig() {
+		return instance.Path_SQL;
+	}
+
+	public static String getPath_SQLDTD() {
+		return instance.Path_Config + "sql.dtd";
+	}
+
+	public static String getPath_MainConfig() {
+		return instance.Path_Config + "config.xml";
+	}
+
+	public static String getPath_Datasource() {
+		return instance.Path_Config + "datasource.xml";
+	}
+
+	public static String getPath_Upload(String username) {
+		return instance.Path_Application + "/upload/" + username;
+	}
+
+	public static String getPath_Temp() {
+		return instance.Path_Application + "/temp";
+	}
+	
+	public static String getPath_Temp(String username) {
+		return instance.Path_Application + "/temp/" + username;
+	}
+
+	public static String getPath_Template() {
+		return instance.Path_Application + "/template";
+	}
+
+	public static String getPath_WXConfig() {
+		return instance.Path_Config + "weixin.properties";
+	}
+
+	public static Integer getInteger(String name, Integer defaultValue) {
+		String value = getString(name);
+		return Translator.toInteger(value, defaultValue);
+	}
+
+	public static boolean getBoolean(String name, boolean defaultValue) {
+		String value = getString(name);
+		return Translator.toBoolean(value, defaultValue);
+	}
+
+	public static String getString(String name) {
+		if (name == null) {
+			return null;
+		}
+		
+		name = name.toLowerCase();
+		String result = instance.params.get(name);
+		
+		return result;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/ConfigerLoader.java b/IMserver/medeasy/src/chat/server/ConfigerLoader.java
new file mode 100644
index 0000000..d5efeb0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ConfigerLoader.java
@@ -0,0 +1,86 @@
+package chat.server;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+
+public class ConfigerLoader {
+
+	protected static Logger logger;
+	private static ConfigerLoader instance;
+	private Properties properties;
+
+	static {
+		logger = Logger.getLogger(ConfigerLoader.class);
+	}
+
+	private ConfigerLoader() {
+		properties = new Properties();
+	}
+
+	public synchronized static ConfigerLoader getInstance() {
+		if (instance == null) {
+			instance = new ConfigerLoader();
+		}
+
+		return instance;
+	}
+	
+	public static void staticLoad() throws Exception {
+		getInstance();
+		instance.load();
+	}
+
+	public void load() throws Exception {
+		String path = Configer.getPath_MainConfig();
+		File file = new File(path);
+
+		loadOneFile(file);
+	}
+
+	private void loadOneFile(File file) throws Exception {
+		try {
+			logger.debug("load config file:" + file);
+			
+	        BufferedReader reader = new BufferedReader(new FileReader(file));
+	        try {
+		        String line;
+		        
+		        while ((line = reader.readLine()) != null) {
+		        	if (line.startsWith("#")) {
+		        		continue;
+		        	}
+		        	
+	                if (line.isEmpty() || line.matches("^\\s*$")) {
+	                    continue;
+	                }
+	                
+	                int delimiterIdx = line.indexOf(' ');
+	                String key; String value = "";
+	                
+	                if (delimiterIdx > 0) {
+	                    key = line.substring(0, delimiterIdx).trim();
+	                    value = line.substring(delimiterIdx).trim();
+	                } else {
+	                    key = line.trim();
+	                }
+
+	                properties.put(key, value);
+		        }        	
+	        }
+	        finally {
+	        	reader.close();
+	        }
+		} 
+		catch (Exception e) {
+			logger.error("can not load dispatch file: " + file);
+			logger.error(e);
+			throw e;
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/IMserver/medeasy/src/chat/server/Container.java b/IMserver/medeasy/src/chat/server/Container.java
new file mode 100644
index 0000000..82734a5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/Container.java
@@ -0,0 +1,116 @@
+package chat.server;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import frame.util.Util;
+
+public class Container<T> implements Iterable<T> {
+
+	protected static Logger logger;
+	protected String name;
+	private List<String> dependentContainer;
+	protected Map<String, T> items; 
+	protected Map<String, Class<T>> classes;
+	protected boolean dirty;
+	
+	static {
+		logger = Logger.getLogger("Collector");
+	}
+
+	public Container(){
+		name = this.getClass().getSimpleName();
+		
+		dependentContainer = new ArrayList<String>();
+		items = new HashMap<String, T>();
+		classes = new HashMap<String, Class<T>>();
+	}
+	
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public void add(String name, T item) {
+		if (name != null) {
+			items.put(name.toLowerCase(), item);
+		}
+	}
+
+	public T get(String name) {
+		if (name != null) {
+			return items.get(name.toLowerCase());
+		}
+		else {
+			return null;
+		}
+	}
+
+	public List<T> getItemList(){
+		List<T> result = new LinkedList<T>();
+		
+		Set<String> keys = items.keySet();
+		for (String key : keys){
+			result.add(items.get(key));
+		}
+		
+		return result;
+	}
+
+	public void addItemClass (String name, Class<T> clazz) {
+		classes.put(name, clazz);
+	}
+
+	public Iterator<T> iterator() {
+		return new ContainerIterator<T>(this);
+	}
+
+	public void afterLoad() {
+		
+	}
+
+	public boolean contains(String name) {
+		if (name != null) {
+			return items.containsKey(name.toLowerCase());
+		}
+		else {
+			return false;
+		}
+	}
+	
+	public List<String> getDependentContainer() {
+		return dependentContainer;
+	}
+
+	public Map<String, T> getItemMap() {
+		return items;
+	}
+	
+	public void addDependentContainer(String value) {
+		if (!Util.isEmptyStr(value)) {
+			dependentContainer.add(value);			
+		}
+	}
+
+	public boolean isDirty() {
+		return dirty;
+	}
+
+	public void setDirty(boolean dirty) {
+		this.dirty = dirty;
+	}
+	
+	public void clear() {
+		items.clear();
+	}
+}
diff --git a/IMserver/medeasy/src/chat/server/ContainerIterator.java b/IMserver/medeasy/src/chat/server/ContainerIterator.java
new file mode 100644
index 0000000..fd42fd5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ContainerIterator.java
@@ -0,0 +1,40 @@
+package chat.server;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class ContainerIterator<T> implements Iterator<T> {
+
+	private List<String> names;
+	private Container<T> parent;
+	private int pos;
+
+	public ContainerIterator(Container<T> parent) {
+		this.parent = parent;
+		pos = 0;
+		
+		Set<String> keys = parent.items.keySet();
+		names = new ArrayList<String>(keys.size());
+		for (String name: keys) {
+			names.add(name);
+		}
+	}
+	
+	public boolean hasNext() {
+		return pos < names.size();
+	}
+
+	public T next() {
+		if (pos < names.size()) {
+			return parent.items.get(names.get(pos++));
+		}
+		else return null;
+	}
+
+	public void remove() {
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/ContextListener.java b/IMserver/medeasy/src/chat/server/ContextListener.java
new file mode 100644
index 0000000..42a16ac
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ContextListener.java
@@ -0,0 +1,28 @@
+package chat.server;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.log4j.PropertyConfigurator;
+
+public class ContextListener implements ServletContextListener {
+
+	public ContextListener() {      
+
+	}
+
+	public void contextInitialized(ServletContextEvent event) {
+		ServletContext servletContext = event.getServletContext();
+		
+		Configer.init(servletContext);
+		PropertyConfigurator.configure(Configer.getPath_LoggerConfig());
+		
+		ServerInstance.startService(servletContext);
+	}
+
+	public void contextDestroyed(ServletContextEvent arg0) {
+		ServerInstance.stopService();
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/DTDResolver.java b/IMserver/medeasy/src/chat/server/DTDResolver.java
new file mode 100644
index 0000000..7a65ea0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/DTDResolver.java
@@ -0,0 +1,30 @@
+package chat.server;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class DTDResolver implements EntityResolver{
+
+	private InputSource inputSource;
+	
+	public DTDResolver(String path, String systemId) throws FileNotFoundException {
+		InputStream iStream = new FileInputStream(new File(path, systemId));
+		
+		if (iStream != null) {
+			inputSource = new InputSource(iStream);
+		}
+	}
+	
+	@Override
+	public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+		return inputSource;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/ILoader.java b/IMserver/medeasy/src/chat/server/ILoader.java
new file mode 100644
index 0000000..c1a37a2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ILoader.java
@@ -0,0 +1,11 @@
+package chat.server;
+
+public interface ILoader {
+
+	void setName(String name);
+	
+	String getName();
+	
+	void load() throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/Loader.java b/IMserver/medeasy/src/chat/server/Loader.java
new file mode 100644
index 0000000..d5aeb49
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/Loader.java
@@ -0,0 +1,48 @@
+package chat.server;
+
+import org.apache.log4j.Logger;
+
+
+public abstract class Loader implements ILoader {
+
+	protected static Logger logger;
+	protected String name;
+	protected boolean active;
+	protected String path;
+	
+	static {
+		logger = Logger.getLogger(Loader.class);		
+	}
+	
+	public Loader() {
+		
+	}
+
+	public abstract void load() throws Exception;
+	
+	public String getName() {
+		return name;
+	}
+
+	public boolean isActive() {
+		return active;
+	}
+
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getPath() {
+		return path;
+	}
+	
+	@Override
+	public String toString() {
+		return "[" + name + "]: " + path;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/ServerInstance.java b/IMserver/medeasy/src/chat/server/ServerInstance.java
new file mode 100644
index 0000000..85040b2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ServerInstance.java
@@ -0,0 +1,145 @@
+package chat.server;
+
+import javax.servlet.ServletContext;
+
+import org.apache.log4j.Logger;
+
+import chat.module.ModuleLoader;
+import chat.server.netty.NettyAcceptor;
+import frame.persist.DatasuorceLoader;
+import frame.persist.NamedSQLLoader;
+import io.netty.util.ResourceLeakDetector;
+
+
+public class ServerInstance {
+
+	private static Logger logger;
+	private static ServerInstance instance;
+	private String version;
+	public static ServerState state;
+
+	static {
+		logger = Logger.getLogger(ServerInstance.class);
+	}
+	
+	public ServerInstance(ServletContext servletContext) {
+		version = "1.0.0.1";
+	}
+
+	public static void startService(ServletContext servletContext) {
+		try {
+			instance = new ServerInstance(servletContext);
+			instance.start();
+		} 
+		catch (Exception e) {
+			logger.error(e);
+			e.printStackTrace();
+		}
+	}
+
+	public static void stopService() {
+		try {
+			if(instance != null) {
+				instance.stop();
+			}
+			
+		} catch (Exception e) {
+			logger.error(e);
+			e.printStackTrace();
+		}
+	}
+
+	public void start() throws Exception {
+		try {
+			state = ServerState.Starting;
+			
+			//1. write info
+			logger.info("server is startting...");
+			logger.info("server root path is " + Configer.getPath_Application());
+			
+			//2. resource leak
+			ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
+			
+			//3. data source and SQL
+			DatasuorceLoader.staticLoad();
+			NamedSQLLoader.staticLoad();
+			
+			//4. schedule 
+			// dbScheduler銆乮mBusinessScheduler銆乧allbackScheduler
+			
+			//5.
+			ModuleLoader.load();
+			
+			//6銆� start listener list
+			NettyAcceptor.start();
+			
+			state = ServerState.Start;
+		} 
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+		finally {
+			printStartUpMessage();
+		}
+	}
+
+	public void stop() {
+		logger.info("internal server is stopping...");
+
+		NettyAcceptor.stop();
+		
+		logger.info("internal server has been stopped");
+	}
+
+	public void restart() throws Exception {
+		stop();
+		start();
+	}
+
+	private static String echoString(String word, int count) {
+		StringBuilder result = new StringBuilder();
+
+		for (int i = 1; i <= count; i++) {
+			result.append(word);
+		}
+
+		return result.toString();
+	}
+
+	private void printStartUpMessage() {
+		int length_total = 40;
+
+		long total = Math.round((Runtime.getRuntime().totalMemory()) / (1024.0 * 1024));
+		long max = Math.round((Runtime.getRuntime().maxMemory()) / (1024.0 * 1024));
+
+		String envirenment = Configer.getString("EnvironmentName");
+		System.out.println("--->>> " + envirenment + " --->>>");
+
+		System.out.println(echoString("*", length_total + 2));
+		printMessage("Total Memory:" + total + "M", length_total);
+		printMessage("Max Memory:" + max + "M", length_total);
+		printMessage(version, length_total);
+		System.out.println(echoString("*", length_total + 2));
+	}
+
+	private void printMessage(String message, int totalLength) {
+		MessagePos messagePos = new MessagePos(totalLength, message);
+		System.out.println("*" + echoString(" ", messagePos.length_begin) + message + echoString(" ", messagePos.length_end) + "*");
+	}
+
+	private class MessagePos {
+		private int length_begin;
+		private int length_end;
+		private int length_message;
+
+		public MessagePos(int totalLength, String message) {
+			length_message = message.length();
+			length_begin = (totalLength - length_message) / 2;
+			length_end = totalLength - length_begin - length_message;
+		}
+	}
+	
+	public static boolean isStart() {
+		return ServerState.Start == state;
+	}
+}
diff --git a/IMserver/medeasy/src/chat/server/ServerState.java b/IMserver/medeasy/src/chat/server/ServerState.java
new file mode 100644
index 0000000..8d6860e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/ServerState.java
@@ -0,0 +1,7 @@
+package chat.server;
+
+public enum ServerState {
+
+	Starting, Start, Termiting, Termited;
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/Test.java b/IMserver/medeasy/src/chat/server/Test.java
new file mode 100644
index 0000000..179bf4a
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/Test.java
@@ -0,0 +1,23 @@
+package chat.server;
+
+import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
+
+import java.io.UnsupportedEncodingException;
+
+import cn.wildfirechat.common.ErrorCode;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+
+public class Test {
+
+	public static void main(String[] args) throws UnsupportedEncodingException {
+        ByteBuf ackPayload = Unpooled.buffer(1);
+        ErrorCode errorCode = ERROR_CODE_SUCCESS;
+        ackPayload.ensureWritable(1).writeByte(errorCode.getCode());
+        ackPayload.setByte(0, errorCode.getCode());
+        
+        byte[] bytes = ackPayload.array();
+        String value = new String(bytes, "UTF-8");
+        System.out.println(value);
+	}
+}
diff --git a/IMserver/medeasy/src/chat/server/call/CachedJSONWriter.java b/IMserver/medeasy/src/chat/server/call/CachedJSONWriter.java
new file mode 100644
index 0000000..2351f7e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/CachedJSONWriter.java
@@ -0,0 +1,269 @@
+package chat.server.call;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import chat.server.im.ResultPool;
+import frame.object.dao.Page;
+import frame.object.data.Entity;
+import frame.object.data.EntitySet;
+import frame.object.data.EntityTree;
+import frame.object.reader.EntityReaderContainer;
+import frame.object.reader.IEntityReader;
+import frame.object.reader.NameValuePair;
+
+
+public class CachedJSONWriter {
+
+	public final static String Code_URL = "url";
+
+	protected static Logger logger;
+	protected static EntityReaderContainer objectReaderContainer;
+	protected StringBuilderJSONWriter writer; // 鍝嶅簲瀛楃娴�
+
+	static {
+		logger = Logger.getLogger(CachedJSONWriter.class);
+		objectReaderContainer = EntityReaderContainer.getInstance();
+	}
+
+	public CachedJSONWriter() {
+		writer = new StringBuilderJSONWriter();
+	}
+
+	public String create(ResultPool result) throws Exception {
+		writer.beginObject();
+		try {
+			//1. code
+			ResultCode code = result.getCode();
+			writer.write("code", code.getValue());
+			writer.write("message", code.getMsg());
+
+			//2. result
+			List<ResultItem> itemList = result.getItemList();
+			writeResultItems(itemList);
+		}
+		finally {
+			writer.endObject();
+		}
+		
+		return writer.toString();
+	}
+
+	private void writeResultItems(List<ResultItem> itemList) throws Exception {
+		for (ResultItem item: itemList) {
+			String name = item.getName();
+			
+			if (name == null) {
+				name = createValueName(item.getValue());
+				item.setName(name);
+			}
+		}
+		
+		for (ResultItem item: itemList) {
+			String name = item.getName(); 
+			Object value = item.getValue();
+			
+			if (name == null) {
+				continue;
+			}
+			
+			writeData(name, value);
+		}		
+	}
+
+	private String createValueName(Object value) {
+		if (value instanceof Entity) {
+			return IEnvelop.ResultCode_Entity;
+		}
+		else if (value instanceof EntityTree) {
+			return IEnvelop.ResultCode_EntityTree;
+		}
+		else if (value instanceof EntitySet) {
+			return IEnvelop.ResultCode_EntitySet;
+		}
+		else if (value instanceof Page) {
+			return IEnvelop.ResultCode_Page;
+		}
+		else if (value instanceof Collection) {
+			return IEnvelop.ResultCode_EntitySet;
+		}
+		else {
+			return "data";
+		}
+	}
+	
+	private void writeData(String name, Object value) throws Exception {
+		if (value == null) {
+			writer.writeNull(name);
+			return;
+		}
+		
+		//1. entity銆乪ntitySet銆乪ntityTree銆乸age ...
+		if (value instanceof IJsonProvider) {
+			writeJsonProvider(name, (IJsonProvider) value);
+		}
+		//2. collection
+		else if (value instanceof Collection) {
+			writeCollection(name, (Collection<?>) value);
+		}
+		//3. iterator
+		else if (value instanceof Iterable<?>) {
+			writeIterable(name, (Iterable<?>) value);
+		}	
+		//4. map
+		else if (value instanceof Map<?, ?>) {
+			writeMap(name, (Map<?, ?>)value);
+		}
+		//5. string銆乮nteger銆乨ouble銆乨ecimal銆乥oolean銆乨ate銆乷bject ...
+		else {
+			writeObject(name, value);
+		}
+	}
+
+	private void writeMap(String name, Map<?, ?> value) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (value == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginObject();
+		Set<?> keySet = value.keySet();
+		for (Object key : keySet) {
+			Object obj = value.get(key);
+			
+			writeData(key.toString(), obj);
+		}
+
+		writer.endObject();
+		
+	}
+
+	private void writeJsonProvider(String name, IJsonProvider jsonProvider) {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null entity 
+		if (jsonProvider == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. entity data
+		jsonProvider.writeJSONObject(writer);
+	}
+	
+	private void writeCollection(String name, Collection<?> collection) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (collection == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginArray();
+		
+		for (Object obj : collection) {
+			writeData(null, obj);
+		}
+
+		writer.endArray();
+	}
+
+	private void writeIterable(String name, Iterable<?> iterable) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (iterable == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginArray();
+		
+		Iterator<?> iterator = iterable.iterator();
+		
+		while(iterator.hasNext()) {
+			Object obj = iterator.next();
+			writeData(null, obj);
+		}
+
+		writer.endArray();		
+	}
+
+	private void writeObject(String name, Object value) throws Exception {
+		//1. null data 
+		if (value == null) {
+			writer.writeNull(name);
+			return;
+		}
+		
+		if (value instanceof String) {
+			writer.write(name, (String) value);
+		}
+		else if (value instanceof Integer) {
+			writer.write(name, (Integer) value);
+		}
+		else if (value instanceof Double) {
+			writer.write(name, (Double) value);
+		}		
+		else if (value instanceof BigDecimal) {
+			writer.write(name, (BigDecimal) value);
+		}
+		else if (value instanceof Date) {
+			writer.write(name, (Date) value);
+		}
+		else if (value instanceof Boolean) {
+			writer.write(name, (Boolean) value);
+		}
+		else if (value instanceof Enum) {
+			writer.write(name, value.toString());
+		}
+		else if (value instanceof IJsonProvider) {
+			writer.writeName(name);
+			IJsonProvider jsonAvailable = (IJsonProvider) value;
+			jsonAvailable.writeJSONObject(writer);
+		}
+		else {
+			IEntityReader entityReader = objectReaderContainer.getEntityReader(value.getClass());
+			
+			if (value instanceof String[]) {
+				 System.out.println(value);
+			}
+			List<NameValuePair> values = entityReader.getValueList(value);
+			
+			writer.beginObject(name);
+			
+			for (NameValuePair nameValuePair: values) {
+				 writeData(nameValuePair.getName(), nameValuePair.getValue());
+			}
+			
+			writer.endObject();
+		}
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/CallObject.java b/IMserver/medeasy/src/chat/server/call/CallObject.java
new file mode 100644
index 0000000..4cc6571
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/CallObject.java
@@ -0,0 +1,71 @@
+package chat.server.call;
+
+import java.lang.reflect.Method;
+
+import org.apache.log4j.Logger;
+
+import chat.server.im.DataPool;
+import chat.server.im.ResultPool;
+import chat.user.Session;
+import chat.user.User;
+
+
+public abstract class CallObject extends MethodPublisher {
+
+	protected static Logger logger;
+	protected Session session;
+	protected User user;
+	protected DataPool dataPool;
+	protected ResultPool resultPool;
+	
+	static {
+		logger = Logger.getLogger(CallObject.class);
+	}
+	
+	public CallObject() {
+
+	}
+	
+	public void exec(Session session, Operator operator, DataPool dataPool, ResultPool resultPool) {
+		try {
+			Method method = getOneMethod(operator.getMethod());
+			
+			if (method == null) {
+				method = methodMap.get("call");
+			}
+			
+			if (method != null) {
+				this.session = session;
+				
+				if (session != null) {
+					this.user = session.getUser();
+				}
+				
+				this.dataPool = dataPool;
+				this.resultPool = resultPool;
+				
+				try {
+					method.invoke(this);
+				}
+				catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+			else {
+				resultPool.error(ResultCode.Error_Path_NotExists);
+			}
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	protected void onError(Exception e) throws Exception {
+		logger.error(e);
+		
+		if (logger.isTraceEnabled()) {
+			e.printStackTrace();
+		}
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/CallObjectMap.java b/IMserver/medeasy/src/chat/server/call/CallObjectMap.java
new file mode 100644
index 0000000..321ece3
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/CallObjectMap.java
@@ -0,0 +1,66 @@
+package chat.server.call;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import chat.handler.ChannelHandler;
+import chat.handler.ChatRoomHandler;
+import chat.handler.ClientHandler;
+import chat.handler.GroupHandler;
+import chat.handler.FriendshipHandler;
+import chat.handler.MessageHandler;
+import chat.handler.RobotHandler;
+import chat.handler.SensitiveHandler;
+import chat.handler.SystemHandler;
+import chat.handler.FriendCircleHandler;
+
+
+public class CallObjectMap {
+	
+	private static Map<String, Class<? extends CallObject>> objectMap;
+	
+	static {
+		init();
+	}
+
+	public static CallObject get(Operator operator) {
+		try {
+			String key = operator.getObject();
+			key = key.toLowerCase();
+			
+			Class<? extends CallObject> clazz = objectMap.get(key);
+			
+			if (clazz == null) {
+				return null;
+			}
+			
+			CallObject object = clazz.newInstance();
+			return object;
+		}
+		catch (Exception e) {
+			return null;
+		}
+	}
+
+	private static void init() {
+		//1.
+		objectMap = new HashMap<String, Class<? extends CallObject>>();
+		
+		addOneCallObject("client", ClientHandler.class);
+		addOneCallObject("chatroom", ChatRoomHandler.class);
+		addOneCallObject("sensitive", SensitiveHandler.class);
+		addOneCallObject("friend", FriendshipHandler.class);	
+		addOneCallObject("message", MessageHandler.class);
+		addOneCallObject("group", GroupHandler.class);
+		addOneCallObject("channel", ChannelHandler.class);
+		addOneCallObject("robot", RobotHandler.class);	
+		addOneCallObject("system", SystemHandler.class);
+		addOneCallObject("friendcircle", FriendCircleHandler.class);
+	}
+
+	private static void addOneCallObject(String key, Class<? extends CallObject> clazz) {
+		key = key.toLowerCase();
+		objectMap.put(key, clazz);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/HttpEnvelopWriter.java b/IMserver/medeasy/src/chat/server/call/HttpEnvelopWriter.java
new file mode 100644
index 0000000..38a8ec7
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/HttpEnvelopWriter.java
@@ -0,0 +1,292 @@
+package chat.server.call;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import chat.server.im.ResultPool;
+import frame.object.dao.Page;
+import frame.object.data.Entity;
+import frame.object.data.EntitySet;
+import frame.object.data.EntityTree;
+import frame.object.reader.EntityReaderContainer;
+import frame.object.reader.IEntityReader;
+import frame.object.reader.NameValuePair;
+
+public class HttpEnvelopWriter {
+
+	public final static String Code_URL = "url";
+
+	protected static Logger logger;
+	protected static HttpEnvelopWriter instance;
+	protected static EntityReaderContainer objectReaderContainer;
+
+	static {
+		logger = Logger.getLogger(HttpEnvelopWriter.class);
+		objectReaderContainer = EntityReaderContainer.getInstance();
+	}
+
+	public static synchronized HttpEnvelopWriter getInstance() {
+		if (instance == null) {
+			instance = new HttpEnvelopWriter();
+		}
+		
+		return instance;
+	}
+
+	private HttpEnvelopWriter() {
+		
+	}
+
+	public StringBuilder writeToString(ResultPool result) {
+		StringBuilderJSONWriter writer = new StringBuilderJSONWriter();
+		
+		writer.beginObject();
+		try {
+			if (result.isNeedReturnCode()) {
+				//1. code
+				ResultCode code = result.getCode();
+				writer.write("code", code.getValue());
+				writer.write("message", code.getMsg());
+
+				//2. result
+				writer.beginObject(result.getRootName());				
+			}
+			
+			List<ResultItem> itemList = result.getItemList();
+			writeResultItems(writer, itemList);
+			
+			writer.endObject();
+		}
+		catch (Exception e) {
+		}
+		finally {
+			if (result.isNeedReturnCode()) {
+				writer.endObject();
+			}
+		}
+		
+		return writer.getContent();
+	}
+	
+	private void writeResultItems(IJSONWriter writer, List<ResultItem> itemList) throws Exception {
+		for (ResultItem item: itemList) {
+			String name = item.getName();
+			
+			if (name == null) {
+				name = createValueName(item.getValue());
+				item.setName(name);
+			}
+		}
+		
+		for (ResultItem item: itemList) {
+			String name = item.getName(); 
+			Object value = item.getValue();
+			boolean needEncode = item.isNeedEncode();
+			
+			if (name == null) {
+				continue;
+			}
+			
+			writeData(writer, name, value, needEncode);
+		}		
+	}
+
+	private String createValueName(Object value) {
+		if (value instanceof Entity) {
+			return IEnvelop.ResultCode_Entity;
+		}
+		else if (value instanceof EntityTree) {
+			return IEnvelop.ResultCode_EntityTree;
+		}
+		else if (value instanceof EntitySet) {
+			return IEnvelop.ResultCode_EntitySet;
+		}
+		else if (value instanceof Page) {
+			return IEnvelop.ResultCode_Page;
+		}
+		else if (value instanceof Collection) {
+			return IEnvelop.ResultCode_EntitySet;
+		}
+		else {
+			return "data";
+		}
+	}
+	
+	private void writeData(IJSONWriter writer, String name, Object value, boolean needEncode) throws Exception {
+		if (value == null) {
+			writer.writeNull(name);
+			return;
+		}
+		
+		//1. entity銆乪ntitySet銆乪ntityTree銆乸age ...
+		if (value instanceof IJsonProvider) {
+			writeJsonProvider(writer, name, (IJsonProvider) value);
+		}
+		//2. collection
+		else if (value instanceof Collection) {
+			writeCollection(writer, name, (Collection<?>) value, needEncode);
+		}
+		//3. iterator
+		else if (value instanceof Iterable<?>) {
+			writeIterable(writer, name, (Iterable<?>) value, needEncode);
+		}	
+		//4. map
+		else if (value instanceof Map<?, ?>) {
+			writeMap(writer, name, (Map<?, ?>)value, needEncode);
+		}
+		//5. string銆乮nteger銆乨ouble銆乨ecimal銆乥oolean銆乨ate銆乷bject ...
+		else {
+			writeObject(writer, name, value, needEncode);
+		}
+	}
+
+	private void writeMap(IJSONWriter writer, String name, Map<?, ?> value, boolean needEncode) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (value == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginObject();
+		Set<?> keySet = value.keySet();
+		for (Object key : keySet) {
+			Object obj = value.get(key);
+			
+			writeData(writer, key.toString(), obj, needEncode);
+		}
+
+		writer.endObject();
+		
+	}
+
+	private void writeJsonProvider(IJSONWriter writer, String name, IJsonProvider jsonProvider) {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null entity 
+		if (jsonProvider == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. entity data
+		jsonProvider.writeJSONObject(writer);
+	}
+	
+	private void writeCollection(IJSONWriter writer, String name, Collection<?> collection, boolean needEncode) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (collection == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginArray();
+		
+		for (Object obj : collection) {
+			writeData(writer, null, obj, needEncode);
+		}
+
+		writer.endArray();
+	}
+
+	private void writeIterable(IJSONWriter writer, String name, Iterable<?> iterable, boolean needEncode) throws Exception {
+		//1. name
+		if (name != null) {
+			writer.writeName(name);
+		}
+		
+		//2. null data 
+		if (iterable == null) {
+			writer.writeNull();
+			return;
+		}
+		
+		//3. collection data
+		writer.beginArray();
+		
+		Iterator<?> iterator = iterable.iterator();
+		
+		while(iterator.hasNext()) {
+			Object obj = iterator.next();
+			writeData(writer, null, obj, needEncode);
+		}
+
+		writer.endArray();		
+	}
+
+	private void writeObject(IJSONWriter writer, String name, Object value, boolean needEncode) throws Exception {
+		//1. null data 
+		if (value == null) {
+			writer.writeNull(name);
+			return;
+		}
+		
+		if (value instanceof String) {
+			writer.write(name, (String) value, needEncode);
+		}
+		else if (value instanceof Integer) {
+			writer.write(name, (Integer) value);
+		}
+		else if (value instanceof Double) {
+			writer.write(name, (Double) value);
+		}		
+		else if (value instanceof BigDecimal) {
+			writer.write(name, (BigDecimal) value);
+		}
+		else if (value instanceof Date) {
+			writer.write(name, (Date) value);
+		}
+		else if (value instanceof Boolean) {
+			writer.write(name, (Boolean) value);
+		}
+		else if (value instanceof Enum) {
+			writer.write(name, value.toString(), false);
+		}
+		else if (value instanceof Long) {
+			writer.write(name, value.toString(), false);
+		}
+		else if (value instanceof IJsonProvider) {
+			writer.writeName(name);
+			IJsonProvider jsonAvailable = (IJsonProvider) value;
+			jsonAvailable.writeJSONObject(writer);
+		}
+		else {
+			IEntityReader entityReader = objectReaderContainer.getEntityReader(value.getClass());
+			
+			if (value instanceof String[]) {
+				 System.out.println(value);
+			}
+			List<NameValuePair> values = entityReader.getValueList(value);
+			
+			writer.beginObject(name);
+			
+			for (NameValuePair nameValuePair: values) {
+				 writeData(writer, nameValuePair.getName(), nameValuePair.getValue(), needEncode);
+			}
+			
+			writer.endObject();
+		}
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/IEnvelop.java b/IMserver/medeasy/src/chat/server/call/IEnvelop.java
new file mode 100644
index 0000000..6b42437
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/IEnvelop.java
@@ -0,0 +1,33 @@
+package chat.server.call;
+
+public interface IEnvelop {
+
+	public final static String ResultCode_Success = "success";
+	public final static String ResultCode_ErrorCode = "errorcode";
+	public final static String ResultCode_ErrorMessage = "errormessage";
+	public final static String ResultCode_Message = "message";
+	
+	public final static String ResultCode_Entity = "entity";
+	public final static String ResultCode_EntitySet = "entityset";
+	public final static String ResultCode_EntityTree = "entitytree";
+	public final static String ResultCode_DataMeta = "datapropertys";
+	public final static String ResultCode_TotalCount = "total";
+	public final static String ResultCode_BarCodeResult = "barcoderesult";	
+	
+	public final static String ResultCode_Page = "page";
+	public final static String ResultCode_Page_BeginRecordNo = "beginRecordNo";
+	public final static String ResultCode_Page_Size = "size";
+	public final static String ResultCode_Page_EndRecordNo = "endRecordNo";
+	public final static String ResultCode_Page_RecordCount = "recordCount";
+	public final static String ResultCode_Page_PageNo = "pageNo";
+	public final static String ResultCode_Page_PageCount = "pageCount";	
+	
+	public final static String ResultCode_MessageList = "messageList";
+	public final static String ResultCode_StepMessage = "stepMessage";
+	public final static String ResultCode_CurrentPhase = "currentPhase";
+	
+	public final static String Error_Code_Timeout = "timeout";
+	public final static String Error_Code_ServerError = "serverError";
+ 	public final static String Error_Messgae_Timeout = "session timeout";
+ 	public final static String Error_Messgae_ServerError = "server error";
+}
diff --git a/IMserver/medeasy/src/chat/server/call/IJSONWriter.java b/IMserver/medeasy/src/chat/server/call/IJSONWriter.java
new file mode 100644
index 0000000..aebf908
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/IJSONWriter.java
@@ -0,0 +1,65 @@
+package chat.server.call;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+public interface IJSONWriter {
+
+    void beginObject();
+
+    void beginObject(String name);
+
+	void endObject();
+	
+    void beginArray();
+
+    void beginArray(String name);
+
+    void endArray();
+
+    void write(String name, String value);
+    
+    void write(String name, String value, boolean needEncode);
+    
+    void write(String name, Integer value);
+    
+    void write(String name, Double value);
+    
+    void write(String name, Long value);
+
+    void write(String name, BigDecimal value);
+
+    void write(String name, boolean value);
+
+    void write(String name, Date value);
+
+	void write(String name, IJsonProvider jsonProvider);
+	
+	void write(String name, List<? extends IJsonProvider> list);	
+    
+	void writeJSON(String name, String json);
+    
+	void writeNull(String name);
+	
+	void write(IJsonProvider jsonProvider);
+
+    void writeName(String name);
+    
+    void writeValue(String value);
+    
+    void writeValue(int value);
+
+    void writeValue(BigDecimal value);
+
+    void writeValue(boolean value);
+
+    void writeValue(Date value);
+
+	void writeNull();
+	
+	void writeJSON(String json);
+	
+	String encode(String value);
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/IJsonProvider.java b/IMserver/medeasy/src/chat/server/call/IJsonProvider.java
new file mode 100644
index 0000000..c595696
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/IJsonProvider.java
@@ -0,0 +1,9 @@
+package chat.server.call;
+
+public interface IJsonProvider {
+
+	void writeJSONObject(IJSONWriter writer);
+	
+	void writeJSONData(IJSONWriter writer);
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/JSONObject.java b/IMserver/medeasy/src/chat/server/call/JSONObject.java
new file mode 100644
index 0000000..4d02cc7
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/JSONObject.java
@@ -0,0 +1,164 @@
+package chat.server.call;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+public class JSONObject {
+	
+    private StringBuilder content;
+    private boolean empty;
+
+    public JSONObject() {
+        content = new StringBuilder();
+        empty = true;
+    }
+
+    public void beginObject() {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("{");
+        empty = true;
+    }
+
+    public void beginObject(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": {");
+        empty = true;
+    }
+
+	public void endObject() {
+        content.append("}");
+        empty = false;
+    }
+
+    public void beginArray() {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("[");
+        empty = true;
+    }
+
+    public void beginArray(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": [");
+        empty = true;
+    }
+
+    public void endArray() {
+        content.append("]");
+        empty = false;
+    }
+
+    public void addValue(String name, String value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": \"" + value + "\"");
+        empty = false;
+    }
+    
+    public void addValue(String name, int value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + value);
+        empty = false;
+    }
+
+    public void addValue(String name, BigDecimal value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + value);
+        empty = false;
+    }
+
+    public void addValue(String name, boolean value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + (value ? "true" : "false"));
+        empty = false;
+    }
+
+    public void addValue(String name, Date value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": \"" + value + "\"");
+        empty = false;
+    }
+
+    public void addValue(String value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + value + "\"");
+        empty = false;
+    }
+    public void addValue(int value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append(value);
+        empty = false;
+    }
+
+    public void addValue(BigDecimal value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append(value);
+        empty = false;
+    }
+
+    public void addValue(boolean value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append(value ? "true" : "false");
+        empty = false;
+    }
+
+    public void addValue(Date value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + value + "\"");
+        empty = false;
+    }
+
+    private String toLower(String name) {
+    	if (name == null) {
+    		return "empty";
+    	}
+    	
+    	return name.toLowerCase();
+	}
+
+	@Override
+	public String toString() {
+		return content.toString();
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/call/MethodPublisher.java b/IMserver/medeasy/src/chat/server/call/MethodPublisher.java
new file mode 100644
index 0000000..851bcba
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/MethodPublisher.java
@@ -0,0 +1,70 @@
+package chat.server.call;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class MethodPublisher {
+
+	protected Map<String, Method> methodMap;
+	protected Map<String, Method> allMethodMap;
+	
+	public MethodPublisher() {
+		methodMap = new HashMap<String, Method>();
+		allMethodMap = new HashMap<String, Method>();
+
+		collectMethod();
+		publishMethod();
+	}
+	
+	public Method getMethod(String lower) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	protected void collectMethod() {
+		Method[] methods = this.getClass().getDeclaredMethods();
+
+		for (Method one : methods) {
+			allMethodMap.put(one.getName().toLowerCase(), one);
+		}
+	}
+
+	protected abstract void publishMethod();
+
+	protected void addOneMethod(String name) {
+		addOneMethod(name, name);
+	}
+	
+	protected void addOneMethod(String methodName, String key) {
+		if (key == null || methodName == null) {
+			return;
+		}
+
+		methodName = methodName.toLowerCase();
+		Method method = allMethodMap.get(methodName);
+
+		if (method != null) {
+			key = key.toLowerCase();
+			
+			method.setAccessible(true);
+			methodMap.put(key, method);
+		}
+	}
+	
+	protected Method getOneMethod(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		key = key.toLowerCase();
+		Method method = methodMap.get(key);
+		
+		return method;
+	}
+
+	public Map<String, Method> getMethodMap() {
+		return methodMap;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/call/MultiCounter.java b/IMserver/medeasy/src/chat/server/call/MultiCounter.java
new file mode 100644
index 0000000..25ed8c3
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/MultiCounter.java
@@ -0,0 +1,10 @@
+package chat.server.call;
+
+public class MultiCounter {
+
+	public static boolean isGranted(Operator operation) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/Operator.java b/IMserver/medeasy/src/chat/server/call/Operator.java
new file mode 100644
index 0000000..ef12d91
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/Operator.java
@@ -0,0 +1,57 @@
+package chat.server.call;
+
+import chat.server.im.OperateTable;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttPublishMessage;
+
+public class Operator {
+
+	private String path;
+	private String key;
+	private String object;
+	private String method;
+	private String topic;
+	
+	
+	public Operator(String path, String object, String method) {
+		this.path = path;
+		this.key = path.toLowerCase();
+		this.object = object;
+		this.method = method;
+		
+	}
+	
+	public Operator(MqttMessage message) {
+		// TODO Auto-generated constructor stub
+	}
+	
+	public static Operator getInstance(String uri, String topic) {
+		return OperateTable.get(uri, topic);
+	}
+	
+	public static Operator getInstance(MqttPublishMessage message) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public String getPath() {
+		return path;
+	}
+
+	public String getKey() {
+		return key;
+	}
+
+	public String getObject() {
+		return object;
+	}
+
+	public String getMethod() {
+		return method;
+	}
+
+	public String getTopic() {
+		return topic;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/call/ResultCode.java b/IMserver/medeasy/src/chat/server/call/ResultCode.java
new file mode 100644
index 0000000..499dc22
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/ResultCode.java
@@ -0,0 +1,41 @@
+package chat.server.call;
+
+public enum ResultCode {
+
+    Success(0, "success"),
+    Error_Invalid_Mobile(1, "鏃犳晥鐨勭數璇濆彿鐮�"),
+    Error_Send_SMS_Over_Frequency(3, "璇锋眰楠岃瘉鐮佸お棰戠箒"),
+    Error_Server_Error(4, "鏈嶅姟鍣ㄥ紓甯�"),
+    Error_Code_Expired(5, "楠岃瘉鐮佸凡杩囨湡"),
+    Error_Code_Incorrect(6, "楠岃瘉鐮侀敊璇�"),
+    Error_Server_Config_Error(7, "鏈嶅姟鍣ㄩ厤缃敊璇�"),
+    Error_Session_Expired(8, "浼氳瘽涓嶅瓨鍦ㄦ垨宸茶繃鏈�"),
+    Error_Session_Not_Verified(9, "浼氳瘽娌℃湁楠岃瘉"),
+    Error_Session_Not_Scaned(10, "浼氳瘽娌℃湁琚壂鐮�"),
+    Error_Server_Not_Implement(11, "鍔熻兘娌℃湁瀹炵幇"),
+    Error_Group_Announcement_Not_Exist(12, "缇ゅ叕鍛婁笉瀛樺湪"),
+    Error_Not_Login(13, "娌℃湁鐧诲綍"),
+    Error_Not_Right(14, "娌℃湁鏉冮檺"),
+    Error_Invalid_Parameter(15, "鏃犳晥鍙傛暟"),
+    Error_Not_Exist(16, "瀵硅薄涓嶅瓨鍦�"),
+    Error_User_Name_Already_Exist(17, "鐢ㄦ埛鍚嶅凡缁忓瓨鍦�"),
+    Error_Session_Canceled(18, "浼氳瘽宸茬粡鍙栨秷"),
+	Error_Path_NotExists(19, "璁块棶璺緞涓嶅瓨鍦�");
+
+    private int value;
+    private String msg;
+    
+    ResultCode(int code, String msg) {
+        this.value = code;
+        this.msg = msg;
+    }
+
+	public int getValue() {
+		return value;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/call/ResultItem.java b/IMserver/medeasy/src/chat/server/call/ResultItem.java
new file mode 100644
index 0000000..6f2949e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/ResultItem.java
@@ -0,0 +1,51 @@
+package chat.server.call;
+
+public class ResultItem {
+
+	private String name;
+	private Object value;
+	private IJsonProvider beanWriter;
+	private boolean needEncode;
+	
+	public ResultItem() {
+		needEncode = true;
+	}
+	
+	public ResultItem(String name, Object value) {
+		this.name = name;
+		this.value = value;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Object getValue() {
+		return value;
+	}
+
+	public void setValue(Object value) {
+		this.value = value;
+	}
+
+	public void setBeanWriter(IJsonProvider beanWriter) {
+		this.beanWriter = beanWriter;
+	}
+
+	public IJsonProvider getBeanWriter() {
+		return beanWriter;
+	}
+
+	public boolean isNeedEncode() {
+		return needEncode;
+	}
+
+	public void setNeedEncode(boolean needEncode) {
+		this.needEncode = needEncode;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/call/ResultOutputType.java b/IMserver/medeasy/src/chat/server/call/ResultOutputType.java
new file mode 100644
index 0000000..1296cc5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/ResultOutputType.java
@@ -0,0 +1,7 @@
+package chat.server.call;
+
+public enum ResultOutputType {
+
+	JSON, Bytes;
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/call/StringBuilderJSONWriter.java b/IMserver/medeasy/src/chat/server/call/StringBuilderJSONWriter.java
new file mode 100644
index 0000000..4de8315
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/call/StringBuilderJSONWriter.java
@@ -0,0 +1,358 @@
+package chat.server.call;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Date;
+import java.util.List;
+
+public class StringBuilderJSONWriter implements IJSONWriter {
+	
+    private StringBuilder content;
+    private boolean empty;
+    private boolean encode;
+    private boolean nameReady;
+    private boolean autoLowerName;
+    
+
+    public StringBuilderJSONWriter() {
+        content = new StringBuilder();
+        empty = true;
+        encode = true;
+        nameReady = false;
+        autoLowerName = false;
+    }
+
+    public void beginObject() {
+        if (!nameReady && !empty) {
+        	content.append(", ");
+        }
+
+        content.append("{");
+        empty = true;
+        nameReady = false;
+    }
+
+    public void beginObject(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        if (name != null) {
+        	content.append("\"" + toLower(name) + "\": {");
+        }
+        else {
+        	content.append("{");
+        }
+        
+        empty = true;
+    }
+
+	public void endObject() {
+        content.append("}");
+        empty = false;
+        nameReady = false;
+    }
+
+    public void beginArray() {
+        if (!nameReady && !empty) {
+            content.append(", ");
+        }
+
+        content.append("[");
+        empty = true;
+        nameReady = false;
+    }
+
+    public void beginArray(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        if (name != null) {
+        	content.append("\"" + toLower(name) + "\": [");
+        }
+        else {
+        	content.append("[");
+        }
+        
+        empty = true;
+        nameReady = false;
+    }
+
+    public void endArray() {
+        content.append("]");
+        empty = false;
+        nameReady = false;
+    }
+
+    public void write(String name, String value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": \"" + encodeValue(value) + "\"");
+        empty = false;
+    }
+    
+    public void write(String name, String value, boolean needEncode) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        if (needEncode) {
+        	content.append("\"" + toLower(name) + "\":\"" + encodeValue(value) + "\"");
+        }
+        else {
+        	content.append("\"" + toLower(name) + "\":\"" + value + "\"");
+        }
+        
+        empty = false;
+    }
+    
+    public void write(String name, Integer value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + String.valueOf(value));
+        empty = false;
+    }
+    
+    public void write(String name, Double value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + String.valueOf(value));
+        empty = false;
+    }
+    
+    public void write(String name, Long value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + String.valueOf(value));
+        empty = false;
+    }
+
+    public void write(String name, BigDecimal value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + String.valueOf(value));
+        empty = false;
+    }
+
+    public void write(String name, boolean value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": " + (value ? "true" : "false"));
+        empty = false;
+    }
+
+    public void write(String name, Date value) {
+        if (!empty) {
+            content.append(", ");
+        }
+
+        content.append("\"" + toLower(name) + "\": \"" + value + "\"");
+        empty = false;
+    }
+    
+
+	public void write(String name, IJsonProvider jsonProvider) {
+        writeName(name);
+        
+        if (jsonProvider == null) {
+        	writeNull();
+        	return;
+        }
+        
+        jsonProvider.writeJSONObject(this);
+	}
+	
+	public void write(String name, List<? extends IJsonProvider> list) {
+        writeName(name);
+        
+        if (list == null) {
+        	writeNull();
+        	return;
+        }
+        
+        beginArray();
+        
+        for (IJsonProvider json: list) {
+        	json.writeJSONObject(this);	
+        }
+        
+        endArray();
+	}
+	
+	public void write(IJsonProvider jsonProvider) {
+        if (jsonProvider == null) {
+        	writeNull();
+        	return;
+        }
+        
+        jsonProvider.writeJSONObject(this);		
+	}
+    
+	public void writeJSON(String name, String json) {
+        if (!empty) {
+            content.append(", ");
+        }
+        
+        if (name != null) {
+        	content.append("\"" + toLower(name) + "\": " + json);
+        }
+        else {
+        	content.append(json);
+        }
+        
+        empty = false;
+	}
+    
+	public void writeNull(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+        
+        if (name != null) {
+        	content.append("\"" + toLower(name) + "\": null");
+        }
+        else {
+        	content.append("null");
+        }
+        
+        empty = false;
+        nameReady = false;
+	}
+
+    public void writeName(String name) {
+        if (!empty) {
+            content.append(", ");
+        }
+        
+        if (name != null) {
+        	content.append("\"" + toLower(name) + "\": ");
+        }
+        
+        nameReady = true;
+    }
+    
+    public void writeValue(String value) {
+        content.append("\"" + encodeValue(value) + "\"");
+        empty = false;
+        nameReady = false;
+    }
+    
+    public void writeValue(int value) {
+        content.append(String.valueOf(value));
+        empty = false;
+        nameReady = false;
+    }
+
+    public void writeValue(BigDecimal value) {
+        content.append(String.valueOf(value));
+        empty = false;
+        nameReady = false;
+    }
+
+    public void writeValue(boolean value) {
+        content.append(value ? "true" : "false");
+        empty = false;
+        nameReady = false;
+    }
+
+    public void writeValue(Date value) {
+        content.append("\"" + value + "\"");
+        empty = false;
+        nameReady = false;
+    }
+
+	public void writeNull() {
+        content.append("null");
+        empty = false;
+        nameReady = false;
+	}
+	
+	public void writeJSON(String json) {
+        if (!empty) {
+            content.append(", ");
+        }
+        
+        content.append(json);
+        empty = false;
+        nameReady = false;
+	}
+	
+    private String toLower(String name) {
+    	if (name == null) {
+    		return "empty";
+    	}
+    	
+    	if (autoLowerName) {
+    		return name.toLowerCase();
+    	}
+    	else {
+    		return name;
+    	}
+	}
+    
+    private String encodeValue(String value) {
+		if (!encode) {
+			return value;
+		}
+		
+		String result = "";
+
+		if (value == null) {
+			return result;
+		}
+
+		try {
+			result = URLEncoder.encode(value, "UTF-8");
+			result = result.replace("+", "%20");
+		}
+		catch (Exception e) {
+			result = value;
+		}
+
+		return result;
+	}
+
+	public boolean isEncode() {
+		return encode;
+	}
+
+	public void setEncode(boolean encode) {
+		this.encode = encode;
+	}
+
+	@Override
+	public String encode(String value) {
+		try {
+			String result = URLEncoder.encode(value, "UTF-8");
+			return result;
+		} 
+		catch (UnsupportedEncodingException e) {
+		}
+		
+		return value;
+	}
+	
+	public StringBuilder getContent() {
+		return content;
+	}
+
+	public static void main(String[] args) throws UnsupportedEncodingException {
+		String value = "%E9%82%B5%E5%98%89%E7%A2%A7%E9%92%B0";
+		System.out.println(URLDecoder.decode(value, "UTF-8"));
+	}
+}
diff --git a/IMserver/medeasy/src/chat/server/im/DataPool.java b/IMserver/medeasy/src/chat/server/im/DataPool.java
new file mode 100644
index 0000000..bbd955e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/DataPool.java
@@ -0,0 +1,370 @@
+package chat.server.im;
+
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Base64;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.json.JSONObject;
+
+import com.google.protobuf.GeneratedMessage;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.xiaoleilu.hutool.json.JSONArray;
+
+import chat.module.entity.MessageRecord;
+import chat.security.AES;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.user.Session;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.IMHttpWrapper;
+import frame.util.ContentBuilder;
+import frame.variant.translator.Translator;
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.http.FullHttpRequest;
+
+public class DataPool {
+
+	private static Logger logger;
+	private static WFCMessageParseTable messageParseTable;
+	private RequestType requestType;
+	private FullHttpRequest httpRequest;
+	private JSONObject jsonObject;
+	private String body;
+	private String secret;
+	private byte[] rawData;
+	private byte[] data;
+	private byte[] srcBytes;
+	private IMHttpWrapper httpWrapper;
+	private int messageId;
+	private String phone;
+	
+	public String getPhone() {
+		return phone;
+	}
+
+	public void setPhone(String phone) {
+		this.phone = phone;
+	}
+
+	static { 
+		logger = Logger.getLogger(IMDispatcher.class);
+		messageParseTable = WFCMessageParseTable.getInstance();
+	}
+	
+	//short 
+	public DataPool(RequestType requestType, Session session, FullHttpRequest httpRequest) {
+		//1.
+		this.requestType = requestType;
+		this.httpRequest = httpRequest;
+		//2.
+		if (session != null) {
+			secret = session.getSecret();
+		}
+		
+		//3.
+		body = readHttpRequestJSON();
+		
+		if (body == null) {
+			return;
+		}
+		
+		if (body.startsWith("{")) {
+			jsonObject = new JSONObject(body);
+		}
+		else if (secret != null) {
+			httpWrapper = createHttpWrapper(body, secret);
+		}
+	}
+	
+	//long
+	public DataPool(RequestType requestType, Session session, MqttPublishMessage message) throws Exception {
+		//1.
+		this.requestType = requestType;
+		this.messageId = message.variableHeader().packetId();
+		
+		if (session != null) {
+			secret = session.getSecret();
+		}
+		
+		//2.
+//        ByteBuf payload = message.payload();
+//        byte[] content = readBytesAndRewind(payload);
+//        
+//        if (content == null) {
+//        	return;
+//        }
+//        
+//        data = AES.AESDecrypt(content, secret, true);
+//        
+//        if (secret != null) {
+//			httpWrapper = createHttpWrapper(new String(data), secret);
+//		}
+		
+        ByteBuf payload = message.payload();
+        byte[] content = readBytesAndRewind(payload);
+        
+        if (content == null) {
+        	return;
+        }
+        
+        content = AES.AESDecrypt(content, secret, true);
+        
+        if (content == null) {
+        	return;
+        }
+		
+		if (secret != null) {
+			try {
+				 body = null;
+	             byte[] bytes = Base64.getDecoder().decode(new String(content));
+	             bytes = AES.AESDecrypt(bytes, secret, true);
+	             httpWrapper = WFCMessage.IMHttpWrapper.parseFrom(bytes);
+			} catch(Exception e) {
+				 httpWrapper = null;
+				 srcBytes = content;
+			}
+		}
+		
+//		if (body == null) {
+//			return;
+//		}
+//		
+//		if (body.startsWith("{")) {
+//			jsonObject = new JSONObject(body);
+//		}
+//		else if (secret != null) {
+//			httpWrapper = createHttpWrapper(body, secret);
+//		}
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T getWFCMessage(Class<? extends GeneratedMessage> clazz) {
+		try {
+			byte[] bytes = null;
+			
+			if (httpWrapper != null) {
+				bytes = httpWrapper.getData().toByteArray();
+			}
+			else if (srcBytes != null) {
+				bytes = srcBytes;
+			}
+			else if (body != null) {
+				bytes = body.getBytes();
+			}
+			
+			if (bytes == null) {
+				return null;
+			}
+			
+			Method method = messageParseTable.getMethod(clazz);
+			
+			T result = (T) method.invoke(clazz, bytes);
+			return result;
+		} 
+		catch (Exception e) {
+			if (logger.isDebugEnabled())
+			   e.printStackTrace();
+			return null;
+		} 
+	}
+	
+	protected String readHttpRequestJSON() {
+    	String result = null;
+    	try {
+    		byte[] bytes = readBytesAndRewind(httpRequest.content());
+    		result = new String(bytes, StandardCharsets.UTF_8);
+    	}
+    	
+    	catch (Exception e) {
+    		e.printStackTrace();
+    	}
+
+    	return result;    
+    }
+    
+    protected String readPublishMessageJSON(MqttPublishMessage message) {
+    	String result = null;
+    	try {
+            ByteBuf payload = message.payload();
+            byte[] content = readBytesAndRewind(payload);
+            
+            if (content == null) {
+            	return null;
+            }
+            
+            byte[] clearContent = AES.AESDecrypt(content, secret, true);
+            
+            if (clearContent == null) {
+            	return null;
+            }
+            
+            srcBytes = clearContent;
+            result = new String(clearContent);
+    	}
+    	catch (Exception e) {
+    		e.printStackTrace();
+    	}
+
+    	return result;
+    }
+    
+    public static byte[] readBytesAndRewind(ByteBuf payload) {
+        byte[] payloadContent = new byte[payload.readableBytes()];
+        int mark = payload.readerIndex();
+        payload.readBytes(payloadContent);
+        payload.readerIndex(mark);
+        
+        return payloadContent;
+    }
+     
+    public Object getObject(String name) {
+		if (jsonObject != null) {
+			return jsonObject.get(name);
+		}
+		
+		return null;
+    }
+    
+	public String getString(String name) {
+		try {
+			 if (jsonObject != null) {
+				 return jsonObject.getString(name);
+			 }
+			 
+			 
+		} 
+		catch (Exception e) {
+			 return null;
+		}
+		return null;
+	}
+
+	public Integer getInteger(String name, Integer defaultValue) {
+		Object value = getObject(name);
+		return Translator.toInteger(value, defaultValue);
+	}
+	
+	
+	
+	public Date getDate(String string) throws ParseException {
+		// TODO Auto-generated method stub
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+		return sdf.parse(string);
+	}
+
+	public JSONArray getJSONArray(String name) {
+		Object obj = getObject(name);
+		
+		if (obj == null) {
+			return null;
+		}
+		
+		return (JSONArray) obj;
+	}
+
+	public String getHeader(String name) {
+		return httpRequest.headers().get(name);
+	}
+
+	public MessageRecord getMessageRecord() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public List<String> getList(String string) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+	public String getBody() {
+		return body;
+	}
+
+	public void decode() {
+		data = AES.AESDecrypt(rawData, secret, true);
+	}
+
+	public byte[] getRawData() {
+		return rawData;
+	}
+
+	public byte[] getData() {
+		return data;
+	}
+
+	public IMHttpWrapper getHttpWrapper() {
+		return httpWrapper;
+	}
+
+	public static IMHttpWrapper createHttpWrapper(String content, String secret) {
+    	WFCMessage.IMHttpWrapper result = null;
+    	
+    	try {
+            byte[] bytes = Base64.getDecoder().decode(content);
+            bytes = AES.AESDecrypt(bytes, secret, true);
+            result = WFCMessage.IMHttpWrapper.parseFrom(bytes);
+    	}
+    	catch(Exception e) {}
+
+		return result;
+	}
+
+	public String getRequestURI() {
+		if (httpRequest == null) {
+			return null;
+		}
+		
+		return httpRequest.uri();
+	}
+
+	public String getRequestTopic() {
+		if (httpWrapper == null) {
+			return null;
+		}
+		
+		return httpWrapper.getRequest();
+	}
+
+	public RequestType getRequestType() {
+		return requestType;
+	}
+
+	public FullHttpRequest getHttpRequest() {
+		return httpRequest;
+	}
+
+	public int getMessageId() {
+		return messageId;
+	}
+
+	public void setMessageId(int messageId) {
+		this.messageId = messageId;
+	}
+
+	public JSONObject getJsonObject() {
+		return jsonObject;
+	}
+
+	public void setJsonObject(JSONObject jsonObject) {
+		this.jsonObject = jsonObject;
+	}
+
+	@Override
+	public String toString() {
+		ContentBuilder builder = new ContentBuilder();
+		builder.append("requestType: " + requestType);
+		builder.append("jsonObject: " + jsonObject);
+		builder.append("body: " + body);
+		builder.append("rawData: " + rawData);
+		builder.append("httpWrapper: " + httpWrapper);
+		builder.append("messageId: " + messageId);
+		
+		return builder.toString();
+	}
+	
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/im/IMDispatcher.java b/IMserver/medeasy/src/chat/server/im/IMDispatcher.java
new file mode 100644
index 0000000..73f8f73
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/IMDispatcher.java
@@ -0,0 +1,157 @@
+package chat.server.im;
+
+import org.apache.log4j.Logger;
+
+import chat.message.Callback;
+import chat.server.call.CallObject;
+import chat.server.call.CallObjectMap;
+import chat.server.call.Operator;
+import chat.server.call.ResultCode;
+import chat.server.moquette.message.ClientID;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.user.Session;
+import chat.user.SessionStore;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.FullHttpRequest;
+
+public class IMDispatcher extends SimpleChannelInboundHandler<FullHttpRequest> {
+	
+	protected static Logger logger;
+
+	
+	static {
+		logger = Logger.getLogger(IMDispatcher.class);
+	}
+	
+	public IMDispatcher() {
+
+	}
+	
+	//read short connection
+    public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest httpRequest) throws Exception {
+    	//1. session
+    	ClientID clientID = ClientID.valueOf(httpRequest);
+    	Session session = SessionStore.get(clientID);
+        //2. data pool
+    	DataPool dataPool = new DataPool(RequestType.Short, session, httpRequest);
+    	
+    	//3. operator, dataPool, resultPool
+        String uri = dataPool.getRequestURI();
+    	String topic = dataPool.getRequestTopic();
+    	
+    	Operator operator = Operator.getInstance(uri, topic);
+        int messageId = dataPool.getMessageId();
+        String secret = session != null ? session.getSecret() : "";
+        
+        ResultPool resultPool = new ResultPool(RequestType.Short, topic, messageId, secret);
+        
+        try {
+            //4. execute 
+        	if (operator != null) {
+            	if (logger.isDebugEnabled()) {
+            		logger.debug("receive request(short): " + httpRequest.uri() + ", method: " + operator.getMethod() + ", topic: " + topic);
+            	}
+            	
+                CallObject callObject = CallObjectMap.get(operator);
+        		
+                if (callObject == null) {
+                	logger.error("unknown request(short) path: " + uri);
+                	resultPool.error(ResultCode.Error_Path_NotExists);
+                	resultPool.add("error", "Path_NotExists" + uri);
+                }
+                
+                System.out.println(operator.getTopic());
+                callObject.exec(session, operator, dataPool, resultPool);
+                
+            	if (logger.isDebugEnabled()) {
+            		logger.debug("return " + operator.getMethod() + " short(" + topic + ")");
+            	}
+        	}
+        	else {
+            	logger.error("unknown request(short) path: " + uri + ", topic: " + topic);
+            	resultPool.error(ResultCode.Error_Path_NotExists);
+            	resultPool.add("error", "Path_NotExists" + uri);
+        	}
+        }
+        finally {
+            //5. write back
+            Object data = resultPool.getResultData();
+    		ctx.writeAndFlush(data);
+        }
+    	
+    	//6. callback
+    	Callback callback = resultPool.getCallback();
+    	
+    	if (callback != null) {
+    		callback.exec();
+    	}
+    }
+	
+    //read long connection
+	public void channelRead0(Channel channel, MqttPublishMessage message) throws Exception {
+        ClientID clientID = ClientID.valueOf(channel);
+        Session session = SessionStore.get(clientID);
+        
+        if (session == null) {
+        	return;
+        }
+        
+        System.out.println("long:" + channel);
+        if (session != null) {
+            session.setChannel(channel);
+            session.refreshLastActiveTime();
+        }        
+        
+        String topic = message.variableHeader().topicName();
+        System.out.println("Topic===============>:" + topic);
+        
+        Operator operator = Operator.getInstance(null, topic);
+        
+        if (operator == null) {
+        	logger.error("unknown publish(long): " + topic);
+        	return;
+        }
+        
+    	if (logger.isDebugEnabled()) {
+    		logger.debug("receive request(long): method: " + operator.getMethod() + ", topic: " + topic);
+    	}
+        
+        //2. do dispatch
+        DataPool dataPool = new DataPool(RequestType.Long, session, message);
+        
+        int messageId = message.variableHeader().packetId();//dataPool.getMessageId();
+        String secret = session.getSecret();
+        ResultPool resultPool = new ResultPool(RequestType.Long, topic, messageId, secret);
+        
+        //3. execute
+        CallObject callObject = CallObjectMap.get(operator);
+        
+        if (callObject == null) {
+        	logger.error("unknown request(long): " + topic);
+        	return;
+        }
+        
+        callObject.exec(session, operator, dataPool, resultPool);
+        
+        //4. write back
+		Object data = resultPool.getResultData();
+		
+		System.out.println("send message:" + channel);
+		
+		channel.writeAndFlush(data);
+		
+    	if (logger.isDebugEnabled()) {
+    		logger.debug("return " + operator.getMethod() + " long(" + topic + ")");
+    	}
+    	
+    	//5. callback
+    	Callback callback = resultPool.getCallback();
+    	
+    	if (callback != null) {
+    		callback.exec();
+    	}
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/im/IMTopic.java b/IMserver/medeasy/src/chat/server/im/IMTopic.java
new file mode 100644
index 0000000..eed2a2c
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/IMTopic.java
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the Wildfire Chat package.
+ * (c) Heavyrain2012 <heavyrain.lee@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+package chat.server.im;
+
+public interface IMTopic {
+	
+	String SendMessageTopic = "MS";
+    String MultiCastMessageTopic = "MMC";
+    String RecallMessageTopic = "MR";
+    String RecallMultiCastMessageTopic = "MRMC";
+	String PullMessageTopic = "MP";
+	String NotifyMessageTopic = "MN";
+    String NotifyRecallMessageTopic = "RMN";
+    String BroadcastMessageTopic = "MBC";
+
+    String GetUserSettingTopic = "UG";
+    String PutUserSettingTopic = "UP";
+    String NotifyUserSettingTopic = "UN";
+
+    String CreateGroupTopic = "GC";
+	String AddGroupMemberTopic = "GAM";
+	String KickoffGroupMemberTopic = "GKM";
+	String QuitGroupTopic = "GQ";
+	String DismissGroupTopic = "GD";
+	String ModifyGroupInfoTopic = "GMI";
+    String ModifyGroupAliasTopic = "GMA";
+    String ModifyGroupMemberAliasTopic = "GMMA";
+    String GetGroupInfoTopic = "GPGI";
+    String GetGroupMemberTopic = "GPGM";
+    String TransferGroupTopic = "GTG";
+    String SetGroupManagerTopic = "GSM";
+
+    String GetUserInfoTopic = "UPUI";
+    String ModifyMyInfoTopic = "MMI";
+
+	String GetQiniuUploadTokenTopic = "GQNUT";
+
+    String AddFriendRequestTopic = "FAR";
+    String HandleFriendRequestTopic = "FHR";
+    String FriendRequestPullTopic = "FRP";
+    String NotifyFriendRequestTopic = "FRN";
+    String RriendRequestUnreadSyncTopic = "FRUS";
+
+    String DeleteFriendTopic = "FDL";
+    String FriendPullTopic = "FP";
+    String NotifyFriendTopic = "FN";
+    String BlackListUserTopic = "BLU";
+    String SetFriendAliasTopic = "FALS";
+
+
+    String UploadDeviceTokenTopic = "UDT";
+
+    String UserSearchTopic = "US";
+
+    String JoinChatroomTopic = "CRJ";
+    String QuitChatroomTopic = "CRQ";
+    String GetChatroomInfoTopic = "CRI";
+    String GetChatroomMemberTopic = "CRMI";
+
+    String RouteTopic = "ROUTE";
+
+    String CreateChannelTopic = "CHC";
+    String ModifyChannelInfoTopic = "CHMI";
+    String TransferChannelInfoTopic = "CHT";
+    String DestoryChannelInfoTopic = "CHD";
+    String ChannelSearchTopic = "CHS";
+    String ChannelListenTopic = "CHL";
+    String ChannelPullTopic = "CHP";
+
+    String GetTokenTopic = "GETTOKEN";
+    String DestroyUserTopic = "DESTROYUSER";
+
+    String LoadRemoteMessagesTopic = "LRM";
+    String KickoffPCClientTopic = "KPCC";
+}
diff --git a/IMserver/medeasy/src/chat/server/im/OperateTable.java b/IMserver/medeasy/src/chat/server/im/OperateTable.java
new file mode 100644
index 0000000..3c93a4c
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/OperateTable.java
@@ -0,0 +1,224 @@
+package chat.server.im;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import chat.consts.APIPath;
+import chat.server.call.Operator;
+
+public class OperateTable {
+	
+	private static Map<String, Operator> pathOperatorMap;
+	private static Map<String, Operator> topicOperatorMap;
+	
+	static {
+		init();
+	}
+
+	public static Operator get(String path, String topic) {
+		if (topic != null) {
+			topic = topic.toLowerCase();
+			return topicOperatorMap.get(topic);
+		}
+		
+		if (path != null) {
+			path = path.toLowerCase();
+			
+			int pos = path.indexOf("?");
+			if (pos > 0) {
+				path = path.substring(0, pos);
+			}
+			
+			return pathOperatorMap.get(path);
+		}
+		
+		return null;
+	}
+
+	private static void init() {
+		pathOperatorMap = new HashMap<String, Operator>();
+		
+		//1. client
+		addOnePathOperator("/login", "client", "login");
+		addOnePathOperator("/send_code", "client", "sendSMSCode");
+		addOnePathOperator("/oneLogin", "client", "oneLogin");
+		
+		//鏈嬪弸鍦�
+		addOnePathOperator("/friendcircle/getList", "friendcircle", "getList");
+		addOnePathOperator("/friendcircle/getOneUserList", "friendcircle", "getOneUserList");
+		addOnePathOperator("/friendcircle/getOneCircleObject", "friendcircle", "getOneCircleObject");
+		addOnePathOperator("/friendcircle/createOneCircleObject", "friendcircle", "createOneCircleObject");
+		addOnePathOperator("/friendcircle/addOneAttention", "friendcircle", "addOneAttention");
+		addOnePathOperator("/friendcircle/addOneCollect", "friendcircle", "addOneCollect");
+		addOnePathOperator("/friendcircle/addOneThumbsup", "friendcircle", "addOneThumbsup");
+		addOnePathOperator("/friendcircle/addOneComment", "friendcircle", "addOneComment");
+		addOnePathOperator("/friendcircle/addOneForword", "friendcircle", "addOneForword");
+		
+		//鍖昏鏃犲咖璋冪敤鎺ュ彛娣诲姞鐢ㄦ埛淇℃伅
+//		addOnePathOperator("/createOneUser", "client", "createOneUser");
+//		//鍖昏鏃犲咖璋冪敤鎺ュ彛淇敼鐢ㄦ埛淇℃伅
+//		addOnePathOperator("/modifyOneUser", "client", "modifyOneUser");
+		//鍖昏鏃犲咖璋冪敤鎺ュ彛鍙戞秷鎭�
+		addOnePathOperator("/notifyMesage", "client", "notifyMesage");
+		
+		addOnePathOperator(APIPath.User_Get_Info, "client", "getUserInfo");	
+		addOnePathOperator(APIPath.Create_User, "client", "createUser");
+		addOnePathOperator(APIPath.Destroy_User, "client", "destroyUser");
+		addOnePathOperator(APIPath.CreateOrUpdate_Device, "client", "createDevise");
+		addOnePathOperator(APIPath.Get_Device, "client", "getOneDevise");
+		addOnePathOperator(APIPath.Get_User_Devices, "client", "getDeviseList");		
+		addOnePathOperator(APIPath.User_Get_Token, "client", "getToken");
+		addOnePathOperator(APIPath.User_Update_Block_Status, "client", "updateBlockStatus");
+		addOnePathOperator(APIPath.User_Get_Blocked_List, "client", "getBlockedList");
+		addOnePathOperator(APIPath.User_Check_Block_Status, "client", "checkBlockStatus");
+		addOnePathOperator(APIPath.User_Get_Online_Status, "client", "getOnlineStatus");
+
+		//2. chat room
+		addOnePathOperator(APIPath.Create_Chatroom, "chatroom", "create");
+		addOnePathOperator(APIPath.Chatroom_Destroy, "chatroom", "destroy");
+		addOnePathOperator(APIPath.Chatroom_Info, "chatroom", "getOne");
+		addOnePathOperator(APIPath.Chatroom_SetBlacklist, "chatroom", "setBlacklist");
+		addOnePathOperator(APIPath.Chatroom_GetBlacklist, "chatroom", "getBlacklist");
+		addOnePathOperator(APIPath.Chatroom_SetManager, "chatroom", "setManager");
+		addOnePathOperator(APIPath.Chatroom_GetManagerList, "chatroom", "getManagerList");
+		addOnePathOperator(APIPath.Chatroom_MuteAll, "chatroom", "muteAll");
+		
+		//3. sensitive word
+		addOnePathOperator(APIPath.Sensitive_Add, "sensitive", "add");
+		addOnePathOperator(APIPath.Sensitive_Del, "sensitive", "delete");
+		addOnePathOperator(APIPath.Sensitive_Query, "sensitive", "query");
+		
+		//4. friend
+		addOnePathOperator(APIPath.Friend_Update_Status, "friend", "updateStatus");
+		addOnePathOperator(APIPath.Friend_Get_List, "friend", "getList");
+		addOnePathOperator(APIPath.Blacklist_Update_Status, "friend", "updateBlackList");
+		addOnePathOperator(APIPath.Friend_Get_Alias, "friend", "getAlias");
+		addOnePathOperator(APIPath.Friend_Set_Alias, "friend", "setAlias");
+		addOnePathOperator(APIPath.Friend_Send_Request, "friend", "sendRequest");
+		addOnePathOperator(APIPath.Friend_Get_Requests, "friend", "getRequest");
+		
+		//5. message
+		addOnePathOperator(APIPath.Msg_Send, "message", "send");
+		addOnePathOperator(APIPath.Msg_Recall, "message", "recall");
+		addOnePathOperator(APIPath.Msg_Delete, "message", "delete");
+		addOnePathOperator(APIPath.Msg_Broadcast, "message", "broadcast");
+		addOnePathOperator(APIPath.Msg_Multicast, "message", "multicast");
+		addOnePathOperator(APIPath.Msg_RecallBroadCast, "message", "broadcastRecall");
+		addOnePathOperator(APIPath.Msg_RecallMultiCast, "message", "multicastRecall");
+		
+		//6. group
+		addOnePathOperator(APIPath.Group_Dismiss, "group", "dismiss");
+		addOnePathOperator(APIPath.Group_Transfer, "group", "transfer");
+		addOnePathOperator(APIPath.Group_Get_Info, "group", "getOne");
+		addOnePathOperator(APIPath.Group_Member_List, "group", "getMemberList");
+		
+		addOnePathOperator(APIPath.Group_Modify_Info, "group", "modifyOne");
+
+		addOnePathOperator(APIPath.Group_Member_Add, "group", "addMember");
+		addOnePathOperator(APIPath.Group_Member_Kickoff, "group", "kickoffMember");
+		addOnePathOperator(APIPath.Group_Member_Quit, "group", "quitMember");
+		addOnePathOperator(APIPath.Group_Set_Manager, "group", "setManager");
+		addOnePathOperator(APIPath.Group_Mute_Member, "group", "muteMember");
+		addOnePathOperator(APIPath.Group_Allow_Member, "group", "allowMember");
+		addOnePathOperator(APIPath.Get_User_Groups, "group", "getUserGroups");
+		
+//		addOneTopicOperator(IMTopic.GetGroupInfoTopic, "group", "getInfo");
+//		addOneTopicOperator(IMTopic.GetGroupMemberTopic, "client", "getMemberList");
+		
+		//7. channel
+		addOnePathOperator(APIPath.Create_Channel, "channel", "create");
+		addOnePathOperator(APIPath.Channel_User_Info, "channel", "getOneUser");
+		addOnePathOperator(APIPath.Channel_Update_Profile, "channel", "modifyProfile");
+		addOnePathOperator(APIPath.Channel_Get_Profile, "channel", "getProfile");
+		addOnePathOperator(APIPath.Channel_Message_Send, "channel", "sendMessage");
+		addOnePathOperator(APIPath.Channel_Subscribe, "channel", "subscribe");
+		addOnePathOperator(APIPath.Channel_Subscriber_List, "channel", "getSubscriberList");
+		
+		//8. robot
+		addOnePathOperator(APIPath.Create_Robot, "robot", "create");
+		addOnePathOperator(APIPath.Robot_User_Info, "robot", "getOne");
+		addOnePathOperator(APIPath.Robot_Message_Send, "robot", "sendMessage");
+	    
+		//9. system
+		addOnePathOperator("/route", "system", "route");
+		addOnePathOperator("/fs", "system", "uploadFileToServer");
+		addOnePathOperator(APIPath.Get_System_Setting, "system", "getSetting");
+		addOnePathOperator(APIPath.Put_System_Setting, "system", "setSetting");
+		
+		//
+		topicOperatorMap = new HashMap<String, Operator>();
+		
+		addOneTopicOperator("route", "system", "route");
+		addOneTopicOperator("GMUT", "system", "getMediaUploadToken");
+		addOneTopicOperator(IMTopic.GetQiniuUploadTokenTopic, "system", "getQiniuUploadToken");
+		addOneTopicOperator(IMTopic.GetTokenTopic, "system", "getToken");
+		addOneTopicOperator(IMTopic.ModifyMyInfoTopic, "system", "modifyMyInfo");
+		addOneTopicOperator(IMTopic.MultiCastMessageTopic, "system", "multiCastMessage");
+		addOneTopicOperator(IMTopic.RecallMessageTopic, "system", "recallMessage");
+		addOneTopicOperator(IMTopic.SendMessageTopic, "system", "sendMessage");
+		addOneTopicOperator(IMTopic.UploadDeviceTokenTopic, "system", "uploadDeviceToken");
+		
+		addOneTopicOperator(IMTopic.FriendPullTopic, "client", "pullFriend");
+		addOneTopicOperator(IMTopic.FriendRequestPullTopic, "client", "pullRequestFriend");//FRP
+		addOneTopicOperator(IMTopic.HandleFriendRequestTopic, "client", "handleFriend");
+		addOneTopicOperator(IMTopic.AddFriendRequestTopic, "client", "addFriend");//FAR
+		addOneTopicOperator(IMTopic.DeleteFriendTopic, "client", "deleteFriend");
+		addOneTopicOperator(IMTopic.SetFriendAliasTopic, "client", "setFriendAlias");
+		addOneTopicOperator(IMTopic.NotifyFriendRequestTopic, "client", "notifyFriend");//FRN
+		
+		addOneTopicOperator(IMTopic.DestroyUserTopic, "client", "destoryUser");
+		//鏌ユ壘浜哄憳
+		addOneTopicOperator(IMTopic.UserSearchTopic, "client", "userSearch");
+		addOneTopicOperator(IMTopic.DismissGroupTopic, "client", "dismissGroup");
+		
+		addOneTopicOperator(IMTopic.GetUserInfoTopic, "client", "getUser");//UPUI
+		addOneTopicOperator(IMTopic.PullMessageTopic, "client", "pullMessage");//MP
+		addOneTopicOperator(IMTopic.NotifyMessageTopic, "client", "notifyMessage");//MN
+		addOneTopicOperator(IMTopic.LoadRemoteMessagesTopic, "client", "loadRemoteMessage");
+		addOneTopicOperator(IMTopic.GetUserSettingTopic, "client", "getUserSetting");
+		addOneTopicOperator(IMTopic.PutUserSettingTopic, "client", "putUserSetting");
+		addOneTopicOperator(IMTopic.BlackListUserTopic, "client", "blackListUser");
+		addOneTopicOperator(IMTopic.BroadcastMessageTopic, "client", "broadCastMessage");
+		addOneTopicOperator(IMTopic.ChannelListenTopic, "client", "channelListen");
+		addOneTopicOperator(IMTopic.ChannelSearchTopic, "client", "channelSearch");
+		addOneTopicOperator(IMTopic.ModifyChannelInfoTopic, "client", "modifyChannel");
+		addOneTopicOperator(IMTopic.CreateChannelTopic, "client", "createChannel");
+		addOneTopicOperator(IMTopic.DestoryChannelInfoTopic, "client", "destoryChannel");
+		addOneTopicOperator(IMTopic.ChannelPullTopic, "client", "pullChannel");
+		addOneTopicOperator(IMTopic.TransferChannelInfoTopic, "client", "transferChannel");
+		
+		addOneTopicOperator(IMTopic.GetChatroomInfoTopic, "client", "chatRoomInfo");
+		addOneTopicOperator(IMTopic.GetChatroomMemberTopic, "client", "getChatRoomMember");
+		addOneTopicOperator(IMTopic.JoinChatroomTopic, "client", "joinChatRoom");
+		addOneTopicOperator(IMTopic.QuitChatroomTopic, "client", "quitChatRoom");
+		
+		addOneTopicOperator(IMTopic.KickoffGroupMemberTopic, "client", "kickOffGroup");
+		addOneTopicOperator(IMTopic.KickoffPCClientTopic, "client", "kickoffPCClient");
+		
+		addOneTopicOperator(IMTopic.CreateGroupTopic, "group", "createGroup");
+		addOneTopicOperator(IMTopic.GetGroupInfoTopic, "group", "getInfo");	//GPGI	
+		addOneTopicOperator(IMTopic.GetGroupMemberTopic, "group", "getMemberList");//GPGM
+		addOneTopicOperator(IMTopic.AddGroupMemberTopic, "group", "addMembers");
+		addOneTopicOperator(IMTopic.ModifyGroupAliasTopic, "group", "modifyGroupAlias");
+		addOneTopicOperator(IMTopic.ModifyGroupInfoTopic, "group", "modifyGroup");
+		addOneTopicOperator(IMTopic.QuitGroupTopic, "group", "quitGroup");
+		addOneTopicOperator(IMTopic.SetGroupManagerTopic, "group", "setGroupManager");
+		addOneTopicOperator(IMTopic.RriendRequestUnreadSyncTopic, "group", "friendUnread");
+		addOneTopicOperator(IMTopic.TransferGroupTopic, "group", "transferGroup");
+		
+//		addOneTopicOperator("im", "", "route");
+	}
+
+	private static void addOnePathOperator(String path, String object, String method) {
+		Operator operator = new Operator(path, object, method);
+		pathOperatorMap.put(operator.getKey(), operator);
+	}
+	
+	private static void addOneTopicOperator(String topic, String object, String method) {
+		Operator operator = new Operator(topic, object, method);
+		topicOperatorMap.put(operator.getKey(), operator);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/im/RequestType.java b/IMserver/medeasy/src/chat/server/im/RequestType.java
new file mode 100644
index 0000000..d835a3b
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/RequestType.java
@@ -0,0 +1,7 @@
+package chat.server.im;
+
+public enum RequestType {
+
+	Short, Long;
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/im/ResultPool.java b/IMserver/medeasy/src/chat/server/im/ResultPool.java
new file mode 100644
index 0000000..5b24e20
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/ResultPool.java
@@ -0,0 +1,300 @@
+package chat.server.im;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.xiaoleilu.hutool.util.StrUtil;
+
+import chat.message.Callback;
+import chat.message.SendMessageCallback;
+import chat.security.AES;
+import chat.server.call.HttpEnvelopWriter;
+import chat.server.call.ResultCode;
+import chat.server.call.ResultItem;
+import chat.server.call.ResultOutputType;
+import chat.server.moquette.message.ModifiedMqttPubAckMessage;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageIdVariableHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttQoS;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.DefaultHttpHeaders;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpHeaderValues;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+
+public class ResultPool {
+
+	private static HttpEnvelopWriter httpEnvelopWriter;
+	
+	private RequestType requestType;
+	private String topic;
+	private ResultCode code;
+	private String rootName;
+	private List<ResultItem> items;
+	private int messageId;
+	private String secret;
+	private ResultOutputType outputType; 
+	private int resultCode;
+	private byte[] bytes;
+	private Object content = Unpooled.EMPTY_BUFFER;
+	private boolean needReturnCode;
+	
+	static {
+		httpEnvelopWriter = HttpEnvelopWriter.getInstance();
+	}
+	
+	public ResultPool(RequestType requestType, String topic, int messageId, String secret) {
+		this.rootName = "result";
+		this.items = new ArrayList<ResultItem>();
+		this.code = ResultCode.Success;
+		this.outputType = ResultOutputType.Bytes;
+		this.requestType = requestType;
+		this.resultCode = ResultCode.Success.getValue();
+		this.topic = topic;
+		this.messageId = messageId;
+		this.secret = secret;
+		this.needReturnCode = true;
+	}
+	
+	public Object getResultData() {
+		//1. get data
+		ByteBuf payload = null;
+				
+		if (ResultOutputType.JSON == outputType) {
+			payload = getJSONPayload();
+		}
+		else if (ResultOutputType.Bytes == outputType) {
+			payload = getBytesPayload();
+		}
+		
+		if (payload == null) {
+			return null;
+		}
+		
+		//2. get result
+		Object result = null;
+		
+		if (RequestType.Short  == requestType) {
+			result = getFullResponse(payload);
+		}
+		else if (RequestType.Long  == requestType) {
+			result = getMqttMessage(payload);
+		}
+		
+		return result;
+	}
+	
+	public ByteBuf getJSONPayload() {
+		StringBuilder builder = httpEnvelopWriter.writeToString(this);
+		ByteBuf payload = Unpooled.copiedBuffer(builder.toString(), Charset.forName("utf-8"));
+		
+		return payload;
+	}
+
+	public ByteBuf getBytesPayload() {
+		//1.
+        ByteBuf payload = Unpooled.buffer();
+        payload.ensureWritable(1).writeByte(resultCode);
+        
+        //2.
+		if (bytes != null) {
+			byte[] data = AES.AESEncrypt(bytes, secret);
+			payload.ensureWritable(data.length).writeBytes(data);
+		}
+		
+        //3. return
+		return payload;
+	}
+	
+	public FullHttpResponse getFullResponse(ByteBuf payload) {
+		//1. new response
+		FullHttpResponse result = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, payload);
+//		FullHttpResponse result;
+//		if (ResultOutputType.JSON == outputType) {
+//			result = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, payload);
+//		} 
+//		else {
+//	        byte[] response = new byte[payload.readableBytes()];
+//	        payload.readBytes(response);
+//			
+//			this.content = Unpooled.copiedBuffer(response);
+//			
+//			ByteBuf byteBuf = (ByteBuf) content;
+//			
+//			result = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
+//		}
+
+		//2. header
+		HttpHeaders headers = new DefaultHttpHeaders();
+		
+		headers.set(HttpHeaderNames.CONNECTION.toString(), HttpHeaderValues.KEEP_ALIVE.toString());
+		
+		if (ResultOutputType.JSON == outputType) {
+			//headers.set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
+			headers.set(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=utf-8");
+			headers.set(HttpHeaderNames.CONTENT_ENCODING.toString(), "utf-8");
+			//headers.set(HttpHeaderNames.CONTENT_TYPE.toString(), StrUtil.format("{};charset={}", "application/json", "UTF-8"));
+		}
+		else {
+			headers.set(HttpHeaderNames.CONTENT_TYPE.toString(), "application/octet-stream");
+//			headers.set(HttpHeaderNames.CONNECTION.toString(), HttpHeaderValues.KEEP_ALIVE.toString());
+		}
+		
+		headers.set(HttpHeaderNames.CONTENT_LENGTH.toString(), payload.readableBytes());
+		result.headers().add(headers);
+		
+		//3. return
+		return result;
+	}
+	
+	public MqttMessage getMqttMessage(ByteBuf payload) {
+		if (payload == null) {
+			return null;
+		}
+		
+        MqttMessageIdVariableHeader header = MqttMessageIdVariableHeader.from(messageId);
+        MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.PUBACK, false, MqttQoS.AT_MOST_ONCE, false, 0);
+        ModifiedMqttPubAckMessage pubAckMessage = new ModifiedMqttPubAckMessage(fixedHeader, header, payload);
+        
+		return pubAckMessage;
+	}
+	
+	public void add(Object value) {
+		add(null, value);
+	}
+	
+	public void add(String name, Object value) {
+		outputType = ResultOutputType.JSON;		
+		add(name, value, true);
+	}
+	
+	public void add(String name, Object value, boolean needEncode) {
+		ResultItem resultItem = null;
+		if (("key").equals(name)) {
+			outputType = ResultOutputType.JSON;	
+		}
+		
+		if (name != null) {
+			for (ResultItem item : items) {
+				if (name.equalsIgnoreCase(item.getName())) {
+					resultItem = item;
+					break;
+				}
+			}
+		}
+		
+		if (resultItem == null) {
+			resultItem = new ResultItem();
+			resultItem.setName(name);
+		}
+		
+		resultItem.setValue(value);
+		resultItem.setNeedEncode(needEncode);
+		
+		items.add(resultItem);	
+	}
+
+	public void error(ResultCode code) {
+		this.code = code;
+	}
+
+	public void success() {
+		this.code = ResultCode.Success;
+	}
+
+	public boolean isSuccess() {
+		return this.code == ResultCode.Success;
+	}
+
+	public List<ResultItem> getItemList() {
+		return items;
+	}
+
+	public String getErrorMessage() {
+		return code.getMsg();
+	}
+
+	public int getErrorCode() {
+		return code.getValue();
+	}
+
+	public ResultCode getCode() {
+		return code;
+	}
+
+	public ResultOutputType getOutputType() {
+		return outputType;
+	}
+
+	public void setOutputType(ResultOutputType outputType) {
+		this.outputType = outputType;
+	}
+
+	public String getRootName() {
+		return rootName;
+	}
+
+	public void setRootName(String rootName) {
+		this.rootName = rootName;
+	}
+	
+	public void setBytes(byte[] bytes) {
+		outputType = ResultOutputType.Bytes;
+		
+		if (bytes != null) {
+			ByteBuf ackPayload = Unpooled.buffer();
+			ackPayload.ensureWritable(bytes.length).writeBytes(bytes);
+			
+		    byte[] resBytes = new byte[ackPayload.readableBytes()];
+		    ackPayload.getBytes(0, resBytes);
+			this.bytes = resBytes;			
+		} else {
+			this.bytes = bytes;
+		}
+	}
+	
+	public void setBytes(int resultCode, byte[] bytes) {
+		this.outputType = ResultOutputType.Bytes;	
+		this.resultCode = resultCode;
+		this.bytes = bytes;
+	}
+	
+	public RequestType getRequestType() {
+		return requestType;
+	}
+
+	public void setRequestType(RequestType requestType) {
+		this.requestType = requestType;
+	}
+
+	public String getTopic() {
+		return topic;
+	}
+
+	public Callback getCallback() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public void setCallback(SendMessageCallback callback) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public boolean isNeedReturnCode() {
+		return needReturnCode;
+	}
+
+	public void setNeedReturnCode(boolean needReturnCode) {
+		this.needReturnCode = needReturnCode;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/im/WFCMessageParseTable.java b/IMserver/medeasy/src/chat/server/im/WFCMessageParseTable.java
new file mode 100644
index 0000000..b326de9
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/im/WFCMessageParseTable.java
@@ -0,0 +1,58 @@
+package chat.server.im;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.protobuf.GeneratedMessage;
+
+public class WFCMessageParseTable {
+
+	private static WFCMessageParseTable instance;
+	private Map<Class<? extends GeneratedMessage>, Method> clazzMethodMap;
+	
+	public static synchronized WFCMessageParseTable getInstance() {
+		if (instance == null) {
+			instance = new WFCMessageParseTable();
+		}
+		
+		return instance;
+	}
+	
+	private WFCMessageParseTable() {
+		clazzMethodMap = new HashMap<Class<? extends GeneratedMessage>, Method>();
+	}
+	
+	public Method getMethod(Class<? extends GeneratedMessage> clazz) {
+		if (clazz == null) {
+			return null;
+		}
+		
+		Method result = clazzMethodMap.get(clazz);
+		
+		if (result == null) {
+			synchronized (this) {
+				result = clazzMethodMap.get(clazz);
+				
+				if (result == null) {
+					result = doGetMethod(clazz);
+					clazzMethodMap.put(clazz, result);
+				}
+			}
+		}
+		
+		return result;
+	}
+
+	private Method doGetMethod(Class<? extends GeneratedMessage> clazz) {
+		try {
+			Method method = clazz.getMethod("parseFrom", byte[].class);
+			return method;
+		} 
+		catch (Exception e) {
+		} 
+		
+		return null;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/BytesMetricsCollector.java b/IMserver/medeasy/src/chat/server/moquette/BytesMetricsCollector.java
new file mode 100644
index 0000000..b54b183
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/BytesMetricsCollector.java
@@ -0,0 +1,24 @@
+package chat.server.moquette;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class BytesMetricsCollector {
+
+	private AtomicLong readBytes = new AtomicLong();
+    private AtomicLong wroteBytes = new AtomicLong();
+
+    public Metrics computeMetrics() {
+        Metrics allMetrics = new Metrics();
+        allMetrics.incrementRead(readBytes.get());
+        allMetrics.incrementWrote(wroteBytes.get());
+        return allMetrics;
+    }
+
+    public void sumReadBytes(long count) {
+        readBytes.getAndAdd(count);
+    }
+
+    public void sumWroteBytes(long count) {
+        wroteBytes.getAndAdd(count);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MessageMetricsCollector.java b/IMserver/medeasy/src/chat/server/moquette/MessageMetricsCollector.java
new file mode 100644
index 0000000..2a51975
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MessageMetricsCollector.java
@@ -0,0 +1,27 @@
+package chat.server.moquette;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MessageMetricsCollector {
+
+    private AtomicLong readMsgs = new AtomicLong();
+    private AtomicLong wroteMsgs = new AtomicLong();
+
+    public Metrics computeMetrics() {
+        Metrics metrics = new Metrics();
+        
+        metrics.incrementRead(readMsgs.get());
+        metrics.incrementWrote(wroteMsgs.get());
+        
+        return metrics;
+    }
+
+    public void sumReadMessages(long count) {
+        readMsgs.getAndAdd(count);
+    }
+
+    public void sumWroteMessages(long count) {
+        wroteMsgs.getAndAdd(count);
+    }
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/Metrics.java b/IMserver/medeasy/src/chat/server/moquette/Metrics.java
new file mode 100644
index 0000000..633778c
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/Metrics.java
@@ -0,0 +1,29 @@
+package chat.server.moquette;
+
+public class Metrics {
+
+    private long readBytes;
+    private long wroteBytes;
+
+    public void incrementRead(long numBytes) {
+    	readBytes += numBytes;
+    }
+
+    public void incrementWrote(long numBytes) {
+    	wroteBytes += numBytes;
+    }
+
+    public long readLength() {
+        return readBytes;
+    }
+
+    public long wroteLength() {
+        return wroteBytes;
+    }
+
+	@Override
+	public String toString() {
+		return "Read bytes=" + readBytes + ", written bytes=" + wroteBytes;
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttBytesMetricsHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttBytesMetricsHandler.java
new file mode 100644
index 0000000..fad8986
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttBytesMetricsHandler.java
@@ -0,0 +1,73 @@
+package chat.server.moquette;
+
+import org.apache.log4j.Logger;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.util.Attribute;
+import io.netty.util.AttributeKey;
+
+public class MqttBytesMetricsHandler extends ChannelDuplexHandler {
+	
+    private static Logger logger;
+    private static AttributeKey<Metrics> ATTR_KEY_METRICS;
+    private static AttributeKey<String> ATTR_KEY_USERNAME;
+
+    private BytesMetricsCollector collector;
+    
+    static {
+    	logger = Logger.getLogger(MqttBytesMetricsHandler.class);
+    	ATTR_KEY_METRICS = AttributeKey.valueOf("BytesMetrics");
+    	ATTR_KEY_USERNAME = AttributeKey.valueOf("username");
+    }
+
+    public MqttBytesMetricsHandler(BytesMetricsCollector collector) {
+        this.collector = collector;
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        Attribute<Metrics> attr = ctx.channel().attr(ATTR_KEY_METRICS);
+        attr.set(new Metrics());
+
+        super.channelActive(ctx);
+    }
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+        Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        metrics.incrementRead(((ByteBuf) msg).readableBytes());
+        ctx.fireChannelRead(msg);
+    }
+
+    @Override
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+        Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        metrics.incrementWrote(((ByteBuf) msg).writableBytes());
+        ctx.write(msg, promise);
+    }
+
+    @Override
+    public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+        Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        String userId = ctx.channel().attr(ATTR_KEY_USERNAME).get();
+        if (userId == null) {
+            userId = "";
+        }
+
+        logger.info("channel<" + userId + "> closing after" + metrics);
+        
+        collector.sumReadBytes(metrics.readLength());
+        collector.sumWroteBytes(metrics.wroteLength());
+        
+        super.close(ctx, promise);
+    }
+
+    public static Metrics getBytesMetrics(Channel channel) {
+        return channel.attr(ATTR_KEY_METRICS).get();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttCodecUtil.java b/IMserver/medeasy/src/chat/server/moquette/MqttCodecUtil.java
new file mode 100644
index 0000000..07f6bc5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttCodecUtil.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package chat.server.moquette;
+
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttQoS;
+import io.netty.handler.codec.DecoderException;
+
+final class MqttCodecUtil {
+
+    private static final char[] TOPIC_WILDCARDS = {'#', '+'};
+    private static final int MIN_CLIENT_ID_LENGTH = 1;
+    private static final int MAX_CLIENT_ID_LENGTH = 23;
+
+    static boolean isValidPublishTopicName(String topicName) {
+        // publish topic name must not contain any wildcard
+        for (char c : TOPIC_WILDCARDS) {
+            if (topicName.indexOf(c) >= 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static boolean isValidMessageId(int messageId) {
+        return messageId != 0;
+    }
+
+    public static boolean isValidClientId(MqttVersion mqttVersion, String clientId) {
+        if (mqttVersion == MqttVersion.MQTT_3_1) {
+            return clientId != null && clientId.length() >= MIN_CLIENT_ID_LENGTH &&
+                clientId.length() <= MAX_CLIENT_ID_LENGTH;
+        }
+        if (mqttVersion.protocolLevel() >= MqttVersion.MQTT_3_1_1.protocolLevel()) {
+            // In 3.1.3.1 Client Identifier of MQTT 3.1.1 specification, The Server MAY allow ClientId鈥檚
+            // that contain more than 23 encoded bytes. And, The Server MAY allow zero-length ClientId.
+            return clientId != null;
+        }
+        throw new IllegalArgumentException(mqttVersion + " is unknown mqtt version");
+    }
+
+    static MqttFixedHeader validateFixedHeader(MqttFixedHeader mqttFixedHeader) {
+        switch (mqttFixedHeader.messageType()) {
+            case PUBREL:
+            case SUBSCRIBE:
+            case UNSUBSCRIBE:
+                if (mqttFixedHeader.qosLevel() != MqttQoS.AT_LEAST_ONCE) {
+                    throw new DecoderException(mqttFixedHeader.messageType().name() + " message must have QoS 1");
+                }
+            default:
+                return mqttFixedHeader;
+        }
+    }
+
+    static MqttFixedHeader resetUnusedFields(MqttFixedHeader mqttFixedHeader) {
+        switch (mqttFixedHeader.messageType()) {
+            case CONNECT:
+            case CONNACK:
+            case PUBACK:
+            case PUBREC:
+            case PUBCOMP:
+            case SUBACK:
+            case UNSUBACK:
+            case PINGREQ:
+            case PINGRESP:
+            //case DISCONNECT:
+                if (mqttFixedHeader.isDup() ||
+                        mqttFixedHeader.qosLevel() != MqttQoS.AT_MOST_ONCE ||
+                        mqttFixedHeader.isRetain()) {
+                    return new MqttFixedHeader(
+                            mqttFixedHeader.messageType(),
+                            false,
+                            MqttQoS.AT_MOST_ONCE,
+                            false,
+                            mqttFixedHeader.remainingLength());
+                }
+                return mqttFixedHeader;
+            case PUBREL:
+            case SUBSCRIBE:
+            case UNSUBSCRIBE:
+                if (mqttFixedHeader.isRetain()) {
+                    return new MqttFixedHeader(
+                            mqttFixedHeader.messageType(),
+                            mqttFixedHeader.isDup(),
+                            mqttFixedHeader.qosLevel(),
+                            false,
+                            mqttFixedHeader.remainingLength());
+                }
+                return mqttFixedHeader;
+            default:
+                return mqttFixedHeader;
+        }
+    }
+
+    private MqttCodecUtil() { }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttDecodHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttDecodHandler.java
new file mode 100644
index 0000000..a9cb1ec
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttDecodHandler.java
@@ -0,0 +1,531 @@
+package chat.server.moquette;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import chat.server.moquette.MqttDecodHandler.DecoderState;
+import chat.server.moquette.message.MqttConnAckVariableHeader;
+import chat.server.moquette.message.MqttConnectPayload;
+import chat.server.moquette.message.MqttConnectReturnCode;
+import chat.server.moquette.message.MqttConnectVariableHeader;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageFactory;
+import chat.server.moquette.message.MqttMessageIdVariableHeader;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttQoS;
+import chat.server.moquette.message.MqttSubAckPayload;
+import chat.server.moquette.message.MqttSubscribePayload;
+import chat.server.moquette.message.MqttTopicSubscription;
+import chat.server.moquette.message.MqttUnsubscribePayload;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.DecoderException;
+import io.netty.handler.codec.ReplayingDecoder;
+import io.netty.util.CharsetUtil;
+
+public class MqttDecodHandler extends ReplayingDecoder<DecoderState> {
+
+    private static final int DEFAULT_MAX_BYTES_IN_MESSAGE = 262144; //256K
+    
+    private static Logger logger = Logger.getLogger(MqttDecodHandler.class);
+
+    /**
+     * States of the decoder.
+     * We start at READ_FIXED_HEADER, followed by
+     * READ_VARIABLE_HEADER and finally READ_PAYLOAD.
+     */
+    enum DecoderState {
+        READ_FIXED_HEADER,
+        READ_VARIABLE_HEADER,
+        READ_PAYLOAD,
+        BAD_MESSAGE,
+    }
+
+    private MqttFixedHeader mqttFixedHeader;
+    private Object variableHeader;
+    private int bytesRemainingInVariablePart;
+
+    private final int maxBytesInMessage;
+
+    public MqttDecodHandler() {
+      this(DEFAULT_MAX_BYTES_IN_MESSAGE);
+    }
+
+    public MqttDecodHandler(int maxBytesInMessage) {
+        super(DecoderState.READ_FIXED_HEADER);
+        logger.debug("MqttDecodHandler=>1");
+        this.maxBytesInMessage = maxBytesInMessage;
+    }
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
+    	logger.debug("begin decode");
+    	try {
+            switch (state()) {
+	            case READ_FIXED_HEADER:
+	            	logger.debug("decode Read_FIXED_HEADER");
+	                mqttFixedHeader = decodeFixedHeader(buffer);
+	                bytesRemainingInVariablePart = mqttFixedHeader.remainingLength();
+	                checkpoint(DecoderState.READ_VARIABLE_HEADER);
+	                break;
+	            case READ_VARIABLE_HEADER:  
+	            	logger.debug("decode READ_VARIABLE_HEADER");
+	                if (bytesRemainingInVariablePart > maxBytesInMessage) {
+	                    throw new DecoderException("too large message: " + bytesRemainingInVariablePart + " bytes");
+	                }
+	                final Result<?> decodedVariableHeader = decodeVariableHeader(buffer, mqttFixedHeader);
+	                variableHeader = decodedVariableHeader.value;
+	                bytesRemainingInVariablePart -= decodedVariableHeader.numberOfBytesConsumed;
+	                checkpoint(DecoderState.READ_PAYLOAD);
+	                break;
+	            case READ_PAYLOAD: 
+	            	logger.debug("decode READ_PAYLOAD");
+	                final Result<?> decodedPayload =
+	                        decodePayload(
+	                                buffer,
+	                                mqttFixedHeader.messageType(),
+	                                bytesRemainingInVariablePart,
+	                                variableHeader);
+	                bytesRemainingInVariablePart -= decodedPayload.numberOfBytesConsumed;
+	                if (bytesRemainingInVariablePart != 0) {
+	                    throw new DecoderException(
+	                            "non-zero remaining payload bytes: " +
+	                                    bytesRemainingInVariablePart + " (" + mqttFixedHeader.messageType() + ')');
+	                }
+	                checkpoint(DecoderState.READ_FIXED_HEADER);
+	                MqttMessage message = MqttMessageFactory.newMessage(
+	                        mqttFixedHeader, variableHeader, decodedPayload.value);
+	                mqttFixedHeader = null;
+	                variableHeader = null;
+	                out.add(message);
+	            case BAD_MESSAGE:
+	                // Keep discarding until disconnection.
+	            	logger.debug("decode BAD_MESSAGE");
+	                buffer.skipBytes(actualReadableBytes());
+	                break;
+	            default:
+	                // Shouldn't reach here.
+	                throw new Error();
+            }
+    	}
+    	catch (Exception cause) {
+    		cause.printStackTrace();
+        	out.add(invalidMessage(cause));
+    	}
+    }
+
+    private MqttMessage invalidMessage(Throwable cause) {
+      logger.debug("decode invalidMessage");
+      checkpoint(DecoderState.BAD_MESSAGE);
+      return MqttMessageFactory.newInvalidMessage(cause);
+    }
+
+    /**
+     * Decodes the fixed header. It's one byte for the flags and then variable bytes for the remaining length.
+     *
+     * @param buffer the buffer to decode from
+     * @return the fixed header
+     */
+    private static MqttFixedHeader decodeFixedHeader(ByteBuf buffer) {
+    	logger.debug("decode decodeFixedHeader");
+    	
+        short b1 = buffer.readUnsignedByte();
+
+        MqttMessageType messageType = MqttMessageType.valueOf(b1 >> 4);
+        boolean dupFlag = (b1 & 0x08) == 0x08;
+        int qosLevel = (b1 & 0x06) >> 1;
+        boolean retain = (b1 & 0x01) != 0;
+
+        int remainingLength = 0;
+        int multiplier = 1;
+        short digit;
+        int loops = 0;
+        do {
+            digit = buffer.readUnsignedByte();
+            remainingLength += (digit & 127) * multiplier;
+            multiplier *= 128;
+            loops++;
+        } while ((digit & 128) != 0 && loops < 4);
+
+        // MQTT protocol limits Remaining Length to 4 bytes
+        if (loops == 4 && (digit & 128) != 0) {
+            throw new DecoderException("remaining length exceeds 4 digits (" + messageType + ')');
+        }
+        MqttFixedHeader decodedFixedHeader =
+                new MqttFixedHeader(messageType, dupFlag, MqttQoS.valueOf(qosLevel), retain, remainingLength);
+        return MqttCodecUtil.validateFixedHeader(MqttCodecUtil.resetUnusedFields(decodedFixedHeader));
+    }
+
+    /**
+     * Decodes the variable header (if any)
+     * @param buffer the buffer to decode from
+     * @param mqttFixedHeader MqttFixedHeader of the same message
+     * @return the variable header
+     */
+    private static Result<?> decodeVariableHeader(ByteBuf buffer, MqttFixedHeader mqttFixedHeader) {
+        switch (mqttFixedHeader.messageType()) {
+            case CONNECT:
+            	logger.debug("decode==>decodeVariableHeader==>CONNECT");
+                return decodeConnectionVariableHeader(buffer);
+
+            case CONNACK:
+            	logger.debug("decode==>decodeVariableHeader==>CONNACK");
+                return decodeConnAckVariableHeader(buffer);
+
+            case SUBSCRIBE:
+            case UNSUBSCRIBE:
+            case SUBACK:
+            case UNSUBACK:
+            case PUBACK:
+            case PUBREC:
+            case PUBCOMP:
+            case PUBREL:
+            	logger.debug("decode==>decodeVariableHeader==>PUBREL");
+                return decodeMessageIdVariableHeader(buffer);
+
+            case PUBLISH:
+            	logger.debug("decode==>decodeVariableHeader==>PUBLISH");
+                return decodePublishVariableHeader(buffer, mqttFixedHeader);
+
+            case PINGREQ:
+            case PINGRESP:
+            case DISCONNECT:
+                // Empty variable header
+            	logger.debug("decode==>decodeVariableHeader==>DISCONNECT");
+                return new Result<Object>(null, 0);
+        }
+        return new Result<Object>(null, 0); //should never reach here
+    }
+
+    private static Result<MqttConnectVariableHeader> decodeConnectionVariableHeader(ByteBuf buffer) {
+    	logger.debug("decode==>decodeConnectionVariableHeader");
+    	
+        final Result<String> protoString = decodeString(buffer);
+        int numberOfBytesConsumed = protoString.numberOfBytesConsumed;
+
+        final byte protocolLevel = buffer.readByte();
+        numberOfBytesConsumed += 1;
+
+        final MqttVersion mqttVersion = MqttVersion.fromProtocolNameAndLevel(protoString.value, protocolLevel);
+
+        final int b1 = buffer.readUnsignedByte();
+        numberOfBytesConsumed += 1;
+
+        final Result<Integer> keepAlive = decodeMsbLsb(buffer);
+        numberOfBytesConsumed += keepAlive.numberOfBytesConsumed;
+
+        final boolean hasUserName = (b1 & 0x80) == 0x80;
+        final boolean hasPassword = (b1 & 0x40) == 0x40;
+        final boolean willRetain = (b1 & 0x20) == 0x20;
+        final int willQos = (b1 & 0x18) >> 3;
+        final boolean willFlag = (b1 & 0x04) == 0x04;
+        final boolean cleanSession = (b1 & 0x02) == 0x02;
+        if (mqttVersion.protocolLevel() >= MqttVersion.MQTT_3_1_1.protocolLevel()) {
+            final boolean zeroReservedFlag = (b1 & 0x01) == 0x0;
+            if (!zeroReservedFlag) {
+                // MQTT v3.1.1: The Server MUST validate that the reserved flag in the CONNECT Control Packet is
+                // set to zero and disconnect the Client if it is not zero.
+                // See http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349230
+                throw new DecoderException("non-zero reserved flag");
+            }
+        }
+
+        final MqttConnectVariableHeader mqttConnectVariableHeader = new MqttConnectVariableHeader(
+                mqttVersion.protocolName(),
+                mqttVersion.protocolLevel(),
+                hasUserName,
+                hasPassword,
+                willRetain,
+                willQos,
+                willFlag,
+                cleanSession,
+                keepAlive.value);
+        return new Result<MqttConnectVariableHeader>(mqttConnectVariableHeader, numberOfBytesConsumed);
+    }
+
+    private static Result<MqttConnAckVariableHeader> decodeConnAckVariableHeader(ByteBuf buffer) {
+    	logger.debug("decode==>decodeConnAckVariableHeader");
+    	
+        final boolean sessionPresent = (buffer.readUnsignedByte() & 0x01) == 0x01;
+        byte returnCode = buffer.readByte();
+        final int numberOfBytesConsumed = 2;
+        final MqttConnAckVariableHeader mqttConnAckVariableHeader =
+                new MqttConnAckVariableHeader(MqttConnectReturnCode.valueOf(returnCode), sessionPresent);
+        return new Result<MqttConnAckVariableHeader>(mqttConnAckVariableHeader, numberOfBytesConsumed);
+    }
+
+    private static Result<MqttMessageIdVariableHeader> decodeMessageIdVariableHeader(ByteBuf buffer) {
+    	logger.debug("decode==>decodeMessageIdVariableHeader");
+    	
+        final Result<Integer> messageId = decodeMessageId(buffer);
+        return new Result<MqttMessageIdVariableHeader>(
+                MqttMessageIdVariableHeader.from(messageId.value),
+                messageId.numberOfBytesConsumed);
+    }
+
+    private static Result<MqttPublishVariableHeader> decodePublishVariableHeader(
+            ByteBuf buffer,
+            MqttFixedHeader mqttFixedHeader) {
+    	logger.debug("decode==>decodePublishVariableHeader");
+    	
+        final Result<String> decodedTopic = decodeString(buffer);
+        if (!MqttCodecUtil.isValidPublishTopicName(decodedTopic.value)) {
+            throw new DecoderException("invalid publish topic name: " + decodedTopic.value + " (contains wildcards)");
+        }
+        int numberOfBytesConsumed = decodedTopic.numberOfBytesConsumed;
+
+        int messageId = -1;
+        if (mqttFixedHeader.qosLevel().value() > 0) {
+            final Result<Integer> decodedMessageId = decodeMessageId(buffer);
+            messageId = decodedMessageId.value;
+            numberOfBytesConsumed += decodedMessageId.numberOfBytesConsumed;
+        }
+        final MqttPublishVariableHeader mqttPublishVariableHeader =
+                new MqttPublishVariableHeader(decodedTopic.value, messageId);
+        return new Result<MqttPublishVariableHeader>(mqttPublishVariableHeader, numberOfBytesConsumed);
+    }
+
+    private static Result<Integer> decodeMessageId(ByteBuf buffer) {
+    	logger.debug("decode==>decodeMessageId");
+    	
+        final Result<Integer> messageId = decodeMsbLsb(buffer);
+        if (!MqttCodecUtil.isValidMessageId(messageId.value)) {
+            throw new DecoderException("invalid messageId: " + messageId.value);
+        }
+        return messageId;
+    }
+
+    /**
+     * Decodes the payload.
+     *
+     * @param buffer the buffer to decode from
+     * @param messageType  type of the message being decoded
+     * @param bytesRemainingInVariablePart bytes remaining
+     * @param variableHeader variable header of the same message
+     * @return the payload
+     */
+    private static Result<?> decodePayload(
+            ByteBuf buffer,
+            MqttMessageType messageType,
+            int bytesRemainingInVariablePart,
+            Object variableHeader) {
+        switch (messageType) {
+            case CONNECT:
+            	logger.debug("decode==>decodePayload==>CONNECT");
+                return decodeConnectionPayload(buffer, (MqttConnectVariableHeader) variableHeader);
+
+            case SUBSCRIBE:
+            	logger.debug("decode==>decodePayload==>SUBSCRIBE");
+                return decodeSubscribePayload(buffer, bytesRemainingInVariablePart);
+
+            case SUBACK:
+            	logger.debug("decode==>decodePayload==>SUBACK");
+                return decodeSubackPayload(buffer, bytesRemainingInVariablePart);
+
+            case UNSUBSCRIBE:
+            	logger.debug("decode==>decodePayload==>UNSUBSCRIBE");
+                return decodeUnsubscribePayload(buffer, bytesRemainingInVariablePart);
+
+            case PUBLISH:
+            	logger.debug("decode==>decodePayload==>PUBLISH");
+                return decodePublishPayload(buffer, bytesRemainingInVariablePart);
+
+            default:
+                // unknown payload , no byte consumed
+                return new Result<Object>(null, 0);
+        }
+    }
+
+    private static Result<MqttConnectPayload> decodeConnectionPayload(
+            ByteBuf buffer,
+            MqttConnectVariableHeader mqttConnectVariableHeader) {
+    	logger.debug("decode==>decodeConnectionPayload");
+    	
+        final Result<String> decodedClientId = decodeString(buffer);
+        final String decodedClientIdValue = decodedClientId.value;
+        final MqttVersion mqttVersion = MqttVersion.fromProtocolNameAndLevel(mqttConnectVariableHeader.name(),
+                (byte) mqttConnectVariableHeader.version());
+        if (!MqttCodecUtil.isValidClientId(mqttVersion, decodedClientIdValue)) {
+            throw new MqttIdentifierRejectedException("invalid clientIdentifier: " + decodedClientIdValue);
+        }
+        int numberOfBytesConsumed = decodedClientId.numberOfBytesConsumed;
+
+        Result<String> decodedWillTopic = null;
+        Result<String> decodedWillMessage = null;
+        if (mqttConnectVariableHeader.isWillFlag()) {
+            decodedWillTopic = decodeString(buffer, 0, 32767);
+            numberOfBytesConsumed += decodedWillTopic.numberOfBytesConsumed;
+            decodedWillMessage = decodeAsciiString(buffer);
+            numberOfBytesConsumed += decodedWillMessage.numberOfBytesConsumed;
+        }
+        Result<String> decodedUserName = null;
+        Result<byte[]> decodedPassword = null;
+        if (mqttConnectVariableHeader.hasUserName()) {
+            decodedUserName = decodeString(buffer);
+            numberOfBytesConsumed += decodedUserName.numberOfBytesConsumed;
+        }
+        if (mqttConnectVariableHeader.hasPassword()) {
+            decodedPassword = decodeByte(buffer);
+            numberOfBytesConsumed += decodedPassword.numberOfBytesConsumed;
+        }
+
+        final MqttConnectPayload mqttConnectPayload =
+                new MqttConnectPayload(
+                        decodedClientId.value,
+                        decodedWillTopic != null ? decodedWillTopic.value : null,
+                        decodedWillMessage != null ? decodedWillMessage.value : null,
+                        decodedUserName != null ? decodedUserName.value : null,
+                        decodedPassword != null ? decodedPassword.value : null);
+        return new Result<MqttConnectPayload>(mqttConnectPayload, numberOfBytesConsumed);
+    }
+
+    private static Result<MqttSubscribePayload> decodeSubscribePayload(
+            ByteBuf buffer,
+            int bytesRemainingInVariablePart) {
+    	logger.debug("decode==>decodeSubscribePayload");
+    	
+        final List<MqttTopicSubscription> subscribeTopics = new ArrayList<MqttTopicSubscription>();
+        int numberOfBytesConsumed = 0;
+        while (numberOfBytesConsumed < bytesRemainingInVariablePart) {
+            final Result<String> decodedTopicName = decodeString(buffer);
+            numberOfBytesConsumed += decodedTopicName.numberOfBytesConsumed;
+            int qos = buffer.readUnsignedByte() & 0x03;
+            numberOfBytesConsumed++;
+            subscribeTopics.add(new MqttTopicSubscription(decodedTopicName.value, MqttQoS.valueOf(qos)));
+        }
+        return new Result<MqttSubscribePayload>(new MqttSubscribePayload(subscribeTopics), numberOfBytesConsumed);
+    }
+
+    private static Result<MqttSubAckPayload> decodeSubackPayload(
+            ByteBuf buffer,
+            int bytesRemainingInVariablePart) {
+    	logger.debug("decode==>decodeSubackPayload");
+    	
+        final List<Integer> grantedQos = new ArrayList<Integer>();
+        int numberOfBytesConsumed = 0;
+        while (numberOfBytesConsumed < bytesRemainingInVariablePart) {
+            int qos = buffer.readUnsignedByte() & 0x03;
+            numberOfBytesConsumed++;
+            grantedQos.add(qos);
+        }
+        return new Result<MqttSubAckPayload>(new MqttSubAckPayload(grantedQos), numberOfBytesConsumed);
+    }
+
+    private static Result<MqttUnsubscribePayload> decodeUnsubscribePayload(
+            ByteBuf buffer,
+            int bytesRemainingInVariablePart) {
+    	logger.debug("decode==>decodeUnsubscribePayload");
+    	
+        final List<String> unsubscribeTopics = new ArrayList<String>();
+        int numberOfBytesConsumed = 0;
+        while (numberOfBytesConsumed < bytesRemainingInVariablePart) {
+            final Result<String> decodedTopicName = decodeString(buffer);
+            numberOfBytesConsumed += decodedTopicName.numberOfBytesConsumed;
+            unsubscribeTopics.add(decodedTopicName.value);
+        }
+        return new Result<MqttUnsubscribePayload>(
+                new MqttUnsubscribePayload(unsubscribeTopics),
+                numberOfBytesConsumed);
+    }
+
+    private static Result<ByteBuf> decodePublishPayload(ByteBuf buffer, int bytesRemainingInVariablePart) {
+    	logger.debug("decode==>decodePublishPayload");
+    	
+        ByteBuf b = buffer.readRetainedSlice(bytesRemainingInVariablePart);
+        return new Result<ByteBuf>(b, bytesRemainingInVariablePart);
+    }
+
+    private static Result<String> decodeString(ByteBuf buffer) {
+    	logger.debug("decode==>decodeString");
+    	
+        return decodeString(buffer, 0, Integer.MAX_VALUE);
+    }
+
+    private static Result<String> decodeAsciiString(ByteBuf buffer) {
+    	logger.debug("decode==>decodeAsciiString");
+    	
+        Result<String> result = decodeString(buffer, 0, Integer.MAX_VALUE);
+        final String s = result.value;
+        for (int i = 0; i < s.length(); i++) {
+            if (s.charAt(i) > 127) {
+                return new Result<String>(null, result.numberOfBytesConsumed);
+            }
+        }
+        return new Result<String>(s, result.numberOfBytesConsumed);
+    }
+
+    private static Result<byte[]> decodeByte(ByteBuf buffer) {
+    	logger.debug("decode==>decodeByte");
+    	
+        return decodeByte(buffer, 0, Integer.MAX_VALUE);
+    }
+
+    private static Result<String> decodeString(ByteBuf buffer, int minBytes, int maxBytes) {
+    	logger.debug("decode==>decodeString");
+    	
+        final Result<Integer> decodedSize = decodeMsbLsb(buffer);
+        int size = decodedSize.value;
+        int numberOfBytesConsumed = decodedSize.numberOfBytesConsumed;
+        if (size < minBytes || size > maxBytes) {
+            buffer.skipBytes(size);
+            numberOfBytesConsumed += size;
+            return new Result<String>(null, numberOfBytesConsumed);
+        }
+        String s = buffer.toString(buffer.readerIndex(), size, CharsetUtil.UTF_8);
+        buffer.skipBytes(size);
+        numberOfBytesConsumed += size;
+        return new Result<String>(s, numberOfBytesConsumed);
+    }
+
+    private static Result<byte[]> decodeByte(ByteBuf buffer, int minBytes, int maxBytes) {
+    	logger.debug("decode==>decodeByte");
+    	
+        final Result<Integer> decodedSize = decodeMsbLsb(buffer);
+        int size = decodedSize.value;
+        int numberOfBytesConsumed = decodedSize.numberOfBytesConsumed;
+        if (size < minBytes || size > maxBytes) {
+            buffer.skipBytes(size);
+            numberOfBytesConsumed += size;
+            return new Result<>(null, numberOfBytesConsumed);
+        }
+        byte[] s = new byte[size];
+        buffer.getBytes(buffer.readerIndex(), s, 0, size);
+        buffer.skipBytes(size);
+        numberOfBytesConsumed += size;
+        return new Result<>(s, numberOfBytesConsumed);
+    }
+
+    private static Result<Integer> decodeMsbLsb(ByteBuf buffer) {
+    	logger.debug("decode==>decodeMsbLsb=>1");
+    	
+        return decodeMsbLsb(buffer, 0, 65535);
+    }
+
+    private static Result<Integer> decodeMsbLsb(ByteBuf buffer, int min, int max) {
+    	logger.debug("decode==>decodeMsbLsb=>2");
+    	
+        short msbSize = buffer.readUnsignedByte();
+        short lsbSize = buffer.readUnsignedByte();
+        final int numberOfBytesConsumed = 2;
+        int result = msbSize << 8 | lsbSize;
+        if (result < min || result > max) {
+            result = -1;
+        }
+        return new Result<Integer>(result, numberOfBytesConsumed);
+    }
+
+    private static final class Result<T> {
+
+        private final T value;
+        private final int numberOfBytesConsumed;
+
+        Result(T value, int numberOfBytesConsumed) {
+            this.value = value;
+            this.numberOfBytesConsumed = numberOfBytesConsumed;
+        }
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttDispatcher.java b/IMserver/medeasy/src/chat/server/moquette/MqttDispatcher.java
new file mode 100644
index 0000000..38854a0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttDispatcher.java
@@ -0,0 +1,249 @@
+package chat.server.moquette;
+
+import org.apache.log4j.Logger;
+
+import chat.server.ServerInstance;
+import chat.server.im.IMDispatcher;
+import chat.server.moquette.message.ClientID;
+import chat.server.moquette.message.MqttConnAckMessage;
+import chat.server.moquette.message.MqttConnAckVariableHeader;
+import chat.server.moquette.message.MqttConnectAckPayload;
+import chat.server.moquette.message.MqttConnectMessage;
+import chat.server.moquette.message.MqttConnectPayload;
+import chat.server.moquette.message.MqttConnectReturnCode;
+import chat.server.moquette.message.MqttConnectVariableHeader;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttQoS;
+import chat.user.Session;
+import chat.user.SessionStore;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.ConnectAckPayload;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.AttributeKey;
+import io.netty.util.ReferenceCountUtil;
+
+public class MqttDispatcher extends ChannelInboundHandlerAdapter {
+
+    private static AttributeKey<Object> ATTR_KEEPALIVE = AttributeKey.valueOf("keepAlive");
+    private static AttributeKey<Object> ATTR_CLEANSESSION = AttributeKey.valueOf("cleanSession");
+    private static AttributeKey<Object> ATTR_CLIENTID = AttributeKey.valueOf("ClientID");
+
+	private static Logger logger;
+	private static IMDispatcher imDispatcher;
+	
+	static {
+		logger = Logger.getLogger(MqttDispatcher.class);
+		imDispatcher = new IMDispatcher();
+	}
+	
+	public MqttDispatcher() {
+		
+	}
+	
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object message) {
+        try {
+            MqttMessage msg = (MqttMessage) message;
+            MqttMessageType messageType = msg.messageType();
+            
+            logger.info("Processing MQTT message, type=" + messageType);
+            
+            Channel channel = ctx.channel();
+
+            switch (messageType) {
+                case CONNECT:
+                    processConnect(channel, msg);
+                    break;
+                case DISCONNECT:
+                    processDisconnect(channel, msg);
+                    break;
+                case PUBLISH:
+                	MqttPublishMessage mess = (MqttPublishMessage) msg;
+                	String topic = mess.variableHeader().topicName();
+                	if (topic.equals("MP")) {
+                		System.out.println("MP");
+                	}
+                    processPublish(channel, msg);
+                    break;
+                case PINGREQ:
+                	processPing(channel, msg);
+                    break;
+                default:
+                	logger.error("Unkonwn MessageType:" + messageType);
+                    break;
+            }
+        } 
+        catch (Throwable ex) {
+        	logger.error("Exception was caught while processing MQTT message, " + ex.getCause(), ex);
+            ctx.fireExceptionCaught(ex);
+            ctx.close();
+        } 
+        finally {
+            ReferenceCountUtil.release(message);
+        }
+    }
+    
+	public void processConnect(Channel channel, MqttMessage msg) {
+    	if (logger.isDebugEnabled()) {
+            logger.debug("receive connect(channel=)" + channel.id());
+    	}
+    	
+		MqttConnectMessage message = (MqttConnectMessage) msg;
+        MqttConnectPayload payload = message.payload();
+        
+        ClientID clientID = ClientID.valueOf(payload);
+
+        //1. if starting or terminated
+        if (!ServerInstance.isStart()) {
+            channel.close();
+            return;
+        }
+        
+        //2. if empty client id
+        if (clientID.isEmpty()) {
+            MqttConnAckMessage badIdMessage = createConnAckMessageFalse(MqttConnectReturnCode.CONNECTION_REFUSED_IDENTIFIER_REJECTED, null);
+            channel.writeAndFlush(badIdMessage);
+            channel.close();
+            return;
+        }
+        
+        //3. set channel attribute
+        MqttConnectVariableHeader header = message.variableHeader();
+        customizeChannel(channel, clientID, header);
+        
+        //4. session
+        clientID.setValueTo(channel);
+        
+        Session session = SessionStore.get(clientID);
+        
+        if (session != null) {
+            session.setChannel(channel);
+            session.refreshLastActiveTime();
+        }
+        
+        //5. write ACK message
+        ConnectAckPayload ackPayload = createConnAckPayload(session);
+        MqttConnAckMessage successMessage = createConnAckMessage(MqttConnectReturnCode.CONNECTION_ACCEPTED, ackPayload.toByteArray());
+        channel.writeAndFlush(successMessage);
+        
+        //6. notify user state
+//        User user = session.getUser();
+//        user.notify(PublishedOperator.Online);
+    }
+    
+    private ConnectAckPayload createConnAckPayload(Session session) {
+    	long timestamp = System.currentTimeMillis();
+        long messageHead = timestamp; //session.getMessageHead();
+        long friendHead = timestamp;//session.getFriendHead();
+        long friendRqHead = timestamp;//session.getFriendRqHead();
+        long settingHead = timestamp;//session.getSettingHead();
+        
+        ConnectAckPayload.Builder builder = WFCMessage.ConnectAckPayload.newBuilder();
+        builder.setMsgHead(messageHead);
+        builder.setFriendHead(friendHead);
+        builder.setFriendRqHead(friendRqHead);
+        builder.setSettingHead(settingHead);
+        builder.setServerTime(System.currentTimeMillis());     
+
+        ConnectAckPayload payload = builder.build();
+        return payload;
+    }
+    
+	private MqttConnAckMessage createConnAckMessage(MqttConnectReturnCode code, byte[] data) {
+        MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNACK, false, MqttQoS.AT_MOST_ONCE, false, 0);
+        MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(code, true);
+        
+        MqttConnAckMessage result = new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader, new MqttConnectAckPayload(data));
+		return result;
+	}
+	
+	private MqttConnAckMessage createConnAckMessageFalse(MqttConnectReturnCode code, byte[] data) {
+        MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(MqttMessageType.CONNACK, false, MqttQoS.AT_MOST_ONCE, false, 0);
+        MqttConnAckVariableHeader mqttConnAckVariableHeader = new MqttConnAckVariableHeader(code, false);
+        
+        MqttConnAckMessage result = new MqttConnAckMessage(mqttFixedHeader, mqttConnAckVariableHeader, new MqttConnectAckPayload(data));
+		return result;
+	}	
+    
+	private void customizeChannel(Channel channel, ClientID clientID, MqttConnectVariableHeader header) {
+		//1. set clientID
+		channel.attr(ATTR_CLIENTID).set(clientID.getValue());
+		
+		//2. live time
+        int keepAliveTimeSeconds = header.keepAliveTimeSeconds();
+		channel.attr(ATTR_KEEPALIVE).set(keepAliveTimeSeconds);
+		
+		//3.  clean session
+		boolean cleanSession = header.isCleanSession();
+		channel.attr(ATTR_CLEANSESSION).set(cleanSession);
+
+		//4. idle time
+		ChannelPipeline pipeline = channel.pipeline();
+		
+        if (pipeline.names().contains("idleStateHandler")) {
+            pipeline.remove("idleStateHandler");
+        }
+        
+        int idleTime = Math.round(keepAliveTimeSeconds * 1.5f);
+        pipeline.addFirst("idleStateHandler", new IdleStateHandler(idleTime, 0, 0));
+	}
+
+	public void processDisconnect(Channel channel, MqttMessage msg) throws InterruptedException {
+    	if (logger.isDebugEnabled()) {
+            logger.debug("receive disconnect(channel=)" + channel.id());
+    	}
+    	
+    	ClientID clientID = ClientID.valueOf(channel);
+    	
+    	//1. flush
+    	channel.flush();
+
+    	//2. if empty
+        if (clientID.isEmpty()) {
+            channel.close();
+            return;
+        }
+
+        //3. close session channel
+        Session session = SessionStore.get(clientID);
+        
+        if (session == null) {
+        	return;
+        }
+        
+        session.refreshLastActiveTime();
+        session.closeChannel();
+        
+        //4. delete session
+        SessionStore.delete(clientID);
+    }
+    
+    public void processPublish(Channel channel, MqttMessage message) throws Exception {
+    	if (logger.isDebugEnabled()) {
+    		logger.debug("receive request(channel=)" + channel.id() + ": publish");
+    	}
+    	
+    	MqttPublishMessage publishMessage = (MqttPublishMessage) message;
+    	imDispatcher.channelRead0(channel, publishMessage);
+    }
+    
+    private void processPing(Channel channel, MqttMessage message) {
+    	if (logger.isDebugEnabled()) {
+        	logger.debug("receive ping(channel=)" + channel.id());
+    	}
+    	
+        MqttFixedHeader pingHeader = new MqttFixedHeader(MqttMessageType.PINGRESP, false, MqttQoS.AT_MOST_ONCE, false, 0);
+        MqttMessage result = new MqttMessage(pingHeader);
+        channel.writeAndFlush(result);		
+	}
+    
+    
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttEncodHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttEncodHandler.java
new file mode 100644
index 0000000..14d4818
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttEncodHandler.java
@@ -0,0 +1,451 @@
+package chat.server.moquette;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import chat.server.moquette.message.MqttConnAckMessage;
+import chat.server.moquette.message.MqttConnectAckPayload;
+import chat.server.moquette.message.MqttConnectMessage;
+import chat.server.moquette.message.MqttConnectPayload;
+import chat.server.moquette.message.MqttConnectVariableHeader;
+import chat.server.moquette.message.MqttFixedHeader;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageIdVariableHeader;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttPublishVariableHeader;
+import chat.server.moquette.message.MqttSubAckMessage;
+import chat.server.moquette.message.MqttSubscribeMessage;
+import chat.server.moquette.message.MqttSubscribePayload;
+import chat.server.moquette.message.MqttTopicSubscription;
+import chat.server.moquette.message.MqttUnsubscribeMessage;
+import chat.server.moquette.message.MqttUnsubscribePayload;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import io.netty.util.CharsetUtil;
+import io.netty.util.internal.EmptyArrays;
+
+public class MqttEncodHandler extends MessageToMessageEncoder<MqttMessage> {
+
+    public static final MqttEncodHandler INSTANCE = new MqttEncodHandler();
+    
+    private static Logger logger = Logger.getLogger(MqttEncodHandler.class);
+
+    public MqttEncodHandler() { }
+    
+	public static ChannelHandler getInstance() {
+		return INSTANCE;
+	}
+
+    @Override
+    protected void encode(ChannelHandlerContext ctx, MqttMessage msg, List<Object> out) throws Exception {
+    	//logger.debug("begin encode");
+        out.add(doEncode(ctx.alloc(), msg));
+    }
+
+    /**
+     * This is the main encoding method.
+     * It's only visible for testing.
+     *
+     * @param byteBufAllocator Allocates ByteBuf
+     * @param message MQTT message to encode
+     * @return ByteBuf with encoded bytes
+     */
+    static ByteBuf doEncode(ByteBufAllocator byteBufAllocator, MqttMessage message) {
+    	try {
+            switch (message.fixedHeader().messageType()) {
+	            case CONNECT:
+	            	logger.debug("encode CONNECT");
+	                return encodeConnectMessage(byteBufAllocator, (MqttConnectMessage) message);
+	
+	            case CONNACK:
+	            	logger.debug("encode CONNACK");
+	                return encodeConnAckMessage(byteBufAllocator, (MqttConnAckMessage) message);
+	
+	            case PUBLISH:
+	            	logger.debug("encode PUBLISH");
+	                return encodePublishMessage(byteBufAllocator, (MqttPublishMessage) message);
+	
+	            case SUBSCRIBE:
+	            	logger.debug("encode SUBSCRIBE");
+	                return encodeSubscribeMessage(byteBufAllocator, (MqttSubscribeMessage) message);
+	
+	            case UNSUBSCRIBE:
+	            	logger.debug("encode UNSUBSCRIBE");
+	                return encodeUnsubscribeMessage(byteBufAllocator, (MqttUnsubscribeMessage) message);
+	
+	            case SUBACK:
+	            	logger.debug("encode SUBACK");
+	                return encodeSubAckMessage(byteBufAllocator, (MqttSubAckMessage) message);
+	
+	            case UNSUBACK:
+	            case PUBACK:
+	            case PUBREC:
+	            case PUBREL:
+	            case PUBCOMP:
+	            	logger.debug("encode PUBCOMP");
+	                return encodeMessageWithOnlySingleByteFixedHeaderAndMessageId(byteBufAllocator, message);
+	
+	            case PINGREQ:
+	            case PINGRESP:
+	            case DISCONNECT:
+	            	logger.debug("encode DISCONNECT");
+	                return encodeMessageWithOnlySingleByteFixedHeader(byteBufAllocator, message);
+	
+	            default:
+	                throw new IllegalArgumentException(
+	                        "Unknown message type: " + message.fixedHeader().messageType().value());
+	        }
+    	}
+    	catch (Exception e) {
+    		e.printStackTrace();
+    		return null;
+    	}
+    }
+
+    private static ByteBuf encodeConnectMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttConnectMessage message) {
+    	logger.debug("encode encodeConnectMessage");
+    	
+        int payloadBufferSize = 0;
+
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        MqttConnectVariableHeader variableHeader = message.variableHeader();
+        MqttConnectPayload payload = message.payload();
+        MqttVersion mqttVersion = MqttVersion.fromProtocolNameAndLevel(variableHeader.name(),
+                (byte) variableHeader.version());
+
+        // Client id
+        String clientIdentifier = payload.clientIdentifier();
+        if (!MqttCodecUtil.isValidClientId(mqttVersion, clientIdentifier)) {
+            throw new MqttIdentifierRejectedException("invalid clientIdentifier: " + clientIdentifier);
+        }
+        byte[] clientIdentifierBytes = encodeStringUtf8(clientIdentifier);
+        payloadBufferSize += 2 + clientIdentifierBytes.length;
+
+        // Will topic and message
+        String willTopic = payload.willTopic();
+        byte[] willTopicBytes = willTopic != null ? encodeStringUtf8(willTopic) : EmptyArrays.EMPTY_BYTES;
+        String willMessage = payload.willMessage();
+        byte[] willMessageBytes = willMessage != null ? encodeStringUtf8(willMessage) : EmptyArrays.EMPTY_BYTES;
+        if (variableHeader.isWillFlag()) {
+            payloadBufferSize += 2 + willTopicBytes.length;
+            payloadBufferSize += 2 + willMessageBytes.length;
+        }
+
+        String userName = payload.userName();
+        byte[] userNameBytes = userName != null ? encodeStringUtf8(userName) : EmptyArrays.EMPTY_BYTES;
+        if (variableHeader.hasUserName()) {
+            payloadBufferSize += 2 + userNameBytes.length;
+        }
+
+        byte[] passwordBytes = payload.password();
+        if (variableHeader.hasPassword()) {
+            payloadBufferSize += 2 + passwordBytes.length;
+        }
+
+        // Fixed header
+        byte[] protocolNameBytes = mqttVersion.protocolNameBytes();
+        int variableHeaderBufferSize = 2 + protocolNameBytes.length + 4;
+        int variablePartSize = variableHeaderBufferSize + payloadBufferSize;
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variablePartSize);
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variablePartSize);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        writeVariableLengthInt(buf, variablePartSize);
+
+        buf.writeShort(protocolNameBytes.length);
+        buf.writeBytes(protocolNameBytes);
+
+        buf.writeByte(variableHeader.version());
+        buf.writeByte(getConnVariableHeaderFlag(variableHeader));
+        buf.writeShort(variableHeader.keepAliveTimeSeconds());
+
+        // Payload
+        buf.writeShort(clientIdentifierBytes.length);
+        buf.writeBytes(clientIdentifierBytes, 0, clientIdentifierBytes.length);
+        if (variableHeader.isWillFlag()) {
+            buf.writeShort(willTopicBytes.length);
+            buf.writeBytes(willTopicBytes, 0, willTopicBytes.length);
+            buf.writeShort(willMessageBytes.length);
+            buf.writeBytes(willMessageBytes, 0, willMessageBytes.length);
+        }
+        if (variableHeader.hasUserName()) {
+            buf.writeShort(userNameBytes.length);
+            buf.writeBytes(userNameBytes, 0, userNameBytes.length);
+        }
+        if (variableHeader.hasPassword()) {
+            buf.writeShort(passwordBytes.length);
+            buf.writeBytes(passwordBytes, 0, passwordBytes.length);
+        }
+        return buf;
+    }
+
+    private static int getConnVariableHeaderFlag(MqttConnectVariableHeader variableHeader) {
+    	logger.debug("encode getConnVariableHeaderFlag");
+    	
+        int flagByte = 0;
+        if (variableHeader.hasUserName()) {
+            flagByte |= 0x80;
+        }
+        if (variableHeader.hasPassword()) {
+            flagByte |= 0x40;
+        }
+        if (variableHeader.isWillRetain()) {
+            flagByte |= 0x20;
+        }
+        flagByte |= (variableHeader.willQos() & 0x03) << 3;
+        if (variableHeader.isWillFlag()) {
+            flagByte |= 0x04;
+        }
+        if (variableHeader.isCleanSession()) {
+            flagByte |= 0x02;
+        }
+        return flagByte;
+    }
+
+    private static ByteBuf encodeConnAckMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttConnAckMessage message) {
+    	logger.debug("encode encodeConnAckMessage");
+    	
+        int length = 4;
+        MqttConnectAckPayload payload = null;
+        if (message.payload() != null) {
+            payload = (MqttConnectAckPayload)message.payload();
+            if (payload.getData() != null && payload.getData().length > 0) {
+                length += payload.getData().length;
+            }
+        }
+        ByteBuf buf = byteBufAllocator.buffer(length);
+        buf.writeByte(getFixedHeaderByte1(message.fixedHeader()));
+        buf.writeByte(length - 2);
+        buf.writeByte(message.variableHeader().isSessionPresent() ? 0x01 : 0x00);
+        buf.writeByte(message.variableHeader().connectReturnCode().byteValue());
+        if (length > 4) {
+            buf.writeBytes(payload.getData());
+        }
+
+        return buf;
+    }
+
+    private static ByteBuf encodeSubscribeMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttSubscribeMessage message) {
+    	logger.debug("encode encodeSubscribeMessage");
+    	
+        int variableHeaderBufferSize = 2;
+        int payloadBufferSize = 0;
+
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        MqttMessageIdVariableHeader variableHeader = message.variableHeader();
+        MqttSubscribePayload payload = message.payload();
+
+        for (MqttTopicSubscription topic : payload.topicSubscriptions()) {
+            String topicName = topic.topicName();
+            byte[] topicNameBytes = encodeStringUtf8(topicName);
+            payloadBufferSize += 2 + topicNameBytes.length;
+            payloadBufferSize += 1;
+        }
+
+        int variablePartSize = variableHeaderBufferSize + payloadBufferSize;
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variablePartSize);
+
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variablePartSize);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        writeVariableLengthInt(buf, variablePartSize);
+
+        // Variable Header
+        int messageId = variableHeader.messageId();
+        buf.writeShort(messageId);
+
+        // Payload
+        for (MqttTopicSubscription topic : payload.topicSubscriptions()) {
+            String topicName = topic.topicName();
+            byte[] topicNameBytes = encodeStringUtf8(topicName);
+            buf.writeShort(topicNameBytes.length);
+            buf.writeBytes(topicNameBytes, 0, topicNameBytes.length);
+            buf.writeByte(topic.qualityOfService().value());
+        }
+
+        return buf;
+    }
+
+    private static ByteBuf encodeUnsubscribeMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttUnsubscribeMessage message) {
+    	logger.debug("encode encodeUnsubscribeMessage");
+    	
+        int variableHeaderBufferSize = 2;
+        int payloadBufferSize = 0;
+
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        MqttMessageIdVariableHeader variableHeader = message.variableHeader();
+        MqttUnsubscribePayload payload = message.payload();
+
+        for (String topicName : payload.topics()) {
+            byte[] topicNameBytes = encodeStringUtf8(topicName);
+            payloadBufferSize += 2 + topicNameBytes.length;
+        }
+
+        int variablePartSize = variableHeaderBufferSize + payloadBufferSize;
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variablePartSize);
+
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variablePartSize);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        writeVariableLengthInt(buf, variablePartSize);
+
+        // Variable Header
+        int messageId = variableHeader.messageId();
+        buf.writeShort(messageId);
+
+        // Payload
+        for (String topicName : payload.topics()) {
+            byte[] topicNameBytes = encodeStringUtf8(topicName);
+            buf.writeShort(topicNameBytes.length);
+            buf.writeBytes(topicNameBytes, 0, topicNameBytes.length);
+        }
+
+        return buf;
+    }
+
+    private static ByteBuf encodeSubAckMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttSubAckMessage message) {
+    	logger.debug("encode encodeSubAckMessage");
+    	
+        int variableHeaderBufferSize = 2;
+        int payloadBufferSize = message.payload().grantedQoSLevels().size();
+        int variablePartSize = variableHeaderBufferSize + payloadBufferSize;
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variablePartSize);
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variablePartSize);
+        buf.writeByte(getFixedHeaderByte1(message.fixedHeader()));
+        writeVariableLengthInt(buf, variablePartSize);
+        buf.writeShort(message.variableHeader().messageId());
+        for (int qos : message.payload().grantedQoSLevels()) {
+            buf.writeByte(qos);
+        }
+
+        return buf;
+    }
+
+    @SuppressWarnings("deprecation")
+	private static ByteBuf encodePublishMessage(
+            ByteBufAllocator byteBufAllocator,
+            MqttPublishMessage message) {
+    	logger.debug("encode encodePublishMessage");
+    	
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        MqttPublishVariableHeader variableHeader = message.variableHeader();
+        ByteBuf payload = message.payload().duplicate();
+
+        String topicName = variableHeader.topicName();
+        byte[] topicNameBytes = encodeStringUtf8(topicName);
+
+        int variableHeaderBufferSize = 2 + topicNameBytes.length +
+                (mqttFixedHeader.qosLevel().value() > 0 ? 2 : 0);
+        int payloadBufferSize = payload.readableBytes();
+        int variablePartSize = variableHeaderBufferSize + payloadBufferSize;
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variablePartSize);
+
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variablePartSize);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        writeVariableLengthInt(buf, variablePartSize);
+        buf.writeShort(topicNameBytes.length);
+        buf.writeBytes(topicNameBytes);
+        if (mqttFixedHeader.qosLevel().value() > 0) {
+            buf.writeShort(variableHeader.messageId());
+        }
+        buf.writeBytes(payload);
+
+        return buf;
+    }
+
+    private static ByteBuf encodeMessageWithOnlySingleByteFixedHeaderAndMessageId(
+            ByteBufAllocator byteBufAllocator,
+            MqttMessage message) {
+    	logger.debug("encode encodeMessageWithOnlySingleByteFixedHeaderAndMessageId");
+    	
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        MqttMessageIdVariableHeader variableHeader = (MqttMessageIdVariableHeader) message.variableHeader();
+        int msgId = variableHeader.messageId();
+
+        int variableHeaderBufferSize = 2; // variable part only has a message id
+        
+        ByteBuf payload = null;
+        if (message.payload() != null) {
+        	payload = ((ByteBuf)message.payload()).duplicate();
+        	variableHeaderBufferSize += payload.readableBytes();
+		}
+        int fixedHeaderBufferSize = 1 + getVariableLengthInt(variableHeaderBufferSize);
+        ByteBuf buf = byteBufAllocator.buffer(fixedHeaderBufferSize + variableHeaderBufferSize);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        writeVariableLengthInt(buf, variableHeaderBufferSize);
+        buf.writeShort(msgId);
+        if (payload != null) {
+        	buf.writeBytes(payload);
+		}
+
+        return buf;
+    }
+
+    private static ByteBuf encodeMessageWithOnlySingleByteFixedHeader(
+            ByteBufAllocator byteBufAllocator,
+            MqttMessage message) {
+    	//logger.debug("encode encodeMessageWithOnlySingleByteFixedHeader");
+    	
+        MqttFixedHeader mqttFixedHeader = message.fixedHeader();
+        ByteBuf buf = byteBufAllocator.buffer(2);
+        buf.writeByte(getFixedHeaderByte1(mqttFixedHeader));
+        buf.writeByte(0);
+
+        return buf;
+    }
+
+    private static int getFixedHeaderByte1(MqttFixedHeader header) {
+    	//logger.debug("encode getFixedHeaderByte1");
+    	
+        int ret = 0;
+        ret |= header.messageType().value() << 4;
+        if (header.isDup()) {
+            ret |= 0x08;
+        }
+        ret |= header.qosLevel().value() << 1;
+        if (header.isRetain()) {
+            ret |= 0x01;
+        }
+        return ret;
+    }
+
+    private static void writeVariableLengthInt(ByteBuf buf, int num) {
+    	//logger.debug("encode writeVariableLengthInt");
+    	
+        do {
+            int digit = num % 128;
+            num /= 128;
+            if (num > 0) {
+                digit |= 0x80;
+            }
+            buf.writeByte(digit);
+        } while (num > 0);
+    }
+
+    private static int getVariableLengthInt(int num) {
+        int count = 0;
+        do {
+            num /= 128;
+            count++;
+        } while (num > 0);
+        return count;
+    }
+
+    private static byte[] encodeStringUtf8(String s) {
+      //logger.debug("encode encodeStringUtf8");
+      return s.getBytes(CharsetUtil.UTF_8);
+    }
+
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttIdentifierRejectedException.java b/IMserver/medeasy/src/chat/server/moquette/MqttIdentifierRejectedException.java
new file mode 100644
index 0000000..d00b8ef
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttIdentifierRejectedException.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package chat.server.moquette;
+
+import io.netty.handler.codec.DecoderException;
+
+/**
+ * A {@link MqttIdentifierRejectedException} which is thrown when a CONNECT request contains invalid client identifier.
+ */
+public final class MqttIdentifierRejectedException extends DecoderException {
+
+    private static final long serialVersionUID = -1323503322689614981L;
+
+    /**
+     * Creates a new instance
+     */
+    public MqttIdentifierRejectedException() { }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttIdentifierRejectedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttIdentifierRejectedException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttIdentifierRejectedException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttIdleTimeoutHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttIdleTimeoutHandler.java
new file mode 100644
index 0000000..42539ff
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttIdleTimeoutHandler.java
@@ -0,0 +1,42 @@
+package chat.server.moquette;
+
+import org.apache.log4j.Logger;
+
+import chat.server.moquette.message.ClientID;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+
+
+public class MqttIdleTimeoutHandler extends ChannelDuplexHandler {
+
+    private static Logger logger;
+    
+    static {
+    	logger = Logger.getLogger(MqttIdleTimeoutHandler.class);
+    }
+
+    @Override
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        if (evt instanceof IdleStateEvent) {
+            IdleState e = ((IdleStateEvent) evt).state();
+            if (e == IdleState.READER_IDLE) {
+            	ClientID clientId = ClientID.valueOf(ctx.channel());
+            	logger.info("Firing channel inactive event. MqttClientId = " + clientId);
+
+                ctx.fireChannelInactive();
+                ctx.close();
+            }
+        } 
+        else {
+            if (logger.isDebugEnabled()) {
+            	ClientID clientId = ClientID.valueOf(ctx.channel());
+            	logger.debug("Firing Netty event. MqttClientId = " + clientId + ", eventClass = " + evt.getClass().getName());
+            }
+            
+            super.userEventTriggered(ctx, evt);
+        }
+    }
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttMessageLoggerHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttMessageLoggerHandler.java
new file mode 100644
index 0000000..9cccb5b
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttMessageLoggerHandler.java
@@ -0,0 +1,90 @@
+package chat.server.moquette;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import chat.server.moquette.message.ClientID;
+import chat.server.moquette.message.MessageID;
+import chat.server.moquette.message.MqttMessage;
+import chat.server.moquette.message.MqttMessageType;
+import chat.server.moquette.message.MqttPublishMessage;
+import chat.server.moquette.message.MqttSubAckMessage;
+import chat.server.moquette.message.MqttSubscribeMessage;
+import chat.server.moquette.message.MqttUnsubscribeMessage;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+
+public class MqttMessageLoggerHandler extends ChannelDuplexHandler {
+
+    private static Logger logger;
+
+    static {
+    	logger = Logger.getLogger(MqttMessageLoggerHandler.class);
+    }
+    
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object message) {
+        logMQTTMessage(ctx, message, "C->B");
+        ctx.fireChannelRead(message);
+    }
+
+    private void logMQTTMessage(ChannelHandlerContext ctx, Object message, String direction) {
+        if (!(message instanceof MqttMessage)) {
+            return;
+        }
+        MqttMessage msg = (MqttMessage) message;
+        ClientID clientID = ClientID.valueOf(ctx.channel());
+        MqttMessageType messageType = msg.fixedHeader().messageType();
+        
+        switch (messageType) {
+            case CONNECT:
+            case CONNACK:
+            case PINGREQ:
+            case PINGRESP:
+            case DISCONNECT:
+            	logger.info(direction + " " + messageType + " <" + clientID + ">");
+                break;
+            case SUBSCRIBE:
+                MqttSubscribeMessage subscribe = (MqttSubscribeMessage) msg;
+            	logger.info(direction + " SUBSCRIBE " + clientID + " to topics <" + subscribe.payload().topicSubscriptions() + ">");
+                break;
+            case UNSUBSCRIBE:
+                MqttUnsubscribeMessage unsubscribe = (MqttUnsubscribeMessage) msg;
+            	logger.info(direction + " UNSUBSCRIBE " + clientID + " to topics <" + unsubscribe.payload().topics() + ">");
+                break;
+            case PUBLISH:
+                MqttPublishMessage publish = (MqttPublishMessage) msg;
+            	logger.info(direction + " PUBLISH " + clientID + " to topics <" + publish.variableHeader().topicName() + ">");
+                break;
+            case PUBREC:
+            case PUBCOMP:
+            case PUBREL:
+            case PUBACK:
+            case UNSUBACK:
+            	logger.info(direction + " " + messageType + " " + clientID + " packetID " + MessageID.valueOf(msg));
+                break;
+            case SUBACK:
+                MqttSubAckMessage suback = (MqttSubAckMessage) msg;
+                List<Integer> grantedQoSLevels = suback.payload().grantedQoSLevels();
+
+                logger.info(direction + " SUBACK " + clientID + " packetID " + MessageID.valueOf(msg) + ", grantedQoses " + grantedQoSLevels);
+                break;
+        }
+    }
+
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+    	ClientID clientID = ClientID.valueOf(ctx.channel());
+        logger.info("Channel closed " + clientID);
+        
+        ctx.fireChannelInactive();
+    }
+
+    @Override
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+        logMQTTMessage(ctx, msg, "C<-B");
+        ctx.write(msg, promise);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttMessageMetricsHandler.java b/IMserver/medeasy/src/chat/server/moquette/MqttMessageMetricsHandler.java
new file mode 100644
index 0000000..80eaf86
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttMessageMetricsHandler.java
@@ -0,0 +1,72 @@
+package chat.server.moquette;
+
+import org.apache.log4j.Logger;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.util.Attribute;
+import io.netty.util.AttributeKey;
+
+public class MqttMessageMetricsHandler extends ChannelDuplexHandler {
+	
+    private static Logger logger;
+    private static AttributeKey<Metrics> ATTR_KEY_METRICS;
+    private static AttributeKey<String> ATTR_KEY_USERNAME;
+
+    private MessageMetricsCollector collector;
+    
+    static {
+    	logger = Logger.getLogger(MqttMessageMetricsHandler.class);
+    	
+    	ATTR_KEY_METRICS = AttributeKey.valueOf("MessageMetrics");
+    	ATTR_KEY_USERNAME = AttributeKey.valueOf("username");
+    }
+
+    public MqttMessageMetricsHandler(MessageMetricsCollector collector) {
+        this.collector = collector;
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        Attribute<Metrics> attr = ctx.channel().attr(ATTR_KEY_METRICS);
+        attr.set(new Metrics());
+
+        super.channelActive(ctx);
+    }
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+    	Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        metrics.incrementRead(1);
+        ctx.fireChannelRead(msg);
+    }
+
+    @Override
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+    	Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        metrics.incrementWrote(1);
+        ctx.write(msg, promise);
+    }
+
+    @Override
+    public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+    	Metrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
+        String userId = ctx.channel().attr(ATTR_KEY_USERNAME).get();
+        if (userId == null) {
+            userId = "";
+        }
+
+        logger.info("channel<" + userId + "> closing after " + metrics);
+        
+        collector.sumReadMessages(metrics.readLength());
+        collector.sumWroteMessages(metrics.wroteLength());
+        
+        super.close(ctx, promise);
+    }
+
+    public static Metrics getMessageMetrics(Channel channel) {
+        return channel.attr(ATTR_KEY_METRICS).get();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttUnacceptableProtocolVersionException.java b/IMserver/medeasy/src/chat/server/moquette/MqttUnacceptableProtocolVersionException.java
new file mode 100644
index 0000000..43ceb0a
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttUnacceptableProtocolVersionException.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package chat.server.moquette;
+
+import io.netty.handler.codec.DecoderException;
+
+/**
+ * A {@link MqttUnacceptableProtocolVersionException} which is thrown when
+ * a CONNECT request contains unacceptable protocol version.
+ */
+public final class MqttUnacceptableProtocolVersionException extends DecoderException {
+
+    private static final long serialVersionUID = 4914652213232455749L;
+
+    /**
+     * Creates a new instance
+     */
+    public MqttUnacceptableProtocolVersionException() { }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttUnacceptableProtocolVersionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttUnacceptableProtocolVersionException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new instance
+     */
+    public MqttUnacceptableProtocolVersionException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/MqttVersion.java b/IMserver/medeasy/src/chat/server/moquette/MqttVersion.java
new file mode 100644
index 0000000..38084b8
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/MqttVersion.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package chat.server.moquette;
+
+import io.netty.util.CharsetUtil;
+import io.netty.util.internal.ObjectUtil;
+
+/**
+ * Mqtt version specific constant values used by multiple classes in mqtt-codec.
+ */
+public enum MqttVersion {
+    MQTT_3_1("MQIsdp", (byte) 3),
+    MQTT_3_1_1("MQTT", (byte) 4),
+    Wildfire_1("MQTT", (byte) 5),
+    Wildfire_2("MQTT", (byte) 6),
+    Wildfire_Max("MQTT", (byte) 7);
+
+    private final String name;
+    private final byte level;
+
+    MqttVersion(String protocolName, byte protocolLevel) {
+        name = ObjectUtil.checkNotNull(protocolName, "protocolName");
+        level = protocolLevel;
+    }
+
+    public String protocolName() {
+        return name;
+    }
+
+    public byte[] protocolNameBytes() {
+        return name.getBytes(CharsetUtil.UTF_8);
+    }
+
+    public byte protocolLevel() {
+        return level;
+    }
+
+    public static MqttVersion fromProtocolNameAndLevel(String protocolName, byte protocolLevel) {
+        for (MqttVersion mv : values()) {
+            if (mv.name.equals(protocolName)) {
+                if (mv.level == protocolLevel) {
+                    return mv;
+                } else {
+                    continue;
+                }
+            }
+        }
+        throw new MqttUnacceptableProtocolVersionException(protocolName + "is unknown protocol name");
+    }
+
+    public static MqttVersion fromProtocolLevel(int protocolLevel) {
+        for (MqttVersion mv : values()) {
+            if (mv.level == (byte )protocolLevel) {
+                return mv;
+            }
+        }
+        throw new MqttUnacceptableProtocolVersionException(protocolLevel + "is unknown protocol level");
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/ClientID.java b/IMserver/medeasy/src/chat/server/moquette/message/ClientID.java
new file mode 100644
index 0000000..d507e11
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/ClientID.java
@@ -0,0 +1,97 @@
+package chat.server.moquette.message;
+
+import java.util.Base64;
+
+import io.moquette.spi.impl.security.AES;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.util.AttributeKey;
+
+public class ClientID {
+	
+    private static final AttributeKey<Object> Attr_Key_ClientId;
+	private String value;
+	
+	static {
+    	Attr_Key_ClientId = AttributeKey.valueOf("clientId");
+	}
+	
+	public ClientID() {
+		
+	}
+
+	public static ClientID valueOf(FullHttpRequest httpRequest) {
+		ClientID result = new ClientID();
+		
+		try {
+			String cid = httpRequest.headers().get("cid");
+			
+	        if (cid == null) {
+	        	return result;
+	        }
+	        
+	        byte[] bytes = Base64.getDecoder().decode(cid);
+	        bytes = AES.AESDecrypt(bytes, "", true);
+	        
+	        result.value = new String(bytes);
+		}
+		catch (Exception e) {
+		}
+		
+		return result;
+	}
+
+	public static ClientID valueOf(MqttConnectPayload payload) {
+		ClientID result = new ClientID();
+		String value = payload.clientIdentifier();
+		result.value = value;
+		
+		return result;
+	}
+	
+	public static ClientID valueOf(ChannelHandlerContext ctx) {
+		Channel channel = ctx.channel();
+		return valueOf(channel);
+	}
+
+	public static ClientID valueOf(Channel channel) {
+		ClientID result = new ClientID();
+		
+		if (channel == null) {
+			return result;
+		}
+		
+		String value = String.valueOf(channel.attr(Attr_Key_ClientId).get());
+		result.value = value;
+		
+		return result;
+	}
+
+	public void setValueTo(Channel channel) {
+		channel.attr(Attr_Key_ClientId).set(value);
+	}
+	
+	public boolean isEmpty() {
+		if (value == null) {
+			return true;
+		}
+		
+		if ("".equals(value)) {
+			return true;
+		}
+		
+		return false;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	@Override
+	public String toString() {
+		//return "<" + value + ">";
+		return value;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MessageID.java b/IMserver/medeasy/src/chat/server/moquette/message/MessageID.java
new file mode 100644
index 0000000..7d1d8c0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MessageID.java
@@ -0,0 +1,33 @@
+package chat.server.moquette.message;
+
+public class MessageID {
+
+	private Integer value;
+	
+	public MessageID() {
+		
+	}
+	
+	public static MessageID valueOf(MqttMessage message) {
+		MessageID result = new MessageID();
+		
+		if (message == null) {
+			return result;
+		}
+		
+		Integer value = ((MqttMessageIdVariableHeader) message.variableHeader()).messageId();
+		result.value = value;
+		
+		return result;
+	}
+
+	public Integer getValue() {
+		return value;
+	}
+
+	@Override
+	public String toString() {
+		return "<" + value + ">";
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/ModifiedMqttPubAckMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/ModifiedMqttPubAckMessage.java
new file mode 100644
index 0000000..6d20178
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/ModifiedMqttPubAckMessage.java
@@ -0,0 +1,15 @@
+package chat.server.moquette.message;
+
+import io.netty.buffer.ByteBuf;
+
+public class ModifiedMqttPubAckMessage extends MqttMessage {
+	
+    public ModifiedMqttPubAckMessage(MqttFixedHeader mqttFixedHeader, MqttMessageIdVariableHeader variableHeader, ByteBuf payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckMessage.java
new file mode 100644
index 0000000..be54690
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckMessage.java
@@ -0,0 +1,18 @@
+package chat.server.moquette.message;
+
+public class MqttConnAckMessage extends MqttMessage {
+
+    public MqttConnAckMessage(MqttFixedHeader mqttFixedHeader, MqttConnAckVariableHeader variableHeader) {
+        super(mqttFixedHeader, variableHeader);
+    }
+
+    public MqttConnAckMessage(MqttFixedHeader mqttFixedHeader, MqttConnAckVariableHeader variableHeader, MqttConnectAckPayload payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttConnAckVariableHeader variableHeader() {
+        return (MqttConnAckVariableHeader) super.variableHeader();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckVariableHeader.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckVariableHeader.java
new file mode 100644
index 0000000..a4a0201
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnAckVariableHeader.java
@@ -0,0 +1,33 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttConnAckVariableHeader {
+
+    private final MqttConnectReturnCode connectReturnCode;
+
+    private final boolean sessionPresent;
+
+    public MqttConnAckVariableHeader(MqttConnectReturnCode connectReturnCode, boolean sessionPresent) {
+        this.connectReturnCode = connectReturnCode;
+        this.sessionPresent = sessionPresent;
+    }
+
+    public MqttConnectReturnCode connectReturnCode() {
+        return connectReturnCode;
+    }
+
+    public boolean isSessionPresent() {
+        return sessionPresent;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("connectReturnCode=").append(connectReturnCode)
+            .append(", sessionPresent=").append(sessionPresent)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectAckPayload.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectAckPayload.java
new file mode 100644
index 0000000..ada7e73
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectAckPayload.java
@@ -0,0 +1,25 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttConnectAckPayload {
+
+    private final byte[] data;
+
+    public MqttConnectAckPayload(byte[] data) {
+        this.data = data;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("data=").append(data)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectMessage.java
new file mode 100644
index 0000000..06a690f
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectMessage.java
@@ -0,0 +1,19 @@
+package chat.server.moquette.message;
+
+public class MqttConnectMessage extends MqttMessage {
+
+    public MqttConnectMessage(MqttFixedHeader fixedHeader, MqttConnectVariableHeader variableHeader, MqttConnectPayload payload) {
+        super(fixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttConnectVariableHeader variableHeader() {
+        return (MqttConnectVariableHeader) super.variableHeader();
+    }
+
+    @Override
+    public MqttConnectPayload payload() {
+        return (MqttConnectPayload) super.payload();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectPayload.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectPayload.java
new file mode 100644
index 0000000..1763053
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectPayload.java
@@ -0,0 +1,58 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttConnectPayload {
+
+    private final String clientIdentifier;
+    private final String willTopic;
+    private final String willMessage;
+    private final String userName;
+    private final byte[] password;
+
+    public MqttConnectPayload(
+            String clientIdentifier,
+            String willTopic,
+            String willMessage,
+            String userName,
+            byte[] password) {
+        this.clientIdentifier = clientIdentifier;
+        this.willTopic = willTopic;
+        this.willMessage = willMessage;
+        this.userName = userName;
+        this.password = password;
+    }
+
+    public String clientIdentifier() {
+        return clientIdentifier;
+    }
+
+    public String willTopic() {
+        return willTopic;
+    }
+
+    public String willMessage() {
+        return willMessage;
+    }
+
+    public String userName() {
+        return userName;
+    }
+
+    public byte[] password() {
+        return password;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("clientIdentifier=").append(clientIdentifier)
+            .append(", willTopic=").append(willTopic)
+            .append(", willMessage=").append(willMessage)
+            .append(", userName=").append(userName)
+            .append(", password=").append(password)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectReturnCode.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectReturnCode.java
new file mode 100644
index 0000000..d5c34b9
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectReturnCode.java
@@ -0,0 +1,44 @@
+package chat.server.moquette.message;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public enum MqttConnectReturnCode {
+
+    CONNECTION_ACCEPTED((byte) 0x00),
+    CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION((byte) 0X01),
+    CONNECTION_REFUSED_IDENTIFIER_REJECTED((byte) 0x02),
+    CONNECTION_REFUSED_SERVER_UNAVAILABLE((byte) 0x03),
+    CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD((byte) 0x04),
+    CONNECTION_REFUSED_NOT_AUTHORIZED((byte) 0x05),
+    CONNECTION_REFUSED_UNEXPECT_NODE((byte) 0X06),
+    CONNECTION_REFUSED_SESSION_NOT_EXIST((byte) 0x07);
+
+    private static final Map<Byte, MqttConnectReturnCode> VALUE_TO_CODE_MAP;
+
+    static {
+        final Map<Byte, MqttConnectReturnCode> valueMap = new HashMap<Byte, MqttConnectReturnCode>();
+        for (MqttConnectReturnCode code: values()) {
+            valueMap.put(code.byteValue, code);
+        }
+        VALUE_TO_CODE_MAP = Collections.unmodifiableMap(valueMap);
+    }
+
+    private final byte byteValue;
+
+    MqttConnectReturnCode(byte byteValue) {
+        this.byteValue = byteValue;
+    }
+
+    public byte byteValue() {
+        return byteValue;
+    }
+
+    public static MqttConnectReturnCode valueOf(byte b) {
+        if (VALUE_TO_CODE_MAP.containsKey(b)) {
+            return VALUE_TO_CODE_MAP.get(b);
+        }
+        throw new IllegalArgumentException("unknown connect return code: " + (b & 0xFF));
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectVariableHeader.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectVariableHeader.java
new file mode 100644
index 0000000..55618a2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttConnectVariableHeader.java
@@ -0,0 +1,80 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttConnectVariableHeader {
+
+    private final String name;
+    private final int version;
+    private final boolean hasUserName;
+    private final boolean hasPassword;
+    private final boolean isWillRetain;
+    private final int willQos;
+    private final boolean isWillFlag;
+    private final boolean isCleanSession;
+    private final int keepAliveTimeSeconds;
+
+    public MqttConnectVariableHeader(String name, int version, boolean hasUserName, boolean hasPassword, boolean isWillRetain, int willQos, boolean isWillFlag, boolean isCleanSession, int keepAliveTimeSeconds) {
+        this.name = name;
+        this.version = version;
+        this.hasUserName = hasUserName;
+        this.hasPassword = hasPassword;
+        this.isWillRetain = isWillRetain;
+        this.willQos = willQos;
+        this.isWillFlag = isWillFlag;
+        this.isCleanSession = isCleanSession;
+        this.keepAliveTimeSeconds = keepAliveTimeSeconds;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public int version() {
+        return version;
+    }
+
+    public boolean hasUserName() {
+        return hasUserName;
+    }
+
+    public boolean hasPassword() {
+        return hasPassword;
+    }
+
+    public boolean isWillRetain() {
+        return isWillRetain;
+    }
+
+    public int willQos() {
+        return willQos;
+    }
+
+    public boolean isWillFlag() {
+        return isWillFlag;
+    }
+
+    public boolean isCleanSession() {
+        return isCleanSession;
+    }
+
+    public int keepAliveTimeSeconds() {
+        return keepAliveTimeSeconds;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("name=").append(name)
+            .append(", version=").append(version)
+            .append(", hasUserName=").append(hasUserName)
+            .append(", hasPassword=").append(hasPassword)
+            .append(", isWillRetain=").append(isWillRetain)
+            .append(", isWillFlag=").append(isWillFlag)
+            .append(", isCleanSession=").append(isCleanSession)
+            .append(", keepAliveTimeSeconds=").append(keepAliveTimeSeconds)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttFixedHeader.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttFixedHeader.java
new file mode 100644
index 0000000..0e58ddf
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttFixedHeader.java
@@ -0,0 +1,56 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.ObjectUtil;
+
+public class MqttFixedHeader {
+	
+    private final MqttMessageType messageType;
+    private final boolean isDup;
+    private final MqttQoS qosLevel;
+    private final boolean isRetain;
+    private final int remainingLength;
+
+    public MqttFixedHeader(MqttMessageType messageType, boolean isDup, MqttQoS qosLevel, boolean isRetain, int remainingLength) {
+        this.messageType = ObjectUtil.checkNotNull(messageType, "messageType");
+        this.isDup = isDup;
+        this.qosLevel = ObjectUtil.checkNotNull(qosLevel, "qosLevel");
+        this.isRetain = isRetain;
+        this.remainingLength = remainingLength;
+    }
+
+    public MqttMessageType messageType() {
+        return messageType;
+    }
+
+    public boolean isDup() {
+        return isDup;
+    }
+
+    public MqttQoS qosLevel() {
+        return qosLevel;
+    }
+
+    public boolean isRetain() {
+        return isRetain;
+    }
+
+    public int remainingLength() {
+        return remainingLength;
+    }
+
+    @Override
+    public String toString() {
+    	StringBuilder result = new StringBuilder();
+    	
+    	result.append(this.getClass().getSimpleName());
+    	result.append('[');
+    	result.append("messageType=").append(messageType);
+    	result.append(", isDup=").append(isDup);
+    	result.append(", qosLevel=").append(qosLevel);
+    	result.append(", isRetain=").append(isRetain);
+    	result.append(", remainingLength=").append(remainingLength);
+    	result.append(']');
+    	
+        return result.toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessage.java
new file mode 100644
index 0000000..56b73fb
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessage.java
@@ -0,0 +1,64 @@
+package chat.server.moquette.message;
+
+import io.netty.handler.codec.DecoderResult;
+import io.netty.util.internal.StringUtil;
+
+public class MqttMessage {
+
+    private final MqttFixedHeader mqttFixedHeader;
+    private final Object variableHeader;
+    private final Object payload;
+    private final DecoderResult decoderResult;
+
+    public MqttMessage(MqttFixedHeader mqttFixedHeader) {
+        this(mqttFixedHeader, null, null);
+    }
+
+    public MqttMessage(MqttFixedHeader mqttFixedHeader, Object variableHeader) {
+        this(mqttFixedHeader, variableHeader, null);
+    }
+
+    public MqttMessage(MqttFixedHeader mqttFixedHeader, Object variableHeader, Object payload) {
+        this(mqttFixedHeader, variableHeader, payload, DecoderResult.SUCCESS);
+    }
+
+    public MqttMessage(MqttFixedHeader mqttFixedHeader, Object variableHeader, Object payload, DecoderResult decoderResult) {
+        this.mqttFixedHeader = mqttFixedHeader;
+        this.variableHeader = variableHeader;
+        this.payload = payload;
+        this.decoderResult = decoderResult;
+    }
+    
+	public MqttMessageType messageType() {
+		return fixedHeader().messageType();
+	}
+
+    public MqttFixedHeader fixedHeader() {
+        return mqttFixedHeader;
+    }
+
+    public Object variableHeader() {
+        return variableHeader;
+    }
+
+    public Object payload() {
+        return payload;
+    }
+
+    public DecoderResult decoderResult() {
+        return decoderResult;
+    }
+    
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("fixedHeader=").append(fixedHeader() != null ? fixedHeader().toString() : "")
+            .append(", variableHeader=").append(variableHeader() != null ? variableHeader.toString() : "")
+            .append(", payload=").append(payload() != null ? payload.toString() : "")
+            .append(']')
+            .toString();
+    }
+	    
+}
+
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageFactory.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageFactory.java
new file mode 100644
index 0000000..626865e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageFactory.java
@@ -0,0 +1,70 @@
+package chat.server.moquette.message;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.DecoderResult;
+
+public class MqttMessageFactory {
+
+	   public static MqttMessage newMessage(MqttFixedHeader mqttFixedHeader, Object variableHeader, Object payload) {
+	        switch (mqttFixedHeader.messageType()) {
+	            case CONNECT :
+	                return new MqttConnectMessage(
+	                        mqttFixedHeader,
+	                        (MqttConnectVariableHeader) variableHeader,
+	                        (MqttConnectPayload) payload);
+
+	            case CONNACK:
+	                return new MqttConnAckMessage(mqttFixedHeader, (MqttConnAckVariableHeader) variableHeader);
+
+	            case SUBSCRIBE:
+	                return new MqttSubscribeMessage(
+	                        mqttFixedHeader,
+	                        (MqttMessageIdVariableHeader) variableHeader,
+	                        (MqttSubscribePayload) payload);
+
+	            case SUBACK:
+	                return new MqttSubAckMessage(
+	                        mqttFixedHeader,
+	                        (MqttMessageIdVariableHeader) variableHeader,
+	                        (MqttSubAckPayload) payload);
+
+	            case UNSUBACK:
+	                return new MqttUnsubAckMessage(
+	                        mqttFixedHeader,
+	                        (MqttMessageIdVariableHeader) variableHeader);
+
+	            case UNSUBSCRIBE:
+	                return new MqttUnsubscribeMessage(
+	                        mqttFixedHeader,
+	                        (MqttMessageIdVariableHeader) variableHeader,
+	                        (MqttUnsubscribePayload) payload);
+
+	            case PUBLISH:
+	                return new MqttPublishMessage(
+	                        mqttFixedHeader,
+	                        (MqttPublishVariableHeader) variableHeader,
+	                        (ByteBuf) payload);
+
+	            case PUBACK:
+	                return new MqttPubAckMessage(mqttFixedHeader, (MqttMessageIdVariableHeader) variableHeader);
+	            case PUBREC:
+	            case PUBREL:
+	            case PUBCOMP:
+	                return new MqttMessage(mqttFixedHeader, variableHeader);
+
+	            case PINGREQ:
+	            case PINGRESP:
+	            case DISCONNECT:
+	                return new MqttMessage(mqttFixedHeader);
+
+	            default:
+	                throw new IllegalArgumentException("unknown message type: " + mqttFixedHeader.messageType());
+	        }
+	    }
+
+	    public static MqttMessage newInvalidMessage(Throwable cause) {
+	        return new MqttMessage(null, null, null, DecoderResult.failure(cause));
+	    }
+
+	    private MqttMessageFactory() { }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageIdVariableHeader.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageIdVariableHeader.java
new file mode 100644
index 0000000..bf6a5a2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageIdVariableHeader.java
@@ -0,0 +1,32 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttMessageIdVariableHeader {
+
+    private final int messageId;
+
+    public static MqttMessageIdVariableHeader from(int messageId) {
+      if (messageId < 1 || messageId > 0xffff) {
+        throw new IllegalArgumentException("messageId: " + messageId + " (expected: 1 ~ 65535)");
+      }
+      return new MqttMessageIdVariableHeader(messageId);
+    }
+
+    private MqttMessageIdVariableHeader(int messageId) {
+        this.messageId = messageId;
+    }
+
+    public int messageId() {
+        return messageId;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("messageId=").append(messageId)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageType.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageType.java
new file mode 100644
index 0000000..f9fcc34
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttMessageType.java
@@ -0,0 +1,39 @@
+package chat.server.moquette.message;
+
+public enum MqttMessageType {
+
+    CONNECT(1),
+    CONNACK(2),
+    PUBLISH(3),
+    PUBACK(4),
+    PUBREC(5),
+    PUBREL(6),
+    PUBCOMP(7),
+    SUBSCRIBE(8),
+    SUBACK(9),
+    UNSUBSCRIBE(10),
+    UNSUBACK(11),
+    PINGREQ(12),
+    PINGRESP(13),
+    DISCONNECT(14);
+
+    private final int value;
+
+    MqttMessageType(int value) {
+        this.value = value;
+    }
+
+    public int value() {
+        return value;
+    }
+
+    public static MqttMessageType valueOf(int type) {
+        for (MqttMessageType t : values()) {
+            if (t.value == type) {
+                return t;
+            }
+        }
+        throw new IllegalArgumentException("unknown message type: " + type);
+    }
+    
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttPubAckMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttPubAckMessage.java
new file mode 100644
index 0000000..f9e2628
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttPubAckMessage.java
@@ -0,0 +1,14 @@
+package chat.server.moquette.message;
+
+public class MqttPubAckMessage extends MqttMessage {
+
+    public MqttPubAckMessage(MqttFixedHeader mqttFixedHeader, MqttMessageIdVariableHeader variableHeader) {
+        super(mqttFixedHeader, variableHeader);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishMessage.java
new file mode 100644
index 0000000..85e9b54
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishMessage.java
@@ -0,0 +1,99 @@
+package chat.server.moquette.message;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufHolder;
+import io.netty.util.IllegalReferenceCountException;
+
+public class MqttPublishMessage extends MqttMessage implements ByteBufHolder {
+
+    public MqttPublishMessage(
+            MqttFixedHeader mqttFixedHeader,
+            MqttPublishVariableHeader variableHeader,
+            ByteBuf payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttPublishVariableHeader variableHeader() {
+        return (MqttPublishVariableHeader) super.variableHeader();
+    }
+
+    @Override
+    public ByteBuf payload() {
+        return content();
+    }
+
+    @Override
+    public ByteBuf content() {
+        final ByteBuf data = (ByteBuf) super.payload();
+        
+        if (data == null) {
+        	System.out.println(data);
+        }
+        
+        if (data.refCnt() <= 0) {
+            throw new IllegalReferenceCountException(data.refCnt());
+        }
+        return data;
+    }
+
+    @Override
+    public MqttPublishMessage copy() {
+        return replace(content().copy());
+    }
+
+    @Override
+    public MqttPublishMessage duplicate() {
+        return replace(content().duplicate());
+    }
+
+    @Override
+    public MqttPublishMessage retainedDuplicate() {
+        return replace(content().retainedDuplicate());
+    }
+
+    @Override
+    public MqttPublishMessage replace(ByteBuf content) {
+        return new MqttPublishMessage(fixedHeader(), variableHeader(), content);
+    }
+
+    @Override
+    public int refCnt() {
+        return content().refCnt();
+    }
+
+    @Override
+    public MqttPublishMessage retain() {
+        content().retain();
+        return this;
+    }
+
+    @Override
+    public MqttPublishMessage retain(int increment) {
+        content().retain(increment);
+        return this;
+    }
+
+    @Override
+    public MqttPublishMessage touch() {
+        content().touch();
+        return this;
+    }
+
+    @Override
+    public MqttPublishMessage touch(Object hint) {
+        content().touch(hint);
+        return this;
+    }
+
+    @Override
+    public boolean release() {
+        return content().release();
+    }
+
+    @Override
+    public boolean release(int decrement) {
+        return content().release(decrement);
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishVariableHeader.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishVariableHeader.java
new file mode 100644
index 0000000..092fdbb
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttPublishVariableHeader.java
@@ -0,0 +1,40 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttPublishVariableHeader {
+
+    private final String topicName;
+    private final int packetId;
+
+    public MqttPublishVariableHeader(String topicName, int packetId) {
+        this.topicName = topicName;
+        this.packetId = packetId;
+    }
+
+    public String topicName() {
+        return topicName;
+    }
+
+    /**
+     * @deprecated Use {@link #packetId()} instead.
+     */
+    @Deprecated
+    public int messageId() {
+        return packetId;
+    }
+
+    public int packetId() {
+        return packetId;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("topicName=").append(topicName)
+            .append(", packetId=").append(packetId)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttQoS.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttQoS.java
new file mode 100644
index 0000000..6a4da99
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttQoS.java
@@ -0,0 +1,29 @@
+package chat.server.moquette.message;
+
+public enum MqttQoS {
+	
+    AT_MOST_ONCE(0),
+    AT_LEAST_ONCE(1),
+    EXACTLY_ONCE(2),
+    FAILURE(0x80);
+
+    private final int value;
+
+    MqttQoS(int value) {
+        this.value = value;
+    }
+
+    public int value() {
+        return value;
+    }
+
+    public static MqttQoS valueOf(int value) {
+        for (MqttQoS q: values()) {
+            if (q.value == value) {
+                return q;
+            }
+        }
+        
+        throw new IllegalArgumentException("invalid QoS: " + value);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckMessage.java
new file mode 100644
index 0000000..0bd3cea
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckMessage.java
@@ -0,0 +1,22 @@
+package chat.server.moquette.message;
+
+public class MqttSubAckMessage extends MqttMessage {
+
+    public MqttSubAckMessage(
+            MqttFixedHeader mqttFixedHeader,
+            MqttMessageIdVariableHeader variableHeader,
+            MqttSubAckPayload payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+
+    @Override
+    public MqttSubAckPayload payload() {
+        return (MqttSubAckPayload) super.payload();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckPayload.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckPayload.java
new file mode 100644
index 0000000..aaa2682
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubAckPayload.java
@@ -0,0 +1,52 @@
+package chat.server.moquette.message;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttSubAckPayload {
+
+    private final List<Integer> grantedQoSLevels;
+
+    public MqttSubAckPayload(int... grantedQoSLevels) {
+        if (grantedQoSLevels == null) {
+            throw new NullPointerException("grantedQoSLevels");
+        }
+
+        List<Integer> list = new ArrayList<Integer>(grantedQoSLevels.length);
+        for (int v: grantedQoSLevels) {
+            list.add(v);
+        }
+        this.grantedQoSLevels = Collections.unmodifiableList(list);
+    }
+
+    public MqttSubAckPayload(Iterable<Integer> grantedQoSLevels) {
+        if (grantedQoSLevels == null) {
+            throw new NullPointerException("grantedQoSLevels");
+        }
+        List<Integer> list = new ArrayList<Integer>();
+        for (Integer v: grantedQoSLevels) {
+            if (v == null) {
+                break;
+            }
+            list.add(v);
+        }
+        this.grantedQoSLevels = Collections.unmodifiableList(list);
+    }
+
+    public List<Integer> grantedQoSLevels() {
+        return grantedQoSLevels;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("grantedQoSLevels=").append(grantedQoSLevels)
+            .append(']')
+            .toString();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribeMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribeMessage.java
new file mode 100644
index 0000000..cab3130
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribeMessage.java
@@ -0,0 +1,22 @@
+package chat.server.moquette.message;
+
+public class MqttSubscribeMessage extends MqttMessage {
+
+    public MqttSubscribeMessage(
+            MqttFixedHeader mqttFixedHeader,
+            MqttMessageIdVariableHeader variableHeader,
+            MqttSubscribePayload payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+
+    @Override
+    public MqttSubscribePayload payload() {
+        return (MqttSubscribePayload) super.payload();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribePayload.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribePayload.java
new file mode 100644
index 0000000..18232a4
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttSubscribePayload.java
@@ -0,0 +1,30 @@
+package chat.server.moquette.message;
+
+import java.util.Collections;
+import java.util.List;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttSubscribePayload {
+
+    private final List<MqttTopicSubscription> topicSubscriptions;
+
+    public MqttSubscribePayload(List<MqttTopicSubscription> topicSubscriptions) {
+        this.topicSubscriptions = Collections.unmodifiableList(topicSubscriptions);
+    }
+
+    public List<MqttTopicSubscription> topicSubscriptions() {
+        return topicSubscriptions;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder(StringUtil.simpleClassName(this)).append('[');
+        for (int i = 0; i < topicSubscriptions.size() - 1; i++) {
+            builder.append(topicSubscriptions.get(i)).append(", ");
+        }
+        builder.append(topicSubscriptions.get(topicSubscriptions.size() - 1));
+        builder.append(']');
+        return builder.toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttTopicSubscription.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttTopicSubscription.java
new file mode 100644
index 0000000..bf035a5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttTopicSubscription.java
@@ -0,0 +1,32 @@
+package chat.server.moquette.message;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttTopicSubscription {
+
+    private final String topicFilter;
+    private final MqttQoS qualityOfService;
+
+    public MqttTopicSubscription(String topicFilter, MqttQoS qualityOfService) {
+        this.topicFilter = topicFilter;
+        this.qualityOfService = qualityOfService;
+    }
+
+    public String topicName() {
+        return topicFilter;
+    }
+
+    public MqttQoS qualityOfService() {
+        return qualityOfService;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(StringUtil.simpleClassName(this))
+            .append('[')
+            .append("topicFilter=").append(topicFilter)
+            .append(", qualityOfService=").append(qualityOfService)
+            .append(']')
+            .toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubAckMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubAckMessage.java
new file mode 100644
index 0000000..d80f639
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubAckMessage.java
@@ -0,0 +1,14 @@
+package chat.server.moquette.message;
+
+public class MqttUnsubAckMessage extends MqttMessage {
+
+    public MqttUnsubAckMessage(MqttFixedHeader mqttFixedHeader, MqttMessageIdVariableHeader variableHeader) {
+        super(mqttFixedHeader, variableHeader, null);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribeMessage.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribeMessage.java
new file mode 100644
index 0000000..579ec78
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribeMessage.java
@@ -0,0 +1,21 @@
+package chat.server.moquette.message;
+
+public class MqttUnsubscribeMessage extends MqttMessage {
+
+    public MqttUnsubscribeMessage(
+            MqttFixedHeader mqttFixedHeader,
+            MqttMessageIdVariableHeader variableHeader,
+            MqttUnsubscribePayload payload) {
+        super(mqttFixedHeader, variableHeader, payload);
+    }
+
+    @Override
+    public MqttMessageIdVariableHeader variableHeader() {
+        return (MqttMessageIdVariableHeader) super.variableHeader();
+    }
+
+    @Override
+    public MqttUnsubscribePayload payload() {
+        return (MqttUnsubscribePayload) super.payload();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribePayload.java b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribePayload.java
new file mode 100644
index 0000000..6b5f79e
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/moquette/message/MqttUnsubscribePayload.java
@@ -0,0 +1,30 @@
+package chat.server.moquette.message;
+
+import java.util.Collections;
+import java.util.List;
+
+import io.netty.util.internal.StringUtil;
+
+public class MqttUnsubscribePayload {
+
+    private final List<String> topics;
+
+    public MqttUnsubscribePayload(List<String> topics) {
+        this.topics = Collections.unmodifiableList(topics);
+    }
+
+    public List<String> topics() {
+        return topics;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder(StringUtil.simpleClassName(this)).append('[');
+        for (int i = 0; i < topics.size() - 1; i++) {
+            builder.append("topicName = ").append(topics.get(i)).append(", ");
+        }
+        builder.append("topicName = ").append(topics.get(topics.size() - 1))
+               .append(']');
+        return builder.toString();
+    }
+}
diff --git a/IMserver/medeasy/src/chat/server/netty/ByteBufToWebSocketFrameEncoder.java b/IMserver/medeasy/src/chat/server/netty/ByteBufToWebSocketFrameEncoder.java
new file mode 100644
index 0000000..dd10481
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/ByteBufToWebSocketFrameEncoder.java
@@ -0,0 +1,20 @@
+package chat.server.netty;
+
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
+
+public class ByteBufToWebSocketFrameEncoder extends MessageToMessageEncoder<ByteBuf> {
+
+    @Override
+    protected void encode(ChannelHandlerContext chc, ByteBuf bb, List<Object> out) throws Exception {
+        // convert the ByteBuf to a WebSocketFrame
+        BinaryWebSocketFrame result = new BinaryWebSocketFrame();
+        result.content().writeBytes(bb);
+        out.add(result);
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/server/netty/NettyAcceptor.java b/IMserver/medeasy/src/chat/server/netty/NettyAcceptor.java
new file mode 100644
index 0000000..a7f2f8d
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettyAcceptor.java
@@ -0,0 +1,274 @@
+package chat.server.netty;
+
+import static io.netty.channel.ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+
+import chat.consts.BrokerConstants;
+import chat.server.Configer;
+import chat.server.moquette.BytesMetricsCollector;
+import chat.server.moquette.MessageMetricsCollector;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.util.concurrent.Future;
+
+public class NettyAcceptor {
+
+	private static Logger logger;
+	
+	private static NettyAcceptor instance;
+    private EventLoopGroup bossGroup;
+    private EventLoopGroup workerGroup;
+    
+    private Class<? extends ServerSocketChannel> channelClass;
+    private ChannelFuture httpChannelFuture;
+    private ChannelFuture tcpChannelFuture;
+    private ChannelFuture sslTCPChannelFuture;
+    private ChannelFuture wsChannelFuture;
+    
+    private MessageMetricsCollector messageMetricsCollector;
+    private BytesMetricsCollector bytesMetricsCollector;
+
+	
+	static {
+		logger = Logger.getLogger(NettyAcceptor.class);
+	}
+	
+	private NettyAcceptor() {
+		
+	}
+	
+	public static synchronized NettyAcceptor getInstance() {
+		if (instance == null) {
+			instance = new NettyAcceptor();
+		}
+		
+		return instance;
+	}
+	
+	public static void start() throws Exception {
+		instance = getInstance();
+		instance.doStart();
+	}
+	
+	public static void stop() {
+		try {
+			instance = getInstance();
+			instance.doStop();
+		}
+		catch(Exception e) {
+			logger.error(e);
+		}
+	}
+	
+    public void doStart() throws Exception {
+    	logger.info("Initializing Netty acceptor...");
+    	
+    	//1.
+    	initLocalVariable();
+    	
+        //2. HTTP 鐭繛鎺�
+        initializeHttpTransport();
+        
+        //3. TCP 闀胯繛鎺�
+        initializePlainTCPTransport();
+        
+        //4. SSL 闀胯繛鎺�
+        initializeSSLTCPTransport();
+        
+        //5. WebSocket 闀胯繛鎺�
+        initializeWSSTransport();
+        
+        logger.info("Netty acceptor initialized");
+    }
+    
+	public void doStop() {
+    	logger.info("Closing Netty acceptor...");
+    	
+        //1.
+        closeOneChannel(httpChannelFuture);
+        closeOneChannel(tcpChannelFuture);
+        closeOneChannel(sslTCPChannelFuture);
+        closeOneChannel(wsChannelFuture);
+        
+        //2.
+        closeOneEventLoopGroup("worker group", workerGroup);
+        closeOneEventLoopGroup("boss group", bossGroup);
+    }
+
+	private void initLocalVariable() {
+    	//1. 
+        boolean epoll = Configer.getBoolean(BrokerConstants.NETTY_EPOLL_PROPERTY_NAME, false);
+        if (epoll) {
+            // 鐢变簬鐩墠鍙敮鎸乀CP MQTT锛� 鎵�浠ossGroup鐨勭嚎绋嬫暟閰嶇疆涓�1
+        	logger.info("Netty is using Epoll");
+            bossGroup = new EpollEventLoopGroup(1);
+            workerGroup = new EpollEventLoopGroup();
+            channelClass = EpollServerSocketChannel.class;
+        } 
+        else {
+        	logger.info("Netty is using NIO");
+        	bossGroup = new NioEventLoopGroup(1);
+        	workerGroup = new NioEventLoopGroup();
+            channelClass = NioServerSocketChannel.class;
+        }
+        
+        //2.
+        bytesMetricsCollector = new BytesMetricsCollector();
+        messageMetricsCollector = new MessageMetricsCollector();
+	}
+    
+	private void initializeHttpTransport() throws Exception {
+		String protocol = "HTTP";	
+		Integer port = Configer.getInteger("http_port", null);
+		
+		if (port == null) {
+			logger.info("skip server, Protocol=" + protocol);
+			return;
+		}
+		
+		//2. create bootstrap
+		logger.info("Initializing server. Protocol=" + protocol);
+		NettyHttpChannelInitializer initializer = new NettyHttpChannelInitializer();
+		ServerBootstrap bootStrap = new NettyServerBootstrap(this, initializer);
+		
+		//3. Bind and start to accept incoming connections.
+		httpChannelFuture = bootStrap.bind(port);    
+		httpChannelFuture.sync().addListener(FIRE_EXCEPTION_ON_FAILURE);
+		
+		logger.info("server bounded. Protocol=" + protocol + ": " + port);
+	}
+
+	private void initializePlainTCPTransport() throws Exception {
+		//1. load host and port
+		String protocol = "TCP";
+		Integer port = Configer.getInteger("port", null);
+
+		if (port == null) {
+			logger.info("skip server, Protocol=" + protocol);
+			return;
+		}
+		
+		//2. create bootstrap
+		NettyTCPChannelInitializer initializer = new NettyTCPChannelInitializer();
+        initializer.setMessageMetricsCollector(messageMetricsCollector);
+        initializer.setBytesMetricsCollector(bytesMetricsCollector);
+        
+        ServerBootstrap bootStrap = new NettyServerBootstrap(this, initializer);
+        
+        //3. Bind and start to accept incoming connections.
+        tcpChannelFuture = bootStrap.bind(port);    
+        tcpChannelFuture.sync().addListener(FIRE_EXCEPTION_ON_FAILURE);  
+        
+		logger.info("server bounded. Protocol=" + protocol + ": " + port);
+	}
+
+	private void initializeSSLTCPTransport() throws InterruptedException {
+		//1. load host and port
+		String protocol = "SSL";
+		Integer port = Configer.getInteger("ssl_port", null);
+		
+		if (port == null) {
+			logger.info("skip server, Protocol=" + protocol);
+			return;
+		}
+		
+		//2. create bootstrap
+		NettySSLChannelInitializer initializer = new NettySSLChannelInitializer();
+        initializer.setMessageMetricsCollector(messageMetricsCollector);
+        initializer.setBytesMetricsCollector(bytesMetricsCollector);
+		
+		ServerBootstrap bootStrap = new NettyServerBootstrap(this, initializer);
+
+        //3. Bind and start to accept incoming connections.
+		sslTCPChannelFuture = bootStrap.bind(port);    
+		sslTCPChannelFuture.sync().addListener(FIRE_EXCEPTION_ON_FAILURE);  
+        
+		logger.info("server bounded. Protocol=" + protocol + ": " + port);
+	}
+	
+	private void initializeWSSTransport() throws Exception {
+		//1. load host and port 
+		String protocol = "Secure Websocket";
+		Integer port = Configer.getInteger("ws_port", null);
+		
+		if (port == null) {
+			logger.info("skip server, Protocol=" + protocol);
+			return;
+		}
+		
+		//2. create bootstrap
+        ChannelInitializer<SocketChannel> initializer = new NettyWSChannelInitializer();
+        ServerBootstrap bootStrap = new NettyServerBootstrap(this, initializer);
+
+        //3. Bind and start to accept incoming connections.
+        wsChannelFuture = bootStrap.bind(port);    
+        wsChannelFuture.sync().addListener(FIRE_EXCEPTION_ON_FAILURE);  
+        
+		logger.info("server bounded. Protocol=" + protocol + ": " + port);
+	}
+	
+    private void closeOneChannel(ChannelFuture channelFuture) {
+        if (channelFuture == null) {
+        	return;
+        }
+        	
+        Channel channel = channelFuture.channel();
+        try {
+        	channel.close();
+	    } catch (Exception e) {
+	    }    
+        
+        try {
+        	channel.closeFuture().sync();
+        } catch (Exception e) {
+        }
+	}
+    
+    private void closeOneEventLoopGroup(String name, EventLoopGroup loopGroup) {
+        if (loopGroup == null) {
+        	return;
+        }
+        
+        //1. close gracefully
+        Future<?> waiter = loopGroup.shutdownGracefully();
+
+        logger.info("Waiting for" + name + " event loop groups to terminate...");
+        try {
+        	waiter.await(3, TimeUnit.SECONDS);
+        } 
+        catch (InterruptedException iex) {
+        	logger.warn("An InterruptedException was caught while waiting for event loops to terminate...");
+        }
+        
+        //2. close force
+        if (!loopGroup.isTerminated()) {
+        	logger.warn("Forcing shutdown " + name + "...");
+        	loopGroup.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS);
+        }
+	}
+
+	public EventLoopGroup getBossGroup() {
+		return bossGroup;
+	}
+
+	public EventLoopGroup getWorkerGroup() {
+		return workerGroup;
+	}
+
+	public Class<? extends ServerSocketChannel> getChannelClass() {
+		return channelClass;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/netty/NettyHttpChannelInitializer.java b/IMserver/medeasy/src/chat/server/netty/NettyHttpChannelInitializer.java
new file mode 100644
index 0000000..6212152
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettyHttpChannelInitializer.java
@@ -0,0 +1,33 @@
+package chat.server.netty;  
+
+import chat.server.im.IMDispatcher;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.stream.ChunkedWriteHandler;
+
+public class NettyHttpChannelInitializer extends ChannelInitializer<SocketChannel> {
+
+    
+	@Override
+	protected void initChannel(SocketChannel channel) throws Exception {
+		ChannelPipeline pipeline = channel.pipeline();
+		
+		ChannelHandler decoder = new HttpRequestDecoder();
+		ChannelHandler encoder = new HttpResponseEncoder();
+		ChannelHandler chunkedWriteHandler = new ChunkedWriteHandler();
+		ChannelHandler aggregator = new HttpObjectAggregator(100 * 1024 * 1024);
+		ChannelHandler dispatcher = new IMDispatcher();
+		
+		pipeline.addLast(decoder);
+		pipeline.addLast(encoder);
+		pipeline.addLast(chunkedWriteHandler);
+		pipeline.addLast(aggregator);
+		pipeline.addLast(dispatcher);
+	}
+
+} 
diff --git a/IMserver/medeasy/src/chat/server/netty/NettySSLChannelInitializer.java b/IMserver/medeasy/src/chat/server/netty/NettySSLChannelInitializer.java
new file mode 100644
index 0000000..4105082
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettySSLChannelInitializer.java
@@ -0,0 +1,59 @@
+package chat.server.netty;
+
+import chat.server.Configer;
+import chat.server.im.IMDispatcher;
+import chat.server.moquette.BytesMetricsCollector;
+import chat.server.moquette.MessageMetricsCollector;
+import chat.server.moquette.MqttBytesMetricsHandler;
+import chat.server.moquette.MqttDecodHandler;
+import chat.server.moquette.MqttEncodHandler;
+import chat.server.moquette.MqttIdleTimeoutHandler;
+import chat.server.moquette.MqttMessageLoggerHandler;
+import chat.server.moquette.MqttMessageMetricsHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.timeout.IdleStateHandler;
+
+public class NettySSLChannelInitializer extends ChannelInitializer<SocketChannel> {
+
+    private MessageMetricsCollector messageMetricsCollector;
+    private BytesMetricsCollector bytesMetricsCollector;
+	
+	
+	@Override
+	protected void initChannel(SocketChannel channel) throws Exception {
+		int timeoutSeconds = Configer.getInteger("timeout", 10);
+		
+		ChannelPipeline pipeline = channel.pipeline();
+		
+		ChannelHandler bytesMetricsHandler = new MqttBytesMetricsHandler(bytesMetricsCollector);
+		ChannelHandler idleStateHandler = new IdleStateHandler(timeoutSeconds, 0, 0);
+		ChannelHandler timeoutHandler = new MqttIdleTimeoutHandler();
+//		ChannelHandler sslHandler = new SSLHandler();
+		ChannelHandler decoder = new MqttDecodHandler();
+		ChannelHandler encoder = MqttEncodHandler.getInstance();
+		ChannelHandler messageMetricsHandler = new MqttMessageMetricsHandler(messageMetricsCollector);
+		ChannelHandler messageLogger = new MqttMessageLoggerHandler();
+		ChannelHandler dispatcher = new IMDispatcher();
+		
+		pipeline.addFirst("bytemetrics", bytesMetricsHandler);
+		pipeline.addLast("idleStateHandler", idleStateHandler);
+		pipeline.addAfter("idleStateHandler", "idleEventHandler", timeoutHandler);
+//		pipeline.addLast("ssl", sslHandler);
+		pipeline.addLast("decoder", decoder);
+		pipeline.addLast("encoder", encoder);
+		pipeline.addLast("metrics", messageMetricsHandler);
+		pipeline.addLast("messageLogger", messageLogger);
+		pipeline.addLast("handler", dispatcher);
+	}
+	
+	public void setMessageMetricsCollector(MessageMetricsCollector messageMetricsCollector) {
+		this.messageMetricsCollector = messageMetricsCollector;
+	}
+
+	public void setBytesMetricsCollector(BytesMetricsCollector bytesMetricsCollector) {
+		this.bytesMetricsCollector = bytesMetricsCollector;
+	}
+} 
diff --git a/IMserver/medeasy/src/chat/server/netty/NettyServerBootstrap.java b/IMserver/medeasy/src/chat/server/netty/NettyServerBootstrap.java
new file mode 100644
index 0000000..fd0a958
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettyServerBootstrap.java
@@ -0,0 +1,43 @@
+package chat.server.netty;
+
+import org.apache.log4j.Logger;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.socket.SocketChannel;
+
+public class NettyServerBootstrap extends ServerBootstrap {
+
+	protected static Logger logger;
+    protected static int nettySoBacklog;
+    protected static boolean nettySoReuseaddr;
+    protected static boolean nettyTcpNodelay;
+    protected static boolean nettySoKeepalive;
+
+    
+    static {
+    	logger = Logger.getLogger(NettyServerBootstrap.class);
+    }
+    
+	public NettyServerBootstrap(NettyAcceptor acceptor, ChannelInitializer<SocketChannel> initializer) {
+		init(acceptor, initializer);
+	}
+
+	private void init(NettyAcceptor acceptor, ChannelInitializer<SocketChannel> initializer) {
+		group(acceptor.getBossGroup(), acceptor.getWorkerGroup());
+        channel(acceptor.getChannelClass());
+        childHandler(initializer);
+        
+        option(ChannelOption.SO_BACKLOG, 10240); // 鏈嶅姟绔彲杩炴帴闃熷垪澶у皬
+        option(ChannelOption.SO_REUSEADDR, true);
+        
+        childOption(ChannelOption.SO_KEEPALIVE, true);	
+        childOption(ChannelOption.TCP_NODELAY, true);
+        childOption(ChannelOption.SO_SNDBUF, 1024*64);
+        childOption(ChannelOption.SO_RCVBUF, 1024*64);
+        
+        childHandler(initializer);
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/server/netty/NettyTCPChannelInitializer.java b/IMserver/medeasy/src/chat/server/netty/NettyTCPChannelInitializer.java
new file mode 100644
index 0000000..a3826b5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettyTCPChannelInitializer.java
@@ -0,0 +1,61 @@
+package chat.server.netty; 
+
+import org.apache.log4j.Logger;
+
+import chat.server.Configer;
+import chat.server.moquette.BytesMetricsCollector;
+import chat.server.moquette.MessageMetricsCollector;
+import chat.server.moquette.MqttBytesMetricsHandler;
+import chat.server.moquette.MqttDecodHandler;
+import chat.server.moquette.MqttDispatcher;
+import chat.server.moquette.MqttEncodHandler;
+import chat.server.moquette.MqttIdleTimeoutHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.timeout.IdleStateHandler;
+
+public class NettyTCPChannelInitializer extends ChannelInitializer<SocketChannel> {
+
+//    private MessageMetricsCollector messageMetricsCollector;
+    private BytesMetricsCollector bytesMetricsCollector;
+    
+    protected Logger logger = Logger.getLogger(NettyTCPChannelInitializer.class);
+    
+    
+	@Override
+	protected void initChannel(SocketChannel channel) throws Exception {
+		int timeoutSeconds = Configer.getInteger("timeout", 10);
+		
+		ChannelPipeline pipeline = channel.pipeline();
+		
+		ChannelHandler bytesMetricsHandler = new MqttBytesMetricsHandler(bytesMetricsCollector);
+		ChannelHandler idleStateHandler = new IdleStateHandler(timeoutSeconds, 0, 0);
+		ChannelHandler timeoutHandler = new MqttIdleTimeoutHandler();
+		ChannelHandler decoder = new MqttDecodHandler();
+		ChannelHandler encoder = new MqttEncodHandler();
+		//ChannelHandler messageMetricsHandler = new MqttMessageMetricsHandler(messageMetricsCollector);
+		//ChannelHandler messageLogger = new MqttMessageLoggerHandler();
+		ChannelHandler dispatcher = new MqttDispatcher();
+		
+		pipeline.addFirst("bytemetrics", bytesMetricsHandler);
+		pipeline.addLast("idleStateHandler", idleStateHandler);
+		pipeline.addAfter("idleStateHandler", "idleEventHandler", timeoutHandler);
+		
+		pipeline.addLast("decoder", decoder);
+		pipeline.addLast("encoder", encoder);
+		//pipeline.addLast("metrics", messageMetricsHandler);
+		//pipeline.addLast("messageLogger", messageLogger);
+		pipeline.addLast("handler", dispatcher);
+	}
+
+	public void setMessageMetricsCollector(MessageMetricsCollector messageMetricsCollector) {
+//		this.messageMetricsCollector = messageMetricsCollector;
+	}
+
+	public void setBytesMetricsCollector(BytesMetricsCollector bytesMetricsCollector) {
+		this.bytesMetricsCollector = bytesMetricsCollector;
+	}
+
+} 
diff --git a/IMserver/medeasy/src/chat/server/netty/NettyWSChannelInitializer.java b/IMserver/medeasy/src/chat/server/netty/NettyWSChannelInitializer.java
new file mode 100644
index 0000000..f2c3604
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/NettyWSChannelInitializer.java
@@ -0,0 +1,89 @@
+package chat.server.netty;
+
+import chat.server.Configer;
+import chat.server.im.IMDispatcher;
+import chat.server.moquette.BytesMetricsCollector;
+import chat.server.moquette.MessageMetricsCollector;
+import chat.server.moquette.MqttBytesMetricsHandler;
+import chat.server.moquette.MqttDecodHandler;
+import chat.server.moquette.MqttEncodHandler;
+import chat.server.moquette.MqttIdleTimeoutHandler;
+import chat.server.moquette.MqttMessageLoggerHandler;
+import chat.server.moquette.MqttMessageMetricsHandler;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+
+
+public class NettyWSChannelInitializer extends ChannelInitializer<SocketChannel> {
+
+    private static final String MQTT_SUBPROTOCOL_CSV_LIST = "mqtt, mqttv3.1, mqttv3.1.1";
+    private MessageMetricsCollector messageMetricsCollector;
+    private BytesMetricsCollector bytesMetricsCollector;
+    
+	@Override
+	protected void initChannel(SocketChannel channel) throws Exception {
+		int timeoutSeconds = Configer.getInteger("timeout", 10);
+		
+		ChannelPipeline pipeline = channel.pipeline();
+		
+		ChannelHandler bytesMetricsHandler = new MqttBytesMetricsHandler(bytesMetricsCollector);
+		ChannelHandler idleStateHandler = new IdleStateHandler(timeoutSeconds, 0, 0);
+		ChannelHandler timeoutHandler = new MqttIdleTimeoutHandler();
+		
+		ChannelHandler sslHandler = createSSLHandler();
+		ChannelHandler httpEncoder = new HttpResponseEncoder();
+		ChannelHandler httpDecoder = new HttpRequestDecoder();
+		ChannelHandler aggregator = new HttpObjectAggregator(65536);
+		ChannelHandler webSocketHandler = new WebSocketServerProtocolHandler("/org/fusesource/mqtt", MQTT_SUBPROTOCOL_CSV_LIST);
+		
+		ChannelHandler decoder = new MqttDecodHandler();
+		ChannelHandler encoder = MqttEncodHandler.getInstance();
+		ChannelHandler messageMetricsHandler = new MqttMessageMetricsHandler(messageMetricsCollector);
+		ChannelHandler messageLogger = new MqttMessageLoggerHandler();
+		ChannelHandler dispatcher = new IMDispatcher();
+		
+		pipeline.addFirst("bytemetrics", bytesMetricsHandler);
+		pipeline.addLast("idleStateHandler", idleStateHandler);
+		pipeline.addAfter("idleStateHandler", "idleEventHandler", timeoutHandler);
+		
+        pipeline.addLast("ssl", sslHandler);
+        pipeline.addLast("httpEncoder", httpEncoder);
+        pipeline.addLast("httpDecoder", httpDecoder);
+        pipeline.addLast("aggregator", aggregator);
+        pipeline.addLast("webSocketHandler", webSocketHandler);
+        pipeline.addLast("ws2bytebufDecoder", new WebSocketFrameToByteBufDecoder());
+        pipeline.addLast("bytebuf2wsEncoder", new ByteBufToWebSocketFrameEncoder());
+        
+		pipeline.addLast("decoder", decoder);
+		pipeline.addLast("encoder", encoder);
+		pipeline.addLast("metrics", messageMetricsHandler);
+		pipeline.addLast("messageLogger", messageLogger);
+		pipeline.addLast("handler", dispatcher);
+	}
+
+	public void setMessageMetricsCollector(MessageMetricsCollector messageMetricsCollector) {
+		this.messageMetricsCollector = messageMetricsCollector;
+	}
+
+	public void setBytesMetricsCollector(BytesMetricsCollector bytesMetricsCollector) {
+		this.bytesMetricsCollector = bytesMetricsCollector;
+	}
+	
+    private ChannelHandler createSSLHandler() {
+		/*
+		 * SSLContext sslContext = sslCtxCreator.initSSLContext(); SSLEngine sslEngine =
+		 * sslContext.createSSLEngine(); sslEngine.setUseClientMode(false);
+		 * sslEngine.setNeedClientAuth(false);
+		 * 
+		 * return new SslHandler(sslEngine);
+		 */
+    	return null;
+    }
+} 
diff --git a/IMserver/medeasy/src/chat/server/netty/WebSocketFrameToByteBufDecoder.java b/IMserver/medeasy/src/chat/server/netty/WebSocketFrameToByteBufDecoder.java
new file mode 100644
index 0000000..b058c6d
--- /dev/null
+++ b/IMserver/medeasy/src/chat/server/netty/WebSocketFrameToByteBufDecoder.java
@@ -0,0 +1,20 @@
+package chat.server.netty;
+
+import java.util.List;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageDecoder;
+import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
+
+public class WebSocketFrameToByteBufDecoder extends MessageToMessageDecoder<BinaryWebSocketFrame> {
+
+    @Override
+    protected void decode(ChannelHandlerContext chc, BinaryWebSocketFrame frame, List<Object> out) throws Exception {
+        // convert the frame to a ByteBuf
+        ByteBuf bb = frame.content();
+        bb.retain();
+        
+        out.add(bb);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/sms/Aaa.java b/IMserver/medeasy/src/chat/sms/Aaa.java
new file mode 100644
index 0000000..be706d4
--- /dev/null
+++ b/IMserver/medeasy/src/chat/sms/Aaa.java
@@ -0,0 +1,25 @@
+package chat.sms;
+
+import redis.clients.jedis.Jedis;
+
+public class Aaa {
+
+	public static void main(String[] args) throws Exception {
+		// TODO Auto-generated method stub
+        //杩炴帴鏈湴鐨� Redis 鏈嶅姟
+        //Jedis jedis = new Jedis("139.196.115.152");
+        Jedis jedis = new Jedis("localhost");
+        // 濡傛灉 Redis 鏈嶅姟璁剧疆鏉ュ瘑鐮侊紝闇�瑕佷笅闈㈣繖琛岋紝娌℃湁灏变笉闇�瑕�
+        //jedis.auth("uThyLr0gKTCf"); 
+        System.out.println("杩炴帴鎴愬姛");
+        //jedis.set("doctor:id:1285860235186212861", "{\"id\": \"1612407967685\", \"name\" : \"绋嬪拰\", \"portrait\": \"http://cdn2.wildfirechat.cn/robot.png\", \"roletype\": 1,\"mobile\": \"12211112222\"} ");
+        if (jedis.exists("doctor:id:1285860235186212861"))
+        	jedis.del("doctor:id:1285860235186212861");
+        jedis.set("doctor:id:1285860235186212861", "{\"id\": \"1612407967685\", \"name\" : \"绋�6123467鍜孿", \"portrait\": \"http://cdn2.wildfirechat.cn/robot.png\", \"roletype\": 1,\"mobile\": \"12211112222\"} ");
+        jedis.expire("doctor:id:1285860235186212861", 30);
+        jedis.close();
+        //鏌ョ湅鏈嶅姟鏄惁杩愯
+        System.out.println("鏈嶅姟姝e湪杩愯: "+jedis.ping());
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/sms/OneClickLogin.java b/IMserver/medeasy/src/chat/sms/OneClickLogin.java
new file mode 100644
index 0000000..d959bd5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/sms/OneClickLogin.java
@@ -0,0 +1,131 @@
+package chat.sms;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+import cn.hutool.http.HttpRequest;
+
+public class OneClickLogin {
+
+	private static Logger log = Logger.getLogger(OneClickLogin.class);
+	private final String prikey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALFmv2SAZcnEUPaTNRBdOIL5Eg1e02Vj448AR4DnbMpEQMugM6zIqGik6Ckp43Jo9tXTsm6gvjcwQgYWd7U7FrsMpazH3d0ubtRiVPKxQpZKqfvGu3z6GC75LAy+qToCXecHAGU8eLOke116VrDKXjMkvTi72fhdb7gBQE2pukU1AgMBAAECgYAlRhtsuHWqoS8JwABkQdH/4uliGcx8/zHu9/YOJZH8Jb8fibeR1E9ePVfyXjTF8zv5zZMuH2QYIHGe6dWZJKMvrBNqOucnbdQ8dQMNuD+1Bg2q0zZH5EBa+Q3ISA9jYwoYTLz7sJC/n3IfkNtKQAqDIS8qjMZsmzfSSPhFi0J9AQJBAOogYuY+EPUUxh9stHraMguKWelidDk5dU1GPf+Nvi4+D+LUeqtTqVj/JHKV2CpWAlwfXpwVFiUWAMCoxj2phBUCQQDB+anXyEh4DB3HxMHs1a8P0JqF/G4HLVfRliNp2sJ3jNV9Ypp8F2QMnV7dFt2Lrdpgr8dipFLQkRboWRcj7mShAkEA6Klsfs+4/EQ7qqjVJazFxNAlD5eGVgOyfStLmzTZhIyqLsjmanGGPem256PfIBs+1xtZYpRV4F7gOpS+BDL8DQJAS8wMUzZ/IvHRHUPEZ5BkVPC1wQ+Pyxwryck6U13ZSa/tqI5EQaM+RDOmYwxRTAiGYeuuJNyDQ96+LdLKWQ8JoQJBAI9IJRs440IeEpMqfNZ0jRhKD3tZYXu2rt7fuuDTZmbGqJCWuVuTSveSSt01YZm1ij0aOwRKgIBmIOR3lBn9KP8=";
+	
+	public String mobileLogin(String content) throws Exception {
+		String host = "https://api.verification.jpush.cn/v1/web/loginTokenVerify";
+		Map<String, Object> map = new HashMap<String, Object>();
+		map.put("loginToken", content);
+		
+		Map<String, String> headers = new HashMap<String, String>();
+		headers.put("Authorization","Basic ${base64_auth_string}");
+		headers.put("Content-Type", "application/json");
+		
+		String result = HttpRequest.post(host).header("Authorization", "Basic Y2JlZWUwNWQ2MzA5OThjNjgxODQ2ZGZhOjU5ZDg4MTIzZjJlMjQzMDIxMTY5MTVhMw==").
+				header("Content-Type","application/json")
+				.body(JSON.toJSONString(map))
+				.execute().body();
+		JSONObject jsonObject = JSON.parseObject(result);
+		String cryptograph_phone = (String) jsonObject.get("phone");
+		String phone = decryptPhone(cryptograph_phone, prikey);
+		return phone;
+	}
+	
+	private String decryptPhone(String phone, String prikey) throws Exception {
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(prikey));
+        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
+
+        Cipher cipher=Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, privateKey);
+
+        byte [] b = Base64.getDecoder().decode(phone);
+        return new String(cipher.doFinal(b));		
+	}
+
+	public static void main(String[] args) throws Exception {
+//		CloseableHttpResponse response = null;
+//		CloseableHttpClient httpClient = null;
+//		String responseContent = "";
+//		String JSONBody = "{\"loginToken\":\"STsid0000001542695429579Ob28vB7b0cYTI9w0GGZrv8ujUu05qZvw\",\"exID\":\"1234566\"}";
+//		try {
+//			httpClient = HttpClientBuilder.create().build();
+//			HttpPost httpPost = new HttpPost("https://api.verification.jpush.cn/v1/web/loginTokenVerify");
+//			httpPost.addHeader("Content-Type", "application/json");
+//			httpPost.addHeader("Authorization", "Basic N2Q0MzFlNDJkZmE2YTZkNjkzYWMyZDA0OjVlOTg3YWM2ZDJlMDRkOTVhOWQ4ZjBkMQ==");
+//			httpPost.setEntity(new StringEntity(JSONBody));
+//			response = httpClient.execute(httpPost);
+//			HttpEntity entity = response.getEntity();
+//			responseContent = EntityUtils.toString(entity, "UTF-8");
+//			response.close();
+//			httpClient.close();
+//			System.out.println(responseContent);
+//		} catch (ClientProtocolException e) {
+//			log.error(e);
+//		} catch (IOException e) {
+//			log.error(e);
+//		} finally {
+//			close(response, httpClient);
+//		}
+//		String host = "https://api.verification.jpush.cn/v1/web/loginTokenVerify";
+//		String appKey = "7d431e42dfa6a6d693ac2d04";
+//		String Secret = "5e987ac6d2e04d95a9d8f0d1";
+//		Map<String, Object> map = new HashMap<String, Object>();
+//		map.put("loginToken", "zI2eLaqa6gcMmxwF5DL6J69ShKkzEKHFAHxIkJBwx7uH1GY3WbBfbTWZKXbn3HFAotFh90wkgZHEfTtUe9s6qKufYGB4yn3Rv3bp1rGJ5vWuzx3dAruTVoFxu6+Vozw1xbOGr+7UfLs56ghsyWuyWv2RdrnMeJHZ5/0la21UW9N8Ha1brFP2wl/0HiAITKjlIezpxZfH+g1dx1CUVRC1zRC7s6p+uH60Z2tgVRcus2AdVxgdtkQ+O2OTZMkNGBLzYcw9CQ8vhrUvvFiVoirv90v00gdVEbtfublJlH5OCCvtTFe9w0cJNDB7dHK/LHmQownHQi+Tk6Fh6kN78FmMwXvvugnDGKr977ntg27yjlcfmGd/RiZ1vH26WcI8OCnj");
+//		//map.put("exID", "1234566");
+//		
+//		Map<String, String> headers = new HashMap<String, String>();
+//		headers.put("Authorization","Basic ${base64_auth_string}");
+//		headers.put("Content-Type", "application/json; charset=UTF-8");
+//		
+////		String result = HttpRequest.post(host).header("Authorization", "Basic " + Base64.getUrlEncoder().
+////						encodeToString((appKey + ":" + Secret).getBytes())).
+////						header("Content-Type","application/json")
+////						.body(JSON.toJSONString(map))
+////						.execute().body();
+//		String result = HttpRequest.post(host).header("Authorization", "Basic Y2JlZWUwNWQ2MzA5OThjNjgxODQ2ZGZhOjU5ZDg4MTIzZjJlMjQzMDIxMTY5MTVhMw==").
+//				header("Content-Type","application/json")
+//				.body(JSON.toJSONString(map))
+//				.execute().body();		
+//		System.out.println(result);
+//		JSONObject jsonObject = JSON.parseObject(result);
+//		String cryptograph_phone = (String) jsonObject.get("phone");
+//		String phone = decryptPhone("TQHocUoyw5QCWXq+Mw8Q1x/jNDQAw8ol2Qb4dAoX/ljHP11NBErbL3iv+hMD7D4Jo12NRdp/j2F/H1Geq9xMnFH/OcBgsrIcwqGVgmKqyNtSAsXxT2OYgDQd2oySyw4zKyteQhuOHNhuF6u8oEEs+A6HtUiGvc3gijVZeBxE8zM=", prikey);
+//		System.out.println(phone);		
+	}
+
+	private static void close(Closeable... closeables) {
+		if (closeables != null && closeables.length > 0) {
+			try {
+				for (Closeable closeable : closeables) {
+					if (closeable != null) {
+						closeable.close();
+					}
+				}
+			} catch (IOException e) {
+				log.error(e);
+			}
+		}
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/sms/Record.java b/IMserver/medeasy/src/chat/sms/Record.java
new file mode 100644
index 0000000..a39add2
--- /dev/null
+++ b/IMserver/medeasy/src/chat/sms/Record.java
@@ -0,0 +1,25 @@
+package chat.sms;
+
+public class Record {
+    private final String code;
+    private final String mobile;
+    private final long timestamp;
+
+    public Record(String code, String mobile) {
+        this.code = code;
+        this.mobile = mobile;
+        this.timestamp = System.currentTimeMillis();
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+}
diff --git a/IMserver/medeasy/src/chat/sms/SmsService.java b/IMserver/medeasy/src/chat/sms/SmsService.java
new file mode 100644
index 0000000..0eb58eb
--- /dev/null
+++ b/IMserver/medeasy/src/chat/sms/SmsService.java
@@ -0,0 +1,57 @@
+package chat.sms;
+
+import com.aliyuncs.CommonRequest;
+import com.aliyuncs.CommonResponse;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.exceptions.ServerException;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.google.gson.Gson;
+
+import chat.consts.RestResult;
+
+public class SmsService {
+
+    private static class AliyunCommonResponse {
+        String Message;
+        String Code;
+    }
+	
+    public RestResult.RestCode sendAliyunCode(String mobile, String code) {
+        DefaultProfile profile = DefaultProfile.getProfile("default", "LTAI4GGfU6RdYxSFvQ3LiwSP", "gXh3SVeyOf2eoVTg7OkKutyC8rHg2a");
+        IAcsClient client = new DefaultAcsClient(profile);
+
+        String templateparam = "{\"code\":\"" + code + "\"}";
+        CommonRequest request = new CommonRequest();
+        request.setMethod(MethodType.POST);
+        request.setDomain("dysmsapi.aliyuncs.com");
+        request.setVersion("2017-05-25");
+        request.setAction("SendSms");
+        request.putQueryParameter("PhoneNumbers", mobile);
+        request.putQueryParameter("SignName", "鍖昏鏃犲咖");
+
+        request.putQueryParameter("TemplateCode", "SMS_206100254");
+        request.putQueryParameter("TemplateParam", templateparam);
+        try {
+            CommonResponse response = client.getCommonResponse(request);
+            System.out.println(response.getData());
+            if (response.getData() != null) {
+                AliyunCommonResponse aliyunCommonResponse = new Gson().fromJson(response.getData(), AliyunCommonResponse.class);
+                if (aliyunCommonResponse != null) {
+                    if (aliyunCommonResponse.Code.equalsIgnoreCase("OK")) {
+                        return RestResult.RestCode.SUCCESS;
+                    } else {
+                        System.out.println("Send aliyun sms failure with message:" + aliyunCommonResponse.Message);
+                    }
+                }
+            }
+        } catch (ServerException e) {
+            e.printStackTrace();
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        return RestResult.RestCode.ERROR_SERVER_ERROR;
+    }
+}
diff --git a/IMserver/medeasy/src/chat/tools/Utils.java b/IMserver/medeasy/src/chat/tools/Utils.java
new file mode 100644
index 0000000..fb39496
--- /dev/null
+++ b/IMserver/medeasy/src/chat/tools/Utils.java
@@ -0,0 +1,26 @@
+package chat.tools;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Utils {
+    public static String getRandomCode(int length) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            sb.append(((int)(Math.random()*100))%10);
+        }
+        return sb.toString();
+    }
+    public static boolean isMobile(String mobile) {
+        boolean flag = false;
+        try {
+            Pattern p = Pattern.compile("^(1[3-9][0-9])\\d{8}$");
+            Matcher m = p.matcher(mobile);
+            flag = m.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+        return flag;
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/upload/UploadFile.java b/IMserver/medeasy/src/chat/upload/UploadFile.java
new file mode 100644
index 0000000..16ad861
--- /dev/null
+++ b/IMserver/medeasy/src/chat/upload/UploadFile.java
@@ -0,0 +1,274 @@
+package chat.upload;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import chat.security.DES;
+
+import chat.server.im.ResultPool;
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpContent;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.multipart.Attribute;
+import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
+import io.netty.handler.codec.http.multipart.FileUpload;
+import io.netty.handler.codec.http.multipart.HttpDataFactory;
+import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
+import io.netty.handler.codec.http.multipart.InterfaceHttpData;
+import io.netty.util.internal.StringUtil;
+
+public class UploadFile {
+	
+    private static final String KEY = "imfile";
+    private static final Logger logger = LoggerFactory.getLogger(UploadFile.class);
+    private static final HttpDataFactory factory = new DefaultHttpDataFactory(false);
+
+	public static String multipartUpload(FullHttpRequest request, String requestId) {
+		HttpPostRequestDecoder decoder = null;
+		String key = "";
+		try {
+			 decoder = new HttpPostRequestDecoder(factory, request);
+		} catch (Exception e) {
+             logger.error("Failed to decode file data!", e);
+             e.printStackTrace();
+             return "";
+        }
+		
+		if (decoder != null) {
+			if (request instanceof HttpContent) {
+				HttpContent chunk = (HttpContent) request;
+				try {
+					 decoder.offer(chunk);
+				} catch (Exception e) {
+					 e.printStackTrace();
+					 return "";
+				}
+				
+				long fileTotalSize = 0;
+                if (request.headers().contains("X-File-Total-Size")) {
+                    try {
+                         fileTotalSize = Integer.parseInt(request.headers().get("X-File-Total-Size"));
+                    } catch (Exception e) {
+                         logger.warn("invalid X-File-Total-Size value!");
+                    }
+                }
+                
+                UploadFile uploadFile = new UploadFile();
+                key = uploadFile.readHttpDataChunkByChunk(decoder, requestId, HttpHeaders.isKeepAlive(request));
+			}
+		}
+		return key;
+	}
+	
+	private String readHttpDataChunkByChunk(HttpPostRequestDecoder decoder, String requestId, boolean isKeepAlive) {
+		String returnValue = "";
+		try {
+			 int[] bucket = new int[1];
+			 bucket[0] = -1;
+			 while (decoder.hasNext()) {
+				    InterfaceHttpData data = decoder.next();
+				    if (data != null) {
+				    	try {
+				    		 returnValue = writeFileUploadData(data, requestId, isKeepAlive, bucket);
+				    		 if (returnValue == null) {
+				    			 break;
+				    		 }
+				    	} finally {
+				    		 data.release();
+				    	}
+				    }
+			 }
+		} catch(Exception e) {
+			 logger.info("chunk end");
+			 return returnValue;
+			 //e.printStackTrace();
+		}
+		return returnValue;
+	}
+	
+	private String writeFileUploadData(InterfaceHttpData data, String requestId, boolean isKeepAlive, int[] bucket) {
+		String relativePath = "";
+		try {
+			 if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
+				 FileUpload fileUpload = (FileUpload) data;
+				 
+				 String remoteFileName = fileUpload.getFilename();
+				 long remoteFileSize = fileUpload.length();
+				 
+				 if(bucket[0] == -1) {
+					logger.info("Not authenticated!");
+					return null;
+				 }
+				 
+				 if (StringUtil.isNullOrEmpty(remoteFileName)) {
+					 logger.info("remoteFileName is empty!");
+					 return null;
+				 }
+				 
+				 if (StringUtil.isNullOrEmpty(requestId)) {
+					 logger.info("requestId is empty!");
+					 return null;
+				 }
+				 
+				 if (remoteFileSize > 100 * 1024 * 1024) {
+					 logger.info("file over limit!(" + remoteFileSize + ")");
+					 return null;
+				 }
+				 
+				 String remoteFileExt = "";
+	             if (remoteFileName.lastIndexOf(".") == -1) {
+	                 remoteFileExt = "octetstream";
+	                 remoteFileName = remoteFileName + "." + remoteFileExt;
+
+	             } else {
+	                 remoteFileExt = getFileExt(remoteFileName);
+	             }
+	             
+	             if (StringUtil.isNullOrEmpty(remoteFileExt) || remoteFileExt.equals("ing")) {
+	            	 logger.info("Invalid file extention name");
+	            	 return null;
+	             }
+	             
+	             int remoteFileTotalSize = (int) remoteFileSize;
+	             
+	             ByteBuf byteBuf = null;
+	             int savedThunkSize = 0;
+	             int offset = 0;
+	             
+	             Date nowTime = new Date();
+	             SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/HH");
+	             String datePath = sdf.format(nowTime);
+	             
+	             datePath = "fs/" + bucket[0] + "/" + datePath;
+	             String dir = "D:/media/" + datePath;
+	             
+	             File dirFile = new File(dir);
+	             if (!dirFile.exists()) {
+	            	 if (!dirFile.mkdirs()) {
+	            		 logger.info("鏃犳硶鍒涘缓鏂囦欢");
+	            		 return null;
+	            	 }
+	             }
+	             
+	             String filePath = dir + "/" + (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
+				 
+	             File tmpFile = new File(filePath);
+	             
+	             boolean isError = false;
+	             
+	             while (true) {
+	            	    byte[] thunkData;
+	            	    try {
+	            	    	 byteBuf = fileUpload.getChunk(128 * 1024);
+	            	    	 int readableBytesSize = byteBuf.readableBytes();
+	            	    	 thunkData = new byte[readableBytesSize];
+	            	    	 byteBuf.readBytes(thunkData);
+	            	    	 
+	            	    	 put(tmpFile, offset, thunkData);
+	            	    	 
+	            	    	 savedThunkSize += readableBytesSize;
+	            	    	 offset += readableBytesSize;
+	            	    	 
+	            	    	 if (savedThunkSize >= remoteFileSize) {
+	            	    		 byteBuf.release();
+	            	    		 fileUpload.release();
+	            	    		 
+	            	    		 relativePath = datePath + "/" +  (StringUtil.isNullOrEmpty(remoteFileName) ? requestId : remoteFileName);
+
+	            	    		 break;
+	            	    	 }
+	            	    } catch(Exception e) {
+	            	    	 logger.info("save thunckData error!");
+	            	    	 if (fileUpload != null) {
+	            	    		 fileUpload.release();
+	            	    	 }
+	            	    	 
+	            	    	 if (byteBuf != null) {
+	            	    		 byteBuf.release();
+	            	    	 }
+	            	    	 isError = true;
+	            	    	 
+	            	    	 return null;
+	            	    } finally {
+	            	    	 thunkData = null;
+	            	    	 if (isError) {
+	            	    		 tmpFile.delete();
+	            	    	 }
+	            	    }
+	             }
+			 }
+			 else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
+				 Attribute attribute = (Attribute) data;
+				 if (attribute.getName().equals("token")) {
+					 String token = attribute.getValue();
+					 
+					 try {
+						  bucket[0] = validateToken(token);
+						  relativePath = "";
+					 } catch(Exception e) {
+						  logger.info("鏃犳晥鐨則oken!");
+						  return null;
+					 }
+				 }
+			 }
+		} catch(Exception e) {
+			 logger.info("writeHttpData error!", e);
+			 return null;
+		}
+		return relativePath;
+	}
+	
+	public String getFileExt(String fileName) {
+	    int index = fileName.lastIndexOf(".");
+	    if (index == -1) {
+	        return "";
+	    }
+
+	    return fileName.substring(index + 1).toLowerCase();
+	}
+	
+	public void put(File file, long pos, byte[] data) throws Exception {
+		RandomAccessFile raf = null;
+		try {
+			 raf = new RandomAccessFile(file, "rwd");
+			 raf.seek(pos);
+			 raf.write(data);
+		} finally {
+			try {
+				 if (raf != null) {
+					 raf.close();
+				 }
+			} catch (Exception e) {
+				 logger.info("release error!");
+				 e.printStackTrace();
+			}
+		}
+	}
+	
+    public int validateToken(String token) throws InvalidateTokenExecption {
+        try {
+            String signKey = DES.decryptDES(token);
+            String[] parts = signKey.split("\\|");
+            if(parts.length == 3) {
+                if(parts[0].equals(KEY)) {
+                    long timestamp = Long.parseLong(parts[1]);
+                    if(Math.abs(System.currentTimeMillis() - timestamp) < 2 * 60 * 60 * 1000) {
+                        return Integer.parseInt(parts[2]);
+                    }
+                }
+            }
+        } catch (Exception e) {
+        	e.printStackTrace();
+        }
+        throw new InvalidateTokenExecption();
+    }
+    
+    public static class InvalidateTokenExecption extends Exception {}
+	
+}
\ No newline at end of file
diff --git a/IMserver/medeasy/src/chat/user/Client.java b/IMserver/medeasy/src/chat/user/Client.java
new file mode 100644
index 0000000..d3ff557
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Client.java
@@ -0,0 +1,125 @@
+package chat.user;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import chat.server.im.DataPool;
+import frame.object.data.Entity;
+
+public class Client implements IJsonProvider {
+	
+	private String id;
+	private String clientId;
+    private int platform;
+    private String code;
+    private String userId;
+    private User user;
+    private Session session;
+    
+    public Client(String clientId) {
+    	this.clientId = clientId;
+    }
+
+	public void load(DataPool dataPool) throws Exception {
+		id = dataPool.getString("clientId");
+		platform = dataPool.getInteger("platform", 0);
+		try {
+			 code = dataPool.getString("code");
+		} catch (Exception e) {
+			 code = "oneLogin";
+		}
+		
+	}
+	
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		clientId = entity.getString("id");
+		platform = entity.getInteger("platform", 0);
+		code = entity.getString("code");
+		userId = entity.getString("userId");
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("clientId", clientId);
+		entity.set("platform", platform);
+		entity.set("code", code);
+		entity.set("userId", userId);
+	}
+	
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		Token token = session.getToken();
+		
+		writer.write("token", new String(token.getFullValue()));
+		writer.write("userId", user.getId());
+		writer.write("userName", user.getName());
+		writer.write("portrait", user.getPortrait());
+		writer.write("register", user.isStranger());
+	}
+	
+	public String getId() {
+		return id;
+	}
+
+	public int getPlatform() {
+		return platform;
+	}
+	
+	public String getCode() {
+		return code;
+	}
+
+	public User getUser() {
+		return user;
+	}
+
+	public String getUserName() {
+		return user.getName();
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+
+	public void setUser(User user) {
+		this.user = user;
+		
+		if (user == null) {
+			userId = null;
+			return;
+		}
+		
+		userId = user.getId();
+		
+		user.addClient(this);
+	}
+
+	public void setUserId(String userId) {
+		this.userId = userId;
+	}
+
+	public void createSession() throws Exception {
+		session = SessionStore.getOrCreate(this);		
+	}
+
+	public Session getSession() {
+		return session;
+	}
+	
+	@Override
+	public int hashCode() {
+		if (id == null) {
+			return 0;
+		}
+		
+		return id.hashCode();
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/user/ClientStore.java b/IMserver/medeasy/src/chat/user/ClientStore.java
new file mode 100644
index 0000000..7af54d9
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/ClientStore.java
@@ -0,0 +1,147 @@
+package chat.user;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import chat.server.im.DataPool;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.persist.NamedSQL;
+
+public class ClientStore {
+
+	private static Map<String, Client> clientMap;
+	
+	static {
+		init();
+	}
+    
+	private static void init() {
+		clientMap = new ConcurrentHashMap<String, Client>();
+	}	
+
+	public static void loadOne(Entity entity) {
+		String id = entity.getString("id");
+		
+		Client client = new Client(id);
+		client.load(entity);
+		
+		addOne(client);
+	}
+	
+	public static void addOne(Client client) {
+		if (client == null) {
+			return;
+		}
+		
+		String userId = client.getUserId();
+		User user = UserStore.getById(userId);
+		
+		//client.setUser(user);
+		
+		clientMap.put(client.getId(), client);
+	}
+	
+	public static Client getOrCreate(DataPool dataPool) throws Exception {
+		String id = dataPool.getString("clientId");
+		
+		//1. get from cache
+		Client clientResult = get(id);
+		
+		//2. get from database
+		if (clientResult == null) {
+			clientResult = loadOneClient(id);
+		}
+		
+		//3. create new client
+		if (clientResult == null) {
+			clientResult = new Client(id);
+			clientResult.load(dataPool);
+			
+			clientResult = createOneClient(clientResult);
+		}
+		
+		//4. user has loaded
+		User user = clientResult.getUser();
+		
+		if (user != null) {
+			return clientResult;
+		}
+		
+		//5. user not load
+		String userId = clientResult.getUserId();
+		
+		if (userId != null) {
+			user = UserStore.getById(userId);
+			clientResult.setUser(user);
+		}
+		
+		if (user != null) {
+			return clientResult;
+		}
+		
+		//userId = ID.newValue();
+		//6. new user
+		user = new User(null);
+		user.load(dataPool);
+		user = UserStore.getOrCreate(user);
+		
+		clientResult.setUser(user);
+		updateOneClient(clientResult);
+		
+		return clientResult;
+	}
+	
+	public static Client get(String clientId) {
+        if (clientId == null) {
+            return null;
+        }
+        
+        return clientMap.get(clientId);
+    }
+	
+    public static boolean contains(String clientId) {
+        if (clientId == null) {
+            return false;
+        }
+        
+        return clientMap.containsKey(clientId);
+    }
+    
+	private static Client loadOneClient(String clientId) throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getOneClient");
+		namedSQL.setParam("id", clientId);
+		Entity entity = namedSQL.getEntity();
+		
+		if (entity == null) {
+			return null;
+		}
+		
+		Client client = new Client(clientId);
+		client.load(entity);
+		
+		return client;
+	}
+
+	private static Client createOneClient(Client client) throws Exception {
+		DataObject dataObject = DataObject.getInstance("client");
+		
+		Entity entity = dataObject.newEntity();
+		client.pushTo(entity);
+			
+		dataObject.insertToDataBase(entity);
+		return client;
+	}
+	
+	private static Client updateOneClient(Client client) throws Exception {
+		DataObject dataObject = DataObject.getInstance("client");
+		
+		Entity entity = dataObject.newEntity();
+		client.pushTo(entity);
+			
+		dataObject.updateToDataBase(entity);
+		return client;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/user/Doctor.java b/IMserver/medeasy/src/chat/user/Doctor.java
new file mode 100644
index 0000000..bd1e7d0
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Doctor.java
@@ -0,0 +1,5 @@
+package chat.user;
+
+public class Doctor {
+
+}
diff --git a/IMserver/medeasy/src/chat/user/Notify.java b/IMserver/medeasy/src/chat/user/Notify.java
new file mode 100644
index 0000000..3595c3d
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Notify.java
@@ -0,0 +1,185 @@
+package chat.user;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import chat.server.im.DataPool;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+
+public class Notify implements IJsonProvider {
+	
+	private String id;
+	private String sender;
+    private String roletype;
+    private String target;
+    private String msgtitle;
+    private String msgcontent;
+    private Date msgtime;
+	private String isread;
+    
+    private Session session;
+    
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+    
+    public Notify() {}
+    
+    public Notify(String id) {
+    	this.id = id;
+    }
+    
+	public static boolean saveNotify(Notify notify) {
+		try {
+			 DataObject dataObject = DataObject.getInstance("notify");
+			
+			 Entity entity = dataObject.newEntity();
+			 notify.pushTo(entity);
+			 dataObject.insertToDataBase(entity);
+			 return true;
+		} catch (Exception e) {
+			return false;
+		}
+	}    
+
+	public void load(DataPool dataPool) throws Exception {
+		id = dataPool.getString("id");
+		sender = dataPool.getString("sender");
+		roletype = dataPool.getString("roletype");
+		target = dataPool.getString("target");
+		msgtitle = dataPool.getString("msgtitle");
+		msgcontent = dataPool.getString("msgcontent");
+		msgtime = dataPool.getDate(dataPool.getString("msgtime"));
+	}
+	
+	public void load(Entity entity) {
+		id = entity.getString("id");
+		sender = entity.getString("sender");
+		roletype = entity.getString("roletype");
+		target = entity.getString("target");
+		msgtitle = entity.getString("msgtitle");
+		msgcontent = entity.getString("msgcontent");
+		try {
+			 msgtime = sdf.parse(entity.getString("msgtime"));
+		} catch (ParseException e) {
+			 // TODO Auto-generated catch block
+			 e.printStackTrace();
+		}
+	}
+	
+	public void pushTo(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("sender", sender);
+		entity.set("roletype", roletype);
+		entity.set("target", target);
+		entity.set("msgtitle", msgtitle);
+		entity.set("msgcontent", msgcontent);
+		entity.set("msgtime", msgtime);
+		entity.set("isread", isread);
+	}
+	
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		Token token = session.getToken();
+		
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getSender() {
+		return sender;
+	}
+
+	public void setSender(String sender) {
+		this.sender = sender;
+	}
+
+	public String getRoletype() {
+		return roletype;
+	}
+
+	public void setRoletype(String roletype) {
+		this.roletype = roletype;
+	}
+
+	public String getTarget() {
+		return target;
+	}
+
+	public void setTarget(String target) {
+		this.target = target;
+	}
+
+	public String getMsgtitle() {
+		return msgtitle;
+	}
+
+	public void setMsgtitle(String msgtitle) {
+		this.msgtitle = msgtitle;
+	}
+
+	public String getMsgcontent() {
+		return msgcontent;
+	}
+
+	public void setMsgcontent(String msgcontent) {
+		this.msgcontent = msgcontent;
+	}
+
+	public Date getMsgtime() {
+		return msgtime;
+	}
+
+	public void setMsgtime(Date msgtime) {
+		this.msgtime = msgtime;
+	}
+
+	public SimpleDateFormat getSdf() {
+		return sdf;
+	}
+
+	public void setSdf(SimpleDateFormat sdf) {
+		this.sdf = sdf;
+	}
+
+	public void setSession(Session session) {
+		this.session = session;
+	}
+
+	public Session getSession() {
+		return session;
+	}
+	
+	public String getIsread() {
+		return isread;
+	}
+
+	public void setIsread(String isread) {
+		this.isread = isread;
+	}
+
+	@Override
+	public int hashCode() {
+		if (id == null) {
+			return 0;
+		}
+		
+		return id.hashCode();
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/user/NotifyContent.java b/IMserver/medeasy/src/chat/user/NotifyContent.java
new file mode 100644
index 0000000..e628516
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/NotifyContent.java
@@ -0,0 +1,24 @@
+package chat.user;
+
+public class NotifyContent {
+	
+	private String title;
+	private NotifyContentDetail content;
+	
+	public String getTitle() {
+		return title;
+	}
+	
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public NotifyContentDetail getContent() {
+		return content;
+	}
+
+	public void setContent(NotifyContentDetail content) {
+		this.content = content;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/NotifyContentDetail.java b/IMserver/medeasy/src/chat/user/NotifyContentDetail.java
new file mode 100644
index 0000000..a5db886
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/NotifyContentDetail.java
@@ -0,0 +1,71 @@
+package chat.user;
+
+import java.util.List;
+
+public class NotifyContentDetail {
+
+	private String doctorId;
+	private String name;
+	private String portrait;
+	private String mobile;
+	private String roletype;
+	private List<String> rejectreason;
+	private int gender;
+	
+	public String getDoctorId() {
+		return doctorId;
+	}
+	
+	public void setDoctorId(String doctorId) {
+		this.doctorId = doctorId;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getPortrait() {
+		return portrait;
+	}
+	
+	public void setPortrait(String portrait) {
+		this.portrait = portrait;
+	}
+	
+	public String getMobile() {
+		return mobile;
+	}
+	
+	public void setMobile(String mobile) {
+		this.mobile = mobile;
+	}
+	
+	public String getRoletype() {
+		return roletype;
+	}
+	
+	public void setRoletype(String roletype) {
+		this.roletype = roletype;
+	}
+	
+	public List<String> getRejectreason() {
+		return rejectreason;
+	}
+
+	public void setRejectreason(List<String> rejectreason) {
+		this.rejectreason = rejectreason;
+	}
+
+	public int getGender() {
+		return gender;
+	}
+	
+	public void setGender(int gender) {
+		this.gender = gender;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/NotifyStore.java b/IMserver/medeasy/src/chat/user/NotifyStore.java
new file mode 100644
index 0000000..0483656
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/NotifyStore.java
@@ -0,0 +1,115 @@
+package chat.user;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import chat.server.im.DataPool;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.persist.NamedSQL;
+
+public class NotifyStore {
+
+	private static Map<String, Notify> notifyMap;
+	
+	static {
+		init();
+	}
+    
+	private static void init() {
+		notifyMap = new ConcurrentHashMap<String, Notify>();
+	}	
+
+	public static void loadOne(Entity entity) {
+		String id = entity.getString("id");
+		
+		Notify notify = new Notify(id);
+		notify.load(entity);
+		
+		addOne(notify);
+	}
+	
+	public static void addOne(Notify notify) {
+		if (notify == null) {
+			return;
+		}
+		
+		notifyMap.put(notify.getId(), notify);
+	}
+	
+	public static Notify getOrCreate(DataPool dataPool) throws Exception {
+		String id = dataPool.getString("id");
+		
+		//1. get from cache
+		Notify notifyResult = get(id);
+		
+		//2. get from database
+		if (notifyResult == null) {
+			notifyResult = loadOneNotify(id);
+		}
+		
+		//3. create new client
+		if (notifyResult == null) {
+			notifyResult = new Notify(id);
+			notifyResult.load(dataPool);
+			
+			notifyResult = createOneNotify(notifyResult);
+		}
+		
+		updateOneNotify(notifyResult);
+		
+		return notifyResult;
+	}
+	
+	public static Notify get(String notifyId) {
+        if (notifyId == null) {
+            return null;
+        }
+        
+        return notifyMap.get(notifyId);
+    }
+	
+    public static boolean contains(String notifyId) {
+        if (notifyId == null) {
+            return false;
+        }
+        
+        return notifyMap.containsKey(notifyId);
+    }
+    
+	private static Notify loadOneNotify(String notifyId) throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance("getOneNotify");
+		namedSQL.setParam("id", notifyId);
+		Entity entity = namedSQL.getEntity();
+		
+		if (entity == null) {
+			return null;
+		}
+		
+		Notify notify = new Notify(notifyId);
+		notify.load(entity);
+		
+		return notify;
+	}
+
+	private static Notify createOneNotify(Notify notify) throws Exception {
+		DataObject dataObject = DataObject.getInstance("notify");
+		
+		Entity entity = dataObject.newEntity();
+		notify.pushTo(entity);
+			
+		dataObject.insertToDataBase(entity);
+		return notify;
+	}
+	
+	private static Notify updateOneNotify(Notify notify) throws Exception {
+		DataObject dataObject = DataObject.getInstance("notify");
+		
+		Entity entity = dataObject.newEntity();
+		notify.pushTo(entity);
+			
+		dataObject.updateToDataBase(entity);
+		return notify;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/user/NotifySubject.java b/IMserver/medeasy/src/chat/user/NotifySubject.java
new file mode 100644
index 0000000..296e76a
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/NotifySubject.java
@@ -0,0 +1,43 @@
+package chat.user;
+
+import java.util.Date;
+
+public class NotifySubject {
+	
+	private String sender;
+	private String msgtitle;
+	private NotifyContent msgcontent;
+	private Date msgtime;
+	
+	public String getSender() {
+		return sender;
+	}
+	
+	public void setSender(String sender) {
+		this.sender = sender;
+	}
+	
+	public String getMsgtitle() {
+		return msgtitle;
+	}
+	
+	public void setMsgtitle(String msgtitle) {
+		this.msgtitle = msgtitle;
+	}
+	
+	public NotifyContent getMsgcontent() {
+		return msgcontent;
+	}
+	
+	public void setMsgcontent(NotifyContent msgcontent) {
+		this.msgcontent = msgcontent;
+	}
+	public Date getMsgtime() {
+		return msgtime;
+	}
+	
+	public void setMsgtime(Date msgtime) {
+		this.msgtime = msgtime;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/Patient.java b/IMserver/medeasy/src/chat/user/Patient.java
new file mode 100644
index 0000000..f0b9b75
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Patient.java
@@ -0,0 +1,5 @@
+package chat.user;
+
+public class Patient {
+
+}
diff --git a/IMserver/medeasy/src/chat/user/ResultMessage.java b/IMserver/medeasy/src/chat/user/ResultMessage.java
new file mode 100644
index 0000000..7a45bd4
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/ResultMessage.java
@@ -0,0 +1,29 @@
+package chat.user;
+
+public class ResultMessage {
+
+	private boolean flag;
+	private String message;
+	
+	public ResultMessage(boolean flag, String message) {
+		this.flag = flag;
+		this.message = message;
+	}
+	
+	public boolean isFlag() {
+		return flag;
+	}
+	
+	public void setFlag(boolean flag) {
+		this.flag = flag;
+	}
+	
+	public String getMessage() {
+		return message;
+	}
+	
+	public void setMessage(String message) {
+		this.message = message;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/Session.java b/IMserver/medeasy/src/chat/user/Session.java
new file mode 100644
index 0000000..1eec1c9
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Session.java
@@ -0,0 +1,87 @@
+package chat.user;
+
+import java.util.UUID;
+
+import io.netty.channel.Channel;
+
+public class Session {
+
+	private Client client;
+	private Status status;
+    private Token token;
+    private String secret;
+    private Channel channel;
+    private long lastActiveTime;
+
+    
+    public Session(Client client) throws Exception {
+    	this.client = client;
+    	this.secret = UUID.randomUUID().toString();
+    	this.token = new Token(client.getUserId(), secret);
+    }
+    
+	public void closeChannel() {
+		try {
+			channel.closeFuture();
+		}
+		catch (Exception e) {
+		}
+	}
+	
+	public void setChannel(Channel channel) {
+		this.channel = channel;
+	}
+	
+	public Token getToken() {
+		return token;
+	}
+
+	public String getSecret() {
+		return secret;
+	}
+
+	public User getUser() {
+		return client.getUser();
+	}
+
+	public Client getClient() {
+		return client;
+	}
+
+	public Status getStatus() {
+		return status;
+	}
+
+	public Channel getChannel() {
+		return channel;
+	}
+
+	public long getLastActiveTime() {
+		return lastActiveTime;
+	}
+
+	public void refreshLastActiveTime() {
+		lastActiveTime = System.currentTimeMillis();		
+	}
+
+	public long getMessageHead() {
+		// TODO Auto-generated method stub
+		return lastActiveTime;
+	}
+
+	public long getFriendHead() {
+		// TODO Auto-generated method stub
+		return lastActiveTime;
+	}
+
+	public long getFriendRqHead() {
+		// TODO Auto-generated method stub
+		return lastActiveTime;
+	}
+
+	public long getSettingHead() {
+		// TODO Auto-generated method stub
+		return lastActiveTime;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/SessionStore.java b/IMserver/medeasy/src/chat/user/SessionStore.java
new file mode 100644
index 0000000..0cb6299
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/SessionStore.java
@@ -0,0 +1,97 @@
+package chat.user;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import chat.server.moquette.message.ClientID;
+
+
+public class SessionStore {
+
+	private static Map<String, Session> sessionMap;
+
+	static {
+		init();
+	}
+	
+	private static void init() {
+		sessionMap = new ConcurrentHashMap<String, Session>();
+	}
+	
+	public static Session getOrCreate(Client client) throws Exception {
+        if (client == null) {
+            return null;
+        }
+        
+        String clientId = client.getId();
+        Session result = sessionMap.get(clientId);
+        
+        if (result == null) {
+        	result = new Session(client);
+        	sessionMap.put(clientId, result);
+        }
+        
+        return result;
+    }
+	
+	public static Session get(ClientID clientId) {
+        if (clientId == null) {
+            return null;
+        }
+        
+        if (clientId.isEmpty()) {
+        	return null;
+        }
+        
+        String key = clientId.getValue();
+        Session result = sessionMap.get(key);
+        
+        return result;
+    }
+	
+	public static Session get(String clientId) {
+        if (clientId == null) {
+            return null;
+        }
+        
+        Session result = sessionMap.get(clientId);
+        return result;
+    }
+	
+	public static void delete(ClientID clientID) {
+        if (clientID == null) {
+            return;
+        }
+        
+        String key = clientID.getValue();
+        sessionMap.remove(key);
+	}
+	
+    public static boolean contains(String clientId) {
+        if (clientId == null) {
+            return false;
+        }
+        
+        return sessionMap.containsKey(clientId);
+    }
+    
+    public static void clearSessionByUser(String userId) {
+    	User user = User.getInstance(userId);
+    	
+    	if (user == null) {
+    		return;
+    	}
+    	
+    	Set<Client> clientSet = user.getClientSet();
+    	
+    	for (Client client: clientSet) {
+    		String clientId = client.getId();
+    		Session session = sessionMap.get(clientId);
+    		
+    		session.closeChannel();
+    		sessionMap.remove(clientId);
+    	}
+    }
+
+}
diff --git a/IMserver/medeasy/src/chat/user/Status.java b/IMserver/medeasy/src/chat/user/Status.java
new file mode 100644
index 0000000..f76f732
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Status.java
@@ -0,0 +1,5 @@
+package chat.user;
+
+public class Status {
+
+}
diff --git a/IMserver/medeasy/src/chat/user/Token.java b/IMserver/medeasy/src/chat/user/Token.java
new file mode 100644
index 0000000..38e7d77
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/Token.java
@@ -0,0 +1,33 @@
+package chat.user;
+
+import chat.security.DES;
+
+public class Token {
+
+	private static String KEY = "testim";
+	private String value;
+	private String fullValue;
+	
+	public Token(String userId, String secret) throws Exception {
+		generateValue(userId, secret);
+	}
+
+	private void generateValue(String userId, String secret) throws Exception {
+		String text = KEY + "|" + (System.currentTimeMillis()) + "|" + userId;
+		value = DES.encryptDES(text);
+		fullValue = value + "|" + secret + "|" + secret;
+	}
+
+	public String getValue() {
+		return value;
+	}
+	
+	public byte[] getFullValue() {
+		return fullValue.getBytes();
+	}
+
+	public static void setKey(String key) {
+        KEY = key;
+    }
+	
+}
diff --git a/IMserver/medeasy/src/chat/user/User.java b/IMserver/medeasy/src/chat/user/User.java
new file mode 100644
index 0000000..813a4c5
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/User.java
@@ -0,0 +1,716 @@
+package chat.user;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import chat.module.ConcurrentMapList;
+import chat.module.ModuleLoader;
+import chat.module.UserMessageList;
+import chat.module.entity.FriendRequest;
+import chat.module.entity.FriendShip;
+import chat.module.entity.MessageContainer;
+import chat.module.entity.MessageRecord;
+import chat.module.entity.MessageRelation;
+import chat.module.entity.MessageType;
+import chat.module.entity.PrivateFriend;
+import chat.module.entity.PublishOperator;
+import chat.module.friendcircle.FriendCircle;
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import chat.server.im.DataPool;
+import chat.server.im.IMTopic;
+import chat.util.MessageShardingUtil;
+import cn.wildfirechat.proto.ProtoConstants;
+import cn.wildfirechat.proto.WFCMessage;
+import cn.wildfirechat.proto.WFCMessage.HandleFriendRequest;
+import cn.wildfirechat.proto.WFCMessage.Message;
+import cn.wildfirechat.proto.WFCMessage.Message.Builder;
+import frame.object.data.Entity;
+import frame.object.data.ID;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+
+public class User implements IJsonProvider {
+
+	private String id;
+	private String mobile;
+	private String name;
+	private String displayName;
+	private String portrait;
+	private String password;
+	private int gender;
+	private boolean stranger;
+	private String roletype;
+	private long timestamp;
+	private String bizid;
+	private String extra;
+	private String rejectreason;
+	
+	private WFCMessage.UserResult userResult;
+    private Set<Client> clientSet;
+    
+	protected ConcurrentMapList<List<FriendShip>> friendShipList;
+	protected ConcurrentMapList<List<FriendShip>> pushFriendList;
+	//protected ConcurrentMapList<FriendShip> pushFriendList;
+	private UserMessageList messageList;
+	private FriendCircle friendCircle;
+	
+	public User() {}
+	
+    public User(String id) {
+    	clientSet = new HashSet<Client>();
+    	friendShipList = new ConcurrentMapList<List<FriendShip>>();
+    	pushFriendList = new ConcurrentMapList<List<FriendShip>>();
+    	messageList = new UserMessageList();
+    	friendCircle = new FriendCircle();
+    }
+
+	public static User getInstance(String userId) {
+		User result = UserStore.getById(userId);
+		return result;
+	}
+	
+	public static User setUserInfo(NotifyContentDetail contentDetail) {
+		String rejectReasonMerge = "";
+		User user = new User();
+		user.setId(ID.newValue());
+		user.setBizid(contentDetail.getDoctorId());
+		user.setName(contentDetail.getName());
+		user.setDisplayName(contentDetail.getName());
+		user.setPortrait(contentDetail.getPortrait());
+		user.setMobile(contentDetail.getMobile());
+		user.setRoletype(contentDetail.getRoletype());
+		user.setExtra(contentDetail.getDoctorId());
+		if (contentDetail.getRejectreason() == null) {
+			rejectReasonMerge = "";
+		} else {
+			for (String rejectReason : contentDetail.getRejectreason()) {
+				 rejectReasonMerge = rejectReasonMerge + rejectReason + "#separate#";
+			}			
+		}
+
+		user.setRejectreason(suitableStr(rejectReasonMerge, "#separate#"));
+		return user;
+	}
+	
+	public static String suitableStr(String body, String sep) {
+		String result = "";
+		if (body == null || body.equals("")) {
+			return "";
+		}
+		int index = body.lastIndexOf(sep);
+		result = body.substring(0, index);
+		return result;
+	}
+	
+	public static User getInstance(Client client) throws Exception {
+		String userId = client.getUserId();
+		
+		if (userId == null) {
+			return null;
+		}
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getOneUserByClientId");
+		namedSQL.setParam("clientId", client.getId());
+		
+		Entity entity = namedSQL.getEntity();
+		
+		User user = new User(userId);
+		user.load(entity);
+		
+		return user;
+	}
+
+	public void createInitFrieldShip(User user) {
+		// TODO Auto-generated method stub
+		try {
+			 FriendShip friendShip = new FriendShip();
+			 User friend =  UserStore.getById("user004");
+			
+			 friendShip = new FriendShip(user, "user004", "open");
+			 friendShip.addFriendShipToDataBase();
+			 user.addOneFrieldShip(user.getId(), friendShip);
+			
+			 friendShip = friendShip.getReverseInstance();
+			 friend.addOneFrieldShip(friendShip.getUserid(), friendShip);
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+	
+	public void modifyFrieldShipStatus(FriendShip friendShip, String status) {
+		try {
+			 friendShip.updateFriendShipToDataBase("open");
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+	
+    public Client getClient(String userId) {
+    	Client clientReturn = null;
+    	if (userId == null || ("").equals(userId)) {
+    		return clientReturn;
+    	}
+    	for (Client client:clientSet) {
+    		 if (client.getUser().getId().equals(userId)) {
+    			 clientReturn = client;
+    			 break;
+    		 }
+    	}
+		return clientReturn;
+	}
+
+	public void load(DataPool dataPool) {
+		try {
+			 mobile = dataPool.getString("mobile");
+			 if (mobile == null) {
+				 mobile = dataPool.getPhone();
+			 }
+		} catch (Exception e) {
+			 mobile = dataPool.getPhone();
+		} finally {
+			if (dataPool.getString("roletype") != null) {
+				if (dataPool.getString("roletype").equals("doctor")) {
+					roletype = "1";
+				}
+				else if  (dataPool.getString("roletype").equals("")) {
+					roletype = "2";
+				}
+			}
+		}
+	}
+	
+	public void reLoad(User user) {
+		
+		name = user.getName();
+		portrait = user.getPortrait();
+		roletype = user.getRoletype();
+		mobile = user.getMobile();
+		displayName = user.getDisplayName();
+		gender = user.getGender();
+		rejectreason = user.getRejectreason();
+			
+	}
+	
+	public void load(Entity entity) {
+		if (entity == null) {
+			return;
+		}
+		
+		id = entity.getString("id");
+		mobile = entity.getString("mobile");
+		name = entity.getString("name");
+		displayName = entity.getString("displayName");
+		portrait = entity.getString("portrait");
+		password = entity.getString("password");
+		stranger = entity.getBoolean("stranger", false);
+		roletype = entity.getString("roletype");
+		extra = entity.getString("extra");
+		bizid = entity.getString("bizid");
+		rejectreason = entity.getString("rejectreason");
+		
+		userResult = null;
+	}
+	
+	//灏嗘病鏈夋帴鏀跺埌鐨勬秷鎭斁鍏ユ秷鎭槦鍒椾腑
+	public void addOneUnreceivedMessage(MessageRelation messageRelation) {
+		// TODO Auto-generated method stub
+		if (messageRelation == null) {
+			return;
+		}
+		
+		if (MessageType.unreceived == MessageType.parse(messageRelation.getStatuscode())) {
+			messageRelation.getMessageRecord().setMessage(createOneMessage(messageRelation.getMessageRecord(), messageRelation));
+			messageList.getMessageList().add(messageRelation);
+			
+		} 
+		else if (MessageType.received == MessageType.parse(messageRelation.getStatuscode())){
+			messageList.setPos(messageList.getPos() + 1);
+		}
+	}
+	
+	public WFCMessage.Message createOneMessage(MessageRecord message, MessageRelation messageRelation) {
+		WFCMessage.Message messageWFC = null;
+		
+		try {
+			 WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
+			 builder.setMessageId(message.getMessageid());
+			 builder.setServerTimestamp(message.getTimestamp());
+			 builder.setFromUser(message.getSenderId());
+			 
+			 WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
+			 cb.setType(messageRelation.getType());
+			 cb.setTarget(messageRelation.getTargetid());
+			 cb.setLine(messageRelation.getLine());
+			 builder.setConversation(cb.build());
+			 
+			 WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder();
+			 contentBuilder.setType(message.getType());
+			 contentBuilder.setSearchableContent(message.getContent());
+			 contentBuilder.setMediaType(0);
+			 contentBuilder.setPersistFlag(message.getPersistflag());
+	         contentBuilder.setExpireDuration(0);
+	         contentBuilder.setMentionedType(0);
+	         
+	         WFCMessage.MessageContent messageContent = contentBuilder.build();
+	         
+	         builder.setContent(messageContent);
+	         
+	         messageWFC = builder.build();
+			 
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+		return messageWFC;
+	}	
+
+	public void addOneFrieldShip(String friendId, FriendShip friendShip) {
+		List<FriendShip> friendShipS = friendShipList.get(friendId);
+		if (friendShipS == null) {
+			friendShipS = new ArrayList<FriendShip>();
+		}
+		
+		friendShipS.add(friendShip);
+		friendShipList.addMapList(friendId, friendShipS);
+	}
+	
+	public void addOnePushFriendShip(String friendId, FriendShip friendShip) {
+		List<FriendShip> friendShipS = pushFriendList.get(friendId);
+		if (friendShipS == null) {
+			friendShipS = new ArrayList<FriendShip>();
+		}
+		
+		friendShipS.add(friendShip);
+		pushFriendList.addMapList(friendId, friendShipS);
+	}
+	
+	//澧炲姞鏈嬪弸璇锋眰娑堟伅
+	public void addUserFriendShip(String userid, WFCMessage.AddFriendRequest request) {
+		long[] head = new long[1];
+		
+		WFCMessage.FriendRequest.Builder friendRequestBuilder = WFCMessage.FriendRequest.newBuilder();
+		friendRequestBuilder.setFromUid(userid);
+		friendRequestBuilder.setToUid(request.getTargetUid());
+		friendRequestBuilder.setReason(request.getReason());
+		friendRequestBuilder.setStatus(ProtoConstants.FriendRequestStatus.RequestStatus_Sent);
+		friendRequestBuilder.setToReadStatus(false);
+		friendRequestBuilder.setUpdateDt(System.currentTimeMillis());
+		WFCMessage.FriendRequest friendRequest = friendRequestBuilder.build();
+		
+		FriendShip friendShip = new FriendShip(UserStore.getById(userid), request.getTargetUid(), "apply");
+		friendShip.setFriendRequest(friendRequest);
+		
+		friendShip.addFriendShipToDataBase();
+		
+		UserStore.getById(userid).addOnePushFriendShip(userid, friendShip);
+		UserStore.getById(request.getTargetUid()).addOnePushFriendShip(request.getTargetUid(), friendShip);
+		
+		head[0] = System.currentTimeMillis();
+		//鍙戦�氱煡
+		FriendRequest friendData = new FriendRequest(userid, request.getTargetUid());
+		ModuleLoader.getImBusinessScheduler().execute(() -> friendData.notifyOneFriendRequest(IMTopic.NotifyFriendRequestTopic, request, head[0], userid));
+	}
+	
+	//娣诲姞鏈嬪弸鐨勫鏂癸紝鎺ュ彈璇锋眰
+	public void handleFriendRequest(String userId, WFCMessage.HandleFriendRequest request, WFCMessage.Message.Builder msgBuilder, long[] heads) {
+		// TODO Auto-generated method stub
+		if (request.getStatus() != ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) {
+			return;
+		}
+		
+		List<FriendShip> friendShipList = getApplyFriendShip(userId);
+		FriendShip loadFriendShip = null;
+		MessageContainer messageContainer;
+		
+		WFCMessage.FriendRequest existRequest = null;
+		
+		try {
+			 for (FriendShip friendShip : friendShipList) {
+			 	  if (friendShip.getUserid().equals(request.getTargetUid()) && friendShip.getFriendid().equals(userId)) {
+			 	 	  existRequest = friendShip.getFriendRequest();
+			 	 	  loadFriendShip = friendShip;
+			 	 	  break;
+			 	  }
+			 }
+			 
+			 if (existRequest != null) {
+			 	 existRequest = existRequest.toBuilder().setStatus(request.getStatus()).setUpdateDt(System.currentTimeMillis()).build();
+			 	 
+			 	 //1.鍒涘缓chatspace 鍗曡亰
+			 	 PrivateFriend privateGroup = new PrivateFriend(UserStore.getById(request.getTargetUid()).getName() + "--" + UserStore.getById(userId).getName(), UserStore.getById(request.getTargetUid()));
+			 	 privateGroup.createPrivateFriend();
+			 	 ModuleLoader.getPrivateFriendBucket().addOne(privateGroup.getId(), privateGroup);
+			 	 
+			 	 //2.鍒涘缓member
+			 	 List<String> userList = new ArrayList<String>();
+			 	 userList.add(request.getTargetUid());
+			 	 userList.add(userId);
+			 	 messageContainer = ModuleLoader.getPrivateFriendBucket().getOne(privateGroup.getId());
+			 	 messageContainer.addInitMembers(privateGroup.getId(), userList);
+			 	 
+			 	 //3.淇敼frienship涓殑鐘舵�侊紝灏嗙敵璇�(apply)鐘舵�佷慨鏀规垚閫氳繃(open)鐘舵��
+			 	 modifyFrieldShipStatus(loadFriendShip, "open");
+			 	 
+			 	 //4.灏嗙敵璇风姸鎬佷腑鐨勮褰曞垹闄�
+			 	 delApplyFriendShip(request.getTargetUid());
+			 	 getApplyFriendShip(userId);
+			 	 
+			 	 //5.灏嗗弻鏂瑰姞鍏riendship鍏崇郴涓�
+			 	 addOneFrieldShip(request.getTargetUid(), loadFriendShip);
+                 heads[0] = System.currentTimeMillis();
+			 	 loadFriendShip = loadFriendShip.getReverseInstance();
+				 addOneFrieldShip(userId, loadFriendShip);
+				 heads[1] = System.currentTimeMillis();
+				 
+                 msgBuilder.setConversation(WFCMessage.Conversation.newBuilder().setTarget(userId).setLine(0).setType(ProtoConstants.ConversationType.ConversationType_Private).build());
+                 msgBuilder.setContent(WFCMessage.MessageContent.newBuilder().setType(1).setSearchableContent(existRequest.getReason()).build());				 
+			 }
+		} catch(Exception e) {
+			 e.printStackTrace();
+		}
+	}
+
+	public void pushTo(Entity entity) throws Exception {
+		String id = ID.newValue();
+		entity.set("id", id);
+		setId(id);
+		entity.set("mobile", mobile);
+		entity.set("name", name);
+		entity.set("displayName", displayName);
+		entity.set("portrait", portrait);
+		entity.set("password", password);
+		entity.set("roletype", roletype);
+		entity.set("extra", extra);
+		entity.set("bizid", bizid);
+		entity.set("rejectreason", rejectreason);
+	}
+	
+	public void pushToModify(Entity entity) throws Exception {
+		entity.set("id", id);
+		entity.set("mobile", mobile);
+		entity.set("name", name);
+		entity.set("displayName", displayName);
+		entity.set("portrait", portrait);
+		entity.set("password", password);
+		entity.set("roletype", roletype);
+		entity.set("extra", extra);
+		entity.set("bizid", bizid);
+		entity.set("rejectreason", rejectreason);
+	}	
+	
+	public void updateDoctorId() throws Exception {
+		
+	}
+	
+	public WFCMessage.UserResult toWFCUserResult() {
+		if (userResult != null) {
+			return userResult;
+		}
+		
+		WFCMessage.User wfcUser = toWFCUser();
+		
+		WFCMessage.UserResult.Builder resultBuilder = WFCMessage.UserResult.newBuilder();
+        resultBuilder.setUser(wfcUser);
+        resultBuilder.setCode(ProtoConstants.UserResultCode.Success);
+        
+        userResult = resultBuilder.build();
+        
+        return userResult;
+	}
+	
+	public WFCMessage.User toWFCUser() {
+		WFCMessage.User.Builder userBuilder = WFCMessage.User.newBuilder();
+		userBuilder.setUid(id);
+		userBuilder.setName(name);
+		userBuilder.setDisplayName(displayName);
+		
+		userBuilder.setPortrait(portrait);
+		userBuilder.setMobile(mobile);
+		
+		if (extra != null && !extra.equals("")) {
+			userBuilder.setExtra(extra);
+		} else {
+			userBuilder.setExtra("");
+		}
+		
+		return userBuilder.build();
+	}
+
+	/**
+	  * 灏嗘秷鎭叧绯绘寕鍒版帴鏀跺鎴蜂笅闈�
+	 * @param relation
+	 * private UserMessageList messageList;
+	 */
+	public void pushOneMessageRelation(MessageRelation relation) {
+		// TODO Auto-generated method stub
+		this.messageList.getMessageList().add(relation);
+	}
+
+	public List<Message> getUnreceivedMessageList() throws Exception {
+		List<Message> result = new ArrayList<WFCMessage.Message>();
+		
+		int pos = messageList.getPos() ; 
+		int size = messageList.getMessageList().size();
+		
+		//add one message
+		for (int i = pos; i < size; i++) {
+			//1.
+			MessageRelation relation = messageList.getMessageList().get(i);
+			result.add(relation.getMessageRecord().getMessage());
+			
+			//2. update state
+			relation.updateStatusToDataBase(relation, "received");
+			
+			//3.淇敼宸茶涓嬫爣鎸囬拡
+			messageList.setPos(pos+1);
+		}
+		
+		return result;
+	}
+
+	public void addClient(Client client) {
+		for (Client clientP: clientSet) {
+			 if (clientP.getId().equals(client.getId())) {
+				 clientSet.remove(clientP);
+				 break;
+			 }
+		}
+		clientSet.add(client);
+	}
+
+	public void setDefaultValues() throws Exception {
+		//1. name 
+		NamedSQL namedSQL = NamedSQL.getInstance("nextval");
+		namedSQL.setParam("name", "usr");
+		int value = SQLRunner.getInteger(namedSQL);
+		
+		name = "User" + value;
+		displayName = name;
+		
+		//2. 
+		portrait = "http://cdn2.wildfirechat.cn/robot.png";
+
+		//3.
+		stranger = true;
+		timestamp = System.currentTimeMillis();
+//		if (!roletype.equals("")) {
+//			this.extra = getRoleUserId(mobile, roletype);
+//		}
+	}
+	
+	public Map<String, String> getRoleUserId(String phone, String roleType) throws Exception {
+		String strSQL = "";
+		Map<String, String> returnMap = new HashMap<String, String>();
+		if (roletype.equals("1")) {
+			strSQL = " select id, doctor_name as name from medo_doctor where doctor_mobile = '"+phone+"' ";
+		} else if (roletype.equals("2")) {
+			strSQL = " select id, client_name from as name from medeasy_client.mecl_client where mobile = '"+phone+"' ";
+		}
+		
+		PreparedStatement st = ModuleLoader.connDB.prepareStatement(strSQL);
+		ResultSet rs = st.executeQuery();
+		while(rs.next()){
+			 returnMap.put("id", rs.getString("id"));
+			 returnMap.put("name", rs.getString("name"));
+		}
+		return returnMap;
+	}
+	
+	/**
+	 * 
+	 * @param 鏌ヨ鍏抽敭瀛�
+	 * @param fuzzy  0  妯$硦鏌ヨ
+	 * @param page  椤垫暟
+	 * @author hefeixia 20210216
+	 * @return
+	 */
+	public List<cn.wildfirechat.proto.WFCMessage.User> searchUser(String keyword, int searchType, int page) {
+		// TODO Auto-generated method stub
+		ArrayList<WFCMessage.User> outUser = new ArrayList<WFCMessage.User>();
+		
+		Map<String, User> userAll = UserStore.getIdUserMap();
+		
+		for (User user : userAll.values()) {
+			 if (user.name.contains(keyword) || user.mobile.contains(keyword) || user.displayName.contains(keyword)) {
+				 WFCMessage.User.Builder builder = WFCMessage.User.newBuilder();
+				 builder.setUid(user.getId());
+				 builder.setName(user.getName());
+				 builder.setPortrait(user.getPortrait());
+				 builder.setMobile(user.getMobile());
+				 builder.setDisplayName(user.getDisplayName());
+				 builder.setExtra(user.getExtra());
+				 
+				 WFCMessage.User usr = builder.build();
+				 outUser.add(usr);
+			 }
+		}
+		
+		return outUser;
+	}	
+	
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		writer.write("userId", id);
+		writer.write("name", name);
+		writer.write("displayName", displayName);
+		writer.write("portrait", portrait);
+		writer.write("gender", gender);
+		writer.write("mobile", mobile);
+		writer.write("roletype", roletype);
+		writer.write("extra", extra);
+		writer.write("email", "");
+		writer.write("roletype", 1);
+		writer.write("bizid", bizid);
+		writer.write("rejectreason", rejectreason);
+	}
+	
+	@Override
+	public int hashCode() {
+		if (id == null) {
+			return 0;
+		}
+		
+		return id.hashCode();
+	}
+
+	public String getDisplayName() {
+		return displayName;
+	}
+
+	public void setDisplayName(String displayName) {
+		this.displayName = displayName;
+	}
+
+	public int getGender() {
+		return gender;
+	}
+
+	public void setGender(int gender) {
+		this.gender = gender;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public void setMobile(String mobile) {
+		this.mobile = mobile;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setPortrait(String portrait) {
+		this.portrait = portrait;
+	}
+
+	public void setPassword(String password) {
+		this.password = password;
+	}
+	
+	public List<FriendShip> getFriendship(String userId) {
+		List<FriendShip> result = friendShipList.get(userId);
+		return result;
+	}
+	
+	public List<FriendShip> getApplyFriendShip(String userId) {
+		List<FriendShip> result = pushFriendList.get(userId);
+		return result;		
+	}
+	
+	public void delApplyFriendShip(String userId) {
+		pushFriendList.delete(userId);
+	}
+
+	public String getExtra() {
+		return extra;
+	}
+
+	public void setExtra(String extra) {
+		this.extra = extra;
+	}
+	
+	public String getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getPassword() {
+		return password;
+	}
+
+	public String getPortrait() {
+		return portrait;
+	}
+
+	public String getMobile() {
+		return mobile;
+	}
+
+	public Set<Client> getClientSet() {
+		return clientSet;
+	}
+
+	public void notify(PublishOperator operator) {
+
+	}
+
+	public boolean isStranger() {
+		return stranger;
+	}
+
+	public void setStranger(boolean stranger) {
+		this.stranger = stranger;
+	}
+
+	public long getUpdateDt() {
+		return timestamp;
+	}
+
+	public String getRejectreason() {
+		return rejectreason;
+	}
+
+	public void setRejectreason(String rejectreason) {
+		this.rejectreason = rejectreason;
+	}
+
+	public String getBizid() {
+		return bizid;
+	}
+
+	public void setBizid(String bizid) {
+		this.bizid = bizid;
+	}
+
+	public String getRoletype() {
+		return roletype;
+	}
+
+	public void setRoletype(String roletype) {
+		this.roletype = roletype;
+	}
+	
+	public FriendCircle getFriendCircle() {
+		return friendCircle;
+	}
+
+}
diff --git a/IMserver/medeasy/src/chat/user/UserStore.java b/IMserver/medeasy/src/chat/user/UserStore.java
new file mode 100644
index 0000000..c008e32
--- /dev/null
+++ b/IMserver/medeasy/src/chat/user/UserStore.java
@@ -0,0 +1,282 @@
+package chat.user;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import chat.medeasy.HttpClientUtil;
+import chat.module.ModuleLoader;
+import chat.module.entity.Group;
+import chat.module.entity.Member;
+import chat.module.entity.MessageContainer;
+import chat.module.entity.PrivateFriend;
+import chat.redis.RedisUtil;
+import frame.object.data.DataObject;
+import frame.object.data.Entity;
+import frame.persist.NamedSQL;
+
+public class UserStore {
+
+	private static Map<String, User> idUserMap;
+	private static Map<String, User> phoneUserMap;
+	private static Map<String, User> extraUserMap;
+	private static User cachedUser;
+	private static String cachedUserId;	
+	
+	static {
+		init();
+	}
+    
+	private static void init() {
+		idUserMap = new ConcurrentHashMap<String, User>();
+		phoneUserMap = new ConcurrentHashMap<String, User>();
+		extraUserMap = new ConcurrentHashMap<String, User>();
+	}
+	
+	public static void loadOne(Entity entity) {
+		String id = entity.getString("id");
+		
+		User user = new User(id);
+		user.load(entity);
+		
+		addOne(user);
+	}
+	
+	public static void addOne(User user) {
+		if (user == null) {
+			return;
+		}
+		
+		String id = user.getId();
+		idUserMap.put(id, user);
+		
+		String phone = user.getMobile();
+		if (phone != null) {
+			phoneUserMap.put(phone, user);
+		}
+		
+		String extra = user.getExtra();
+		if (extra != null) {
+			extraUserMap.put(extra, user);
+		}
+	}
+
+	public static User getOrCreate(User user) throws Exception {
+		String userId = user.getId();
+		String phone = user.getMobile();
+		//String bizid = user.getBizid();
+		String flag = "";
+		
+		User userResult = null;
+		
+		//1. get user by id
+		if (userId != null) {
+			//1.1 get from cache
+			userResult = getById(userId);
+			
+			//1.2 get from database
+			if (userResult == null) {
+				userResult = loadOneUserById(userId);
+			}
+		}
+		//2. get user by phone
+		else if (phone != null) {
+			//2.1 get from cache
+			userResult = getByPhone(phone);
+			
+			//2.2 get from database
+			if (userResult == null) {
+				userResult = loadOneUserByPhone(phone);
+			}
+		}
+		
+		//3. create new user
+		if (userResult == null) {
+			userResult = user;
+			
+			userResult.setDefaultValues();
+			userResult = createOneUser(userResult);
+			
+			//璋冪敤鍖昏鏃犲咖鎺ュ彛锛屽悓姝ュ垱寤鸿处鍙� 闇�绛夋帴鍙h皟閫�  甯屾湜鐢ㄨ皟鐢ㄤ慨鏀�
+			Map<String, String> heads = new HashMap<String, String>();
+			heads.put("Content-Type", "application/json");
+			String json = "{\"doctorMobile\":\""+phone+"\",\"certificateStatus\": 0,\"sourceType\": 2}";
+			HttpClientUtil.execHttpClient(json, "http://api-test.medeasy123.com/doctor/api/save", heads);
+			
+			if (!userResult.getRoletype().equals("")) {
+				Map<String, String> userMap = user.getRoleUserId(userResult.getMobile(), userResult.getRoletype());
+				userResult.setExtra(userMap.get("id"));
+				userResult.setName(userMap.get("name"));
+				userResult.setDisplayName(userMap.get("name"));
+		    }
+			
+			//淇敼extra
+			int resultRecord = UserStore.modifyUser(userResult, "id", null);
+			 
+			if (user.getRoletype().equals("1")) {
+				 flag = "doctor:id:" + user.getExtra();
+			} else if (user.getRoletype().equals("2")) {
+				 flag = "client:id:" + user.getExtra();
+			}
+			String jsonStr = "{\"id\": \""+user.getExtra()+"\", \"name\" : \""+user.getName()+"\", \"portrait\": \""+user.getPortrait()+"\", \"roletype\": \""+user.getRoletype()+"\",\"mobile\": \""+user.getMobile()+"\"}";
+			RedisUtil.createRedisKey(flag, jsonStr);
+			
+			UserStore.addOne(user);
+		}
+		
+		return userResult;
+	}
+	
+	public static User getCachedById(String userId) {
+        if (userId == null) {
+            return null;
+        }
+        
+        if (userId.equals(cachedUserId)) {
+        	return cachedUser;
+        }
+        
+        cachedUserId = userId;
+        cachedUser = idUserMap.get(cachedUserId);
+        
+        return cachedUser;
+    }	
+
+	public static User getById(String userId) {
+        if (userId == null) {
+            return null;
+        }
+        
+        return idUserMap.get(userId);
+    }
+	
+	public static User getByExtra(String extra) {
+		if (extra == null) {
+			return null;
+		}
+		
+		return extraUserMap.get(extra);
+	}
+	
+	private static User getByPhone(String phone) {
+        if (phone == null) {
+            return null;
+        }
+        
+        return phoneUserMap.get(phone);
+	}
+	
+	private static User loadOneUserById(String userId) throws Exception {
+		if (userId == null) {
+			return null;
+		}
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getOneUserById");
+		namedSQL.setParam("id", userId);
+		Entity entity = namedSQL.getEntity();
+		
+		if (entity == null) {
+			return null;
+		}
+		
+		User user = new User(userId);
+		user.load(entity);
+		
+		return user;
+	}
+	
+	private static User loadOneUserByPhone(String phone) throws Exception {
+		if (phone == null) {
+			return null;
+		}
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("getOneUserByPhone");
+		namedSQL.setParam("phone", phone);
+		Entity entity = namedSQL.getEntity();
+		
+		if (entity == null) {
+			return null;
+		}
+		
+		User user = new User(null);
+		user.load(entity);
+		
+		return user;
+	}
+	
+	public static User createOneUser(User user)  {
+		String flag = "";
+		MessageContainer messageContainer;
+		try {
+			 DataObject dataObject = DataObject.getInstance("usr");
+			
+			 Entity entity = dataObject.newEntity();
+			 user.pushTo(entity);
+			 dataObject.insertToDataBase(entity);
+			 
+			 UserStore.addOne(user);
+			 
+			 //1.鍒涘缓chatspace 鍗曡亰
+			 PrivateFriend privateGroup = new PrivateFriend("鍖荤敓鍔╃悊", user);
+			 privateGroup.createPrivateFriend();
+			 ModuleLoader.getPrivateFriendBucket().addOne(privateGroup.getId(), privateGroup);
+			 
+			 //2.鍒涘缓member
+			 List<String> userList = new ArrayList<String>();
+			 userList.add(user.getId());
+			 userList.add("user004");
+			 messageContainer = ModuleLoader.getPrivateFriendBucket().getOne(privateGroup.getId());
+			 messageContainer.addInitMembers(privateGroup.getId(), userList);
+			 
+			 //3?.闇�瑕佸彂涓�鏉℃秷鎭殏鏃堕渶涓嶉渶瑕�
+			 
+			 //4.鍒涘缓frienship
+			 user.createInitFrieldShip(user);
+
+			 return user;			
+		} catch(Exception e) {
+			 return null;
+		}
+	}
+	
+	public static int modifyUser(User user, String pointColumn) {
+		return modifyUser(user, pointColumn, null);
+	}
+	
+	/**
+	 * 
+	 * @param userId
+	 * @return
+	 */
+	public static int modifyUser(User user, String pointColumn, Map<String, String> excludeColumn) {
+		if (user == null) {
+			return -2;
+		}
+		
+		try {
+			 DataObject dataObject = DataObject.getInstance("usr");
+			 Entity entity = dataObject.newEntity();
+			 user.pushToModify(entity);
+			 int result = dataObject.updateToDateBaseWill(entity, pointColumn, excludeColumn);
+			 
+			 return result;
+		} catch (Exception e) {
+			return 0;
+		}
+	}
+
+	public static boolean contains(String userId) {
+        if (userId == null) {
+            return false;
+        }
+        
+        return idUserMap.containsKey(userId);
+    }
+
+	public static Map<String, User> getIdUserMap() {
+		return idUserMap;
+	}
+    
+}
diff --git a/IMserver/medeasy/src/chat/util/ByteStrToStr.java b/IMserver/medeasy/src/chat/util/ByteStrToStr.java
new file mode 100644
index 0000000..7da4a82
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/ByteStrToStr.java
@@ -0,0 +1,34 @@
+package chat.util;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+import com.google.protobuf.ByteString;
+
+public class ByteStrToStr {
+
+	public static String transformStr(ByteString src) {
+		byte[] input = src.toByteArray();
+		ByteBuffer buffer = ByteBuffer.allocate(input.length);
+	    buffer.put(input);
+	    buffer.flip();
+	    
+	    Charset charset = null;
+	    CharsetDecoder decoder = null;
+	    CharBuffer charBuffer = null;
+
+	    try {
+	         charset = Charset.forName("UTF-8");
+	         decoder = charset.newDecoder();
+	         charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
+
+	         return charBuffer.toString();
+	    } catch (Exception ex) {
+	        ex.printStackTrace();
+	    }
+	    return "";
+	}	
+
+}
diff --git a/IMserver/medeasy/src/chat/util/BytesSelfUtil.java b/IMserver/medeasy/src/chat/util/BytesSelfUtil.java
new file mode 100644
index 0000000..bdb7135
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/BytesSelfUtil.java
@@ -0,0 +1,13 @@
+package chat.util;
+
+import io.netty.buffer.ByteBuf;
+
+public class BytesSelfUtil {
+
+	public static byte[]  getReadableBytes(ByteBuf ackPayload) {
+	    byte[] resBytes = new byte[ackPayload.readableBytes()];
+	    ackPayload.getBytes(0, resBytes);
+		return resBytes;
+	}	
+
+}
diff --git a/IMserver/medeasy/src/chat/util/DBUtil.java b/IMserver/medeasy/src/chat/util/DBUtil.java
new file mode 100644
index 0000000..666d4bd
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/DBUtil.java
@@ -0,0 +1,95 @@
+package chat.util;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+public class DBUtil {
+
+	private DruidDataSource dataSource;
+	
+	public static boolean IsEmbedDB = false;
+	
+	public DBUtil() {
+		dataSource = new DruidDataSource();
+		this.dataSource.setDriverClassName("com.mysql.jdbc.Driver");
+		this.dataSource.setUrl("jdbc:mysql://rm-uf65021a947ky5h453o.mysql.rds.aliyuncs.com:3306/medeasy_doctor?useSSL=false");
+		this.dataSource.setUsername("user");
+		this.dataSource.setPassword("U7t6XJnnHMii");
+		//璁剧疆杩炴帴姹犲垵濮嬪寲鐨勮繛鎺ヤ釜鏁�
+		//this.dataSource.setPoolPreparedStatements(true);
+		//this.dataSource.setMaxOpenPreparedStatements(25);
+		this.dataSource.setInitialSize(50);
+		this.dataSource.setMaxActive(100);
+		this.dataSource.setMinIdle(20);
+	}
+	
+	public DruidDataSource getDataSource() {
+		return dataSource;
+	}
+	
+	public Connection getConnection() {
+		Connection conn = null;
+		try {
+			  conn = dataSource.getConnection();
+		} catch (SQLException e) {
+			  e.printStackTrace();
+		}
+		return conn;
+	}
+	
+	public void close(Connection conn, PreparedStatement pst, ResultSet rs) {
+		if (rs != null) {
+			try {
+				  rs.close();
+			} catch (SQLException e) {
+				  e.printStackTrace();
+			}
+		}
+		close(conn, pst);
+	}
+	
+	public void close(Connection conn, PreparedStatement pst) {
+		if (pst != null) {
+			try {
+				 pst.close();
+			} catch(SQLException e) {
+				 e.printStackTrace();
+			}
+		}
+		close(conn);
+	}
+	
+	public void close(Connection conn) {
+		if (conn != null) {
+			try {
+				 conn.close();
+			} catch(SQLException e) {
+				 e.printStackTrace();
+			}
+		}
+	}
+	
+	public void commit(Connection conn) {
+		if (conn != null) {
+			try {
+				 conn.commit();
+			} catch(SQLException e) {
+				 e.printStackTrace();
+			}
+		}
+	}
+	
+	public void rollback(Connection conn) {
+		if (conn != null) {
+			try {
+				 conn.rollback();
+			} catch(Exception e) {
+				 e.printStackTrace();
+			}
+		}
+	}
+}
diff --git a/IMserver/medeasy/src/chat/util/I18n.java b/IMserver/medeasy/src/chat/util/I18n.java
new file mode 100644
index 0000000..3ee4253
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/I18n.java
@@ -0,0 +1,82 @@
+package chat.util;
+
+import io.netty.util.internal.StringUtil;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLDecoder;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class I18n {
+    private static ClassLoader Loader = null;
+    static {
+	        String configPath = System.getProperty("wildfirechat.path", null);
+	        String classPath = I18n.class.getResource("/").getPath();
+	        classPath = classPath.replace("WEB-INF/classes", "");
+	        try {
+				 classPath = URLDecoder.decode(classPath, "UTF-8");
+			} catch (UnsupportedEncodingException e1) {
+				 // TODO Auto-generated catch block
+				 e1.printStackTrace();
+			}
+	        String resBundlePaht = "config/i18n";
+	        
+	        File file = new File(classPath, resBundlePaht);
+	        URL[] urls = new URL[0];
+	        try {
+	             urls = new URL[]{file.toURI().toURL()};
+	             Loader = new URLClassLoader(urls);
+	        } catch (MalformedURLException e) {
+	            e.printStackTrace();
+	        }
+    }
+
+    private static Map<String, ResourceBundle> bundleMap = new ConcurrentHashMap<>();
+
+    public static String getString(String language, String key) {
+        ResourceBundle bundle = bundleMap.get(language);
+
+        if (StringUtil.isNullOrEmpty(language)) language = "zh_CN";
+
+        if (bundle == null) {
+            bundle = ResourceBundle.getBundle("messages", new Locale(language), Loader);
+            bundleMap.put(language, bundle);
+        }
+
+        try {
+            return bundle.getString(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "绯熺硶锛屽瓧绗︿覆 " + key + " 娌℃湁鎵惧埌";
+    }
+
+    public static void test() throws MalformedURLException {
+
+        // 璁剧疆瀹氬埗鐨勮瑷�鍥藉浠g爜
+        Locale locale1 = new Locale("zh");
+        Locale locale2 = new Locale("en");
+        ResourceBundle rb = ResourceBundle.getBundle("messages", locale1, Loader);
+
+        // 鑾峰緱鐩稿簲鐨刱ey鍊�
+        String greeting = rb.getString("Above_Greeting_Message");
+        String userInfo = rb.getString("Friend_Can_Start_Chat");
+
+        System.out.println(greeting);
+        System.out.println(userInfo);
+    }
+
+    public static void main(String[] args) throws Exception {
+        //test();
+    	//String configPath = System.getProperty("medeasy.path", null);
+    	String aa = System.getProperty("user.dir");
+    	String bb = I18n.class.getResource("/").getPath();//I18n.class.getResource("/").getPath();
+    	System.out.println(aa);
+    	bb = URLDecoder.decode(bb, "UTF-8");
+        System.out.println(bb);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/util/MessageShardingUtil.java b/IMserver/medeasy/src/chat/util/MessageShardingUtil.java
new file mode 100644
index 0000000..836ac63
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/MessageShardingUtil.java
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the Wildfire Chat package.
+ * (c) Heavyrain2012 <heavyrain.lee@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+package chat.util;
+
+import java.util.Calendar;
+import java.util.Date;
+
+public class MessageShardingUtil {
+    private static SpinLock mLock = new SpinLock();
+    private static volatile int rotateId = 0;
+    private static volatile long timeId = 0;
+    private static int nodeId = 0;
+
+    private static int rotateIdWidth = 15;
+    private static int rotateIdMask = 0x7FFF;
+
+    private static int nodeIdWidth = 6;
+    private static int nodeIdMask = 0x3F;
+
+    private static final long T201801010000 = 1514736000000L;
+
+    public static void setNodeId(int nodeId) {
+        MessageShardingUtil.nodeId = nodeId;
+    }
+
+    /**
+     * ID = timestamp(43) + nodeId(6) + rotateId(15)
+     * 鎵�浠ユ椂闂撮檺鍒舵槸鍒�2157/5/15锛�2鐨�42娆″箓浠h〃鐨勬椂闂� + (2018-1970)锛夈�傝妭鐐规暟闄愬埗鏄皬浜�64锛屾瘡鍙版湇鍔″櫒姣忔绉掓渶澶氬彂閫�32768鏉℃秷鎭�
+     * @return
+     */
+    public static long generateId() throws Exception {
+        mLock.lock();
+        rotateId = (rotateId + 1)&rotateIdMask;
+        mLock.unLock();
+
+        long id = System.currentTimeMillis() - T201801010000;
+
+        if (id > timeId) {
+            timeId = id;
+            rotateId = 1;
+        } else if(id == timeId) {
+            if (rotateId == (rotateIdMask - 1)) { //褰撳墠绌洪棿宸茬粡鐢ㄥ畬锛岀瓑寰呬笅涓�涓┖闂存墦寮�
+                while (id <= timeId) {
+                    id = System.currentTimeMillis() - T201801010000;
+                }
+                mLock.unLock();
+                return generateId();
+            }
+        } else { //id < timeId;
+            if (rotateId > (rotateIdMask -1)*9/10) { //绌洪棿宸茬粡鎺ヨ繎鐢ㄥ畬
+                if (timeId - id < 3000) { //鏃堕棿鍥炴嫧灏忎簬3绉掞紝绛夊緟鏃堕棿璧朵笂鍥炴嫧涔嬪墠璁板綍
+                    while (id < timeId) {
+                        id = System.currentTimeMillis() - T201801010000;
+                    }
+                    mLock.unLock();
+                    return generateId();
+                } else { //鏃堕棿鍥炴嫧澶т簬3绉掞紝鎶涘嚭寮傚父锛岃繖娈垫椂闂存秷鎭皢涓嶅彲鐢ㄣ��
+                    mLock.unLock();
+                    throw new Exception("Time turn back " + (timeId - id) + " ms, it too long!!!");
+                }
+            } else {
+                id = timeId;
+            }
+
+        }
+
+        id <<= nodeIdWidth;
+        id += (nodeId & nodeIdMask);
+
+        id <<= rotateIdWidth;
+        id += rotateId;
+        return id;
+    }
+
+    public static String getMessageTable(long mid) {
+        if (DBUtil.IsEmbedDB) {
+            return "t_messages";
+        }
+
+        Calendar calendar = Calendar.getInstance();
+        if (mid != Long.MAX_VALUE) {
+            mid >>= (nodeIdWidth + rotateIdWidth);
+            Date date = new Date(mid + T201801010000);
+            calendar.setTime(date);
+        } else {
+            Date date = new Date(System.currentTimeMillis());
+            calendar.setTime(date);
+        }
+        int month = calendar.get(Calendar.MONTH);
+        int year = calendar.get(Calendar.YEAR);
+        year %= 3;
+        return "t_messages_" + (year * 12 + month);
+    }
+
+    public static String getPreviousMessageTable(long mid) {
+        if (DBUtil.IsEmbedDB) {
+            return null;
+        }
+
+        mid >>= (nodeIdWidth + rotateIdWidth);
+        Date date = new Date(mid + T201801010000);
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int month = calendar.get(Calendar.MONTH);
+        int year = calendar.get(Calendar.YEAR);
+        year %= 3;
+        month = month - 1;
+        if (month == -1) {
+            month = 11;
+            year = (year + 3 - 1)%3;
+        }
+        return "t_messages_" + (year * 12 + month);
+    }
+}
diff --git a/IMserver/medeasy/src/chat/util/SpinLock.java b/IMserver/medeasy/src/chat/util/SpinLock.java
new file mode 100644
index 0000000..76853f3
--- /dev/null
+++ b/IMserver/medeasy/src/chat/util/SpinLock.java
@@ -0,0 +1,21 @@
+package chat.util;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public class SpinLock {
+    //java涓師瀛愶紙CAS锛夋搷浣�
+    AtomicReference<Thread> owner = new AtomicReference<>();//鎸佹湁鑷棆閿佺殑绾跨▼瀵硅薄
+    private int count;
+    public void lock() {
+        Thread cur = Thread.currentThread();
+        //lock鍑芥暟灏唎wner璁剧疆涓哄綋鍓嶇嚎绋嬶紝骞朵笖棰勬祴鍘熸潵鐨勫�间负绌恒�倁nlock鍑芥暟灏唎wner璁剧疆涓簄ull锛屽苟涓旈娴嬪�间负褰撳墠绾跨▼銆傚綋鏈夌浜屼釜绾跨▼璋冪敤lock鎿嶄綔鏃剁敱浜巓wner鍊间笉涓虹┖锛屽鑷村惊鐜�
+
+        //涓�鐩磋鎵ц锛岀洿鑷崇涓�涓嚎绋嬭皟鐢╱nlock鍑芥暟灏唎wner璁剧疆涓簄ull锛岀浜屼釜绾跨▼鎵嶈兘杩涘叆涓寸晫鍖恒��
+        while (!owner.compareAndSet(null, cur)){
+        }
+    }
+    public void unLock() {
+        Thread cur = Thread.currentThread();
+        owner.compareAndSet(cur, null);
+    }
+}
diff --git a/IMserver/medeasy/src/frame/object/dao/Filter.java b/IMserver/medeasy/src/frame/object/dao/Filter.java
new file mode 100644
index 0000000..03bdc8d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/Filter.java
@@ -0,0 +1,200 @@
+package frame.object.dao;
+
+import frame.object.meta.EntityMeta;
+import frame.object.meta.Field;
+import frame.util.ContentBuilder;
+import frame.util.Util;
+import frame.variant.IVariantsConsumer;
+import frame.variant.IVariantsProvider;
+import frame.variant.VariantLink;
+import frame.variant.ValueType;
+import frame.variant.translator.ITranslator;
+
+import java.util.*;
+
+public class Filter implements IVariantsConsumer, IVariantsProvider {
+
+	private EntityMeta entityMeta;
+	private Map<String, FilterItem> items;
+	private String rawFilter;
+	private boolean raw = false;
+	private boolean empty;
+
+	
+	public Filter() {
+		items = new HashMap<String, FilterItem>();
+	}
+	
+	public Filter(String filter) {
+		rawFilter = filter;
+		raw = true;
+	}
+	
+	public void addAll(EntityMeta entityMeta, Set<String> excludeNames, IVariantsProvider...valueProviders) throws Exception {
+		this.entityMeta = entityMeta;
+		
+		for (int i = 0; i < valueProviders.length; i++) {
+			IVariantsProvider provider = valueProviders[i];
+			VariantLink.moveOnConsumer(provider, this, excludeNames);
+		}
+	}
+
+	public void add(String fieldName, String value) {
+		this.addItem(fieldName, "=", value);
+	}
+
+	public void addItem(String fieldName, String operator, String value) {
+		FilterItem item = new FilterItem(fieldName, operator, value);
+		items.put(fieldName, item);
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		List<String> result = new ArrayList<String>();
+		result.add("orderby");
+		
+		return result;
+	}
+
+	@Override
+	public boolean containsVariant(String name) {
+		return "filter".equalsIgnoreCase(name);
+	}
+
+	@Override
+	public Object getVariantValue(String name) {
+		return toString();
+	}
+
+	@Override
+	public void setVariant(String name, Object value) throws Exception {
+		if (value == null) {
+			return;
+		}
+		
+		if (entityMeta == null) {
+			throw new Exception("filter entityMeta is null");
+		}
+		
+		if(!entityMeta.contains(name)) {
+			return;
+		}
+		Field field = entityMeta.getField(name);
+		
+		if (field == null) {
+			return;
+		}
+		
+		ITranslator translator = field.getTranslator();
+		ValueType type = field.getValueType();
+		
+		if (ValueType.String == type) {
+			String stringValue = value.toString();
+			String segmentValue = null;
+			
+			//1. like
+			if (stringValue.startsWith("(like)")) {
+				if (stringValue.endsWith("(like)")) {
+					//1.1 all like
+					segmentValue = "'%" + stringValue.substring(7, stringValue.length() - 6) + "%'";
+					addItem(name, "like", segmentValue);
+				}
+				else {
+					//1.2 left like
+					segmentValue = "'%" + stringValue.substring(7) + "'";
+					addItem(name, "like", segmentValue);
+				}
+			}
+			else if (stringValue.endsWith("(like)")) {
+				//1.3 right like
+				segmentValue = "'" + stringValue.substring(0, stringValue.length() - 6) + "%'";
+				addItem(name, "like", segmentValue);
+			}
+			
+			else {
+				//1.3 no like
+				segmentValue = "'" + stringValue + "'";
+				addItem(name, "=", segmentValue);
+			}
+		}
+		else {
+			String segmentValue = translator.toSqlString(value);
+			addItem(name, "=", segmentValue);
+		}
+	}
+	
+	@Override
+	public void setVariants(IVariantsProvider... providers) throws Exception { 
+		if (providers == null || providers.length == 0) {
+			return;
+		}
+		
+		Set<String> keySet = items.keySet();
+		
+		for (String key: keySet) {
+			for (IVariantsProvider provider: providers) {
+				if (provider.containsVariant(key)) {
+					FilterItem item = items.get(key);
+					Object value = provider.getVariantValue(key);
+					
+					if (!Util.isEmptyStr(value)) {
+						item.setValue(String.valueOf(value));
+					}
+				}
+			}
+		}
+	}
+	
+	@Override
+	public boolean isVariantNull(String name) {
+		return empty;
+	}
+
+	
+	public FilterItem getItemByName(String name) {
+		if (items == null) {
+			return null;
+		}
+		return items.get(name);
+	}
+	
+	public FilterItem removeItemByName(String name) {
+		if (items == null) {
+			return null;
+		}
+		return items.remove(name);
+	}
+	
+	public boolean isRaw() {
+		return raw;
+	}
+
+	public String getRawFilter() {
+		return rawFilter;
+	}
+
+	@Override
+	public String toString() {
+		if (raw) {
+			return rawFilter;
+		}
+		
+		if (items.isEmpty()) {
+			return null;
+		}
+		
+		ContentBuilder result = new ContentBuilder(" and ");
+		Set<String> keySet = items.keySet();
+		for (String key : keySet) {
+			FilterItem filterItem = items.get(key);
+			result.append(filterItem.toSQLString());
+		}
+		
+		if (result.isEmpty()) {
+			result.append(" 1 = 1 ");
+		}
+		
+		return "(" + result + ")";
+	}
+	
+}
\ No newline at end of file
diff --git a/IMserver/medeasy/src/frame/object/dao/FilterItem.java b/IMserver/medeasy/src/frame/object/dao/FilterItem.java
new file mode 100644
index 0000000..a775820
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/FilterItem.java
@@ -0,0 +1,51 @@
+package frame.object.dao;
+
+public class FilterItem {
+
+	private String fieldName;
+	private String operator;
+	private String value;
+	private String raw;
+	
+	
+	public FilterItem(String fieldName, String operator, String value) {
+		this.fieldName = fieldName;
+		this.operator = operator;
+		this.value = value;
+		this.raw = null;
+	}
+	
+	public FilterItem(String raw) {
+		this.raw = raw;
+	}
+
+	public String toSQLString() {
+		if (raw != null) {
+			return raw;
+		}
+		
+		return fieldName + " " + operator + " " + value;
+	}
+	
+	public String getFieldName() {
+		return fieldName;
+	}
+
+	public String getOperator() {
+		return operator;
+	}
+
+	public String getValue() {
+		return value;
+	}
+	
+	public void setValue(String value) {
+		this.value = value; 
+	}
+
+	@Override
+	public String toString() {
+		return toSQLString();
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/dao/FilterSegment.java b/IMserver/medeasy/src/frame/object/dao/FilterSegment.java
new file mode 100644
index 0000000..bf4a24f
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/FilterSegment.java
@@ -0,0 +1,5 @@
+package frame.object.dao;
+
+public class FilterSegment {
+
+}
diff --git a/IMserver/medeasy/src/frame/object/dao/MethodPublisher.java b/IMserver/medeasy/src/frame/object/dao/MethodPublisher.java
new file mode 100644
index 0000000..58aaf06
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/MethodPublisher.java
@@ -0,0 +1,54 @@
+package frame.object.dao;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class MethodPublisher {
+
+	protected Map<String, Method> methodMap;
+	protected Map<String, Method> allMethodMap;
+	
+	
+	public MethodPublisher() {
+		methodMap = new HashMap<String, Method>();
+		allMethodMap = new HashMap<String, Method>();
+
+		collectMethod();
+		publishMethod();
+	}
+	
+	public Method getMethod(String lower) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	protected void collectMethod() {
+		Method[] methods = this.getClass().getDeclaredMethods();
+
+		for (Method one : methods) {
+			allMethodMap.put(one.getName().toLowerCase(), one);
+		}
+	}
+
+	protected abstract void publishMethod();
+
+	protected void addMethod(String name) {
+		if (name == null) {
+			return;
+		}
+
+		name = name.toLowerCase();
+		Method method = allMethodMap.get(name);
+
+		if (method != null) {
+			method.setAccessible(true);
+			methodMap.put(name, method);
+		}
+	}
+
+	public Map<String, Method> getMethodMap() {
+		return methodMap;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/dao/OrderBy.java b/IMserver/medeasy/src/frame/object/dao/OrderBy.java
new file mode 100644
index 0000000..d329a2d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/OrderBy.java
@@ -0,0 +1,53 @@
+package frame.object.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import frame.util.Util;
+import frame.variant.IVariantsProvider;
+
+public class OrderBy implements IVariantsProvider {
+
+	private String value;
+	private boolean empty;
+	
+	public OrderBy(String value) {
+		this.value = value;
+		empty = Util.isEmptyStr(value);
+	}
+
+	public String getValue() {
+		if (empty) {
+			return "";
+		}
+		
+		return " order by " + value + " ";
+	}
+
+	public boolean isEmpty() {
+		return empty;
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		List<String> result = new ArrayList<String>();
+		result.add("orderby");
+		
+		return result;
+	}
+
+	@Override
+	public boolean containsVariant(String name) {
+		return "orderby".equalsIgnoreCase(name);
+	}
+
+	@Override
+	public Object getVariantValue(String name) {
+		if (empty) {
+			return "";
+		}
+		
+		return value;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/dao/Page.java b/IMserver/medeasy/src/frame/object/dao/Page.java
new file mode 100644
index 0000000..39ccdbe
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/dao/Page.java
@@ -0,0 +1,197 @@
+package frame.object.dao;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import frame.persist.NamedSQL;
+import frame.variant.IVariantsProvider;
+import frame.variant.expression.IVariantRequestListener;
+import frame.variant.expression.VariantRequestParams;
+
+public class Page implements IVariantRequestListener, IVariantsProvider, IJsonProvider {  
+	
+	private static Set<String> parameterNames;
+    private int pageSize;  
+    private int recordCount;  
+    private int pageNo;
+  
+    static {
+    	parameterNames = new HashSet<String>();
+    	parameterNames.add("pagesize");
+    	parameterNames.add("recordcount");
+    	parameterNames.add("pageno");
+    	parameterNames.add("beginno");   
+    	parameterNames.add(NamedSQL.Param_Limit);
+    }
+    
+    public Page(int recordCount) { 
+    	this.pageSize = 20;
+    	this.pageNo = 1;
+        this.recordCount = recordCount;
+    }  
+    
+	public int getBeginRecordNo() { 
+    	int recordNo = pageSize * (pageNo - 1) + 1; 
+        return recordNo;  
+    }  
+    
+    public int getBeginRecordNo_1() { 
+    	int recordNo = getBeginRecordNo();
+        return recordNo - 1;  
+    } 
+    
+    public int getEndRecordNo() {  
+    	int recordNo = pageSize * pageNo;
+        return Math.min(recordNo, recordCount);  
+    }  
+    
+    public int getPageSize() {  
+        return pageSize;  
+    }  
+  
+    public int getPageNo() {  
+        return pageNo;
+    }  
+  
+    public int getRecordCount() {  
+        return recordCount;  
+    }  
+  
+    public int getPageCount() {  
+        return (int)Math.ceil(recordCount * 1.0d / pageSize);
+    }  
+  
+    public void setRecordCount(int count) {
+    	this.recordCount = count;
+    }
+  
+    public void setPageSize(int value) { 
+    	if (value <= 0) {
+    		return;
+    	}
+    	
+       	pageSize = value;  
+    }  
+    
+	public void setPageNo(int pageNo) {
+		this.pageNo = pageNo;
+	}
+
+	public void set(String name, String value) {
+		name = name.toLowerCase();
+		
+		if ("pageno".equals(name)) {
+			setPageNo(Integer.parseInt(value));
+		}
+		else if ("pagesize".equals(name)) {
+			setPageSize(Integer.parseInt(value));			
+		}
+
+	}
+
+ 	public String toString() {
+		StringBuilder result = new StringBuilder();
+		
+		result.append("size=").append(pageSize).append(",");
+		result.append("recordCount=").append(recordCount).append(",");
+		result.append("pageNo=").append(pageNo);
+		
+		return result.toString();
+	}
+
+	@Override
+	public String getStringValue(String name, VariantRequestParams params) {
+		if ("pageSize".equalsIgnoreCase(name)) {
+			return String.valueOf(pageSize);
+		}
+		else if ("recordCount".equalsIgnoreCase(name)) {
+			return String.valueOf(recordCount);
+		}
+		else if ("pageNo".equalsIgnoreCase(name)) {
+			return String.valueOf(pageNo);
+		}
+		else if ("beginNo".equalsIgnoreCase(name)) {
+			int beginNo = getBeginRecordNo_1();
+			return String.valueOf(beginNo);
+		}
+		else if ("endNo".equalsIgnoreCase(name)) {
+			int endNo = getEndRecordNo();
+			return String.valueOf(endNo);
+		}
+		else if (NamedSQL.Param_Limit.equalsIgnoreCase(name)) {
+			return getLimitSQL();
+		}
+		
+		return null;
+	}
+
+
+	@Override
+	public List<String> getVariantNames() {
+		return new ArrayList<String>(parameterNames);
+	}
+
+	public static Set<String> getVarinatNameSet() {
+		return parameterNames;
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		List<String> result = new ArrayList<String>();
+		result.addAll(parameterNames);
+		
+		return result;
+	}
+
+	@Override
+	public boolean containsVariant(String name) {
+		if (name == null) {
+			return false;
+		}
+		
+		name = name.toLowerCase();
+		return parameterNames.contains(name);
+	}
+
+	@Override
+	public Object getVariantValue(String name) {
+		return getStringValue(name, null);
+	}
+
+	public boolean next() {
+		int pageCount = getPageCount();
+		
+		if (pageNo < pageCount) {
+			pageNo++;
+			return true;
+		}
+		
+		return false;
+	}
+
+	public String getLimitSQL() {
+		return " limit " + getBeginRecordNo_1() + ", " + pageSize;
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();		
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		writer.write("recordcount", getRecordCount());
+		writer.write("pagecount", getPageCount());
+		writer.write("pagesize", getPageSize());
+		writer.write("pageno", getPageNo());
+		writer.write("beginrecordno", getBeginRecordNo());
+		writer.write("endrecordno", getEndRecordNo());
+	}
+	
+}  
\ No newline at end of file
diff --git a/IMserver/medeasy/src/frame/object/data/DataException.java b/IMserver/medeasy/src/frame/object/data/DataException.java
new file mode 100644
index 0000000..28eb40d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/DataException.java
@@ -0,0 +1,18 @@
+package frame.object.data;
+
+public class DataException extends Exception {
+
+	private String code;
+	
+	public DataException(String code, String message) {
+		super(message);
+		this.code = code;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	private static final long serialVersionUID = 1L;
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/DataObject.java b/IMserver/medeasy/src/frame/object/data/DataObject.java
new file mode 100644
index 0000000..34232e1
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/DataObject.java
@@ -0,0 +1,128 @@
+package frame.object.data;
+
+import java.util.List;
+import java.util.Map;
+
+import frame.object.dao.Filter;
+import frame.object.meta.EntityMeta;
+import frame.object.meta.EntityMetaLoader;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+
+
+public class DataObject {
+	
+	private static DataObjectContainer container;
+	private static String SQL_GetEntity = "getEntity";
+	private static String SQL_InsertEntity = "insertEntity";
+	private static String SQL_UpdateEntity = "updateById";
+	
+	private String tableName;
+	private EntityMeta entityMeta;
+	
+
+	static {
+		container = DataObjectContainer.getInstance();
+	}
+	
+	public DataObject(String tableName) {
+		this.tableName = tableName;
+	}
+	
+	public static DataObject getInstance(String dataName) throws Exception {
+		DataObject result = container.get(dataName);
+		
+		if (result == null) {
+			throw new DataException("DataNotExists", "dataobject not exists: " + dataName);
+		}
+		
+		return result;
+	}
+	
+	public static DataObject getInstance(String dataName, boolean nullThrowException) throws Exception {
+		DataObject result = container.get(dataName);
+		
+		if (result == null && nullThrowException) {
+			throw new DataException("DataNotExists", "dataobject not exists: " + dataName);
+		}
+		
+		return result;
+	}
+
+	public Entity newEntity() throws Exception {
+		return new Entity(entityMeta);
+	}
+	
+	public EntitySet newEntitySet() throws Exception {
+		return new EntitySet(entityMeta);
+	}
+	
+	public int insertToDataBase(Entity entity) throws Exception {
+		//1. check empty id
+		if (entity.isEmptyValue("id")) {
+			entity.set("id", ID.newValue());
+		}
+		
+		//2. insert
+		NamedSQL namedSQL = NamedSQL.getInstance(SQL_InsertEntity);
+		namedSQL.setTableName(tableName).setFieldNames(entity.getEntityMeta(), entity).setFieldValues(entity);
+		return SQLRunner.execSQL(namedSQL);
+	}
+	
+	public int updateToDateBaseWill(Entity entity, String updateColumn, Map<String, String> excludeColumn) throws Exception {
+		String updateValue = entity.getString(updateColumn);
+		
+		if (updateValue == null) {
+			return -1;
+		}
+		
+		NamedSQL namedSQL = NamedSQL.getInstance("updateByOther");
+		//namedSQL.setTableName(tableName).setFieldNames(entity.getEntityMeta(), entity, excludeColumn).setFieldValues(entity);
+		namedSQL.setTableName(tableName).setFieldNameValues(entity, excludeColumn);
+		namedSQL.setParam("appointColumn", updateColumn);
+		namedSQL.setParam("appointValue", updateValue);
+		
+		return SQLRunner.execSQL(namedSQL);
+	}
+
+	public int updateToDataBase(Entity entity) throws Exception {
+		String id = entity.getString("id");
+		
+		if (id == null) {
+			return 0;
+		}
+		
+		NamedSQL namedSQL = NamedSQL.getInstance(SQL_UpdateEntity);
+		namedSQL.setTableName(tableName).setFieldNameValues(entity).setParam("id", id);
+		return SQLRunner.execSQL(namedSQL);		
+	}
+	
+	public EntityMeta getEntityMeta() throws Exception {
+		if (entityMeta == null) {
+			synchronized (this) {
+				if (entityMeta == null) {
+					loadEntityMeta();
+				}
+			}
+		}
+
+		return entityMeta;
+	}
+
+	private void loadEntityMeta() throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance(SQL_GetEntity);
+
+		Filter filter = new Filter();
+		filter.addItem("1", "<>", "1");
+
+		namedSQL.setTableName(tableName).setFilter(filter);
+
+		EntityMetaLoader entityMetaLoader = new EntityMetaLoader();
+		entityMeta = entityMetaLoader.getEntityMetaByNamedSQL(namedSQL);
+	}
+
+	public String getTableName() {
+		return tableName;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/DataObjectContainer.java b/IMserver/medeasy/src/frame/object/data/DataObjectContainer.java
new file mode 100644
index 0000000..07f0267
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/DataObjectContainer.java
@@ -0,0 +1,46 @@
+package frame.object.data;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DataObjectContainer {
+
+	private static DataObjectContainer instance;
+	private static Map<String, DataObject> dataObjectMap;
+	private Object locker;
+	
+	
+	private DataObjectContainer() {
+		dataObjectMap = new ConcurrentHashMap<String, DataObject>();
+		locker = new Object();
+	}
+	
+	public synchronized static DataObjectContainer getInstance() {
+		if (instance == null) {
+			instance = new DataObjectContainer();
+		}
+		
+		return instance;
+	}
+	
+	public DataObject get(String tableName) throws Exception {
+		if (tableName == null) {
+			return null;
+		}
+		
+		tableName = tableName.toLowerCase();
+		DataObject result = dataObjectMap.get(tableName);
+		
+		if (result == null) {
+			synchronized (locker) {
+				if (result == null) {
+					result = new DataObject(tableName);
+					result.getEntityMeta();
+				}
+			}
+		}
+		
+		return result;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/Entity.java b/IMserver/medeasy/src/frame/object/data/Entity.java
new file mode 100644
index 0000000..3a63d39
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/Entity.java
@@ -0,0 +1,419 @@
+package frame.object.data;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import frame.object.meta.EntityMeta;
+import frame.util.Util;
+import frame.variant.IVariantsConsumer;
+import frame.variant.IVariantsProvider;
+import frame.variant.ValueType;
+import frame.variant.VariantLink;
+import frame.variant.translator.ITranslator;
+import frame.variant.translator.StringTranslator;
+import frame.variant.translator.Translator;
+
+
+public class Entity implements IVariantsConsumer, IVariantsProvider, IJsonProvider {
+
+	private boolean deleted = false;
+	private EntityMeta entityMeta;
+	private Object[] dataArray;
+
+	
+	public Entity(EntityMeta tableMeta) {
+		this.entityMeta = tableMeta;
+		dataArray = new Object[tableMeta.getFieldCount()];
+	}
+
+	public void set(int i, Object object) {
+		dataArray[i] = object;
+	}
+
+	public Entity set(String name, Object value) throws Exception {
+		Integer idx = entityMeta.getIndex(name);
+		
+		if (idx == null) {
+			return this;
+		}
+		
+		if (value == null) {
+			dataArray[idx] = null;
+		}
+		else {
+			ITranslator translator = entityMeta.getTranslator(idx);
+			Object obj = Translator.toTranslatorTypeValue(value, translator.getDataClass());
+			dataArray[idx] = obj;
+		}
+		
+		return this;
+	}
+
+	public ID getID() {
+		return new ID(getVarinatValue("id"));
+	}
+	
+	public void setID(ID id) throws Exception {
+		set("id", id.getValue());
+	}
+
+	public Object getVarinatValue(String field) {
+		int idx = entityMeta.getIndex(field);
+		return dataArray[idx];
+	}
+	
+	public ValueType getValueType(int idx) {
+		return entityMeta.getValueType(idx);
+	}
+	
+	public Object getValue(int idx) {
+		return dataArray[idx];
+	}
+	
+	public Object getValue(String fieldName) {
+		Integer idx = entityMeta.getIndex(fieldName);
+		
+		if (idx == null) {
+			return null;
+		}
+		
+		return dataArray[idx];
+	}
+
+	public String getString(String fieldName) {
+		Integer idx = entityMeta.getIndex(fieldName);
+		
+		if (idx == null) {
+			return null;
+		}
+		
+		return getString(idx, null);
+	}
+
+	public String getString(String fieldName, String defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getString(idx, defaultValue);
+	}
+
+	public String getString(int idx, String defaultValue) {
+		try {
+			Object value = dataArray[idx];
+			ITranslator translator = entityMeta.getTranslator(idx);
+			return translator.toString(value);
+		}
+		catch (Exception e) {
+			return "error";
+		}
+	}
+	
+	public String getQuotedString(String fieldName) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getQuotedString(idx, null);
+	}
+
+	public String getQuotedString(String fieldName, String defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getQuotedString(idx, defaultValue);
+	}
+	
+	public String getQuotedString(int idx, String defaultValue) {
+		String result = getString(idx, defaultValue);
+		return Util.quotedStr(result);
+	}
+	
+	public String getJSONString(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getJSONString(idx);
+	}
+	
+	public String getJSONString(String fieldName, String defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getJSONString(idx, defaultValue);
+	}
+	
+	public String getJSONString(int idx, String defaultValue) {
+		try {
+			return getJSONString(idx);
+		}
+		catch (Exception e) {
+			e.printStackTrace();
+			return "\"error\"";
+		}
+	}
+	
+	public String getJSONString(int idx) throws Exception {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		if (translator == null) {
+			translator = new StringTranslator();
+		}
+		return translator.toJSONString(value);
+	}
+	
+	public String getSQLString(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getSQLString(idx);
+	}
+	
+	public String getSQLString(int idx) throws Exception {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toSqlString(value);
+	}
+	
+	public String getSQLString(int idx, String defaultValue) {
+		try {
+			String result = getSQLString(idx);
+			return result;
+		}
+		catch(Exception e) {
+			return defaultValue;
+		}
+	}
+
+	public String getSchemaString(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getSchemaString(idx);
+	}
+	
+	public String getSchemaString(int idx) throws Exception {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toSchemaString(value);
+	}
+
+	public boolean getBoolean(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getBoolean(idx, false);
+	}
+	
+	public boolean getBoolean(String fieldName, boolean defaultValue) {
+		Integer idx = entityMeta.getIndex(fieldName);
+		
+		if (idx == null) {
+			return defaultValue;
+		}
+		
+		return getBoolean(idx, defaultValue);
+	}	
+	
+	public boolean getBoolean(int idx, boolean defaultValue) {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toBoolean(value, defaultValue);
+	}
+	
+	public Date getDate(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getDate(idx, null);
+	}
+	
+	public Date getDate(String fieldName, Date defaultValue) {
+		Integer idx = entityMeta.getIndex(fieldName);
+		
+		if (idx == null) {
+			return defaultValue;
+		}
+		
+		try {
+			return getDate(idx, defaultValue);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}	
+	
+	public Date getDate(int idx, Date defaultValue) throws Exception {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toDate(value, defaultValue);
+	}
+
+	public Integer getInteger(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getInteger(idx, 0);
+	}
+	
+	public Integer getInteger(String fieldName, int defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getInteger(idx, defaultValue);		
+	}
+	
+	public Integer getInteger(int idx, int defaultValue) {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toInteger(value, defaultValue);
+	}
+	
+	public BigDecimal getBigDecimal(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getBigDecimal(idx, BigDecimal.ZERO);
+	}
+	
+	public BigDecimal getBigDecimal(String fieldName, BigDecimal defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getBigDecimal(idx, defaultValue);
+	}
+	
+	public BigDecimal getBigDecimal(int idx, BigDecimal defaultValue) {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toBigDecimal(value, defaultValue);
+	}
+	
+	public double getDouble(String fieldName) throws Exception {
+		int idx = entityMeta.getIndex(fieldName);
+		return getDouble(idx, 0);
+	}
+	
+	public double getDouble(String fieldName, double defaultValue) {
+		int idx = entityMeta.getIndex(fieldName);
+		return getDouble(idx, defaultValue);
+	}
+	
+	public double getDouble(int idx, double defaultValue) {
+		Object value = dataArray[idx];
+		ITranslator translator = entityMeta.getTranslator(idx);
+		return translator.toDouble(value, defaultValue);
+	}
+
+	public String getSQLTypeCode(String typeField, String lengthField) {
+		Object type = getValue(typeField);
+		Object length = getValue(lengthField);
+		
+		return Translator.toSQLTypeCode(type, length);
+	}
+
+	public String getSQLNullCode(String fieldName) {
+		Object nullable = getValue(fieldName);
+		return Translator.toSQLNullCode(nullable);
+	}
+	
+	public int getFieldCount() {
+		return entityMeta.getFieldCount();
+	}
+
+	public String[] getLowerNames() {
+		return entityMeta.getLowerNames();
+	}
+
+	public EntityMeta getEntityMeta() {
+		return entityMeta;
+	}
+
+	public boolean isEmptyValue(String fieldName) {
+		Integer idx = entityMeta.getIndex(fieldName);
+		
+		if (idx == null) {
+			return true;
+		}
+		
+		return isEmptyValue(idx);
+	}
+	
+	public boolean isEmptyValue(int idx) {
+		return dataArray[idx] == null;
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		String[] lowerNames = entityMeta.getLowerNames();
+		return Arrays.asList(lowerNames);
+	}
+
+	@Override
+	public boolean containsVariant(String name) {
+		return entityMeta.contains(name);
+	}
+
+	public void setVariant(String name, Object value) throws Exception {
+		set(name, value);
+	}
+	
+	public boolean valueEquals(String field, Object anotherValue) {
+		Object value = getVarinatValue(field);
+		
+		if (value == null) {
+			if (anotherValue == null) {
+				return true;
+			}
+			
+			return false;
+		}
+		
+		if (anotherValue == null) {
+			return false;
+		}
+		
+		if (value.getClass().equals(anotherValue.getClass())) {
+			return value.equals(anotherValue);
+		}
+		
+		String valueStr = Translator.toString(value, "");
+		String anotherStr = Translator.toString(anotherValue, "");
+		return valueStr.equals(anotherStr);
+	}
+
+	public boolean isEmpty() {
+		for (int i = 0; i < dataArray.length; i++) {
+			if (dataArray[i] != null) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+
+	public void setDeleted() {
+		deleted = true;
+	}
+
+	public boolean isDeleted() {
+		return deleted;
+	}
+	
+	public String getTableName() {
+		return entityMeta.getTableName();
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginObject();
+		writeJSONData(writer);
+		writer.endObject();		
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		String[] propertyNames = entityMeta.getLowerNames();
+		int cnt = propertyNames.length;
+		
+		for (int i = 0; i < cnt; i++) {
+			writer.writeJSON(propertyNames[i], getJSONString(i, "\"error\""));
+		}		
+	}
+
+	@Override
+	public void setVariants(IVariantsProvider... providers) throws Exception {
+		VariantLink.moveOnConsumer(this, providers);
+	}
+
+	@Override
+	public Object getVariantValue(String name) {
+		return getValue(name);
+	}
+
+	@Override
+	public boolean isVariantNull(String name) {
+		return isEmptyValue(name);
+	}
+
+	public boolean fieldExists(String fieldName) {
+		return entityMeta.contains(fieldName);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntityClassFactory.java b/IMserver/medeasy/src/frame/object/data/EntityClassFactory.java
new file mode 100644
index 0000000..5c5c791
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntityClassFactory.java
@@ -0,0 +1,27 @@
+package frame.object.data;
+
+import java.lang.reflect.Constructor;
+import java.sql.ResultSet;
+
+import frame.object.meta.EntityMeta;
+
+public class EntityClassFactory extends EntityFactory { 
+
+	private Class<? extends Entity> clazz;
+	
+	public EntityClassFactory(Class<? extends Entity> clazz) {
+		this.clazz = clazz;
+	}
+	
+	@Override
+	public Entity createEntity(ResultSet rslt) throws Exception {
+		Constructor<? extends Entity> constructor = clazz.getConstructor(EntityMeta.class);
+		
+		if (constructor == null) {
+			throw new DataException("ConstructorError", "Constructor error : " + clazz.getName());
+		}
+		
+		return constructor.newInstance(entityMeta);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntityFactory.java b/IMserver/medeasy/src/frame/object/data/EntityFactory.java
new file mode 100644
index 0000000..f1ca2be
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntityFactory.java
@@ -0,0 +1,25 @@
+package frame.object.data;
+
+import java.sql.ResultSet;
+
+import frame.object.meta.EntityMeta;
+
+public abstract class EntityFactory {
+
+	protected EntityMeta entityMeta;
+	
+	public EntityFactory() {
+		
+	}
+	
+	public EntityMeta getEntityMeta() {
+		return entityMeta;
+	}
+
+	public void setEntityMeta(EntityMeta entityMeta) {
+		this.entityMeta = entityMeta;
+	}
+
+	public abstract Entity createEntity(ResultSet rslt) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntityInitializer.java b/IMserver/medeasy/src/frame/object/data/EntityInitializer.java
new file mode 100644
index 0000000..a6461d2
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntityInitializer.java
@@ -0,0 +1,42 @@
+package frame.object.data;
+
+import frame.variant.expression.VariantRequestParams;
+
+public class EntityInitializer {
+
+	public void exec(VariantRequestParams variantRequestParams, Entity entity) throws Exception {
+		entity.setID(new ID());
+	}
+
+	public void loadDefaultValue(VariantRequestParams params) throws Exception {
+//		String tableName = entityMeta.getName();
+//		EntityConfig entityConfig = configContainer.getField(tableName);
+//		
+//		if (entityConfig == null) {
+//			set("id", Util.newShortGUID());
+//			return;
+//		}
+//		
+//		for (FieldConfig fieldConfig: entityConfig) {
+//			String name = fieldConfig.getName();
+//			
+//			if (!entityMeta.containsSuperVCode(name)) {
+//				continue;
+//			}
+//			
+//			Object value = fieldConfig.getValue(params);
+//			set(name, value);
+//		}
+	}
+
+	public static EntityInitializer getInstance(String dataName) {
+		EntityInitializer result = EntityInitializerContainer.get(dataName);
+		
+		if (result == null) {
+			result = new EntityInitializer();
+		}
+		
+		return result;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntityInitializerContainer.java b/IMserver/medeasy/src/frame/object/data/EntityInitializerContainer.java
new file mode 100644
index 0000000..71a1688
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntityInitializerContainer.java
@@ -0,0 +1,10 @@
+package frame.object.data;
+
+public class EntityInitializerContainer {
+
+	public static EntityInitializer get(String dataName) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntitySet.java b/IMserver/medeasy/src/frame/object/data/EntitySet.java
new file mode 100644
index 0000000..4aeb9ce
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntitySet.java
@@ -0,0 +1,175 @@
+package frame.object.data;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+import frame.object.meta.EntityMeta;
+
+
+public class EntitySet implements Iterable<Entity>, IJsonProvider {
+
+	protected EntityMeta entityMeta;
+	protected List<Entity> entityList;
+	protected int maxSize;
+	protected Indexes indexes;
+
+	
+	public EntitySet(EntityMeta tableMeta) {
+		this(tableMeta, -1);
+	}
+
+	public EntitySet(EntityMeta entityMeta, int maxSize) {
+		this.entityMeta = entityMeta;
+		
+		if (maxSize > 0) {
+			this.maxSize = maxSize;
+			entityList = new ArrayList<Entity>(maxSize);
+		}
+		else {
+			entityList = new ArrayList<Entity>(15);
+		}
+		
+		indexes = new Indexes(this);
+	}
+
+	public Entity newEntity() {
+		Entity entity = new Entity(entityMeta);
+		return entity;
+	}
+	
+	public Entity append() {
+		Entity entity = new Entity(entityMeta);
+		entityList.add(entity);
+
+		return entity;
+	}
+	
+	public Entity append(Entity entity) {
+		entityList.add(entity);
+		indexes.setDirty();
+		
+		return entity;
+	}
+
+	public Entity getEntity(int idx) {
+		Entity entity = entityList.get(idx);
+		
+		if (entity == null || entity.isDeleted()) {
+			return null;
+		}
+		
+		return entity;
+	}
+	
+	public Entity getEntity(ID id) throws DataException {
+		if (id == null) {
+			return null;
+		}
+		
+		Entity entity = indexes.getEntity("id", id.getValue());
+		
+		if (entity == null || entity.isDeleted()) {
+			return null;
+		}
+		
+		return entity;
+	}
+	
+	public Entity getEntity(String field, Object value) throws DataException {
+		if (field == null) {
+			return null;
+		}
+		
+		Entity entity =  indexes.getEntity(field, value);
+		
+		if (entity == null || entity.isDeleted()) {
+			return null;
+		}
+		
+		return entity;
+	}
+	
+	public void delete(ID id) throws DataException {
+		if (id == null) {
+			return;
+		}
+		
+		Entity entity = indexes.getEntity("id", id.getValue());
+		
+		if (entity == null) {
+			return;
+		}
+		
+		entity.setDeleted();
+	}
+	
+	public void clear() {
+		entityList.clear();
+	}
+
+	public boolean isEmpty() {
+		return entityList.isEmpty();
+	}
+	
+	public boolean isFull() {
+		return entityList.size() >= maxSize;
+	}
+	
+	public String getTableName() {
+		return entityMeta.getTableName();
+	}
+
+	public int getFieldCount() {
+		return entityMeta.getFieldCount();
+	}
+
+	public EntityMeta getEntityMeta() {
+		return entityMeta;
+	}
+
+	public List<Entity> getEntityList() {
+		return entityList;
+	}
+
+
+
+	@Override
+	public Iterator<Entity> iterator() {
+		return new EntitySetIterator(this);
+	}
+
+	public int size() {
+		return entityList.size();
+	}
+
+	public String[] getLowerNames() {
+		return entityMeta.getLowerNames();
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginArray();
+		writeJSONData(writer);
+		writer.endArray();		
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		int lineIndex = 0; int lineNo = 1;
+		
+		for (Entity entity : this) {
+			writer.beginObject();
+			
+			writer.write("lineIndex", lineIndex++);
+			writer.write("lineNo", lineNo++);
+			
+			entity.writeJSONData(writer);
+			
+			writer.endObject();
+		}		
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntitySetIterator.java b/IMserver/medeasy/src/frame/object/data/EntitySetIterator.java
new file mode 100644
index 0000000..26b61b3
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntitySetIterator.java
@@ -0,0 +1,33 @@
+package frame.object.data;
+
+import java.util.Iterator;
+
+public class EntitySetIterator implements Iterator<Entity> {
+
+	private EntitySet entitySet;
+	private int max;
+	private int pos;
+	
+	public EntitySetIterator(EntitySet entitySet) {
+		this.entitySet = entitySet;
+		max = entitySet.size();
+		pos = 0;
+	}
+	
+	@Override
+	public boolean hasNext() {
+		return pos < max;
+	}
+
+	@Override
+	public Entity next() {
+		Entity entity = entitySet.getEntity(pos++);
+		return entity;
+	}
+
+	@Override
+	public void remove() {
+		return;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/EntityTree.java b/IMserver/medeasy/src/frame/object/data/EntityTree.java
new file mode 100644
index 0000000..8fefea7
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/EntityTree.java
@@ -0,0 +1,95 @@
+package frame.object.data;
+
+import chat.server.call.IJSONWriter;
+import frame.object.meta.EntityMeta;
+
+
+public class EntityTree extends EntitySet {
+
+	private EntitySet rootSet;
+	
+	public EntityTree(EntityMeta tableMeta) {
+		super(tableMeta);
+		rootSet = new EntitySet(tableMeta);
+	}
+
+	public EntitySet getChildren(ID parentId) throws DataException {
+		Node parent = getNode(parentId);
+		
+		if (parent == null) {
+			return null;
+		}
+		
+		return parent.children;
+	}
+
+	public Node getNode(ID id) throws DataException {
+		Entity result = getEntity(id);
+		return (Node) result;
+	}
+
+	public EntitySet getRootSet() {
+		return rootSet;
+	}
+	
+	public void initRelation() throws DataException {
+		initFamilyRelation();
+		initLevelRelation();
+	}
+	
+	public void initFamilyRelation() throws DataException {
+		for (Entity entity: this) {
+			Node node = (Node) entity;
+			ID parentId = node.getParentId();
+			
+			if (parentId.isEmpty()) {
+				node.level = 0;
+				rootSet.append(node);
+				continue;
+			}
+			
+			Node parent = getNode(parentId);
+			
+			if (parent == null) {
+				continue;
+			}
+			
+			parent.addChild(node);
+		}
+	}
+	
+	public void initLevelRelation() throws DataException {
+		for (Entity entity: rootSet) {
+			Node node = (Node) entity;
+			doInitLevelRelation(node);
+		}
+	}
+
+	private void doInitLevelRelation(Node parent) {
+		EntitySet children = parent.getChildren();
+		
+		for (Entity entity: children) {
+			Node child = (Node) entity;
+			child.level = parent.level + 1;
+			
+			EntitySet offsprings = child.getChildren();
+			
+			for (Entity offspring: offsprings) {
+				doInitLevelRelation((Node)offspring);
+			}
+		}
+	}
+	
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginArray();
+		
+		for (Entity entity: rootSet) {
+			Node node = (Node)entity;
+			node.writeJSONObject(writer);
+		}
+		
+		writer.endArray();	
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/data/ID.java b/IMserver/medeasy/src/frame/object/data/ID.java
new file mode 100644
index 0000000..4c49155
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/ID.java
@@ -0,0 +1,53 @@
+package frame.object.data;
+
+import frame.util.Util;
+
+public class ID {
+	
+	private String value;
+
+	public ID() {
+		value = Util.newShortGUID();
+	}
+	
+	public static String newValue() {
+		return Util.newShortGUID();
+	}
+	
+	public ID(Object value) {
+		if (value != null) {
+			this.value = value.toString();
+		}
+	}
+	
+	public String getValue() {
+		return value;
+	}
+
+	public boolean isEmpty() {
+		return Util.isEmptyStr(value);
+	}
+
+	public String getQuotedValue() {
+		return Util.quotedStr(value);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (value == null) {
+			return false;
+		}
+		
+		if (obj == null) {
+			return false;
+		}
+		
+		return value.equals(obj.toString());
+	}
+
+	@Override
+	public String toString() {
+		return "id=" + value;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/data/IIndex.java b/IMserver/medeasy/src/frame/object/data/IIndex.java
new file mode 100644
index 0000000..9cd03c8
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/IIndex.java
@@ -0,0 +1,10 @@
+package frame.object.data;
+
+
+public interface IIndex {
+
+	Entity get(Object value);
+	
+	void add(Object value, Entity entity);
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/data/Index.java b/IMserver/medeasy/src/frame/object/data/Index.java
new file mode 100644
index 0000000..7132567
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/Index.java
@@ -0,0 +1,57 @@
+package frame.object.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import frame.object.meta.EntityMeta;
+
+
+public class Index implements IIndex {
+	
+	private String dataName;
+	private String fieldName;
+	private Map<Object, Entity> maps;
+
+	
+	public Index(String dataName, String fieldName) {
+		maps = new HashMap<Object, Entity>();
+		
+		this.dataName = dataName;
+		this.fieldName = fieldName;
+	}
+
+	public void load(EntitySet entitySet) {
+		EntityMeta meta = entitySet.getEntityMeta();
+		int index = meta.getIndex(fieldName);
+		
+		for (Entity entity: entitySet) {
+			Object value = entity.getValue(index);
+			
+			if (value == null) {
+				continue;
+			}
+			
+			maps.put(value, entity);
+		}
+	}
+	
+	public void add(Object value, Entity entity) {
+		if (value == null) {
+			return;
+		}
+		
+		maps.put(value, entity);
+	}
+	
+	public Entity get(Object value) {
+		if (value == null) {
+			return null;
+		}
+		
+		return maps.get(value);
+	}
+
+	public String getName() {
+		return dataName + "." + fieldName;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/object/data/Indexes.java b/IMserver/medeasy/src/frame/object/data/Indexes.java
new file mode 100644
index 0000000..d6611b9
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/Indexes.java
@@ -0,0 +1,61 @@
+package frame.object.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import frame.object.meta.EntityMeta;
+import frame.object.meta.Field;
+import frame.variant.ValueType;
+
+public class Indexes {
+	
+	private EntitySet entitySet;
+	private Map<String, IIndex> indexMap;
+	private boolean dirty;
+	
+	public Indexes(EntitySet entitySet) {
+		indexMap = new HashMap<String, IIndex>();
+		this.entitySet = entitySet;
+	}
+	
+	public Entity getEntity(String fieldName, Object value) throws DataException {
+		if (fieldName == null) {
+			return null;
+		}
+		
+		fieldName = fieldName.toLowerCase();
+		IIndex index = indexMap.get(fieldName);
+		
+		if (dirty || index == null) {
+			index = createIndex(fieldName);
+			indexMap.put(fieldName, index);
+		}
+		
+		Entity entity = index.get(value);
+		return entity;
+	}
+
+	private IIndex createIndex(String fieldName) throws DataException {
+		EntityMeta meta = entitySet.getEntityMeta();
+		Field field = meta.getField(fieldName);
+		
+		if (field == null) {
+			throw new DataException("FieldNotExists", "field not exists: " + fieldName);
+		}
+		
+		ValueType type = field.getValueType();
+		
+		if (ValueType.String != type && ValueType.Long != type && ValueType.Int != type) {
+			throw new DataException("FieldCannotCreateIndex", "filed can not create index: " + fieldName);
+		}
+		
+		Index index = new Index(meta.getTableName(), fieldName);
+		index.load(entitySet);
+		
+ 		return index;
+	}
+
+	public void setDirty() {
+		dirty = true;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/object/data/Node.java b/IMserver/medeasy/src/frame/object/data/Node.java
new file mode 100644
index 0000000..ea2bad6
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/Node.java
@@ -0,0 +1,87 @@
+package frame.object.data;
+
+import chat.server.call.IJSONWriter;
+import frame.object.meta.EntityMeta;
+
+
+public class Node extends Entity {
+
+	protected Node parent;
+	protected EntitySet children;
+	protected int level;
+	
+	
+	public Node(EntityMeta entityMeta) {
+		super(entityMeta);
+		children = new EntitySet(entityMeta);
+		level = 0;
+	}
+	
+	public Node getParent() {
+		return parent;
+	}
+	
+	public EntitySet getChildren() {
+		return children;
+	}
+	
+	public int getLevel() {
+		return level;
+	}
+
+	public void changeParent(Node newParent) throws Exception {
+		//1.
+		parent.deleteChild(this);
+		newParent.addChild(newParent);
+		
+		//2.
+		String parentid = newParent.getString("id");
+		set("parentid", parentid);
+	}
+	
+	private void deleteChild(Node child) {
+//		String id = child.getString("id");
+		//TODO
+	}
+
+	public void addChild(Node child) {
+		child.level = level + 1;
+		children.append(child);
+	}
+
+	public void deleteChildren() {
+		children.clear();
+	}
+	
+	public ID getParentId() {
+		return new ID(getVarinatValue("parentId"));
+	}
+
+	public Node getRoot() {
+		Node current = this;
+		Node parent = current.parent;
+		
+		while (parent != null) {
+			current = parent;
+			parent = current.parent;
+		}
+		
+		return current;
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		//1. node 
+		writer.write("level", level);
+		
+		//2. entity
+		super.writeJSONData(writer);
+		
+		//3. children
+		if (!children.isEmpty()) {
+			writer.writeName("children");
+			children.writeJSONObject(writer);
+		}
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/data/ObjectList.java b/IMserver/medeasy/src/frame/object/data/ObjectList.java
new file mode 100644
index 0000000..5859411
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/data/ObjectList.java
@@ -0,0 +1,45 @@
+package frame.object.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class ObjectList<T> implements Iterable<T> {
+
+	private List<T> itemList;
+	private Map<String, T> itemMap;
+	
+	public ObjectList() {
+		itemList = new ArrayList<T>();
+		itemMap = new HashMap<String, T>();
+	}
+	
+	public void add(String id, T object) throws Exception {
+		if (id == null) {
+			throw new Exception("id is empty");
+		}
+		
+		itemList.add(object);
+		itemMap.put(id, object);
+	}
+	
+	public T get(String id) {
+		return itemMap.get(id);
+	}
+	
+	public T get(int idx) {
+		return itemList.get(idx);
+	}
+	
+	public int size() {
+		return itemList.size();
+	}
+
+	@Override
+	public Iterator<T> iterator() {
+		return itemList.iterator();
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/EntityMeta.java b/IMserver/medeasy/src/frame/object/meta/EntityMeta.java
new file mode 100644
index 0000000..fbfe48a
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/EntityMeta.java
@@ -0,0 +1,196 @@
+package frame.object.meta;
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import frame.persist.loader.ResultMetaFieldReader;
+import frame.variant.ValueType;
+import frame.variant.translator.ITranslator;
+import frame.variant.translator.Translator;
+
+
+public class EntityMeta implements Iterable<Field> {
+
+	protected static Logger logger;
+	
+	protected String tableName;
+	protected List<Field> fieldList;
+	protected String[] names;
+	protected String[] lowerNames;
+	protected Map<String, Integer> nameIndexMap;
+	protected ITranslator[] translators;
+
+	static {
+		logger = Logger.getLogger(EntityMeta.class);
+	}
+
+	protected EntityMeta() {
+		
+	}
+	
+	public EntityMeta(String tableName, IFieldReader fieldReader) throws SQLException {
+		this.tableName = tableName;
+		nameIndexMap = new HashMap<String, Integer>();
+		fieldList = new ArrayList<Field>();
+
+		initFields(fieldReader);
+	}
+
+	public static EntityMeta getInstance(String tableName) throws Exception {
+		EntityMetaLoader loader = new EntityMetaLoader();
+		return  loader.getEntityMetaByTable(tableName);
+	}
+
+	public static EntityMeta getInstance(ResultSetMetaData metaData) throws Exception {
+		ResultMetaFieldReader fieldReader = new ResultMetaFieldReader(metaData);
+		return new EntityMeta("tablemeta", fieldReader);
+	}
+
+	private void initFields(IFieldReader fieldReader) throws SQLException {
+		String fieldName;
+		int columnType;
+		int fieldLength;
+		int nullable;
+		Field field;
+
+		//1. fields
+		fieldReader.first();
+
+		while (fieldReader.next()) {
+			fieldName = fieldReader.getFieldName();
+			columnType = fieldReader.getFieldType();
+			fieldLength = fieldReader.getFieldLength();
+			nullable = fieldReader.getNullable();
+
+			if (fieldName == null) {
+				continue;
+			}
+
+			field = new Field(fieldName);
+			fieldList.add(field);
+
+			field.setType(columnType);
+			field.setLength(fieldLength);
+			field.setNullable(nullable);
+		}
+
+		//2. names
+		int fieldCount = fieldList.size();
+		names = new String[fieldCount];
+		lowerNames = new String[fieldCount];
+
+		String name;
+		for (int i = 0; i < fieldCount; i++) {
+			field = fieldList.get(i);
+			name = field.getName();
+			names[i] = name;
+
+			name = name.toLowerCase();
+			lowerNames[i] = name;
+			nameIndexMap.put(name, i);
+		}
+		
+		//3. translators
+		translators = new ITranslator[fieldCount];
+		
+		for (int i = 0; i < fieldCount; i++) {
+			field = fieldList.get(i);
+			ValueType valueType = field.getValueType();
+			ITranslator translator = Translator.getInstance(valueType);
+			
+			translators[i] = translator;
+			field.setTranslator(translator);
+		}
+	}
+
+	public int getFieldCount() {
+		return fieldList.size();
+	}
+
+	public Iterator<Field> iterator() {
+		return fieldList.iterator();
+	}
+
+	public String getTableName() {
+		return tableName;
+	}
+
+	public List<Field> getFields() {
+		return fieldList;
+	}
+
+	public Field getField(String name) {
+		if (name == null)
+			return null;
+
+		Integer idx = nameIndexMap.get(name.toLowerCase());
+
+		if (idx == null) {
+			return null;
+		}
+
+		return fieldList.get(idx);
+	}
+
+	public Field getField(int idx) {
+		return fieldList.get(idx);
+	}
+	
+	public ValueType getValueType(int idx) {
+		Field field = fieldList.get(idx);
+		return field.getValueType();
+	}
+
+	public Integer getIndex(String fieldName) {
+		if (fieldName == null) {
+			return null;
+		}
+		
+		try {
+			return nameIndexMap.get(fieldName.toLowerCase());
+		}
+		catch (Exception e) {
+			return null;
+		}
+	}
+
+	public String[] getLowerNames() {
+		return lowerNames;
+	}
+
+	public String[] getFieldNames() {
+		return names;
+	}
+	
+	public boolean contains(String name) {
+		if (name == null) {
+			return false;
+		}
+
+		name = name.toLowerCase();
+		return nameIndexMap.containsKey(name);
+	}
+
+	public ITranslator getTranslator(int idx) {
+		return translators[idx];
+	}
+	
+	public ITranslator getTranslator(String name) {
+		name = name.toLowerCase();
+		Integer idx = nameIndexMap.get(name);
+
+		if (idx == null) {
+			return null;
+		}
+		
+		return translators[idx];
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/EntityMetaLoader.java b/IMserver/medeasy/src/frame/object/meta/EntityMetaLoader.java
new file mode 100644
index 0000000..7f58593
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/EntityMetaLoader.java
@@ -0,0 +1,40 @@
+package frame.object.meta;
+
+import java.sql.ResultSetMetaData;
+
+import frame.persist.IMetaDataLoader;
+import frame.persist.NamedSQL;
+import frame.persist.SQLRunner;
+import frame.persist.loader.ResultMetaFieldReader;
+
+
+public class EntityMetaLoader implements IMetaDataLoader {
+	
+	private String metaName;
+	private EntityMeta entityMeta;
+	
+	
+	public EntityMetaLoader() {
+	}
+
+	public EntityMeta getEntityMetaByTable(String tableName) throws Exception {
+		this.metaName = tableName;
+		
+		String sql = "select * from " + tableName + " where 1 <> 1";
+		SQLRunner.getTableMetaData(this, sql);
+		return entityMeta;
+	}
+	
+	public EntityMeta getEntityMetaByNamedSQL(NamedSQL namedSQL) throws Exception {
+		this.metaName = namedSQL.getName();
+		
+		SQLRunner.getTableMetaData(this, namedSQL.getSQL());
+		return entityMeta;
+	}
+	
+	public void load(ResultSetMetaData metaData) throws Exception {
+		ResultMetaFieldReader fieldReader = new ResultMetaFieldReader(metaData);
+		entityMeta = new EntityMeta(metaName, fieldReader);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/Field.java b/IMserver/medeasy/src/frame/object/meta/Field.java
new file mode 100644
index 0000000..8d417e7
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/Field.java
@@ -0,0 +1,420 @@
+package frame.object.meta;
+
+import java.math.BigDecimal;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.translator.ITranslator;
+
+
+public class Field {
+
+	private static Map<Integer, String> sqlTypeMap;
+	private static Set<Integer> sizableType;
+	private String name;
+	private int sqlType;
+	private ValueType type;
+	private int length;
+	private boolean key;
+	private int nullable;
+	private ITranslator translator;
+
+	static {
+		sqlTypeMap = new HashMap<Integer, String>();
+		sizableType = new HashSet<Integer>();
+		initSQLTypeMap();
+	}
+
+	public Field(String name) {
+		nullable = 1;
+		this.name = name;
+	}
+
+	public int getSQLType() {
+		return sqlType;
+	}
+
+	public boolean isKey() {
+		return key;
+	}
+
+	public void setType(ValueType value) {
+		type = value;
+		sqlType = value.toSQLTypes();
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getSQLTypeCode() {
+		String result = sqlTypeMap.get(sqlType);
+
+		if (sizableType.contains(sqlType)) {
+			result = result + "(" + length + ")";
+		}
+
+		return result;
+	}
+
+	public Object getSQLNullCode() {
+		if (nullable == 0) {
+			return "NOT NULL";
+		} else {
+			return "NULL";
+		}
+	}
+
+	public ValueType getValueType() {
+		return type;
+	}
+
+	public void setType(int value) {
+		sqlType = value;
+		type = ValueType.valueOfTypes(value);
+	}
+
+	public void setLength(int length) {
+		this.length = length;
+	}
+
+	public void setNullable(int nullable) {
+		this.nullable = nullable;
+	}
+
+	public String toString() {
+		StringBuilder result = new StringBuilder();
+
+		result.append("fieldName=").append(name).append(",");
+		result.append("dataType=").append(type).append(",");
+		result.append("length=").append(length);
+
+		return result.toString();
+	}
+
+	public void toString(StringBuilder result) {
+		result.append("fieldName=").append(name).append(",");
+		result.append("dataType=").append(type).append(",");
+		result.append("length=").append(length);
+	}
+
+	private static void initSQLTypeMap() {
+		sqlTypeMap.put(Types.ARRAY, "ARRAY");
+		sqlTypeMap.put(Types.BIGINT, "BIGINT");
+		sqlTypeMap.put(Types.BINARY, "BINARY");
+		sqlTypeMap.put(Types.BIT, "BIT");
+		sqlTypeMap.put(Types.BLOB, "BLOB");
+		sqlTypeMap.put(Types.BOOLEAN, "BOOLEAN");
+		sqlTypeMap.put(Types.CHAR, "CHAR");
+		sqlTypeMap.put(Types.CLOB, "CLOB");
+		sqlTypeMap.put(Types.DATALINK, "DATALINK");
+		sqlTypeMap.put(Types.DATE, "DATE");
+		sqlTypeMap.put(Types.DECIMAL, "DECIMAL");
+		sqlTypeMap.put(Types.DISTINCT, "DISTINCT");
+		sqlTypeMap.put(Types.DOUBLE, "DOUBLE");
+		sqlTypeMap.put(Types.FLOAT, "FLOAT");
+		sqlTypeMap.put(Types.INTEGER, "INTEGER");
+		sqlTypeMap.put(Types.LONGNVARCHAR, "LONGNVARCHAR");
+		sqlTypeMap.put(Types.LONGVARBINARY, "LONGVARBINARY");
+		sqlTypeMap.put(Types.LONGVARCHAR, "LONGVARCHAR");
+		sqlTypeMap.put(Types.NCHAR, "NCHAR");
+		sqlTypeMap.put(Types.NCLOB, "NCLOB");
+		sqlTypeMap.put(Types.NULL, "NULL");
+		sqlTypeMap.put(Types.NUMERIC, "NUMERIC");
+		sqlTypeMap.put(Types.NVARCHAR, "NVARCHAR");
+		sqlTypeMap.put(Types.OTHER, "OTHER");
+		sqlTypeMap.put(Types.REAL, "REAL");
+		sqlTypeMap.put(Types.REF, "REF");
+		sqlTypeMap.put(Types.ROWID, "ROWID");
+		sqlTypeMap.put(Types.SMALLINT, "SMALLINT");
+		sqlTypeMap.put(Types.SQLXML, "SQLXML");
+		sqlTypeMap.put(Types.STRUCT, "STRUCT");
+		sqlTypeMap.put(Types.TIME, "TIME");
+		sqlTypeMap.put(Types.TIMESTAMP, "TIMESTAMP");
+		sqlTypeMap.put(Types.TINYINT, "TINYINT");
+		sqlTypeMap.put(Types.VARBINARY, "VARBINARY");
+		sqlTypeMap.put(Types.VARCHAR, "VARCHAR");
+
+		sizableType.add(Types.ARRAY);
+		sizableType.add(Types.CHAR);
+		sizableType.add(Types.LONGNVARCHAR);
+		sizableType.add(Types.LONGVARBINARY);
+		sizableType.add(Types.LONGVARCHAR);
+		sizableType.add(Types.NCHAR);
+		sizableType.add(Types.NVARCHAR);
+		sizableType.add(Types.SQLXML);
+		sizableType.add(Types.VARBINARY);
+		sizableType.add(Types.VARCHAR);
+	}
+
+	public String objectToString(Object obj) throws Exception {
+		if (obj == null) {
+			return null;
+		}
+
+		if (ValueType.String == type) {
+			return (String) obj;
+		} else if (ValueType.Int == type) {
+			return String.valueOf(obj);
+		} else if (ValueType.Double == type) {
+			return String.valueOf(obj);
+		} else if (ValueType.Boolean == type) {
+			return String.valueOf(obj);
+		} else if (ValueType.Date == type) {
+			Date date = null;
+
+			if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Date) {
+				date = (Date) obj;
+			}
+
+			if (date != null) {
+				return Util.DataTimeToString(date);
+			}
+		}
+
+		return String.valueOf(obj);
+	}
+
+	public boolean objectToBoolean(Object obj) {
+		if (obj == null) {
+			return false;
+		}
+
+		if (ValueType.String == type) {
+			return Util.StringToBoolean(String.valueOf(obj));
+		} else if (ValueType.Boolean == type) {
+			return (Boolean) obj;
+		}
+
+		return false;
+	}
+
+	public Integer objectToInteger(Object obj) {
+		if (obj == null) {
+			return null;
+		}
+
+		if (ValueType.String == type) {
+			return Integer.valueOf((String) obj);
+		}
+		else if (ValueType.Int == type) {
+			try {
+				return (Integer) obj;
+			}
+			catch (Exception e) {
+				return Integer.valueOf(String.valueOf(obj));
+			}
+		} 
+		else if (ValueType.Double == type) {
+			return ((Double) obj).intValue();
+		} 
+		else if (ValueType.Decimal == type) {
+			return ((BigDecimal) obj).intValue();
+		} 
+		else {
+			return null;
+		}
+	}
+	
+	public BigDecimal objectToBigDecimal(Object obj) {
+		if (obj == null) {
+			return null;
+		}
+
+		if (ValueType.String == type) {
+			return BigDecimal.valueOf(Double.valueOf((String) obj));
+		}
+		else if (ValueType.Int == type) {
+			return BigDecimal.valueOf((Integer) obj);
+		} 
+		else if (ValueType.Double == type) {
+			return BigDecimal.valueOf((Double) obj);
+		} 
+		else if (ValueType.Decimal == type) {
+			return (BigDecimal) obj;
+		} 
+		else {
+			return null;
+		}
+	}
+
+	public Date objectToDate(Object obj) throws ParseException {
+		if (obj == null) {
+			return null;
+		}
+
+		if (obj instanceof Timestamp) {
+			Timestamp value = (Timestamp) obj;
+			return new Date(value.getTime());
+		}
+
+		if (obj instanceof Date) {
+			return (Date) obj;
+		}
+
+		if (obj instanceof String) {
+			String value = (String) obj;
+			return Util.StringToDate(value);
+		}
+
+		return null;
+	}
+
+	public String objectToSchemaString(Object obj) throws Exception {
+		if (obj == null) {
+			return null;
+		}
+
+		if (ValueType.String == type) {
+			return "\"" + obj.toString() + "\"";
+		} else if (ValueType.Int == type) {
+			return obj.toString();
+		} else if (ValueType.Double == type) {
+			return obj.toString();
+		} else if (ValueType.Boolean == type) {
+			Boolean bool = (Boolean) obj;
+			return String.valueOf(bool);
+		} else if (ValueType.Date == type) {
+			Date date = null;
+
+			if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Date) {
+				date = (Date) obj;
+			}
+
+			if (date != null) {
+				return "\"" + Util.DataTimeToString(date) + "\"";
+			}
+
+			return "\"" + obj.toString() + "\"";
+		}
+
+		return String.valueOf(obj);
+	}
+
+	public String objectToJSONSString(Object obj) throws SQLException {
+		if (obj == null) {
+			return "null";
+		}
+
+		if (ValueType.String == type) {
+			return "\"" + obj.toString().replace("\\", "/") + "\"";
+		} else if (ValueType.Int == type) {
+			return obj.toString();
+		} else if (ValueType.Double == type) {
+			return obj.toString();
+		} else if (ValueType.Decimal == type) {
+			return obj.toString();
+		} else if (ValueType.Boolean == type) {
+			Boolean bool = (Boolean) obj;
+			return String.valueOf(bool);
+		} else if (ValueType.Date == type) {
+			Date date = null;
+
+			if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Date) {
+				date = (Date) obj;
+			}
+
+			if (date != null) {
+				return "\"" + Util.DataTimeToString(date) + "\"";
+			}
+		}
+
+		return "\"" + obj.toString() + "\"";
+	}
+
+	public String objectToSQLString(Object obj) throws Exception {
+		if (obj == null) {
+			return "null";
+		}
+
+		if (ValueType.String == type) {
+			return "'" + obj.toString() + "'";
+		} else if (ValueType.Int == type) {
+			return obj.toString();
+		} else if (ValueType.Double == type) {
+			return obj.toString();
+		} else if (ValueType.Boolean == type) {
+			Boolean bool = (Boolean) obj;
+			return String.valueOf(bool);
+		} else if (ValueType.Date == type) {
+			Date date = null;
+
+			if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Timestamp) {
+				Timestamp timestamp = (Timestamp) obj;
+				date = new Date(timestamp.getTime());
+			} else if (obj instanceof Date) {
+				date = (Date) obj;
+			} else if (obj instanceof String) {
+				date = Util.StringToDate((String) obj);
+			}
+
+			if (date != null) {
+				return Util.newDBDateString(date);
+			}
+		}
+
+		return "'" + obj.toString() + "'";
+	}
+
+	public Object StringToObject(String value) throws ParseException {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+
+		if (ValueType.String == type) {
+			return value;
+		} else if (ValueType.Int == type) {
+			return Integer.valueOf(value);
+		} else if (ValueType.Double == type) {
+			return Double.valueOf(value);
+		} else if (ValueType.Date == type) {
+			return Util.StringToDate(value);
+		}
+
+		return value;
+	}
+
+	public void setValueToStatement(Object obj, PreparedStatement stmt, int paramIdx) throws SQLException {
+		stmt.setObject(paramIdx, obj, sqlType);
+	}
+
+	public void setTranslator(ITranslator translator) {
+		this.translator = translator;
+	}
+
+	public ITranslator getTranslator() {
+		return translator;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/IFieldReader.java b/IMserver/medeasy/src/frame/object/meta/IFieldReader.java
new file mode 100644
index 0000000..2d3a74d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/IFieldReader.java
@@ -0,0 +1,20 @@
+package frame.object.meta;
+
+import java.sql.SQLException;
+
+
+public interface IFieldReader {
+
+	boolean next() throws SQLException;
+
+	String getFieldName() throws SQLException;
+
+	int getFieldType() throws SQLException;
+
+	int getFieldLength() throws SQLException;
+
+	int getNullable() throws SQLException;
+
+	void first();
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/IMetaDataLoader.java b/IMserver/medeasy/src/frame/object/meta/IMetaDataLoader.java
new file mode 100644
index 0000000..ae31e4f
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/IMetaDataLoader.java
@@ -0,0 +1,11 @@
+package frame.object.meta;
+
+import java.sql.ResultSetMetaData;
+
+public interface IMetaDataLoader {
+
+	String getTableName();
+	
+	void load(ResultSetMetaData metaData) throws Exception ;
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/MetaDirection.java b/IMserver/medeasy/src/frame/object/meta/MetaDirection.java
new file mode 100644
index 0000000..4a52e87
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/MetaDirection.java
@@ -0,0 +1,7 @@
+package frame.object.meta;
+
+public enum MetaDirection {
+
+	GetMeta, SetMeta;
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/MetaField.java b/IMserver/medeasy/src/frame/object/meta/MetaField.java
new file mode 100644
index 0000000..a8a3578
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/MetaField.java
@@ -0,0 +1,37 @@
+package frame.object.meta;
+
+public class MetaField {
+
+	private String fieldName;
+	private int fieldType;
+	private int FieldLength;
+	private int nullable;
+
+	public MetaField(String fieldName) {
+		this.fieldName = fieldName;
+	}
+	
+	public MetaField(String fieldName, int fieldType, int FieldLength, int nullable) {
+		this.fieldName = fieldName;
+		this.fieldType = fieldType;
+		this.FieldLength = FieldLength;
+		this.nullable = nullable;
+	}
+
+	public String getFieldName() {
+		return fieldName;
+	}
+
+	public int getFieldType() {
+		return fieldType;
+	}
+
+	public int getFieldLength() {
+		return FieldLength;
+	}
+
+	public int getNullable() {
+		return nullable;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/MetaFieldReader.java b/IMserver/medeasy/src/frame/object/meta/MetaFieldReader.java
new file mode 100644
index 0000000..739ec1e
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/MetaFieldReader.java
@@ -0,0 +1,87 @@
+package frame.object.meta;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class MetaFieldReader implements IFieldReader {
+
+	private static List<MetaField> fields;
+	private MetaField field;
+	private int pos;
+	
+	static {
+		init();
+	}
+	
+	
+	public MetaFieldReader() {
+		pos = -1;
+	}
+	
+	@Override
+	public boolean next() throws SQLException {
+		pos++;
+		
+		if (pos < fields.size()) {
+			field = fields.get(pos);
+			return true;
+		}
+		else {
+			return false;
+		}
+	}
+
+	@Override
+	public String getFieldName() throws SQLException {
+		if (field == null) {
+			return null;
+		}
+		
+		return field.getFieldName();
+	}
+
+	@Override
+	public int getFieldType() throws SQLException {
+		if (field == null) {
+			return Types.VARCHAR;
+		}
+		
+		return field.getFieldType();
+	}
+
+	@Override
+	public int getFieldLength() throws SQLException {
+		if (field == null) {
+			return 0;
+		}
+		
+		return field.getFieldLength();
+	}
+
+	@Override
+	public int getNullable() throws SQLException {
+		if (field == null) {
+			return 1;
+		}
+		
+		return field.getNullable();
+	}
+
+	@Override
+	public void first() {
+		pos = -1;
+	}
+	
+	private static void init() {
+		fields = new ArrayList<MetaField>();
+		fields.add(new MetaField("fieldName", Types.VARCHAR, 64, 0));
+		fields.add(new MetaField("fieldType", Types.VARCHAR, 0, 0));
+		fields.add(new MetaField("fieldLength", Types.INTEGER, 0, 0));
+		fields.add(new MetaField("nullable", Types.VARCHAR, 0, 0));
+		fields.add(new MetaField("displayName", Types.VARCHAR, 64, 0));
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/MetadataMeta.java b/IMserver/medeasy/src/frame/object/meta/MetadataMeta.java
new file mode 100644
index 0000000..3fd63fa
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/MetadataMeta.java
@@ -0,0 +1,11 @@
+package frame.object.meta;
+
+import java.sql.SQLException;
+
+public class MetadataMeta extends EntityMeta {
+
+	public MetadataMeta() throws SQLException {
+		super("dataPropertys", new MetaFieldReader());
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/meta/MetadataSet.java b/IMserver/medeasy/src/frame/object/meta/MetadataSet.java
new file mode 100644
index 0000000..09e26c5
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/meta/MetadataSet.java
@@ -0,0 +1,15 @@
+package frame.object.meta;
+
+import java.sql.SQLException;
+
+import frame.object.data.EntitySet;
+
+
+public class MetadataSet extends EntitySet {
+
+	
+	public MetadataSet() throws SQLException {
+		super(new MetadataMeta());
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/CollectionReader.java b/IMserver/medeasy/src/frame/object/reader/CollectionReader.java
new file mode 100644
index 0000000..c218ac3
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/CollectionReader.java
@@ -0,0 +1,120 @@
+package frame.object.reader;
+
+import java.util.Collection;
+import java.util.List;
+
+import frame.util.ContentBuilder;
+import frame.variant.translator.ITranslator;
+import frame.variant.translator.Translator;
+
+public class CollectionReader extends EntityReader {
+
+	protected IEntityReader valueReader;
+	protected ITranslator translator;
+	
+	public CollectionReader(Class<?> clazz) throws Exception {
+		super(clazz);
+	}
+
+	@Override
+	protected void initValueReader(Class<?> dataType) throws Exception {
+		if (translator == null && valueReader == null) {
+			if (Translator.containsType(dataType)) {
+				translator = Translator.getInstance(dataType);
+			}
+			else {
+				valueReader = EntityReader.getInstance(dataType);
+			}
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public String getString(Object entity) {
+		Collection<Object> collection = (Collection<Object>) entity;
+		
+		if (collection.isEmpty()) {
+			return "[]";
+		}
+		
+		ContentBuilder result = new ContentBuilder();
+		result.append("[");
+		
+		try {
+			initValueReader(collection.iterator().next().getClass());
+		} catch (Exception e) {
+			return e.getMessage();
+		}
+		
+		for (Object value: collection) {
+			try {
+				if (translator != null) {
+					result.append(translator.toString(value), ", ");
+				}
+				else {
+					result.append(valueReader.getString(value), ", ");
+				}
+			}
+			catch (Exception e) {
+				result.append("error", ",");
+			}
+		}
+		
+		result.append("]");
+		return result.toString();
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public String getJSONString(Object entity) throws Exception {
+		Collection<Object> collection = (Collection<Object>) entity;
+		
+		if (collection.isEmpty()) {
+			return "[]";
+		}
+		
+		ContentBuilder result = new ContentBuilder();
+		result.append("[");
+		
+		try {
+			Class<?> clazz = collection.iterator().next().getClass();
+			initValueReader(clazz);
+		} 
+		catch (Exception e) {
+			return e.getMessage();
+		}
+		
+		for (Object value: collection) {
+			try {
+				if (translator != null) {
+					result.append(translator.toJSONString(value), ", ");
+				}
+				else {
+					result.append(valueReader.getJSONString(value), ", ");
+				}
+			}
+			catch (Exception e) {
+				result.append("error", ",");
+			}
+		}
+		
+		result.append("]");
+		return result.toString();
+	}
+
+	@Override
+	public String getJSONString(Object entity, String defaultValue) {
+		try {
+			return getJSONString(entity);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	@Override
+	public List<NameValuePair> getValueList(Object entity) throws Exception {
+		return null;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/EntityReader.java b/IMserver/medeasy/src/frame/object/reader/EntityReader.java
new file mode 100644
index 0000000..cc456d7
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/EntityReader.java
@@ -0,0 +1,76 @@
+package frame.object.reader;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+public abstract class EntityReader implements IEntityReader {
+
+	protected static Logger logger;
+	protected static Set<String> excludeMethods;
+	protected Class<?> clazz;
+
+	static {
+		logger = Logger.getLogger(ObjectReader.class);
+		createExcludeMethodSet();
+	}
+
+	protected EntityReader(Class<?> clazz) {
+		this.clazz = clazz;
+	}
+
+	public static IEntityReader getInstance(Class<?> clazz) throws Exception {
+
+		if (Collection.class.isAssignableFrom(clazz)) {
+			return new CollectionReader(clazz);
+		} 
+		else if (Map.class.isAssignableFrom(clazz)) {
+			return new MapReader(clazz);
+		} 
+		else {
+			return new ObjectReader(clazz);
+		}
+	}
+
+	protected abstract void initValueReader(Class<?> dataType) throws Exception;
+
+	public abstract String getString(Object entity);
+
+	public abstract String getJSONString(Object entity) throws Exception;
+
+	public Class<?> getEntityClass() {
+		return clazz;
+	}
+
+	private static void createExcludeMethodSet() {
+		excludeMethods = new HashSet<String>();
+		excludeMethods.add("getclass");
+		excludeMethods.add("getnames");
+		excludeMethods.add("getsize");
+		excludeMethods.add("containsproperty");
+		excludeMethods.add("loaddata");
+		excludeMethods.add("setdata");
+		excludeMethods.add("setdataString");
+		excludeMethods.add("getdata");
+		excludeMethods.add("getString");
+		excludeMethods.add("getjsonString");
+		excludeMethods.add("getsqlString");
+		excludeMethods.add("getvalue");
+		excludeMethods.add("getdynamicdata");
+		excludeMethods.add("iterator");
+		excludeMethods.add("toString");
+		excludeMethods.add("finalize");
+		excludeMethods.add("wait");
+		excludeMethods.add("hashcode");
+		excludeMethods.add("clone");
+		excludeMethods.add("registernatives");
+		excludeMethods.add("equals");
+		excludeMethods.add("notify");
+		excludeMethods.add("notifyall");
+		excludeMethods.add("getinstance");
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/EntityReaderContainer.java b/IMserver/medeasy/src/frame/object/reader/EntityReaderContainer.java
new file mode 100644
index 0000000..c939f85
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/EntityReaderContainer.java
@@ -0,0 +1,74 @@
+package frame.object.reader;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class EntityReaderContainer {
+
+	private static EntityReaderContainer instance;
+	private Map<Class<?>, IEntityReader> items;
+
+	private EntityReaderContainer() {
+		items = new HashMap<Class<?>, IEntityReader>();
+	}
+
+	public static synchronized EntityReaderContainer getInstance() {
+		if (instance == null) {
+			instance = new EntityReaderContainer();
+		}
+
+		return instance;
+	}
+
+	public IEntityReader getEntityReader(Class<?> clazz) throws Exception {
+
+		IEntityReader reader = items.get(clazz);
+
+		if (reader == null) {
+			reader = EntityReader.getInstance(clazz);
+
+			// 淇濊瘉闆嗗悎绫籧lass銆丮ap绫籧lass涓嶅湪items涓�
+			if (reader instanceof CollectionReader || reader instanceof MapReader) {
+				return reader;
+			}
+			
+			items.put(clazz, reader);
+		}
+
+		return reader;
+	}
+
+	public ObjectReader getObjectReader(Class<?> clazz) throws Exception {
+		IEntityReader reader = items.get(clazz);
+
+		if (reader == null) {
+			reader = new ObjectReader(clazz);
+			items.put(clazz, reader);
+		}
+
+		return (ObjectReader) reader;
+	}
+
+	public MapReader getMapReader(Class<?> clazz) throws Exception {
+		IEntityReader reader = items.get(clazz);
+
+		if (reader == null) {
+			reader = new MapReader(clazz);
+			items.put(clazz, reader);
+		}
+
+		return (MapReader) reader;
+	}
+
+	public CollectionReader getCollectionReader(Class<?> clazz) throws Exception {
+		IEntityReader reader = items.get(clazz);
+
+		if (reader == null) {
+			reader = new CollectionReader(clazz);
+			items.put(clazz, reader);
+		}
+
+		return (CollectionReader) reader;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/IEntityReader.java b/IMserver/medeasy/src/frame/object/reader/IEntityReader.java
new file mode 100644
index 0000000..73e1b8b
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/IEntityReader.java
@@ -0,0 +1,15 @@
+package frame.object.reader;
+
+import java.util.List;
+
+public interface IEntityReader {
+
+	String getString(Object entity);
+	
+	String getJSONString(Object entity) throws Exception;
+	
+	String getJSONString(Object entity, String defaultValue);
+
+	List<NameValuePair> getValueList(Object entity) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/MapReader.java b/IMserver/medeasy/src/frame/object/reader/MapReader.java
new file mode 100644
index 0000000..b0ed50b
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/MapReader.java
@@ -0,0 +1,131 @@
+package frame.object.reader;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import frame.util.ContentBuilder;
+import frame.variant.translator.ITranslator;
+import frame.variant.translator.Translator;
+
+
+public class MapReader extends EntityReader {
+
+	protected ITranslator translator;
+	protected IEntityReader valueReader;
+	
+	public MapReader(Class<?> clazz) throws Exception {
+		super(clazz);
+	}
+
+	@Override
+	protected void initValueReader(Class<?> dataType) throws Exception {
+		if (translator == null && valueReader == null) {
+			if (Translator.containsType(dataType)) {
+				translator = Translator.getInstance(dataType);
+			}
+			else {
+				valueReader = EntityReader.getInstance(dataType);
+			}
+		}
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public String getString(Object entity) {
+		try {
+			Map<Object, Object> map = (Map<Object, Object>) entity;		
+			
+			if (map.isEmpty()) {
+				return "[]";
+			}
+			
+			ContentBuilder result = new ContentBuilder();
+			result.append("[");
+			
+			Set<Object> keys = map.keySet();
+
+			initValueReader(keys.iterator().next().getClass());
+		
+			for (Object key: keys) {
+				Object obj = map.get(key);
+				
+				try {
+					if (translator != null) {
+						result.append(key, ",").append(":").append(translator.toString(obj));
+					}
+					else {
+						result.append(key, ",").append(":").append(valueReader.getString(obj));
+					}					
+				}
+				catch (Exception e) {
+					result.append(key, ",").append(":error");
+				}
+			}
+			
+			result.append("]");
+			return result.toString();
+		} 
+		catch (Exception e) {
+			return e.getMessage();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public String getJSONString(Object entity) throws Exception {
+		Map<Object, Object> map = (Map<Object, Object>) entity;
+		
+		if (map.isEmpty()) {
+			return "{}";
+		}
+		
+		ContentBuilder result = new ContentBuilder();
+		result.append("{");
+		
+		Set<Object> keys = map.keySet();
+		
+		try {
+			Class<?> clazz = keys.iterator().next().getClass();
+			initValueReader(clazz);
+		} catch (Exception e) {
+			return e.getMessage();
+		}
+		
+		for (Object key: keys) {
+			Object obj = map.get(key);
+			
+			try {
+				if (translator != null) {
+					result.append("\"", ",").append(key).append("\":").append(translator.toJSONString(obj));
+				}
+				else {
+					result.append("\"", ",").append(key).append("\":").append(valueReader.getJSONString(obj));
+				}				
+			}
+			catch (Exception e) {
+				result.append("\"", ",").append(key).append("\":\"error\"");
+			}
+		}
+		
+		result.append("}");
+		return result.toString();
+	}
+
+
+	@Override
+	public String getJSONString(Object entity, String defaultValue) {
+		try {
+			return getJSONString(entity);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	@Override
+	public List<NameValuePair> getValueList(Object entity) throws Exception {
+		return null;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/NameValuePair.java b/IMserver/medeasy/src/frame/object/reader/NameValuePair.java
new file mode 100644
index 0000000..5cb9c1e
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/NameValuePair.java
@@ -0,0 +1,20 @@
+package frame.object.reader;
+
+public class NameValuePair {
+
+	private String name;
+	private Object value;
+	
+	public NameValuePair(String name, Object value) {
+		this.name = name;
+		this.value = value;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Object getValue() {
+		return value;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/ObjectPropertyRecorder.java b/IMserver/medeasy/src/frame/object/reader/ObjectPropertyRecorder.java
new file mode 100644
index 0000000..c75e42c
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/ObjectPropertyRecorder.java
@@ -0,0 +1,103 @@
+package frame.object.reader;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import frame.variant.translator.Translator;
+
+public class ObjectPropertyRecorder {
+	
+	private List<String> nameList;
+	private List<String> lowerNameList;
+	private Map<String, Integer> nameMap;
+	private Map<String, PropertyReader> propertyReaderMap;
+	private List<PropertyReader> propertyReaderList;
+	
+	
+	public ObjectPropertyRecorder() {
+		nameList = new ArrayList<String>();
+		lowerNameList = new ArrayList<String>();
+		nameMap = new HashMap<String, Integer>();
+		propertyReaderMap = new HashMap<String, PropertyReader>();
+		propertyReaderList = new LinkedList<PropertyReader>();
+	}
+
+	public void addGetMethod(String key, String property, Method method) throws Exception {
+		if (key == null) {
+			return;
+		}
+		
+		Class<?> returnType = method.getReturnType();
+		String lower = property.toLowerCase();
+		
+		PropertyReader propertyReader = propertyReaderMap.get(key.toLowerCase());
+		
+		if (propertyReader == null) {
+			nameMap.put(lower, nameList.size());
+			
+			nameList.add(property);
+			lowerNameList.add(lower);
+			
+			propertyReader = new PropertyReader(property, returnType);
+			
+			propertyReaderList.add(propertyReader);	
+			propertyReaderMap.put(lower, propertyReader);
+		}
+		
+		propertyReader.setGetMethod(method);			
+	}
+	
+	public void addSetMethod(String key, String property, Method method) throws Exception {
+		if (key == null) {
+			return;
+		}
+		
+		Class<?> paramType = method.getParameterTypes()[0];
+		if (!Translator.containsType(paramType)) {
+			return;
+		}
+		
+		String lower = property.toLowerCase();
+		
+		PropertyReader propertyReader = propertyReaderMap.get(key.toLowerCase());
+		
+		if (propertyReader == null) {
+			nameMap.put(lower, nameList.size());
+			
+			nameList.add(property);
+			lowerNameList.add(lower);
+			
+			propertyReader = new PropertyReader(property, paramType);
+			
+			propertyReaderList.add(propertyReader);	
+			propertyReaderMap.put(lower, propertyReader);
+		}
+		
+		propertyReader.setSetMethod(method);			
+	}
+	
+	public PropertyReader[] getPropertyReaderArray() {
+		PropertyReader[] result = new PropertyReader[propertyReaderList.size()];
+		result = propertyReaderList.toArray(result);
+		
+		return result;
+	}
+
+	public String[] getNameArray() {
+		String[] result = new String[nameList.size()];
+		return nameList.toArray(result);
+	}
+
+	public String[] getLowerNameArray() {
+		String[] result = new String[lowerNameList.size()];
+		return lowerNameList.toArray(result);
+	}
+
+	public Map<String, Integer> getNameMap() {
+		return nameMap;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/ObjectReader.java b/IMserver/medeasy/src/frame/object/reader/ObjectReader.java
new file mode 100644
index 0000000..b8d27eb
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/ObjectReader.java
@@ -0,0 +1,434 @@
+package frame.object.reader;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import frame.object.data.Entity;
+import frame.util.ContentBuilder;
+
+
+public class ObjectReader extends EntityReader implements Iterable<PropertyReader> {
+
+	private int size;
+	private String[] names;
+	private String[] lowerNames;
+	private Map<String, Integer> nameMap;
+	private PropertyReader[] propertyReaderArray;
+	
+	public ObjectReader(Class<?> clazz) throws Exception {
+		super(clazz);
+		initValueReader(clazz);
+	}
+	
+	@Override
+	protected void initValueReader(Class<?> dataType) throws Exception {
+		ObjectPropertyRecorder propertyRecorder = new ObjectPropertyRecorder();
+		
+		Method[] methods;
+		String methodName;
+		String property;
+		char first;
+		
+		while (dataType != null) {
+			//鑷繁鐨勬墍鏈夋柟娉�(鍚鏈�)
+			methods = dataType.getDeclaredMethods();
+		
+			for (Method method: methods) {
+				if (method.isBridge()) {
+					continue;
+				}
+				
+				methodName = method.getName();
+				Class<?>[] params = method.getParameterTypes();
+				
+				if (excludeMethods.contains(methodName.toLowerCase())) {
+					continue;
+				}
+				
+				if (methodName.startsWith("get")) {
+					if (params.length > 0) {
+						continue;
+					}
+							
+					property = methodName.substring(3); 
+					first = property.charAt(0);
+					property = Character.toLowerCase(first) + property.substring(1);
+					
+					propertyRecorder.addGetMethod(property, property, method);
+				}
+				else if (methodName.startsWith("is")) {
+					if (params.length > 0) {
+						continue;
+					}
+					
+					property = methodName.substring(2); 
+					first = property.charAt(0);
+					property = Character.toLowerCase(first) + property.substring(1);
+					
+					propertyRecorder.addGetMethod(property, methodName, method);
+				}
+				else if (methodName.startsWith("set")) {
+					if (params.length > 1) {
+						continue;
+					}
+					
+					property = methodName.substring(3); 
+					first = property.charAt(0);
+					property = Character.toLowerCase(first) + property.substring(1);
+					
+					propertyRecorder.addSetMethod(property, property, method);
+				}
+			}
+			
+			dataType = dataType.getSuperclass();
+		}
+	
+		names = propertyRecorder.getNameArray();
+		lowerNames = propertyRecorder.getLowerNameArray();
+		nameMap = propertyRecorder.getNameMap();
+		propertyReaderArray = propertyRecorder.getPropertyReaderArray();
+		size = propertyReaderArray.length;		
+	}
+
+	@Override
+	public String getString(Object entity) {
+		ContentBuilder result = new ContentBuilder();
+		result.append("[");
+		
+		for (int i = 0; i < size; i++) {
+			String value;
+			try {
+				value = propertyReaderArray[i].getJSONString(entity);
+			} catch (Exception e) {
+				value = "error";
+			}
+			result.append(lowerNames[i], ",").append(":").append(value);
+		}
+		
+		result.append("]");
+		return result.toString();
+	}
+
+	@Override
+	public String getJSONString(Object entity) throws Exception {
+		ContentBuilder result = new ContentBuilder();
+		result.append("{");
+		
+		result.setEmpty(true);
+		
+		for (int i = 0; i < size; i++) {
+			String value = propertyReaderArray[i].getJSONString(entity);
+			result.append("\"", ",").append(lowerNames[i]).append("\":").append(value);
+		}
+		
+		result.append("}");
+		return result.toString();
+	}
+
+	@Override
+	public String getJSONString(Object entity, String defaultValue) {
+		try {
+			return getJSONString(entity);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	public String[] getNames() {
+		return names;
+	}
+	
+	public String[] getLowerNames() {
+		return lowerNames;
+	}
+	
+	public boolean containsProperty(String name) {
+		if (name == null) {
+			return false;
+		}
+		
+		return nameMap.containsKey(name.toLowerCase());
+	}
+	
+	public int size() {
+		return size;
+	}
+	
+	public Integer getIndexByName(String name) {
+		if (name == null) {
+			return null;
+		}
+		
+		return nameMap.get(name.toLowerCase());
+	}
+
+	public PropertyReader getPropertyReader(String name) {
+		if (name == null) {
+			return null;
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			return null;			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader;
+	}
+	
+	public PropertyReader getPropertyReader(int idx) {
+		return propertyReaderArray[idx];
+	}
+	
+	public void setData(String name, Object value, Object entity) throws Exception {
+		if (name == null) {
+			return;
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("set data error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		propertyReader.setData(entity, value);
+	}
+	
+	public void setData(int idx, Object value, Object entity) throws Exception {
+		if (idx >= 0 && idx < size) {
+			PropertyReader propertyReader = propertyReaderArray[idx];
+			propertyReader.setData(entity, value);
+		}
+	}
+	
+	public void setDataString(String name, String value, Object entity) throws Exception {
+		if (name == null) {
+			return;
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("set data String error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		propertyReader.setDataString(entity, value);
+	}
+	
+	public void setDataString(int idx, String value, Object entity) throws Exception {
+		if (idx >= 0 && idx < size) {
+			PropertyReader propertyReader = propertyReaderArray[idx];
+			propertyReader.setDataString(entity, value);
+		}
+	}
+	
+	public Object getData(String name, Object entity) throws Exception {
+		if (name == null) {
+			return null;
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			return null;	
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getObject(entity);
+	}
+	
+	public Object getData(int propertyIndex, Object entity) throws Exception {
+		if (propertyIndex >= 0 && propertyIndex < size) {
+			PropertyReader propertyReader = propertyReaderArray[propertyIndex];
+			return propertyReader.getObject(entity);
+		}
+		else {
+			throw new Exception("get data error: index " + propertyIndex + " out of 0~" + size);
+		}
+	}
+	
+	public String getString(String name, Object entity) {
+		if (name == null) {
+			return "error";
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			return "error";			
+		}
+		
+		try {
+			PropertyReader propertyReader = propertyReaderArray[idx];
+			return propertyReader.getString(entity);
+		}
+		catch (Exception e) {
+			return "error";
+		}
+	}
+	
+	public String getString(int index, Object entity) {
+		if (index >= 0 && index < size) {
+			try {
+				PropertyReader propertyReader = propertyReaderArray[index];
+				return propertyReader.getString(entity);
+			}
+			catch (Exception e) {
+				return "error";
+			}
+		}
+		else {
+			return "error";
+		}
+	}
+	
+	public String getJSONString(String name, Object entity) throws Exception {
+		if (name == null) {
+			return "error";
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			return "error";			
+		}
+		
+		try {
+			PropertyReader propertyReader = propertyReaderArray[idx];
+			return propertyReader.getJSONString(entity);
+		}
+		catch (Exception e) {
+			return "error";
+		}
+	}
+
+	public String getJSONString(int index, Object entity) throws Exception {
+		if (index >= 0 && index < size) {
+			try {
+				PropertyReader propertyReader = propertyReaderArray[index];
+				return propertyReader.getJSONString(entity);
+			}
+			catch (Exception e) {
+				return "\"error\"";
+			}
+		}
+		else {
+			return "\"error\"";
+		}
+	}
+	
+	public String getSQLString(String name, Object entity) throws Exception {
+		if (name == null) {
+			throw new Exception("get sql String error: empty name");
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("get sql String error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getSQLString(entity);
+	}
+	
+	public String getSQLString(int propertyIndex, Object entity) throws Exception {
+		if (propertyIndex >= 0 && propertyIndex < size) {
+			PropertyReader propertyReader = propertyReaderArray[propertyIndex];
+			return propertyReader.getSQLString(entity);
+		}
+		else {
+			throw new Exception("get json String error: index " + propertyIndex + " out of 0~" + size);
+		}
+	}
+	
+	public Integer getInteger(String name, Entity entity) throws Exception {
+		if (name == null) {
+			throw new Exception("get integer error: empty name");
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("get integer error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getInteger(entity);
+	}
+
+	public Double getDouble(String name, Entity entity) throws Exception {
+		if (name == null) {
+			throw new Exception("get double error: empty name");
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("get integer error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getDouble(entity);
+	}
+
+	public Boolean getBoolean(String name, Entity entity) throws Exception {
+		if (name == null) {
+			throw new Exception("get boolean error: empty name");
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("get integer error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getBoolean(entity);
+	}
+
+	public Date getDate(String name, Entity entity) throws Exception {
+		if (name == null) {
+			throw new Exception("get date error: empty name");
+		}
+		
+		Integer idx = nameMap.get(name.toLowerCase());
+		
+		if (idx == null) {
+			throw new Exception("get integer error: " + name + " not exist");			
+		}
+		
+		PropertyReader propertyReader = propertyReaderArray[idx];
+		return propertyReader.getDate(entity);
+	}
+	
+	public String getPropertyName(int idx) {
+		return names[idx];
+	}
+	
+	@Override
+	public Iterator<PropertyReader> iterator() {
+		return new PropertyIterator(this);
+	}
+
+	@Override
+	public List<NameValuePair> getValueList(Object entity) throws Exception {
+		List<NameValuePair> result = new ArrayList<NameValuePair>();
+		
+		for (int i = 0; i < size; i++) {
+			Object value = propertyReaderArray[i].getObject(entity);
+			result.add(new NameValuePair(names[i], value));
+		}
+		
+		return result;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/PropertyIterator.java b/IMserver/medeasy/src/frame/object/reader/PropertyIterator.java
new file mode 100644
index 0000000..bb53672
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/PropertyIterator.java
@@ -0,0 +1,32 @@
+package frame.object.reader;
+
+import java.util.Iterator;
+
+public class PropertyIterator implements Iterator<PropertyReader> {
+
+	private ObjectReader objectReader;
+	private int size;
+	private int pos;
+	
+	public PropertyIterator(ObjectReader objectReader) {
+		this.objectReader = objectReader;
+		this.size = objectReader.size();
+		this.pos = 0;
+	}
+	
+	@Override
+	public boolean hasNext() {
+		return pos < size;
+	}
+
+	@Override
+	public PropertyReader next() {
+		return objectReader.getPropertyReader(pos++);
+	}
+
+	@Override
+	public void remove() {
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/object/reader/PropertyReader.java b/IMserver/medeasy/src/frame/object/reader/PropertyReader.java
new file mode 100644
index 0000000..99dc95d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/object/reader/PropertyReader.java
@@ -0,0 +1,166 @@
+package frame.object.reader;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import frame.variant.translator.ITranslator;
+import frame.variant.translator.Translator;
+
+public class PropertyReader {
+
+	protected String name;
+	protected Class<?> type;	
+	protected Method getMethod;
+	protected Method setMethod;
+	protected ITranslator translator;
+	protected IEntityReader valueReader;
+	
+	public PropertyReader(String property, Class<?> propertyType) throws Exception {
+		name = property;
+		type = propertyType;
+		
+		translator = Translator.getInstance(propertyType);
+	}
+
+	public void setDataString(Object entity, String value) throws Exception {
+		if (setMethod == null) {
+			return;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not set string value to " + type);
+		}
+		
+		Object arg = translator.toTranslatorTypeValue(value);
+		setMethod.invoke(entity, arg);
+	}
+
+	public String getString(Object entity) {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		try {
+			Object value = getMethod.invoke(entity);
+			
+			if (translator != null) {
+				return translator.toString(value);
+			}
+			else {
+				return valueReader.getString(value);
+			}
+		}
+		catch (Exception e) {
+			return "error";
+		}
+	}
+
+	public String getJSONString(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		Object value = getMethod.invoke(entity);
+		
+		if (translator != null) {
+			return translator.toJSONString(value);
+		}
+		else {
+			if (valueReader == null) {
+				valueReader = EntityReader.getInstance(value.getClass());
+			}
+			
+			return valueReader.getJSONString(value);
+		}
+	}
+
+	public String getSQLString(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not get sql string from " + type);
+		}
+		
+		Object value = getMethod.invoke(entity);
+		return translator.toSqlString(value);
+	}
+
+	public Integer getInteger(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not get int from " + type);
+		}
+		
+		Object value = getMethod.invoke(entity);
+		return translator.toInteger(value);
+	}
+
+	public Double getDouble(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not get double from " + type);
+		}
+		
+		Object value = getMethod.invoke(entity);
+		return translator.toDouble(value);	
+	}
+
+	public Boolean getBoolean(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not get boolean from " + type);
+		}
+		
+		Object value = getMethod.invoke(entity);
+		return translator.toBoolean(value);	
+	}
+
+	public Date getDate(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		if (translator == null) {
+			throw new Exception("can not get date from " + type);
+		}
+		
+		Object value = getMethod.invoke(entity);
+		return translator.toDate(value);	
+	}
+	
+	public void setSetMethod(Method setMethod) {
+		this.setMethod = setMethod;
+	}
+
+	public void setGetMethod(Method getMethod) {
+		this.getMethod = getMethod;
+	}
+
+	public void setData(Object entity, Object value) throws Exception {
+		if (setMethod == null) {
+			return;
+		}
+		
+		setMethod.invoke(entity, value);
+	}
+	
+	public Object getObject(Object entity) throws Exception {
+		if (getMethod == null) {
+			return null;
+		}
+		
+		return getMethod.invoke(entity);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/DBDate.java b/IMserver/medeasy/src/frame/persist/DBDate.java
new file mode 100644
index 0000000..e4a354f
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/DBDate.java
@@ -0,0 +1,46 @@
+package frame.persist;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DBDate {
+
+	private static DataBaseType dbType;
+	private Date date;
+	
+	static {
+		dbType = DataBaseType.MySQL;
+	}
+
+	public DBDate() {
+		date = new Date();
+	}
+	
+	public DBDate(Date date) {
+		this.date = date;
+	}
+	
+	public String toSQLString() throws Exception {
+		String result = null;
+		
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+		String value = dateFormat.format(date);
+		
+		if (DataBaseType.Oracle == dbType) {
+			result = "to_date('" + value + "','YYYY-MM-DD')";
+		}
+		else if (DataBaseType.SQLServer == dbType) {
+			result = "('" + value + "')";
+		}
+		else if (DataBaseType.MySQL == dbType) {
+			result = "('" + value + "')";
+		}
+		else {
+			throw new Exception("unknown database type");
+		}
+		
+		return result;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/DBDateTime.java b/IMserver/medeasy/src/frame/persist/DBDateTime.java
new file mode 100644
index 0000000..803cd88
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/DBDateTime.java
@@ -0,0 +1,41 @@
+package frame.persist;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DBDateTime {
+
+	private static DataBaseType dbType;
+	private Date date;
+	
+	public DBDateTime() {
+		date = new Date();
+	}
+	
+	public DBDateTime(Date date) {
+		this.date = date;
+	}
+	
+	public String toSQLString() throws Exception {
+		String result = null;
+		
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		String value = dateFormat.format(date);
+		
+		if (DataBaseType.Oracle == dbType) {
+			result = "to_date('" + value + "','YYYY-MM-DD HH24:MI:SS')";
+		}
+		else if (DataBaseType.SQLServer == dbType) {
+			result = "('" + value + "')";
+		}
+		else if (DataBaseType.MySQL == dbType) {
+			result = "('" + value + "')";
+		}
+		else {
+			throw new Exception("unknown database type");
+		}
+		
+		return result;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/DataBaseType.java b/IMserver/medeasy/src/frame/persist/DataBaseType.java
new file mode 100644
index 0000000..2a3fc3d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/DataBaseType.java
@@ -0,0 +1,29 @@
+package frame.persist;
+
+public enum DataBaseType {
+
+	Oracle, SQLServer, MySQL, Unknown;
+
+	public static DataBaseType valueOfString(String value) {
+		if (value == null) {
+			return Unknown;
+		}
+		
+		if ("Oracle".equalsIgnoreCase(value)) {
+			return Oracle;
+		}
+		
+		if ("SQLServer".equalsIgnoreCase(value)) {
+			return SQLServer;
+		}
+		
+		if ("MySQL".equalsIgnoreCase(value)) {
+			return MySQL;
+		}
+		
+		return Unknown;
+		
+	}
+	
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/DataSourceManager.java b/IMserver/medeasy/src/frame/persist/DataSourceManager.java
new file mode 100644
index 0000000..fcea618
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/DataSourceManager.java
@@ -0,0 +1,83 @@
+package frame.persist;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import frame.util.MapList;
+
+
+public class DataSourceManager {
+
+	private static Logger logger;
+	private static MapList<NamedDataSource> dataSourceList;
+	private static NamedDataSource defaultDataSource;
+	private static NamedDataSource activeDataSource;
+	
+	static {
+		logger = Logger.getLogger(DataSourceManager.class);
+		dataSourceList = new MapList<NamedDataSource>();
+	}
+
+	public static Connection createConnection() {
+		try {
+			if (activeDataSource != null) {
+				return activeDataSource.getConnection();
+			}
+			
+			return defaultDataSource.getConnection();
+		} 
+		catch (SQLException e) {
+			logger.error(e);
+			return null;
+		}
+	}
+	
+	public static Connection createConnection(String name) {
+		try {
+			NamedDataSource dataSource = dataSourceList.get(name);
+			
+			if (dataSource == null) {
+				return null;
+			}
+			
+			return dataSource.getConnection();
+		} 
+		catch (SQLException e) {
+			logger.error(e);
+			return null;
+		}
+	}
+	
+	public static void appendDataSource(NamedDataSource dataSource) throws SQLException {
+		String name = dataSource.getName();
+		
+		if (name == null) {
+			return;
+		}
+		
+		dataSourceList.add(name, dataSource);
+        
+        if (defaultDataSource == null) {
+        	defaultDataSource = dataSource;
+        }
+	}
+
+	public static NamedDataSource getDataSource(String code) {
+		if (code == null) {
+			return null;
+		}
+		
+		return dataSourceList.get(code);
+	}
+
+	public static List<NamedDataSource> getDataSourceList() {
+		return dataSourceList.getItemList();
+	}
+
+	public static void setActiveSource(NamedDataSource dataSource) {
+		activeDataSource = dataSource;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/DatasuorceLoader.java b/IMserver/medeasy/src/frame/persist/DatasuorceLoader.java
new file mode 100644
index 0000000..f3b301a
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/DatasuorceLoader.java
@@ -0,0 +1,132 @@
+package frame.persist;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+import java.util.Iterator;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+import chat.server.Configer;
+import chat.server.DTDResolver;
+import chat.server.Loader;
+import frame.util.Util;
+import frame.variant.translator.Translator;
+
+public class DatasuorceLoader extends Loader {
+
+	private static DatasuorceLoader instance;
+	
+	private static final String Node_Defination = "defination";
+	private static final String Node_Defination_DriverName = "driverName";
+	private static final String Node_Defination_URL = "url";
+	private static final String Node_Defination_UserName = "username";
+	private static final String Node_Defination_Password = "password";
+	
+	public DatasuorceLoader() {
+		path = Configer.getPath_Datasource();		
+	}
+	
+	public static synchronized DatasuorceLoader getInstance() {
+		if (instance == null) {
+			instance = new DatasuorceLoader();
+		}
+		
+		return instance;
+	}
+	
+	public static void staticLoad() {
+		getInstance();
+		instance.load();
+	}
+	
+	@Override
+	public void load() {
+		File file = new File(path);
+		loadOneFile(file);		
+	}
+	
+	private void loadOneFile(File file) {
+		try {
+			logger.debug("load datasource file:" + file);
+			InputStream inputStream = new FileInputStream(file);
+			
+	        try {
+	    		SAXReader reader = new SAXReader();
+	    		
+	    		DTDResolver resolver = new DTDResolver(Configer.getPath_Config(), "datasource.dtd");
+	    		reader.setEntityResolver(resolver);
+	    		reader.setValidation(false);
+	    			
+				Document doc = reader.read(inputStream);
+				Element root = doc.getRootElement();
+					
+				loadDefinations(root);
+					
+			} catch (DocumentException e) {
+				logger.error("can not load sql file: " + file);
+				logger.error(e);
+			} finally {
+				try {
+					inputStream.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+		catch (Exception e) {
+			logger.error(e);
+		}		
+	}
+	
+	private void loadDefinations(Element root) throws SQLException {
+		Iterator<?> iterator = root.elementIterator(Node_Defination);
+		
+		while (iterator.hasNext()) {
+			Element element = (Element) iterator.next();	
+			
+			String code = element.attributeValue("code");
+			if (Util.isEmptyStr(code)) {
+				code = "main";
+			}
+			
+			boolean active = Translator.toBoolean(element.attributeValue("active"), true);
+			
+			if (!active) {
+				continue;
+			}
+			
+			String drivername = element.attributeValue(Node_Defination_DriverName);
+			String url = element.attributeValue(Node_Defination_URL);
+			String username = element.attributeValue(Node_Defination_UserName);
+			String password = element.attributeValue(Node_Defination_Password);
+			String validationQuery = element.attributeValue("validationQuery");
+			
+			NamedDataSource dataSource = new NamedDataSource(code);
+			
+			dataSource.setDriverClassName(drivername);
+	        dataSource.setUrl(url);
+	        dataSource.setUsername(username);
+	        dataSource.setPassword(password);
+	        dataSource.setValidationQuery(validationQuery);
+			
+	        dataSource.setInitialSize(1);
+	        dataSource.setFilters("stat,log4j");
+	        dataSource.setMaxWait(60000);
+	        dataSource.setMinIdle(1);
+	        dataSource.setTimeBetweenEvictionRunsMillis(3000);
+	        dataSource.setMinEvictableIdleTimeMillis(3000 * 500);
+	        dataSource.setRemoveAbandonedTimeout(300);
+	        dataSource.setTestWhileIdle(true);
+	        dataSource.setTestOnBorrow(false);
+	        dataSource.setTestOnReturn(false);
+	        
+	        DataSourceManager.appendDataSource(dataSource);
+		}		
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/IDoubleSavable.java b/IMserver/medeasy/src/frame/persist/IDoubleSavable.java
new file mode 100644
index 0000000..01f09a6
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/IDoubleSavable.java
@@ -0,0 +1,10 @@
+package frame.persist;
+
+import java.sql.PreparedStatement;
+
+
+public interface IDoubleSavable {
+
+	void save(PreparedStatement stmt1, PreparedStatement stmt2, Object... agrs) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/ILoadable.java b/IMserver/medeasy/src/frame/persist/ILoadable.java
new file mode 100644
index 0000000..dd18a93
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/ILoadable.java
@@ -0,0 +1,9 @@
+package frame.persist;
+
+import java.sql.ResultSet;
+
+public interface ILoadable {
+
+	void load(ResultSet rslt, Object... args) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/IMetaDataLoader.java b/IMserver/medeasy/src/frame/persist/IMetaDataLoader.java
new file mode 100644
index 0000000..431f467
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/IMetaDataLoader.java
@@ -0,0 +1,9 @@
+package frame.persist;
+
+import java.sql.ResultSetMetaData;
+
+public interface IMetaDataLoader {
+
+	void load(ResultSetMetaData metaData) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/ISQLContext.java b/IMserver/medeasy/src/frame/persist/ISQLContext.java
new file mode 100644
index 0000000..b6a2390
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/ISQLContext.java
@@ -0,0 +1,8 @@
+package frame.persist;
+
+
+public interface ISQLContext {
+	
+	void setParametersTo(NamedSQL namedSQL) throws  Exception;
+	  
+}
diff --git a/IMserver/medeasy/src/frame/persist/ISavable.java b/IMserver/medeasy/src/frame/persist/ISavable.java
new file mode 100644
index 0000000..e23d770
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/ISavable.java
@@ -0,0 +1,10 @@
+package frame.persist;
+
+import java.sql.PreparedStatement;
+
+public interface ISavable {
+
+	void saveData(PreparedStatement stmt, Object... agrs) throws Exception;
+	
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/IStepLoadable.java b/IMserver/medeasy/src/frame/persist/IStepLoadable.java
new file mode 100644
index 0000000..9112976
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/IStepLoadable.java
@@ -0,0 +1,15 @@
+package frame.persist;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public interface IStepLoadable {
+
+	boolean hasNextForLoad();
+	
+	void load(ResultSet rslt, Object... args) throws Exception;
+
+	void setLoadParameters(PreparedStatement stmt) throws SQLException;
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/IStepSavable.java b/IMserver/medeasy/src/frame/persist/IStepSavable.java
new file mode 100644
index 0000000..eab7354
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/IStepSavable.java
@@ -0,0 +1,12 @@
+package frame.persist;
+
+import java.sql.PreparedStatement;
+
+
+public interface IStepSavable {
+
+	void save(PreparedStatement stmt, Object... args) throws Exception;
+	
+	boolean hasNextForSave();
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/NamedDataSource.java b/IMserver/medeasy/src/frame/persist/NamedDataSource.java
new file mode 100644
index 0000000..a0eee96
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/NamedDataSource.java
@@ -0,0 +1,44 @@
+package frame.persist;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+import chat.server.call.IJSONWriter;
+import chat.server.call.IJsonProvider;
+
+public class NamedDataSource extends DruidDataSource implements IJsonProvider {
+
+	private static final long serialVersionUID = 1L;
+	private String name;
+	
+	public NamedDataSource(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	@Override
+	public void writeJSONObject(IJSONWriter writer) {
+		writer.beginArray();
+		writeJSONData(writer);
+		writer.endArray();		
+	}
+
+	@Override
+	public void writeJSONData(IJSONWriter writer) {
+		writer.write("name", getName());
+		writer.write("dbType", getDbType());
+		writer.write("dbType", getDbType());
+		writer.write("dbType", getDbType());
+		
+		writer.write("connectCount", getConnectCount());
+		writer.write("activeCount", getActiveCount());
+		writer.write("closeCount", getCloseCount());
+		writer.write("destroyCount", getDestroyCount());
+		writer.write("scardCount", getDiscardCount());
+		writer.write("activePeak", getActivePeak());
+		writer.write("createTime", getCreatedTime());
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/NamedSQL.java b/IMserver/medeasy/src/frame/persist/NamedSQL.java
new file mode 100644
index 0000000..563ac75
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/NamedSQL.java
@@ -0,0 +1,530 @@
+package frame.persist;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import frame.object.dao.Filter;
+import frame.object.dao.OrderBy;
+import frame.object.dao.Page;
+import frame.object.data.Entity;
+import frame.object.data.EntitySet;
+import frame.object.meta.EntityMeta;
+import frame.object.meta.Field;
+import frame.util.ContentBuilder;
+import frame.util.Util;
+import frame.variant.IVariantsConsumer;
+import frame.variant.IVariantsProvider;
+import frame.variant.ValueType;
+import frame.variant.VariantLink;
+import frame.variant.expression.Expression;
+import frame.variant.expression.IExpression;
+import frame.variant.expression.VariantList;
+import frame.variant.expression.VariantSegment;
+
+
+public class NamedSQL implements Iterable<VariantSegment>, IExpression, IVariantsConsumer {
+
+	public static final String Code_GetEntity = "getEntity";
+	public static final String Code_GetFirstEntity = "getFirstEntity";
+	public static final String Code_GetCount = "getCount";
+	public static final String Code_InsertEntity = "insertEntity";
+	public static final String Code_UpdateEntityById = "updateById";
+	public static final String Code_DeleteByID = "deleteByID";
+	public static final String Code_DeleteChildrenByID = "deleteChildrenByID";
+	
+	public static final String Param_Schema = "schema";
+	public static final String Param_TableName = "tablename";
+	public static final String Param_FieldNames = "fieldNames";
+	public static final String Param_FieldNameValues = "fieldNameValues";
+	public static final String Param_FieldValues = "fieldValues";
+	public static final String Param_FieldMetas = "fieldMetas";
+	public static final String Param_PlaceHolders = "placeHolders";
+	public static final String Param_Filter = "filter";
+	public static final String Param_FieldNamePlaceHolders = "fieldNamePlaceHolders";
+	public static final String Param_KeyFieldName = "keyFieldName";
+	public static final String Param_OrderBy = "orderby";
+	public static final String Param_Limit = "limit";
+	
+	private static NamedSQLContainer namedSQLContainer;
+	
+	protected String name;
+	protected String sql;
+	protected ValueType returnType;
+	protected Expression expression;
+	
+	static {
+		namedSQLContainer = NamedSQLContainer.getInstance();
+	}
+
+	private NamedSQL(String name) {
+		this.name = name;
+		returnType = ValueType.Void;
+	}
+	
+	public NamedSQL(String name, String sql) throws Exception {
+		this.name = name;
+		this.sql = sql;
+		
+		parseSQL(sql);
+	}
+	
+	protected void parseSQL(String sql) throws Exception {
+		String lower = sql.toLowerCase();
+		
+		if (lower.indexOf("row_number()") > 0) {
+			sql = "select * from (" + sql + ")table_t where rownum > @{beginNo} and rownum <= @{endNo}";
+		}
+		
+		expression = new SQLCreator(sql);
+	}
+
+	public static NamedSQL[] getInstance(String[] names) throws Exception {
+		if (names == null) { return new NamedSQL[0]; };
+		
+		NamedSQL[] result = new NamedSQL[names.length];
+		
+		for (int i = 0; i < names.length; i++) {
+			result[i] = getInstance(names[i]);
+		}
+		
+		return result;
+	}
+	
+	public static NamedSQL getInstance(String name) throws Exception {
+		NamedSQL result = namedSQLContainer.get(name);
+		
+		if (result == null) {
+			result = namedSQLContainer.get(name);
+		}
+		
+		if (result == null) {
+			throw new Exception("can not find named sql: " + name);
+		}
+		
+		result = result.newInstance();
+		return result;
+	}
+	
+	public NamedSQL newInstance() throws Exception {
+		NamedSQL instance = new NamedSQL(this.name);
+		instance.sql = this.sql;
+		instance.expression = this.expression.newInstance();
+		
+		return instance;
+	}
+
+	public String getSQL() throws Exception {
+		String result = expression.getString();
+		return result;
+	}
+	
+	public String getOriginalSql(){
+		return sql;
+	}
+
+	public Result exec() throws Exception {
+		Result result = SQLRunner.getResult(this);
+		return result;
+	}
+	
+	public NamedSQL setSchema(String schema) {
+		return setParam(Param_Schema, schema);
+	}
+
+	public NamedSQL setTableName(String tableName) {
+		return setParam(Param_TableName, tableName.toLowerCase());
+	}
+
+	public NamedSQL setFieldNames(String names) {
+		return setParam(Param_FieldNames, names);
+	}
+	
+	public NamedSQL setFieldNames(EntityMeta tableMeta) {
+		StringBuilder result = new StringBuilder();
+		boolean empty = true;
+		
+		for (Field field: tableMeta) {
+			if (!empty) {
+				result.append(", ");
+			}
+			
+			result.append(field.getName());
+			
+			empty = false;
+		}
+		
+		return setParam(Param_FieldNames, result.toString());
+	}
+	
+	public NamedSQL setFieldNames(EntityMeta tableMeta, Entity entity) {
+		return setFieldNames(tableMeta, entity, "");
+	}
+	
+	public NamedSQL setFieldNames(EntityMeta tableMeta, Entity entity, String excludeColumn) {
+		StringBuilder result = new StringBuilder();
+		boolean empty = true;
+		Field field;
+		
+		for (int i = 0; i < tableMeta.getFieldCount(); i++) {
+			if (entity.isEmptyValue(i)) {
+				continue;
+			}
+				
+			field = tableMeta.getField(i);
+			
+			if (excludeColumn.equals(field.getName())) {
+				continue;
+			}
+			
+			if (!empty) {
+				result.append(", ");
+			}
+
+			result.append(field.getName());
+			empty = false;
+		}
+		
+		return setParam(Param_FieldNames, result.toString());
+	}
+	
+	public NamedSQL setFieldNames(Collection<Field> fields) {
+		ContentBuilder result = new ContentBuilder();
+		
+		for (Field field: fields) {
+			result.append(field.getName(), ", ");
+		}
+		
+		return setParam(Param_FieldNames, result.toString());
+	}
+
+	public NamedSQL setFieldValues(Entity entity) {
+		ContentBuilder result = new ContentBuilder(", ");
+		
+		int max = entity.getFieldCount();
+		
+		for (int i = 0; i < max; i++) {
+			if (entity.isEmptyValue(i)) {
+				continue;
+			}
+				
+			result.append(entity.getSQLString(i, "null"));
+		}
+		
+		return setParam(Param_FieldValues, result.toString());
+	}
+
+	public NamedSQL setTableMeta(EntityMeta entityMeta) {
+		//1. set table name
+		setTableName(entityMeta.getTableName());
+		
+		//2. set field meta
+		ContentBuilder result = new ContentBuilder(", ");
+		
+		for (Field field: entityMeta) {
+			String line = "`" + field.getName() + "` " + field.getSQLTypeCode() + " " + field.getSQLNullCode();
+			result.append(line);
+		}
+		
+		return setParam(Param_FieldMetas, result.toString());
+	}
+	
+	public NamedSQL setTableMeta(String tableName, EntitySet entitySet) {
+		//1. set table name
+		setTableName(tableName);
+		
+		//2. set field meta
+		ContentBuilder result = new ContentBuilder(", ");
+		
+		for (Entity entity: entitySet) {
+			String fieldName = entity.getString("fieldName");
+			String fieldType = entity.getSQLTypeCode("fieldType", "fieldLength");
+			String sqlNullCode = entity.getSQLNullCode("nullable");
+			
+			String line = "`" + fieldName + "` " + fieldType + " " + sqlNullCode;
+			result.append(line);
+		}
+		
+		return setParam(Param_FieldMetas, result.toString());
+	}
+	
+	public NamedSQL setQuotedFieldNames(EntityMeta tableMeta) {
+		ContentBuilder result = new ContentBuilder();
+		
+		for (Field field: tableMeta) {
+			result.append(Util.doubleQuotedStr(field.getName()), ", ");
+		}
+		
+		return setParam(Param_FieldNames, result.toString());
+	}
+
+	public NamedSQL setPlaceHolders(int count) {
+		ContentBuilder result = new ContentBuilder();
+		
+		for (int i = 0; i < count; i++) {
+			result.append("?", ", ");
+		}
+		
+		return setParam(Param_PlaceHolders, result.toString());
+	}
+	
+	public NamedSQL setPlaceHolders(String placeHolders) {
+		return setParam(Param_PlaceHolders, placeHolders);
+	}
+
+	public NamedSQL setFieldNamePlaceHolders(EntityMeta tableMeta) {
+		ContentBuilder result = new ContentBuilder();
+		
+		for (Field field: tableMeta) {
+			result.append(field.getName() + " = ? ", ", ");
+		}
+		
+		return setParam(Param_FieldNamePlaceHolders, result.toString());
+	}
+
+	public NamedSQL setFilter(String filter) {
+		if (Util.isEmptyStr(filter)) {
+			return this;
+		}
+		
+		return setParam(Param_Filter, filter);	
+	}
+	
+	public NamedSQL setFilter(Filter filter) {
+		if (filter == null) {
+			return this;
+		}
+		
+		if (filter.isRaw()) {
+			return setFilter(filter.getRawFilter());
+		}
+		
+		String segment = filter.toString();
+		return setFilter(segment);
+	}
+
+	public NamedSQL setOrderBy(String orderby) {
+		if (Util.isEmptyStr(orderby)) {
+			return this;
+		}
+		
+		return setParam(Param_OrderBy, Util.stringJoin(" order by ", orderby));	
+	}
+	
+	public NamedSQL setOrderBy(OrderBy orderBy) {
+		if (orderBy == null) {
+			return this;
+		}
+		
+		return setParam(Param_OrderBy, orderBy.getValue());	
+	}
+
+	public NamedSQL setPage(Page page) {
+		if (page == null) {
+			return this;
+		}
+		
+		if (expression.containsVariant(Param_Limit)) {
+			setParam(Param_Limit, page.getLimitSQL());
+			return this;
+		}
+		
+		
+		return this;
+	}
+
+//	public NamedSQL setFieldNameValues(Entity entity) throws Exception {
+//		ContentBuilder result = new ContentBuilder();
+//		
+//		EntityMeta tableMeta = entity.getEntityMeta();
+//		int cnt = tableMeta.getFieldCount();
+//		
+//		for (int i = 0; i < cnt; i++) {
+//			if (entity.isEmptyValue(i)) {
+//				continue;
+//			}
+//			
+//			Field field = tableMeta.getField(i);
+//			result.append(field.getName() + "=" + entity.getSQLString(i), ", ");
+//		}
+//		
+//		return setParam(Param_FieldNameValues, result.toString());
+//	}
+	
+	public NamedSQL setFieldNameValues(Entity entity) throws Exception {
+		return setFieldNameValues(entity, null);
+	}
+	
+	public NamedSQL setFieldNameValues(Entity entity, Map<String, String> excludeColumn) throws Exception {
+		ContentBuilder result = new ContentBuilder();
+		
+		EntityMeta tableMeta = entity.getEntityMeta();
+		int cnt = tableMeta.getFieldCount();
+		
+		for (int i = 0; i < cnt; i++) {
+			if (entity.isEmptyValue(i)) {
+				continue;
+			}
+			
+			Field field = tableMeta.getField(i);
+			
+			if (excludeColumn != null) {
+				if (excludeColumn.containsKey(field.getName())) {
+					continue;
+				}
+			}
+			
+			result.append(field.getName() + "=" + entity.getSQLString(i), ", ");
+		}
+		
+		return setParam(Param_FieldNameValues, result.toString());		
+	}
+
+	public NamedSQL setParam(String name, String value) {	
+		VariantSegment variant = expression.getVariant(name);
+		
+		if (variant != null) {
+			variant.setValue(value);
+		}
+		
+		return this;
+	}
+	
+	public NamedSQL setParam(String name, String value, String defaultValue) {
+		if (value == null) {
+			value = defaultValue;
+		}
+		
+		VariantSegment sqllVariant = expression.getVariant(name);
+		
+		if (sqllVariant != null) {
+			sqllVariant.setValue(value);
+		}
+		
+		return this;
+	}
+	
+	public NamedSQL setParam(String name, int value) {
+		String StringValue = String.valueOf(value);
+		return setParam(name, StringValue);
+	}
+	
+	public NamedSQL setParam(String name, BigDecimal value) {
+		String StringValue = value.toString();
+		return setParam(name, StringValue);		
+	}
+	
+	public NamedSQL setParam(String name, Date date) {
+		String StringValue = Util.toMySQLDateStr(date);
+		return setParam(name, StringValue);
+	}
+	
+	public NamedSQL setParam(String name, boolean value) {
+		String StringValue = Util.booleanToStr(value);
+		return setParam(name, StringValue);
+	}
+
+	public String getParam(String name) {
+		VariantSegment variant = expression.getVariant(name);
+		String valueString = variant.getValueString();
+		if (Util.isNull(valueString)) {
+			return null;
+		}
+		return valueString;
+	}
+	
+	public String getName() {
+		return name;
+	}
+
+	public ValueType getReturnType() {
+		return returnType;
+	}
+
+	public void setReturnType(ValueType dataType) {
+		this.returnType = dataType;
+	}
+	
+	@Override
+	public Iterator<VariantSegment> iterator() {
+		return expression.iterator();
+	}
+
+	public void clearVariantValues() {
+		expression.clearVariantValues();
+	}
+
+	public VariantList getVariantList() {
+		return expression.getVariantList();
+	}
+
+	public Expression getExpression() {
+		return expression;
+	}
+
+	@Override
+	public void setVariants(IVariantsProvider... providers) throws Exception {
+		VariantLink.moveOnConsumer(this, providers);
+	}
+	
+	public static int execute(String name, ISQLContext sqlContext) throws Exception {
+		NamedSQL namedSQL = NamedSQL.getInstance(name);
+		sqlContext.setParametersTo(namedSQL);
+		return SQLRunner.execSQL(namedSQL);
+	}
+
+	public String getSQLString() throws Exception {
+		return expression.getString(); 
+	}
+	
+	@Override
+	public String toString() {
+		return expression.getString();
+	}
+
+
+	public void setSql(String sql) throws Exception {
+		this.sql = sql;
+		expression = new SQLCreator(sql);
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		return expression.getVariantNameList();
+	}
+	
+	public Set<String> getVariantNameSet() {
+		return expression.getVariantList().getKeySet();
+	}
+	
+	@Override
+	public boolean containsVariant(String name) {
+		return expression.containsVariant(name);
+	}
+
+	@Override
+	public void setVariant(String name, Object value) throws Exception {
+		expression.setVariant(name, value);
+	}
+
+	@Override
+	public boolean isVariantNull(String name) {
+		return expression.isVariantNull(name);
+	}
+
+	public Entity getEntity() throws Exception {
+		 return SQLRunner.getEntity(this);
+	}
+
+	public EntitySet getEntitySet() throws Exception {
+		return SQLRunner.getEntitySet(this);
+	}
+
+	public int execute() throws Exception {
+		return SQLRunner.execSQL(this);
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/NamedSQLContainer.java b/IMserver/medeasy/src/frame/persist/NamedSQLContainer.java
new file mode 100644
index 0000000..882ef6c
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/NamedSQLContainer.java
@@ -0,0 +1,23 @@
+package frame.persist;
+
+import chat.server.Container;
+
+public class NamedSQLContainer extends Container<NamedSQL> {
+
+	private static NamedSQLContainer instance;
+	
+	
+	private NamedSQLContainer() {
+	}
+	
+	
+	public synchronized static NamedSQLContainer getInstance() {
+		if (instance == null) {
+			instance = new NamedSQLContainer();
+		}
+		
+		return instance;
+	}
+	
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/NamedSQLLoader.java b/IMserver/medeasy/src/frame/persist/NamedSQLLoader.java
new file mode 100644
index 0000000..c1bf90d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/NamedSQLLoader.java
@@ -0,0 +1,135 @@
+package frame.persist;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+import chat.server.Configer;
+import chat.server.DTDResolver;
+import chat.server.Loader;
+import frame.util.Util;
+
+
+public class NamedSQLLoader extends Loader {
+
+	private static NamedSQLLoader instance;
+	private NamedSQLContainer sqlContainer;
+	protected String Node_RootElements;
+	
+	
+	private NamedSQLLoader() throws FileNotFoundException {
+		path = Configer.getPath_SQLConfig();
+		sqlContainer = NamedSQLContainer.getInstance();
+		Node_RootElements = "dataSpace";
+	}
+	
+	public static synchronized NamedSQLLoader getInstance() throws FileNotFoundException {
+		if (instance == null) {
+			if (instance == null) {
+				instance = new NamedSQLLoader();
+			}
+		}
+		
+		return instance;
+	}
+	
+
+	public static void staticLoad() throws FileNotFoundException {
+		getInstance();
+		instance.load();
+	}
+	
+	@Override
+	public void load() {
+		File root = new File(path);
+		File[] files = root.listFiles();
+		
+		for (File config: files) {
+			if (!config.isFile()) {
+				continue;
+			}
+			
+			loadOneFile(config);
+		}
+	}
+	
+	public void reload() {
+		sqlContainer.clear();
+		load();
+	}
+	
+	public void loadOneFile(File file) {
+		try {
+			logger.debug("load sql file:" + file);
+			InputStream inputStream = new FileInputStream(file);
+			
+	        try {
+	    		SAXReader reader = new SAXReader();
+	    		
+	    		DTDResolver resolver = new DTDResolver(Configer.getPath_Config(), "sql.dtd");
+	    		reader.setEntityResolver(resolver);
+	    		reader.setValidation(false);
+	    			
+				Document doc = reader.read(inputStream);
+				Element root = doc.getRootElement();
+				
+				String active = root.attributeValue("active");
+				
+				if (!Util.isEmptyStr(active)) {
+					if (!Util.StringToBoolean(active)) {
+						return;
+					}
+				}
+					
+				loadRootElements(root);
+					
+			} catch (DocumentException e) {
+				logger.error("can not load sql file: " + file);
+				logger.error(e);
+			} finally {
+				try {
+					inputStream.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+		catch (Exception e) {
+			logger.error(e);
+		}
+	}
+	
+	protected void loadRootElements(Element root) throws Exception {
+		Iterator<?> iterator = root.elementIterator(Node_RootElements);
+		
+		while (iterator.hasNext()) {
+			Element element = (Element) iterator.next();	
+			loadOneRootElement(element);
+		}
+	}
+
+	protected void loadOneRootElement(Element element, Object ...args) throws Exception {
+		Iterator<?> sqlIterator = element.elementIterator();
+		
+		while (sqlIterator.hasNext()) {
+			Element statementElemnet = (Element) sqlIterator.next();
+			loadOneSQLElement(statementElemnet, args);
+		}
+	}
+
+	protected void loadOneSQLElement(Element element, Object ...args) throws Exception {
+		String name = element.attributeValue("name");	
+		String sql = element.getTextTrim();
+		
+		NamedSQL namedSQL = new NamedSQL(name, sql);
+		sqlContainer.add(name, namedSQL);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/Result.java b/IMserver/medeasy/src/frame/persist/Result.java
new file mode 100644
index 0000000..7c4feb9
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/Result.java
@@ -0,0 +1,81 @@
+package frame.persist;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.object.data.Entity;
+import frame.object.data.EntitySet;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class Result {
+	
+	private ValueType dataType;
+	private Value variant;
+	private Object object;
+	
+	public Result() {
+		dataType = ValueType.Void;
+	}
+
+	public void setValue(Integer value) {
+		variant = new Value(value);
+		dataType = ValueType.Int;  
+	}
+	
+	public void setValue(String value) {
+		variant = new Value(value);
+		dataType = ValueType.String;  
+	}
+
+	public void setValue(BigDecimal value) {
+		variant = new Value(value);
+		dataType = ValueType.Decimal;
+	}
+
+	public void setValue(Date value) {
+		variant = new Value(value);
+		dataType = ValueType.Date;
+	}
+
+	public void setValue(Entity value) {
+		object = value;
+		dataType = ValueType.Entity; 
+	}
+
+	public void setValue(EntitySet value) {
+		object = value;
+		dataType = ValueType.EntitySet;		
+	}
+
+	public ValueType getDataType() {
+		return dataType;
+	}
+	
+	public Entity getEntity() {
+		return (Entity)object;
+	}
+
+	public EntitySet getEntitySet() {
+		return (EntitySet)object;
+	}
+
+	public String getString() {
+		return variant.getString();
+	}
+	
+	public int getInt(int defaultValue) {
+		return variant.getInt(defaultValue);
+	}
+	
+	public BigDecimal getBigDecimal() {
+		return variant.getBigDecimal();
+	}
+	
+	public Value getValue() {
+		return variant;
+	}
+
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/SQLBuilder.java b/IMserver/medeasy/src/frame/persist/SQLBuilder.java
new file mode 100644
index 0000000..48de957
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/SQLBuilder.java
@@ -0,0 +1,104 @@
+package frame.persist;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import frame.object.meta.EntityMeta;
+import frame.object.meta.Field;
+import frame.util.Util;
+
+
+public class SQLBuilder {
+
+	public static String getCreateTableSQL(EntityMeta tableMeta, String table, Collection<Field> fields) {
+		Set<Field> allFields = new HashSet<Field>();
+		
+		allFields.addAll(tableMeta.getFields());
+		
+		allFields.addAll(fields);
+		
+		return getCreateTableSQL(allFields, table);
+	}
+	
+	public static String getCreateTableSQL(EntityMeta tableMeta, String table) {
+		Set<Field> fields = new HashSet<Field>();
+		
+		fields.addAll(tableMeta.getFields());
+
+		return getCreateTableSQL(fields, table);
+	}
+	
+	private static String getCreateTableSQL(Collection<Field> fields, String table) {
+		if (table == null) {
+			return null;
+		}
+		
+		StringBuilder result = new StringBuilder();
+		result.append("CREATE TABLE ").append(table.toUpperCase()).append("(");
+		boolean empty = true;
+		
+		for (Field field: fields) {
+			if (!empty) {
+				result.append(", ");
+			}
+			
+			String name = field.getName();
+			result.append(Util.doubleQuotedStr(name.toUpperCase())).append(" ");
+			result.append(field.getSQLTypeCode());
+			
+			empty = false;
+		}
+		
+		result.append(")");
+		
+		return result.toString();		
+	}
+
+	public static String getModifyTableSQL(List<Field> fieldList, String table) {
+		StringBuilder result = new StringBuilder();
+		result.append("ALTER TABLE ").append(table.toUpperCase()).append(" ADD (");
+		boolean empty = true;
+		
+		for (Field field: fieldList) {
+			if (!empty) {
+				result.append(", ");
+			}
+			
+			result.append(field.getName().toUpperCase()).append(" ");
+			result.append(field.getSQLTypeCode()).append(field.getSQLNullCode());
+			
+			empty = false;
+		}
+		
+		result.append(")");
+		
+		return result.toString();
+	}
+
+	public static String getCreateIndexSQL(String table, String[] keyFields) {
+		if (table == null) {
+			return null;
+		}
+		
+		StringBuilder result = new StringBuilder();
+		result.append("CREATE UNIQUE INDEX ").append("IDX_").append(table.toUpperCase());
+		result.append(" ON ").append(table).append(" (");
+		
+		boolean empty = true;
+		
+		for (String field: keyFields) {
+			if (!empty) {
+				result.append(", ");
+			}
+			
+			result.append(field);
+			empty = false;
+		}
+		
+		result.append(")");
+		
+		return result.toString();
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/SQLCreator.java b/IMserver/medeasy/src/frame/persist/SQLCreator.java
new file mode 100644
index 0000000..8fb0fb2
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/SQLCreator.java
@@ -0,0 +1,94 @@
+package frame.persist;
+
+import org.apache.log4j.Logger;
+
+import frame.util.Util;
+import frame.variant.expression.Expression;
+import frame.variant.expression.VariantSegment;
+
+public class SQLCreator extends Expression {
+	
+	protected static Logger logger;
+
+	
+	static {
+		logger = Logger.getLogger(SQLCreator.class);
+	}
+	
+	public SQLCreator(String sql) throws Exception {
+		super(sql, 8);
+	}
+
+	@Override
+	public void addVariant(String name) throws Exception {
+		if (Util.isEmptyStr(name)) {
+			return;
+		}
+		
+		if (variantList.contains(name)) {
+			VariantSegment segment = variantList.get(name);
+			segments.add(segment);
+		}
+		else {
+			SQLVariant segment = new SQLVariant(name);
+			segments.add(segment);
+			variantList.add(name, segment);
+		}	
+	}
+
+	public static String deletePageLimit(String sql) {
+		DataBaseType dbType = DataBaseType.MySQL;
+		
+		if (DataBaseType.MySQL == dbType) {
+			return deleteMySQLPageLimit(sql);
+		}
+		else if (DataBaseType.Oracle == dbType) {
+			return deleteOraclePageLimit(sql);
+		}
+		else if (DataBaseType.SQLServer == dbType) {
+			return deleteSQLServerPageLimit(sql);
+		}
+
+		return null;
+	}
+
+	private static String deleteMySQLPageLimit(String sql) {
+		int pos_beginno = sql.indexOf("@{beginno}");
+		
+		while (pos_beginno > 0) {
+			int pos_pagesize = sql.indexOf("@{pagesize}", pos_beginno + 1);
+			int pos_limit = sql.lastIndexOf("limit ", pos_beginno);
+			
+			if (pos_pagesize > 0 && pos_limit > 0) {
+				sql = sql.substring(0, pos_limit) + sql.substring(pos_pagesize + "@{pagesize}".length());
+			}
+			
+			pos_beginno = sql.indexOf("@{beginno}", pos_beginno + 1);
+		}
+
+		return sql;
+	}
+
+	private static String deleteOraclePageLimit(String sql) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	private static String deleteSQLServerPageLimit(String sql) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+	public static void main(String[] args) {
+		String sql = "select agreement.*, dealer.code, dealer.name,"
+				   + "(select count(1) from agreementArea where agreementArea.parentid = agreement.id) as areaCount,"
+				   + "(select count(1) from agreementProduct where agreementProduct.parentid = agreement.id) as productCount"
+				   + "from agreement"
+				   + "left join dealer on agreement.customerid = dealer.id"
+				   + "where @{filter}"
+				   + "limit @{beginno}, @{pagesize}";
+		
+		sql = deleteMySQLPageLimit(sql);
+		System.out.println(sql);
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/SQLRunner.java b/IMserver/medeasy/src/frame/persist/SQLRunner.java
new file mode 100644
index 0000000..45a66ac
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/SQLRunner.java
@@ -0,0 +1,705 @@
+package frame.persist;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import frame.object.data.Entity;
+import frame.object.data.EntityFactory;
+import frame.object.data.EntitySet;
+import frame.object.data.ObjectList;
+import frame.persist.loader.EntityLoader;
+import frame.persist.loader.EntitySetLoader;
+import frame.persist.loader.ListLoader;
+import frame.persist.loader.ObjectLoader;
+import frame.persist.loader.ValueLoader;
+import frame.util.Util;
+import frame.variant.ValueType;
+
+
+public class SQLRunner {
+	
+	protected static Logger logger;
+	protected static ThreadLocal<Connection> activeConn;
+	private static Set<String> tableSet;
+
+	static {
+		logger = Logger.getLogger(SQLRunner.class);
+		tableSet = new HashSet<String>();
+		activeConn = new ThreadLocal<Connection>();
+	}
+	
+	public static synchronized void beginTrans() throws SQLException {
+		Connection conn = activeConn.get();
+		
+		if (conn == null) {
+			conn = DataSourceManager.createConnection();
+			conn.setAutoCommit(false);
+			activeConn.set(conn);
+		}
+	}
+	
+	public static void commit() throws Exception {
+		Connection conn = activeConn.get();
+		
+		if (conn == null) {
+			throw new Exception("empty conn, can not commit!");
+		}
+		
+		try {
+			conn.commit();
+		}
+		finally {
+			try {
+				conn.close();
+			}
+			catch (Exception e) {
+			}
+			activeConn.remove();	
+		}
+	}
+	
+	public static void rollback() throws Exception {
+		Connection conn = activeConn.get();
+		
+		if (conn == null) {
+			throw new Exception("empty conn, can not commit!");
+		}
+		
+		try {
+			conn.rollback();
+		}
+		finally {
+			try {
+				conn.close();
+			}
+			catch (Exception e) {
+			}
+			activeConn.remove();	
+		}		
+	}
+	
+	public static int execSQL(String sql) throws Exception {
+		return execSQL(null, sql);
+	}
+	
+	public static int execSQL(NamedSQL sql) throws Exception {
+		return execSQL(null, sql.getSQLString());
+	}
+	
+	public static int execSQL(Connection conn, String sql) throws Exception {
+		Statement stmt = null;
+		int result = 0;
+		
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+
+		try {
+			if (conn == null) {
+				conn = DataSourceManager.createConnection();
+			}
+			
+			if (conn != null) {
+				logger.debug(sql);
+				stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+				
+				result = stmt.executeUpdate(sql);
+			}
+		} 
+		catch (SQLException e) {
+			onError(sql, e);
+			throw e;
+		}
+		finally {
+			try {
+				if (stmt != null) {
+					stmt.close();
+				}
+			} catch (SQLException e) {
+			} finally {
+				if (closeFlag && conn != null) {
+					conn.close();
+				}
+			}
+		}
+		return result;
+	}
+	
+	public static void getData(NamedSQL namedSQL, ILoadable loadable, Object ...args) throws Exception {
+		getData(null, namedSQL, loadable, args);
+	}
+	
+	public static void getData(NamedSQL namedSQL, IStepLoadable loadable, Object ...args) throws Exception {
+		getData(null, namedSQL, loadable, args);
+	}
+	
+	public static void getData(Connection conn, NamedSQL namedSQL, ILoadable loadable, Object ...args) throws Exception {
+		ResultSet rslt = null;
+		Statement stmt = null;
+
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+		String sql = namedSQL.getSQL();
+		
+		if (sql != null) {
+			sql.trim();
+			
+			if (!"".equals(sql)) {
+				try {
+					if (conn == null) {
+						conn = DataSourceManager.createConnection();
+					}
+
+					if (conn != null) {
+						logger.debug(sql);
+						stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+						rslt = stmt.executeQuery(sql);
+						
+						loadable.load(rslt, args);
+					}
+					else{
+						throw new SQLException("can not get coinnection");
+					}
+				} 
+				catch (SQLException e) {
+					logger.error("getDataFromDB error:" + e.getMessage());
+					throw e;
+				} 
+				finally {
+					try {
+						if (rslt != null) {
+							rslt.close();
+						}
+					} catch (SQLException e) {
+					}
+					finally {
+						try {
+							if (stmt != null) {
+								stmt.close();
+							}
+						} catch (SQLException e) {
+						}
+						finally {
+							if (closeFlag && conn != null) {
+								conn.close();
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public static void getData(Connection conn, NamedSQL namedSQL, IStepLoadable loadable, Object ...args) throws Exception {
+		ResultSet rslt = null;
+		PreparedStatement stmt = null;
+
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+		String sql = namedSQL.getSQLString();
+		
+		if(!sql.contains("limit")) {
+			sql += " limit ?, ?";
+		}
+		
+		try {
+			if (conn == null) {
+				conn = DataSourceManager.createConnection();
+			}
+
+			if (conn != null) {
+				while (loadable.hasNextForLoad()) {
+					stmt = conn.prepareStatement(sql);
+					loadable.setLoadParameters(stmt);
+					
+					try {
+						try {
+							rslt = stmt.executeQuery();
+							loadable.load(rslt, args);
+						}
+						finally {
+							if (rslt != null) {
+								rslt.close();
+							}
+						}						
+					}
+					finally {
+						if (stmt != null) {
+							stmt.close();
+						}
+					}
+				}
+			}
+			else{
+				throw new SQLException("can not get coinnection");
+			}
+		} 
+		catch (SQLException e) {
+			logger.debug(sql);
+			logger.error("getDataFromDB error:" + e.getMessage());
+			throw e;
+		} 
+		finally {
+			if (closeFlag && conn != null) {
+				conn.close();
+			}
+		}
+	}
+	
+	public static void saveData(NamedSQL namedSQL1, NamedSQL namedSQL2, IDoubleSavable savable, Object ...args) throws Exception {
+		saveData(null, namedSQL1, namedSQL2, savable, args);
+	}
+	
+	public static void saveData(NamedSQL namedSQL, ISavable savable, Object ...args) throws Exception {
+		saveData(null, namedSQL, savable, args);
+	}
+	
+	public static void saveData(Connection conn, NamedSQL namedSQL, ISavable savable, Object ...args) throws Exception {
+		ResultSet rslt = null;
+		PreparedStatement stmt = null;
+
+		String sql = namedSQL.getSQLString();
+		
+		if (sql != null) {
+			sql = sql.trim();
+			
+			if (conn == null) {
+				conn = activeConn.get();
+			}
+			boolean closeFlag = conn == null;
+			
+			if (!"".equals(sql)) {
+				try {
+					if (conn == null) {
+						conn = DataSourceManager.createConnection();
+					}
+					
+					if (conn != null) {
+						logger.debug(sql);
+						stmt = conn.prepareStatement(sql);
+						savable.saveData(stmt, args);
+					}
+					else{
+						throw new SQLException("can not get coinnection");
+					}
+				} 
+				catch (SQLException e) {
+					logger.error("getDataFromDB error:" + e.getMessage());
+					throw e;
+				} finally {
+					try {
+						if (rslt != null) {
+							rslt.close();
+						}
+					} catch (SQLException e) {
+					}
+					finally {
+						try {
+							if (stmt != null) {
+								stmt.close();
+							}
+						} catch (SQLException e) {
+						}
+						finally {
+							if (closeFlag && conn != null) {
+								conn.close();
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public static void saveData(Connection conn, NamedSQL namedSQL1, NamedSQL namedSQL2, IDoubleSavable savable, Object ...args) throws Exception {
+		PreparedStatement stmt1 = null, stmt2 = null;
+
+		String sql1 = namedSQL1.getSQLString();
+		String sql2 = namedSQL2.getSQLString();
+		
+		if (!Util.isEmptyStr(sql1) && !Util.isEmptyStr(sql2)) {
+			if (conn == null) {
+				conn = activeConn.get();
+			}
+			boolean closeFlag = conn == null;
+			
+			try {
+				if (conn == null) {
+					conn = DataSourceManager.createConnection();
+				}
+					
+				if (conn != null) {
+					logger.debug(sql1);
+					logger.debug(sql2);
+					
+					stmt1 = conn.prepareStatement(sql1);
+					stmt2 = conn.prepareStatement(sql2);
+					
+					savable.save(stmt1, stmt2, args);
+				}
+				else{
+					throw new SQLException("can not get coinnection");
+				}
+			} 
+			catch (SQLException e) {
+				logger.error("getDataFromDB error:" + e.getMessage());
+				throw e;
+			} finally {
+				try {
+					if (stmt1 != null) {
+						stmt1.close();
+					}
+				} catch (SQLException e) {
+				}
+				finally {
+					try {
+						if (stmt2 != null) {
+							stmt2.close();
+						}
+					} catch (SQLException e) {
+					}
+					finally {
+						if (closeFlag && conn != null) {
+							conn.close();
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public static void saveData(NamedSQL namedSQL, IStepSavable stepSavable, Object ...args) throws Exception {
+		saveData(null, namedSQL, stepSavable, args);
+	}
+	
+	public static void saveData(Connection conn, NamedSQL namedSQL, IStepSavable stepSavable, Object ...args) throws Exception {
+		PreparedStatement stmt = null;
+
+		String sql = namedSQL.getSQLString();
+		
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+		
+		if (sql != null) {
+			sql.trim();
+			
+			if (!"".equals(sql)) {
+				try {
+					if (conn == null) {
+						conn = DataSourceManager.createConnection();
+					}
+					
+					if (conn != null) {
+						while (stepSavable.hasNextForSave()) {
+							stmt = conn.prepareStatement(sql);
+							
+							try {
+								stepSavable.save(stmt, args);
+							}
+							finally {
+								if (stmt != null) {
+									stmt.close();
+								}
+							}
+						}
+					}
+					else{
+						throw new SQLException("can not get coinnection");
+					}
+				} 
+				catch (SQLException e) {
+					logger.debug(sql);
+					logger.error("getDataFromDB error:" + e.getMessage());
+					throw e;
+				} 
+				finally {
+					if (closeFlag && conn != null) {
+						conn.close();
+					}
+				}
+			}
+		}
+	}
+
+	public static EntitySet getEntitySet(NamedSQL namedSQL) throws Exception {
+		EntitySet result = null;
+		
+		EntitySetLoader entitySetLoader = new EntitySetLoader(namedSQL.getName(), null);
+		getData(namedSQL, entitySetLoader);
+		result = entitySetLoader.getDataSet();
+		
+		return result;
+	}
+	
+	public static EntitySet getEntitySet(NamedSQL namedSQL, EntityFactory entityFactory) throws Exception {
+		EntitySet result = null;
+		
+		EntitySetLoader entitySetLoader = new EntitySetLoader(namedSQL.getName(), entityFactory);
+		getData(namedSQL, entitySetLoader);
+		result = entitySetLoader.getDataSet();
+		
+		return result;
+	}
+	
+	public static <T> ObjectList<T> getList(NamedSQL namedSQL, Class<T> clazz) throws Exception {
+		ObjectList<T> result = null;
+		
+		ListLoader<T> listLoader = new ListLoader<T>(namedSQL.getName(), clazz);
+		getData(namedSQL, listLoader);
+		result = listLoader.getList();
+		
+		return result;
+	}	
+	
+	public static Entity getEntity(NamedSQL namedSQL) throws Exception {
+		Entity result = null;
+		
+		EntityLoader entityLoader = new EntityLoader(namedSQL.getName());
+		getData(namedSQL, entityLoader);
+		result = entityLoader.getEntity();
+		
+		return result;
+	}
+	
+	public static Object getObject(NamedSQL namedSQL, Class<?> clazz) throws Exception {
+		Object result = null;
+		
+		ObjectLoader objectLoader = new ObjectLoader(namedSQL.getName(), clazz);
+		getData(namedSQL, objectLoader);
+		result = objectLoader.getObject();
+		
+		return result;
+	}
+	public static Entity getEntity(NamedSQL namedSQL, EntityFactory entityFactory) throws Exception {
+		Entity result = null;
+
+		EntityLoader entityLoader = new EntityLoader(namedSQL.getName(), entityFactory);
+		getData(namedSQL, entityLoader);
+		result = entityLoader.getEntity();
+
+		return result;
+	}
+
+	public static String getString(NamedSQL namedSQL, int idx) throws Exception {
+		String result = null;
+		
+		ValueLoader valueLoader = new ValueLoader();
+		getData(namedSQL, valueLoader);
+		result = valueLoader.getString();
+		
+		return result;
+	}
+	
+	public static int getInteger(NamedSQL namedSQL) throws Exception {
+		int result = 0;
+		
+		ValueLoader valueLoader = new ValueLoader();
+		getData(namedSQL, valueLoader);
+		result = valueLoader.getInt();
+		
+		return result;
+	}
+	
+	public static BigDecimal getBigDecimal(NamedSQL namedSQL) throws Exception {
+		BigDecimal result = null;
+		
+		ValueLoader valueLoader = new ValueLoader();
+		getData(namedSQL, valueLoader);
+		result = valueLoader.getBigDecimal();
+		
+		return result;
+	}
+	
+	public static Date getDate(NamedSQL namedSQL) throws Exception {
+		Date result = null;
+		
+		ValueLoader valueLoader = new ValueLoader();
+		getData(namedSQL, valueLoader);
+		result = valueLoader.getDate();
+		
+		return result;
+	}
+	
+	public static Result getResult(NamedSQL namedSQL) throws Exception {
+		Result result = new Result();
+		ValueType returnType = namedSQL.getReturnType();
+		
+		if (ValueType.EntitySet == returnType) {
+			EntitySet value = getEntitySet(namedSQL);
+			result.setValue(value);
+		}
+		else if (ValueType.Entity == returnType) {
+			Entity value = getEntity(namedSQL);
+			result.setValue(value);
+		}
+		else if (ValueType.Int == returnType) {
+			int value = getInteger(namedSQL);
+			result.setValue(value);
+		}
+		else if (ValueType.String == returnType) {
+			String value = getString(namedSQL, 1);
+			result.setValue(value);
+		}
+		else if (ValueType.Decimal == returnType) {
+			BigDecimal value = getBigDecimal(namedSQL);
+			result.setValue(value);
+		}
+		else if (ValueType.Date == returnType) {
+			Date value = getDate(namedSQL);
+			result.setValue(value);
+		}		
+		else {
+			int value = execSQL(namedSQL);
+			result.setValue(value);
+		}
+		
+		return result;		
+	}
+
+	public static void getTableMetaData(IMetaDataLoader loader, String sql) throws SQLException {
+		getTableMetaData(null, loader, sql);
+	}
+	
+	public static void getTableMetaData(Connection conn, IMetaDataLoader loader, String sql) throws SQLException {
+		Statement stmt = null;
+		ResultSet rslt = null;
+		
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+		
+		try {
+			if (conn == null) {
+				conn = DataSourceManager.createConnection();
+			}
+
+			stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			
+			logger.debug(sql);
+			
+			rslt = stmt.executeQuery(sql);
+			ResultSetMetaData result = rslt.getMetaData();
+			loader.load(result);
+		} 
+		catch (Exception e) {
+			onError(sql, e);
+		} 
+		finally {
+			try {
+				if (rslt != null) {
+					rslt.close();					
+				}
+			} 
+			catch (SQLException e) {
+			} 
+			finally {
+				try {
+					if (stmt != null) {
+						stmt.close();						
+					}
+				} 
+				catch (SQLException e) {
+				} 
+				finally {
+					if (closeFlag && conn != null) {
+						conn.close();
+					}
+				}
+			}
+		}
+	}
+	
+	public static boolean isTableExists(String tableName, boolean cache) throws Exception {
+		if (tableName == null) {
+			return false;
+		}
+		
+		if (tableSet.contains(tableName.toLowerCase())) {
+			return true;
+		}
+		
+		boolean result = isTableExists(null, tableName);
+		
+		if (result) {
+			tableSet.add(tableName.toLowerCase());
+		}
+		
+		return result;
+	}
+	
+	public static boolean isTableExists(Connection conn, String tableName) throws Exception {
+		String sql = null;
+		Statement stmt = null;
+		ResultSet rslt = null;
+		
+		if (conn == null) {
+			conn = activeConn.get();
+		}
+		boolean closeFlag = conn == null;
+		
+		try {
+			if (conn == null) {
+				conn = DataSourceManager.createConnection();
+			}
+
+			stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+			sql = "select 1 from user_tables where table_name ='" + tableName.toUpperCase() + "'";
+			rslt = stmt.executeQuery(sql);
+			
+			if (rslt.next()) {
+				return true;
+			}
+			
+			return false;
+		} 
+		catch (Exception e) {
+			onError(sql, e);
+			throw e;
+		} 
+		finally {
+			try {
+				if (rslt != null) {
+					rslt.close();					
+				}
+			} 
+			catch (SQLException e) {
+			} 
+			finally {
+				try {
+					if (stmt != null) {
+						stmt.close();						
+					}
+				} 
+				catch (SQLException e) {
+				} 
+				finally {
+					if (closeFlag && conn != null) {
+						conn.close();
+					}
+				}
+			}
+		}
+	}
+	
+	protected static void onError(String sql, Exception e) {
+		logger.error("executor exec error: " + e.getMessage());
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/SQLVariant.java b/IMserver/medeasy/src/frame/persist/SQLVariant.java
new file mode 100644
index 0000000..a6be5db
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/SQLVariant.java
@@ -0,0 +1,29 @@
+package frame.persist;
+
+import frame.variant.expression.VariantSegment;
+
+
+public class SQLVariant extends VariantSegment {
+
+	public SQLVariant(String name) {
+		super(name);
+	}
+
+	@Override
+	public SQLVariant newInstance() {
+		SQLVariant result = new SQLVariant(name);
+		
+		if (NamedSQL.Param_Filter.equalsIgnoreCase(name)) {
+			result.value = " 1 = 1 ";
+		}
+		else if (NamedSQL.Param_OrderBy.equalsIgnoreCase(name)) {
+			result.value = "";
+		}
+		else if (NamedSQL.Param_Limit.equalsIgnoreCase(name)) {
+			result.value = "";
+		}
+		
+		return result;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/Scenario.java b/IMserver/medeasy/src/frame/persist/Scenario.java
new file mode 100644
index 0000000..1a0ce06
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/Scenario.java
@@ -0,0 +1,33 @@
+package frame.persist;
+
+import javax.sql.DataSource;
+
+public class Scenario {
+
+	private String code;
+	private DataSource dataSource;
+	
+	
+	public Scenario(String code) {
+		this.code = code;
+		
+	}
+
+	public void setDataSource(DataSource dataSource) {
+		this.dataSource = dataSource; 
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public DataSource getDataSource() {
+		return dataSource;
+	}
+
+	@Override
+	public String toString() {
+		return "datasource--" + code;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/DataLoader.java b/IMserver/medeasy/src/frame/persist/loader/DataLoader.java
new file mode 100644
index 0000000..25c8aef
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/DataLoader.java
@@ -0,0 +1,44 @@
+package frame.persist.loader;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+import frame.object.meta.EntityMeta;
+import frame.persist.ILoadable;
+
+
+public abstract class DataLoader implements ILoadable {
+
+	protected String tableName;
+	protected EntityMeta entityMeta;
+	
+	
+	protected DataLoader() {
+		
+	}
+	
+	public DataLoader(String tableName) {
+		this.tableName = tableName;
+	}
+
+	public void load(ResultSet rslt, Object... args) throws Exception {
+		ResultSetMetaData metaData = rslt.getMetaData();
+		loadTableMeta(metaData);
+		
+		loadData(rslt);
+	}
+
+	private void loadTableMeta(ResultSetMetaData metaData) throws SQLException {
+		if (entityMeta == null) {
+			ResultMetaFieldReader fieldReader = new ResultMetaFieldReader(metaData);
+			entityMeta = new EntityMeta(tableName, fieldReader);
+		}
+	}
+
+	protected abstract void loadData(ResultSet rslt) throws Exception;
+
+	public void setTableMeta(EntityMeta entityMeta) {
+		this.entityMeta = entityMeta;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/EntityLoader.java b/IMserver/medeasy/src/frame/persist/loader/EntityLoader.java
new file mode 100644
index 0000000..257b017
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/EntityLoader.java
@@ -0,0 +1,53 @@
+package frame.persist.loader;
+
+import frame.object.data.Entity;
+import frame.object.data.EntityFactory;
+
+import java.sql.ResultSet;
+
+public class EntityLoader extends DataLoader {
+
+	private Entity entity;
+	private EntityFactory entityFactory;
+
+	public EntityLoader(String tableName) {
+		super(tableName);
+	}
+
+	public EntityLoader(String tableName, EntityFactory entityFactory) {
+		super(tableName);
+		this.entityFactory = entityFactory;
+	}
+
+	public EntityLoader(Entity entity) {
+		this.entity = entity;
+		
+		this.tableName = entity.getTableName();
+		this.entityMeta = entity.getEntityMeta();
+	}
+
+	@Override
+	protected void loadData(ResultSet rslt) throws Exception {
+		if (rslt.next()) {
+			if (entityFactory != null) {
+				entityFactory.setEntityMeta(entityMeta);
+				entity = entityFactory.createEntity(rslt);
+			}
+
+			entity = new Entity(entityMeta);
+			int cnt = entity.getFieldCount();
+			
+			Object obj;
+			
+			for (int i = 0; i < cnt; i++) {
+				obj = rslt.getObject(i + 1);
+				entity.set(i, obj);
+			}
+		}		
+	}
+
+	public Entity getEntity() {
+		return entity;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/EntitySetLoader.java b/IMserver/medeasy/src/frame/persist/loader/EntitySetLoader.java
new file mode 100644
index 0000000..63480f1
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/EntitySetLoader.java
@@ -0,0 +1,58 @@
+package frame.persist.loader;
+
+import java.sql.ResultSet;
+
+import frame.object.data.Entity;
+import frame.object.data.EntityFactory;
+import frame.object.data.EntitySet;
+
+public class EntitySetLoader extends DataLoader {
+
+	private EntitySet entitySet;
+	private EntityFactory entityFactory;
+	
+	public EntitySetLoader(String tableName, EntityFactory entityFactory) {
+		super(tableName);
+		this.entityFactory = entityFactory;
+	}
+
+	public EntitySetLoader(EntitySet entitySet) {
+		this.entitySet = entitySet;
+		
+		this.tableName = entitySet.getTableName();
+		this.entityMeta = entitySet.getEntityMeta();
+	}
+
+	protected void loadData(ResultSet rslt) throws Exception {
+		entitySet = new EntitySet(entityMeta);
+		int cnt = entitySet.getFieldCount();
+		
+		if (entityFactory != null) {
+			entityFactory.setEntityMeta(entityMeta);
+		}
+		
+		Entity entity;
+		Object obj;
+		
+		while (rslt.next()) {
+			if (entityFactory == null) {
+				entity = new Entity(entityMeta);
+			}
+			else {
+				entity = entityFactory.createEntity(rslt);
+			}
+			
+			entitySet.append(entity);
+			
+			for (int i = 0; i < cnt; i++) {
+				obj = rslt.getObject(i + 1);
+				entity.set(i, obj);
+			}
+		}
+	}
+
+	public EntitySet getDataSet() {
+		return entitySet;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/ListLoader.java b/IMserver/medeasy/src/frame/persist/loader/ListLoader.java
new file mode 100644
index 0000000..37a63bd
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/ListLoader.java
@@ -0,0 +1,63 @@
+package frame.persist.loader;
+
+import frame.object.data.ObjectList;
+import frame.object.meta.Field;
+import frame.object.reader.EntityReaderContainer;
+import frame.object.reader.ObjectReader;
+
+import java.sql.ResultSet;
+import java.util.List;
+
+public class ListLoader<T> extends DataLoader {
+
+	protected static EntityReaderContainer objectReaderContainer;
+	private Class<T> clazz;
+	private ObjectReader objectReader;
+	private ObjectList<T> list;
+	
+	static {
+		objectReaderContainer = EntityReaderContainer.getInstance();
+	}
+
+	public ListLoader(String tableName, Class<T> clazz) throws Exception {
+		super(tableName);
+		
+		this.clazz = clazz;
+		objectReader = objectReaderContainer.getObjectReader(clazz);
+	}
+	
+	@Override 
+	protected void loadData(ResultSet rslt) throws Exception {
+		list = new ObjectList<T>();
+
+		List<Field> fields = entityMeta.getFields();
+		T object; int size = fields.size(); String name;
+		int idx_id = entityMeta.getIndex("id");
+
+		while (rslt.next()) {
+			object = clazz.newInstance();
+			String id = null;
+
+			for (int i = 0; i < size; i++) {
+				Field field = fields.get(i);
+				name = field.getName();
+
+				if (i == idx_id) {
+					id = rslt.getString(i + 1);
+				}
+
+				if (objectReader.containsProperty(name)) {
+					Object value = rslt.getObject(i + 1);
+					objectReader.setData(name, value, object);
+				}
+			}
+
+			list.add(id, object);
+		}
+	}
+
+	public ObjectList<T> getList() {
+		return list;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/ObjectLoader.java b/IMserver/medeasy/src/frame/persist/loader/ObjectLoader.java
new file mode 100644
index 0000000..a786fb0
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/ObjectLoader.java
@@ -0,0 +1,58 @@
+package frame.persist.loader;
+
+import java.sql.ResultSet;
+import java.util.List;
+
+import frame.object.meta.Field;
+import frame.object.reader.EntityReaderContainer;
+import frame.object.reader.ObjectReader;
+
+public class ObjectLoader extends DataLoader {
+
+	protected static EntityReaderContainer objectReaderContainer;
+	private Class<?> clazz;
+	private ObjectReader objectReader;
+	private Object object;
+	
+	static {
+		objectReaderContainer = EntityReaderContainer.getInstance();
+	}
+
+	public ObjectLoader(String tableName, Class<?> clazz) throws Exception {
+		super(tableName);
+		
+		this.clazz = clazz;
+		objectReader = objectReaderContainer.getObjectReader(clazz);
+	}
+	
+	@Override
+	protected void loadData(ResultSet rslt) throws Exception {
+		if (rslt.next()) {
+			if (object == null) {
+				object = clazz.newInstance();
+			}
+			
+			List<Field> fields = entityMeta.getFields();
+			int size = fields.size(); String name;
+			
+			for (int i = 0; i < size; i++) {
+				Field field = fields.get(i);
+				name = field.getName();
+				
+				if (objectReader.containsProperty(name)) {
+					Object value = rslt.getObject(i + 1);
+					objectReader.setData(name, value, object);
+				}
+			}
+		}
+	}
+	
+	public Object getObject() {
+		return object;
+	}
+
+	public void setObject(Object object) {
+		this.object = object;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/ResultMetaFieldReader.java b/IMserver/medeasy/src/frame/persist/loader/ResultMetaFieldReader.java
new file mode 100644
index 0000000..b90d286
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/ResultMetaFieldReader.java
@@ -0,0 +1,50 @@
+package frame.persist.loader;
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+import frame.object.meta.IFieldReader;
+
+public class ResultMetaFieldReader implements IFieldReader {
+	
+	private ResultSetMetaData resultMeta;
+	private int pos;
+	
+	
+	public ResultMetaFieldReader(ResultSetMetaData resultMeta) {
+		this.resultMeta = resultMeta;
+		pos = 0;
+	}
+
+	public String getFieldName() throws SQLException {
+		return resultMeta.getColumnName(pos);
+	}
+
+	public int getFieldType() throws SQLException {
+		int value = resultMeta.getColumnType(pos);
+		return value;
+	}
+
+	public int getFieldLength() throws SQLException {
+		return resultMeta.getColumnDisplaySize(pos);
+	}
+
+	public int getNullable() throws SQLException {
+		return resultMeta.isNullable(pos);
+	}
+
+	public boolean next() throws SQLException {
+		if (pos < resultMeta.getColumnCount()) {
+			pos++;
+			return true;
+		}
+
+		return false;
+	}
+
+	@Override
+	public void first() {
+		pos = 0;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/ResultSetFieldReader.java b/IMserver/medeasy/src/frame/persist/loader/ResultSetFieldReader.java
new file mode 100644
index 0000000..c43ac77
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/ResultSetFieldReader.java
@@ -0,0 +1,47 @@
+package frame.persist.loader;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import frame.object.meta.IFieldReader;
+
+public class ResultSetFieldReader implements IFieldReader {
+
+	private ResultSet resultSet;
+	
+	
+	public ResultSetFieldReader(ResultSet resultSet) {
+		this.resultSet = resultSet;
+	}
+
+	public boolean next() throws SQLException {
+		return resultSet.next();
+	}
+	
+	public String getFieldName() throws SQLException {
+		return resultSet.getString(4);
+	}
+	
+	public int getFieldType() throws SQLException {
+		int value = resultSet.getInt(5);
+		return value;
+	}
+
+	public int getFieldLength() throws SQLException {
+		return resultSet.getInt(7);
+	}
+
+	public int getNullable() throws SQLException {
+		return resultSet.getInt(11);
+	}
+
+	@Override
+	public void first() {
+		try {
+			resultSet.first();
+		}
+		catch (Exception e) {
+		}
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/persist/loader/ValueLoader.java b/IMserver/medeasy/src/frame/persist/loader/ValueLoader.java
new file mode 100644
index 0000000..f521a8d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/persist/loader/ValueLoader.java
@@ -0,0 +1,50 @@
+package frame.persist.loader;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.util.Date;
+
+import frame.persist.ILoadable;
+import frame.variant.translator.Translator;
+
+
+public class ValueLoader implements ILoadable {
+
+	private Object object;
+	
+	public ValueLoader() {
+		
+	}
+
+	@Override
+	public void load(ResultSet rslt, Object... args) throws Exception {
+		if (rslt.next()) {
+			object = rslt.getObject(1);
+		}		
+	}
+	
+	public int getInt() throws Exception {
+		if (object == null) {
+			return 0;
+		}
+		
+		return Translator.toInteger(object, 0);
+	}
+	
+	public String getString() throws Exception {
+		return Translator.toString(object);
+	}
+
+	public BigDecimal getBigDecimal() throws Exception {
+		return Translator.toBigDecimal(object);
+	}
+	
+	public Date getDate() throws Exception {
+		return Translator.toDate(object);
+	}
+
+	public Object getObject() {
+		return object;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/util/ContentBuilder.java b/IMserver/medeasy/src/frame/util/ContentBuilder.java
new file mode 100644
index 0000000..4097146
--- /dev/null
+++ b/IMserver/medeasy/src/frame/util/ContentBuilder.java
@@ -0,0 +1,83 @@
+package frame.util;
+
+public class ContentBuilder {
+
+	protected StringBuilder content;
+	protected boolean empty;
+	protected String division;
+	
+	
+	public ContentBuilder() {
+		empty = true;
+		content = new StringBuilder();
+	}
+	
+	public ContentBuilder(String division) {
+		this.empty = true;
+		this.division = division;
+		this.content = new StringBuilder();
+	}
+	
+	public ContentBuilder append(Object data) {
+		if (data == null) {
+			return this;
+		}
+		
+		return append(data.toString());
+	}
+	
+	public ContentBuilder append(String data) {
+		if (division != null) {
+			if (empty) {
+				empty = false;
+			}
+			else {
+				content.append(division);
+			}			
+		}
+		
+		content.append(data);
+		return this;
+	}
+	
+	public ContentBuilder append(Object data, String division) {
+		if (data == null) {
+			return this;
+		}
+		
+		return append(data.toString(), division);
+	}
+	
+	public ContentBuilder append(String data, String division) {
+		if (empty) {
+			empty = false;
+		}
+		else {
+			content.append(division);
+		}
+		
+		content.append(data);
+		return this;
+	}
+	
+	public ContentBuilder append(char[] data) {
+		return append(data, 0, data.length);
+	}
+	
+	public ContentBuilder append(char[] data, int begin, int length) {
+		content.append(data, begin, length);
+		return this;
+	}
+	
+	public String toString() {
+		return content.toString();
+	}
+	
+	public boolean isEmpty() {
+		return empty;
+	}
+	
+	public void setEmpty(boolean empty) {
+		this.empty = empty;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/util/GUID.java b/IMserver/medeasy/src/frame/util/GUID.java
new file mode 100644
index 0000000..0c27fca
--- /dev/null
+++ b/IMserver/medeasy/src/frame/util/GUID.java
@@ -0,0 +1,18 @@
+package frame.util;
+
+import java.util.UUID;
+
+public class GUID {
+
+	public static String getShort() {
+		UUID uuid = UUID.randomUUID();
+		String value;
+		String result;
+
+		value = uuid.toString();
+		result = value.substring(0, 8) + value.substring(9, 13) + value.substring(14, 18) + value.substring(19, 23)
+				+ value.substring(24, 36);
+		
+		return result;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/util/MapList.java b/IMserver/medeasy/src/frame/util/MapList.java
new file mode 100644
index 0000000..9e8ff3e
--- /dev/null
+++ b/IMserver/medeasy/src/frame/util/MapList.java
@@ -0,0 +1,178 @@
+package frame.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public class MapList<T> implements Iterable<T> {
+
+	protected List<T> itemList;
+	protected Map<String, T> itemMap;
+	protected Map<String, Integer> indexMap;
+	
+	
+	public MapList() {
+		itemList = new ArrayList<T>();
+		itemMap = new HashMap<String, T>();
+	}
+	
+	public void addAll(Map<String, T> map) {
+		Set<String> keys = map.keySet();
+		
+		for (String key: keys) {
+			add(key, map.get(key));
+		}
+	}
+	
+	public void add(String key, T item) {
+		if (key == null) {
+			return;
+		}
+		
+		key = key.toLowerCase();
+		itemMap.put(key, item);
+		itemList.add(item);
+	}
+
+	public void set(String key, T item) {
+		if (key == null) {
+			return;
+		}
+		
+		if (indexMap == null) {
+			indexMap = new HashMap<String, Integer>();
+		}
+		
+		key = key.toLowerCase();
+		
+		if (!itemMap.containsKey(key)) {
+			itemMap.put(key, item);
+			indexMap.put(key, itemList.size());
+			itemList.add(item);
+		}
+		else {
+			Integer idx = indexMap.get(key);
+			itemList.set(idx, item);
+		}
+	}
+	
+	public T get(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		key = key.toLowerCase();
+		return itemMap.get(key);
+	}
+	
+	public T get(int idx) {
+		return itemList.get(idx);
+	}
+	
+	public T remove(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		T obj = itemMap.get(key.toLowerCase());
+		
+		if (obj != null) {
+			itemMap.remove(key);
+			itemList.remove(obj);
+		}
+		
+		return obj;
+	}
+	
+	public List<T> getItemList() {
+		return itemList;
+	}
+	
+	public Set<String> getKeySet() {
+		return itemMap.keySet();
+	}	
+
+	public boolean isEmpty() {
+		return itemList.isEmpty();
+	}
+	
+	public int size() {
+		return itemList.size();
+	}
+	
+	public int mapSize() {
+		return itemMap.size();
+	}
+	
+	public Iterator<T> iterator() {
+		return itemList.iterator();
+	}
+
+	public void clear() {
+		itemList.clear();
+		itemMap.clear();
+	}
+	
+	public String toString(String separator) {
+		ContentBuilder builder = new ContentBuilder(separator);
+		
+		for (String key: itemMap.keySet()) {
+			builder.append(key);
+		}
+		
+		return builder.toString();
+	}
+	
+	public Set<String> keySet() {
+		return itemMap.keySet();
+	}
+
+	public boolean equals(MapList<T> another) {
+		if (another == null) {
+			return false;
+		}
+		
+		if (this == another) {
+			return true;
+		}
+		
+		Set<String> keys = itemMap.keySet();
+		for (String key: keys) {
+			if (!another.contains(key)) {
+				return false;
+			}
+		}
+		
+		Set<String> anotherKeys = another.itemMap.keySet();
+		for (String anotherKey: anotherKeys) {
+			if (!contains(anotherKey)) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+
+	public boolean contains(String key) {
+		if (key == null) {
+			return false;
+		}
+		
+		key = key.toLowerCase();
+		return itemMap.containsKey(key);
+	}
+
+	public Object[] toArray() {
+		return itemList.toArray();
+	}
+
+	@SuppressWarnings("hiding")
+	public <T> T[] toArray(T[] a) {
+		return itemList.toArray(a);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/util/MapTree.java b/IMserver/medeasy/src/frame/util/MapTree.java
new file mode 100644
index 0000000..c1bca8c
--- /dev/null
+++ b/IMserver/medeasy/src/frame/util/MapTree.java
@@ -0,0 +1,105 @@
+package frame.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.log4j.Logger;
+
+public class MapTree<T> implements Iterable<T> {
+
+	protected static Logger logger;
+	protected TreeSet<T> itemList;
+	protected Map<String, T> itemMap;
+	
+	static {
+		logger = Logger.getLogger(MapTree.class);
+	}
+	
+	public MapTree() {
+		itemList = new TreeSet<T>();
+		itemMap = new HashMap<String, T>();
+	}
+	
+	public void add(String key, T item) {
+		if (key == null) {
+			key = "empty";
+		}
+		key = key.toLowerCase();
+		
+		if (itemMap.containsKey(key)) {
+			logger.error("duplicate " + this.getClass().getName() +  " key: " + key);
+			return;
+		}
+		
+		itemMap.put(key, item);
+		itemList.add(item);
+	}
+	
+	public T get(String key) {
+		if (key == null) {
+			key = "empty";
+		}
+		key = key.toLowerCase();
+		
+		return itemMap.get(key);
+	}
+	
+	public T remove(String key) {
+		if (key == null) {
+			return null;
+		}
+		
+		T obj = itemMap.get(key.toLowerCase());
+		
+		if (obj != null) {
+			itemMap.remove(key);
+			itemList.remove(obj);
+		}
+		
+		return obj;
+	}
+	
+	public TreeSet<T> getItemList() {
+		return itemList;
+	}
+
+	public boolean isEmpty() {
+		return itemList.isEmpty();
+	}
+	
+	public int size() {
+		return itemList.size();
+	}
+	
+	public boolean containsKey(String key) {
+		if (key == null) {
+			return false;
+		}
+		
+		key = key.toLowerCase();
+		return itemMap.containsKey(key);
+	}
+
+	@Override
+	public Iterator<T> iterator() {
+		return itemList.iterator();
+	}
+
+	public void clear() {
+		itemList.clear();
+		itemMap.clear();
+	}
+	
+	public String toString(String separator) {
+		ContentBuilder builder = new ContentBuilder(separator);
+		
+		for (String key: itemMap.keySet()) {
+			builder.append(key);
+		}
+		
+		return builder.toString();
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/util/Util.java b/IMserver/medeasy/src/frame/util/Util.java
new file mode 100644
index 0000000..f8908d7
--- /dev/null
+++ b/IMserver/medeasy/src/frame/util/Util.java
@@ -0,0 +1,666 @@
+package frame.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import frame.persist.DataBaseType;
+
+public class Util {
+
+	public static final String TRUE = "T";
+	public static final String FALSE = "F";
+	public static final String String_Return = "\r\n";
+	public static final String String_Escape_newSpace = "\t";
+	public static final String String_Escape_newLine = "\n";
+	public static final String String_Empty = "";
+	public static final String Sql_Empty = "''";
+	public static final String Default_Patter = "(?<=@\\{)(.+?)(?=\\})";
+	public static final String Integer_Patter = "^-?[1-9]\\d*$";
+	public static final String Double_Patter = "^-?([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*|0?\\.0+|0)$";
+	public static final String Separator = "-";
+	public static final String SubSeparator = "_";
+	public static final String comma = " , ";
+	public static final String with = "&";
+	public static final String dollar = "$";
+	public static final String Star = "*";
+	public static final String RMB = "锟�";
+	public static final String ait = "@";
+	public static final String semicolon = ";";
+	public static final String defaultFilter = " 1 = 1 ";
+	public static final String Dot = ".";
+	public static final String Spilt_Dot = "[.]";
+	public static final String Spilt_Line = "\\|";
+	public static final String Spilt_Star = "\\*";
+	public static final String Spilt_Slash = "\\\\";
+	public static final String Spilt_Brackets = "\\[\\]";
+	public static final String Equal = "=";
+	public static final String And = " and ";
+	public static final String Or = " or ";
+	public static final String Standrad_And = "and";
+	public static final String Standrad_Or = "or";
+	public static final String Percentage = "%";
+	public static String like = " like ";
+	public static String Standrad_like = "like";
+	public static String unEqual = " <> ";
+	public static String Standrad_unEqual = "<>";
+	public static final String String_Space = " ";
+	public static final String windows_slash = "/";
+	public static final String java_slash = "\\";
+	public static final String sql_slash = "\\\\";
+
+    public static String newShortGUID() {
+		UUID uuid = UUID.randomUUID();
+		String strGUID;
+		String shortGUID;
+
+		strGUID = uuid.toString();
+		shortGUID = strGUID.substring(0, 8) + strGUID.substring(9, 13) + strGUID.substring(14, 18) + strGUID.substring(19, 23)
+				+ strGUID.substring(24, 36);
+
+		return shortGUID;
+	}
+
+	public static String quotedStr(String str) {
+		if (str != null)
+			return "'" + str + "'";
+		else
+			return "''";
+	}
+	public static String quotedEqualStr(String key, String value) {
+		if (!Util.isEmptyStr(key) && !Util.isEmptyStr(value))
+			return key + String_Space + Equal + String_Space + Util.quotedStr(value);
+		else
+			return null;
+	}
+
+	public static String doubleQuotedStr(String str) {
+		if (str != null)
+			return "\"" + str + "\"";
+		else
+			return "\"\"";
+	}
+
+	public static String quotedLikeStr(String str) {
+		if (str != null)
+			return "'%" + str + "%'";
+		else
+			return "''";
+	}
+
+	public static String bracketStr(String str) {
+		if (str != null)
+			return "(" + str + ")";
+		else
+			return "()";
+	}
+
+	public static String stringJoin(String... strings) {
+		StringBuilder stringBuilder = new StringBuilder();
+		for (String s: strings) {
+			stringBuilder.append(s);
+		}
+		return  stringBuilder.toString();
+	}
+	public static String stringJoin(Object... strings) {
+		StringBuilder stringBuilder = new StringBuilder();
+		for (Object s: strings) {
+			stringBuilder.append(s.toString());
+		}
+		return  stringBuilder.toString();
+	}
+
+	public static String[] split(String str) {
+		if (str == null) {
+			return new String[0];
+		}
+		
+		return str.replace(",", ";").replace("锛�", ";").replace("锛�", ";").split(";");
+	}
+
+	public static String newDBDateString() throws Exception {
+		Date date = new Date();
+		return newDBDateString(date);
+	}
+
+	public static String newDBDateString(Date date) throws Exception {
+		DataBaseType dbType = DataBaseType.MySQL;
+
+		if (DataBaseType.Oracle == dbType) {
+			return newOracleDateString(date);
+		}
+		else if (DataBaseType.SQLServer == dbType) {
+			return newSqlServerDateString(date);
+		}
+		else if (DataBaseType.MySQL == dbType) {
+			return newMySqlDateString(date);
+		}
+		else {
+			return DataTimeToString(date);
+		}
+	}
+
+	public static String toOracleDataStr(String dataStr) {
+		return "to_date('" + dataStr + "','YYYY-MM-DD HH24:MI:SS')";
+	}
+
+	public static String toMySQLDateStr(Date value) {
+		return DataTimeToString(value, "yyyy-MM-dd HH:mm:ss");
+	}
+
+	public static String DataTimeToString(Date value) {
+		return DataTimeToString(value, "yyyy-MM-dd HH:mm:ss");
+	}
+
+	public static String DataTimeToString(Date value, String format) {
+		if (value == null) {
+			return null;
+		}
+
+		String result = "";
+		DateFormat dateFormat = new SimpleDateFormat(format);
+		result = dateFormat.format(value);
+
+		return result;
+	}
+
+	public static String newDateStr() {
+		return newDateTimeStr("yyyy-MM-dd");
+	}
+
+	public static String newDateTimeStr() {
+		return newDateTimeStr("yyyy-MM-dd kk:mm:ss");
+	}
+
+	public static String newDateTimeStr(String fomater) {
+		return getDateTimeStr(new Date(), fomater);
+	}
+
+	public static String getDateTimeStr(Date date, String fomater) {
+		String result = "";
+		DateFormat dateFormat = new SimpleDateFormat(fomater);
+		result = dateFormat.format(date);
+
+		return result;
+	}
+
+	public static String booleanToStr(boolean value) {
+		if (value)
+			return "T";
+		else
+			return "F";
+	}
+
+	public static boolean isEmptyStr(Object str) {
+		boolean result = false;
+
+		if ((str == null) || ("".equals(str)))
+			result = true;
+
+		return result;
+	}
+	
+	public static String IfEmpetyStr(String str, String value) {
+		if (isEmptyStr(str)) {
+			return value;
+		}
+		
+		return str;
+	}
+
+	public static boolean isNull(Object object) {
+		if ((object == null))
+			return true;
+		if (object instanceof String) {
+			return isNull((String)object);
+		}
+
+		return false;
+	}
+
+	public static boolean isNull(String value) {
+		if ((value == null))
+			return true;
+
+		if ("".equals(value)) {
+			return true;
+		}
+
+		if (value.length() == 4) {
+			value = value.toLowerCase();
+			return "null".equals(value);
+		}
+
+		return false;
+	}
+
+	public static String UTF8decode(String str) {
+		if (!isUTF8Encoding(str))
+			return str;
+		byte[] bytes = str.getBytes();
+		ByteBuffer bb = ByteBuffer.wrap(bytes);
+		Charset csets = Charset.forName("UTF-8");
+		CharBuffer c = csets.decode(bb);
+		return c.toString();
+	}
+
+	private static boolean isUTF8Encoding(String str) {
+		byte[] bytes = str.getBytes();
+		for (int i = 0; i < bytes.length; i++) {
+			int byteLen = Byte.toString(bytes[i]).length();
+			if (byteLen == 4)
+				return true;
+			else
+				continue;
+		}
+		return false;
+	}
+
+	public static boolean StringToBoolean(String value) {
+		if (value != null) {
+			value = value.toLowerCase();
+
+			if (value.equals("t")) {
+				return true;
+			}
+			else if (value.equals("y")) {
+				return true;
+			}
+			else if (value.equals("true")) {
+				return true;
+			}
+			else if (value.equals("yes")) {
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+		else
+			return false;
+	}
+
+	public static int StringToInt(String value, int defaultValue) {
+		if (value != null) {
+			try {
+				Double doubleValue = Double.valueOf(value);
+				return doubleValue.intValue();
+			}
+			catch (Exception e) {
+				return defaultValue;
+			}
+		}
+		else
+			return defaultValue;
+	}
+
+	public static BigDecimal StringToBigDecimal(String value, BigDecimal defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+
+		try {
+			BigDecimal decimalValue = BigDecimal.valueOf(Double.valueOf(value));
+			return decimalValue;
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	public static Date StringToDate(String str) throws ParseException {
+		if (Util.isEmptyStr(str)) {
+			return null;
+		}
+
+		Date result = null;
+		String fomater = null;
+		str = str.replace('T', ' ');
+
+		if (str.indexOf("/") == 4) {
+			fomater = "yyyy/MM/dd";
+		}
+		else if (str.indexOf("/") == 2 || str.indexOf("/") == 1) {
+			fomater = "MM/dd/yyyy";
+		}
+		else if (str.indexOf("-") == 2 || str.indexOf("-") == 1) {
+			fomater = "MM-dd-yyyy";
+		}
+		else if (str.indexOf("-") == 4 && str.indexOf(":") < 0) {
+			fomater = "yyyy-MM-dd";
+		}
+		else if (str.indexOf("-") == 4 && str.indexOf(":") > 0) {
+			if (str.split(":").length == 3) {
+				fomater = "yyyy-MM-dd HH:mm:ss";
+			}
+			else {
+				str = str + ":00";
+				fomater = "yyyy-MM-dd HH:mm:00";
+			}
+
+		}
+		else if (str.indexOf(".") == 2 || str.indexOf(".") == 1) {
+			fomater = "MM.dd.yyyy";
+		}
+		else if (str.indexOf(".") == 4) {
+			fomater = "yyyy.MM.dd";
+		}
+		else if (str.indexOf("-") < 0 && str.indexOf("/") < 0) {
+			fomater = "yyyyMMdd";
+		}
+
+		DateFormat dateFormat = new SimpleDateFormat(fomater);
+		result = dateFormat.parse(str);
+
+		return result;
+	}
+
+	public static Date doubleToDate(Double value) throws ParseException {
+		Date result = null;
+
+		if (value != null) {
+			if (value > 195000 && value <= 210001) {
+				value = value * 100 + 01;
+			}
+
+			if (value >= 19500101 && value <= 21000101) {
+				String value_Str = String.valueOf(value.intValue());
+				result = Util.StringToDate(value_Str);
+			}
+			else if (value > (1950 - 1900) * 365 && value < (2100 - 1900) * 365) {
+				int dateValue = value.intValue();
+				double secValue = value - dateValue;
+				Date dayDate = intToDate(dateValue);
+				long sec = Math.round(secValue * 24 * 3600 * 1000);
+
+				result = new Date();
+				result.setTime(dayDate.getTime() + sec);
+				return result;
+			}
+		}
+
+		return result;
+	}
+
+	public static Date intToDate(int value) {
+		Calendar result = Calendar.getInstance();
+		result.set(Calendar.YEAR, 1900);
+		result.set(Calendar.MONTH, 0);
+		result.set(Calendar.DAY_OF_MONTH, 1);
+		result.set(Calendar.HOUR_OF_DAY, 0);
+		result.set(Calendar.MINUTE, 0);
+		result.set(Calendar.SECOND, 0);
+
+		result.add(Calendar.DATE, value - 2);
+		return result.getTime();
+	}
+
+	public static int getArrayContentSize(Object[] datas) {
+		int result = 0;
+
+		for (int i = 0; i < datas.length; i++) {
+			if (datas[i] != null) {
+				result++;
+			}
+		}
+
+		return result;
+	}
+
+	public static String deleteSuffix(String name) {
+		String result = null;
+
+		if (!isEmptyStr(name)) {
+			int pos = name.lastIndexOf(".");
+			result = name.substring(0, pos);
+		}
+
+		return result;
+	}
+
+	public static String[] mergeArray(String[] array1, String[] array2) {
+		if (array1 == null) {
+			return array2;
+		}
+
+		if (array2 == null) {
+			return array2;
+		}
+
+		List<String> set = new ArrayList<String>(array1.length + array2.length);
+
+		for (int i = 0; i < array1.length; i++) {
+			set.add(array1[i]);
+		}
+
+		for (int i = 0; i < array2.length; i++) {
+			if (!set.contains(array2[i])) {
+				set.add(array2[i]);
+			}
+		}
+
+		String[] result = new String[0];
+		return set.toArray(result);
+	}
+
+	public static String newOracleDateString(Date date) {
+		String nowStr = "";
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		nowStr = dateFormat.format(date);
+
+		return "to_date('" + nowStr + "','YYYY-MM-DD HH24:MI:SS')";
+	}
+
+	public static String newMySqlDateString(Date date) {
+		String nowStr = "";
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		nowStr = dateFormat.format(date);
+
+		return "('" + nowStr + "')";
+	}
+
+	public static String newSqlServerDateString(Date date) {
+		String nowStr = "";
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		nowStr = dateFormat.format(date);
+
+		return "('" + nowStr + "')";
+	}
+
+	public static boolean isSameString(String value1, String value2) {
+		if (value1 == null) {
+			if (value2 == null) {
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+		else {
+			if (value2 == null) {
+				return false;
+			}
+			else {
+				return value1.equals(value2);
+			}
+		}
+	}
+
+	public static boolean isSameStringIgnoreCase(String value1, String value2) {
+		if (value1 == null) {
+			if (value2 == null) {
+				return true;
+			}
+			else {
+				return false;
+			}
+		}
+		else {
+			if (value2 == null) {
+				return false;
+			}
+			else {
+				return value1.equalsIgnoreCase(value2);
+			}
+		}
+	}
+
+	public static String toLowerCase(String name, String defaultValue) {
+		if (name == null) {
+			return defaultValue;
+		}
+		else {
+			return name.toLowerCase();
+		}
+	}
+
+	public static String getExceptionStack(Exception e) {
+		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+		PrintStream printStream = new PrintStream(outStream);
+		e.printStackTrace(printStream);
+
+		return outStream.toString();
+	}
+
+	public static Date getSpecialDayOffToday(int dayCount) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(new Date());
+		calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + dayCount);
+		return calendar.getTime();
+	}
+
+	public static String getPassWord(int length) {
+		int[] array = new int[length];
+		char[] chars = new char[length];
+		StringBuilder str = new StringBuilder();
+		int temp = 0;
+		for (int i = 0; i < length; i++) {
+			while (true) {
+				temp = (int) (Math.random() * 1000);
+				if (temp >= 48 && temp <= 57)
+					break;
+				if (temp >= 65 && temp <= 90)
+					break;
+				if (temp >= 97 && temp <= 122)
+					break;
+			}
+
+			array[i] = temp;
+			chars[i] = (char) array[i];
+			str.append(chars[i]);
+		}
+
+		return str.toString();
+	}
+
+	public static String escapeQuoted(String filter) {
+		if (filter == null) {
+			return filter;
+		}
+
+		int length = filter.length();
+
+		if (length <= 1) {
+			return filter;
+		}
+
+		char first = filter.charAt(0);
+		char last = filter.charAt(length - 1);
+
+		if (('\'' == first || '"' == first) && (first == last)) {
+			filter = filter.substring(1, length - 1);
+			filter = filter.trim();
+			return filter;
+		}
+
+		return filter;
+	}
+
+	public static int[] getCurYearMonth() {
+		Date date = new Date();
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		int year = calendar.get(Calendar.YEAR);
+		int month = calendar.get(Calendar.MONTH) + 1;
+		return new int[] { year, month };
+	}
+
+	public static String getTimeStamp(Date date) {
+		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		return dateFormat.format(date);
+	}
+
+	public static String getFileExt(String filename) {
+		int pos = filename.lastIndexOf(".");
+		String ext = filename.substring(pos);
+		return ext;
+	}
+
+	public static int getMonth(String value) throws ParseException {
+		Date date = StringToDate(value);
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return calendar.get(Calendar.MONTH) + 1;
+	}
+
+	public static int getYear(String value) throws ParseException {
+		Date date = StringToDate(value);
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return calendar.get(Calendar.YEAR);
+	}
+
+	public static String joinPath(String parent, String path) {
+		if (isEmptyStr(parent)) {
+			return path;
+		}
+		
+		parent = parent.replace("\\", "/");
+		path = path.replace("\\", "/");
+		
+		if ('/' == parent.charAt(parent.length() - 1)) {
+			parent = parent.substring(0, parent.length() - 1);
+		}
+		
+		if ('/' == path.charAt(0)) {
+			path = path.substring(1);
+		}
+		
+		return parent + "/" + path;
+	}
+
+	public static String deleteInvisiableChar(String value) {
+		if (value == null) {
+            return null;
+        }
+
+        return value.replace("\r", "").replace("\n", "");
+	}
+
+	public static boolean isDigital(String value) {
+		if (value == null) {
+			return false;
+		}
+		
+		for (int i = 0; i < value.length(); i++) {
+			char c = value.charAt(i);
+			if (!Character.isDigit(c)) {
+				return false;
+			}
+		}
+		
+		return true;
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/IVariantsConsumer.java b/IMserver/medeasy/src/frame/variant/IVariantsConsumer.java
new file mode 100644
index 0000000..a1e22a3
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/IVariantsConsumer.java
@@ -0,0 +1,17 @@
+package frame.variant;
+
+import java.util.List;
+
+public interface IVariantsConsumer {
+
+	List<String> getVariantNameList();
+
+	boolean containsVariant(String name);
+	
+	void setVariants(IVariantsProvider... providers) throws Exception;
+
+	void setVariant(String name, Object value) throws Exception;
+
+	boolean isVariantNull(String name);
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/IVariantsProvider.java b/IMserver/medeasy/src/frame/variant/IVariantsProvider.java
new file mode 100644
index 0000000..c0dea32
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/IVariantsProvider.java
@@ -0,0 +1,13 @@
+package frame.variant;
+
+import java.util.List;
+
+public interface IVariantsProvider {
+
+	List<String> getVariantNameList();
+	
+	boolean containsVariant(String name);
+
+	Object getVariantValue(String name);
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/NameValuePair.java b/IMserver/medeasy/src/frame/variant/NameValuePair.java
new file mode 100644
index 0000000..2c656e8
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/NameValuePair.java
@@ -0,0 +1,36 @@
+package frame.variant;
+
+public class NameValuePair {
+
+	private String name;
+	private String value;
+	
+	
+	public NameValuePair(String content) throws Exception {
+		parse(content);
+	}
+	
+	private void parse(String content) throws Exception {
+		if (content == null) {
+			throw new Exception("NameValuePair error : empty content");
+		}
+		
+		int pos = content.indexOf("=");
+		
+		if (pos <= 0) {
+			throw new Exception("NameValuePair error , wrong format : " + content);
+		}
+		
+		name = content.substring(0, pos);
+		value = content.substring(pos + 1);		
+	}
+
+	public String getName() {
+		return name;
+	}
+
+
+	public String getValue() {
+		return value;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/PropertyIterator.java b/IMserver/medeasy/src/frame/variant/PropertyIterator.java
new file mode 100644
index 0000000..fc9b1e6
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/PropertyIterator.java
@@ -0,0 +1,35 @@
+package frame.variant;
+
+import java.util.Iterator;
+
+import frame.object.reader.ObjectReader;
+import frame.object.reader.PropertyReader;
+
+public class PropertyIterator implements Iterator<PropertyReader> {
+
+	private ObjectReader objectReader;
+	private int size;
+	private int pos;
+	
+	public PropertyIterator(ObjectReader objectReader) {
+		this.objectReader = objectReader;
+		this.size = objectReader.size();
+		this.pos = 0;
+	}
+	
+	@Override
+	public boolean hasNext() {
+		return pos < size;
+	}
+
+	@Override
+	public PropertyReader next() {
+		return objectReader.getPropertyReader(pos++);
+	}
+
+	@Override
+	public void remove() {
+		
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/Value.java b/IMserver/medeasy/src/frame/variant/Value.java
new file mode 100644
index 0000000..2e56144
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/Value.java
@@ -0,0 +1,279 @@
+package frame.variant;
+
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.util.Date;
+
+import org.apache.log4j.Logger;
+
+import frame.util.Util;
+import frame.variant.translator.Translator;
+
+public class Value {
+
+	private Object data;
+	private ValueType type;
+	private static Logger logger;
+	
+	
+	static {
+		logger = Logger.getLogger(Value.class);
+	}
+	
+	public Value() {
+		data = null;
+	}
+	
+	public Value(Boolean value) {
+		setData(value);
+	}
+	
+	public Value(Integer value) {
+		setData(value);
+	}
+	
+	public Value(Long value) {
+		setData(value);
+	}
+	
+	public Value(Double value) {
+		setData(value);
+	}
+	
+	public Value(BigDecimal value) {
+		setData(value);
+	}
+	
+	public Value(Date value) {
+		setData(value);
+	}
+	
+	public Value(String value) {
+		setData(value);
+	}
+
+	public void setData(Boolean value) {
+		this.data = value;
+		type = ValueType.Int;		
+	}
+	
+	public void setData(Integer value) {
+		this.data = value;
+		type = ValueType.Int;
+	}
+	
+	public void setData(Long value) {
+		this.data = value;
+		type = ValueType.Long;
+	}
+
+	public void setData(Double value) {
+		this.data = value;
+		type = ValueType.Double;
+	}
+	
+	public void setData(BigDecimal value) {
+		this.data = value;
+		type = ValueType.Decimal;
+	}	
+
+	public void setData(Date value) {
+		this.data = value;
+		type = ValueType.Date;
+	}
+
+	public void setData(String value) {
+		if ("null".equalsIgnoreCase(value)) {
+			this.data = null;
+		}
+		else {
+			this.data = value;				
+		}
+	
+		type = ValueType.String;		
+	}
+
+	public void setData(Object value, ValueType type) {
+		this.data = value;
+		this.type = type;		
+	}
+	
+	public ValueType getType() {
+		return type;
+	}
+
+	public Integer getInt() {
+		Integer result = null;
+		
+		if (data != null) {
+			Class<?> clazz = data.getClass();
+			
+			if (clazz == Integer.class) {
+				result = (Integer)data;
+			}
+			else if (clazz == BigDecimal.class) {
+				result = ((BigDecimal)data).intValue();				
+			}
+			else if (clazz == String.class) {
+				result = Integer.parseInt((String)data);					
+			}
+			else {
+				String value_str = String.valueOf(data);
+				result = Integer.parseInt(value_str);
+			}
+		}
+		else {
+			result = 0;
+		}
+		
+		return result;
+	}
+	
+	public int getInt(int defaultValue) {
+		if (data == null) {
+			return defaultValue;
+		}
+		
+		Integer result = defaultValue;
+		
+		try {
+			result = getInt();
+			
+			if (result == null) {
+				return defaultValue;
+			}
+		}
+		catch(Exception e) {
+			return defaultValue;
+		}
+		
+		return result;
+	}	
+	
+	public Double getDouble() {
+		if (type == ValueType.Int) {
+			return Double.valueOf((Integer)data);
+		}
+		else {
+			try {
+				return (Double)data;				
+			}
+			catch(Exception e) {
+				return Double.valueOf(String.valueOf(data));				
+			}
+		}
+	}
+	
+	public BigDecimal getBigDecimal() {
+		if (type == ValueType.Int) {
+			return BigDecimal.valueOf((Integer)data);
+		}
+		else {
+			try {
+				return BigDecimal.valueOf((Double)data);				
+			}
+			catch(Exception e) {
+				return BigDecimal.valueOf(Double.valueOf(String.valueOf(data)));			
+			}
+		}
+	}
+	
+	public Long getLong() {
+		return (Long) data;
+	}
+
+	public Date getDate() throws ParseException {
+		Date result = null;
+		
+		if (ValueType.Date == type) {
+			result = (Date)data;
+		}
+		else if (ValueType.String == type) {
+			result = Util.StringToDate(data.toString());
+		}
+		else if (ValueType.Int == type) {
+			logger.error("can not parse int to date");
+		}
+		else if (ValueType.Double == type) {
+			logger.error("can not parse double to date");			
+		}
+		
+		return result;
+	}
+	
+	public java.sql.Timestamp getSqlDate() {
+		return new java.sql.Timestamp(((Date)data).getTime());
+	}	
+
+	public String getString() {
+		return Translator.toString(data, null);
+	}
+	
+	public String getString(String defaultValue) {
+		if (data != null) {
+			if (ValueType.Date == type) {
+				String result = data.toString();
+				if (result.length() > 15) {
+					return result.substring(0, 16);
+				}
+			}
+
+			return data.toString();
+		}
+		else {
+			return defaultValue;
+		}
+	}
+	
+	public boolean getBoolean() {
+		String str = getString();
+		
+		boolean result = "T".equalsIgnoreCase(str);
+		result = result || "True".equalsIgnoreCase(str);
+		result = result || "Y".equalsIgnoreCase(str);
+		result = result || "Yes".equalsIgnoreCase(str);		
+		
+		return result;
+	}
+	
+	public boolean getBoolean(boolean defaultValue) {
+		String str = getString();
+		
+		if (Util.isEmptyStr(str)) {
+			return defaultValue;
+		}
+		
+		boolean result = "T".equalsIgnoreCase(str);
+		result = result || "True".equalsIgnoreCase(str);
+		result = result || "Y".equalsIgnoreCase(str);
+		result = result || "Yes".equalsIgnoreCase(str);		
+		
+		return result;
+	}
+	
+	public Object getData() {
+		return data;
+	}
+
+	public boolean isNull() {
+		return data == null;
+	}
+	
+	public boolean isEmpty() {
+		String str = getString();
+		return Util.isEmptyStr(str);
+	}
+	
+	public void setNull() {
+		data = null;
+	}	
+	
+	public void clear() {
+		data = null;
+	}
+
+	public String toString() {
+		return getString();
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/ValueType.java b/IMserver/medeasy/src/frame/variant/ValueType.java
new file mode 100644
index 0000000..4647597
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/ValueType.java
@@ -0,0 +1,233 @@
+package frame.variant;
+
+import java.sql.Types;
+
+
+public enum ValueType {  
+
+	Void, Int, Long, Double, Decimal, Date, String, Boolean, Entity, EntitySet,
+	Float,List;
+
+	public static ValueType valueOfTypes(int value) {
+		if (Types.INTEGER == value) {
+			return Int;
+		}
+		if (Types.BIGINT == value) {
+			return Int;
+		}
+		else if (Types.BIGINT == value) {
+			return Long;
+		}
+		else if (Types.SMALLINT == value) {
+			return Int;
+		}
+		else if (Types.TINYINT == value) {
+			return Int;
+		}
+		else if (Types.DECIMAL == value) {
+			return Decimal;
+		}
+		else if (Types.NUMERIC == value) {
+			return Decimal;
+		}	
+		else if (Types.DOUBLE == value) {
+			return Double;
+		}
+		else if (Types.FLOAT == value) {
+			return Double;
+		}
+		else if (Types.DATE == value) {
+			return Date;
+		}	
+		else if (Types.TIME == value) {
+			return Date;
+		}	
+		else if (Types.TIMESTAMP == value) {
+			return Date;
+		}	
+		else if (Types.BOOLEAN == value) {
+			return Boolean;
+		}		
+		else if (Types.BIT == value) {
+			return Boolean;
+		}
+		else {
+			return String;
+		}
+	}
+
+	public static ValueType valueOfString(String value) {
+		if (value == null) {
+			return String;
+		}
+		
+		value = value.toLowerCase();
+		
+		if ("String".equals(value)) {
+			return String;
+		}
+		else if ("char".equals(value)) {
+			return String;
+		}
+		else if ("varchar".equals(value)) {
+			return String;
+		}
+		else if ("vchar".equals(value)) {
+			return String;
+		}
+		else if ("text".equals(value)) {
+			return String;
+		}
+		else if ("int".equals(value)) {
+			return Int;
+		}
+		else if ("tinyint".equals(value)) {
+			return Int;
+		}
+		else if ("smallint".equals(value)) {
+			return Int;
+		}
+		else if ("bigint".equals(value)) {
+			return Int;
+		}
+		else if ("long".equals(value)) {
+			return Int;
+		}
+		else if ("number".equals(value)) {
+			return Double;
+		}
+		else if ("decimal".equals(value)) {
+			return Double;
+		}
+		else if ("float".equals(value)) {
+			return Double;
+		}
+		else if ("double".equals(value)) {
+			return Double;
+		}
+		else if ("date".equals(value)) {
+			return Date;
+		}
+		else if ("time".equals(value)) {
+			return Date;
+		}
+		else if ("datetime".equals(value)) {
+			return Date;
+		}
+		else if ("boolean".equals(value)) {
+			return Boolean;
+		}
+		else if ("entity".equals(value)) {
+			return Entity;
+		}
+		else if ("entityset".equals(value)) {
+			return EntitySet;
+		}
+		else {
+			return String;
+		}
+	}
+	
+	public String toJavaScriptType() {
+		int no = ordinal();
+
+		if (no == 0) {
+			return "String";
+		}
+		else if (no == 1) {
+			return "integer";
+		}
+		else if (no == 2) {
+			return "double";
+		}
+		else if (no == 3) {
+			return "date";
+		}
+		else if (no == 4) {
+			return "boolean";
+		}
+
+		return "String";
+	}
+
+	public static ValueType valueOfSAPTypes(String type) {
+		if (type == null) {
+			return String;
+		}
+		
+		type = type.trim().toLowerCase();
+		
+		if ("c".equalsIgnoreCase(type)) {
+			return String;
+		}
+		else if ("n".equalsIgnoreCase(type)) {
+			return String;
+		}
+		else if ("t".equalsIgnoreCase(type)) {
+			return String;
+		}	
+		else if ("d".equalsIgnoreCase(type)) {
+			return String;
+		}
+		else if ("i".equalsIgnoreCase(type)) {
+			return Int;
+		}
+		else if ("f".equalsIgnoreCase(type)) {
+			return Double;
+		}
+		else if ("p".equalsIgnoreCase(type)) {
+			return Double;
+		}
+		else if ("x".equalsIgnoreCase(type)) {
+			return String;
+		}
+		
+		return String;
+	}
+
+	public Class<?> getJavaClass() {
+		if (Int.equals(this)) {
+			return Integer.class;
+		}
+		else if (Double.equals(this)) {
+			return java.lang.Double.class;
+		}
+		else if (Float.equals(this)) {
+			return java.lang.Float.class;
+		}
+		else if (Decimal.equals(this)) {
+
+			return java.math.BigDecimal.class;
+		}
+		else if (Date.equals(this)) {
+			return java.util.Date.class;
+		}
+		else if (List.equals(this)) {
+			return java.util.List.class;
+		}
+		else if (Boolean.equals(this)) {
+			return java.lang.Boolean.class;
+		}
+		else {
+			return java.lang.String.class;
+		}
+	}
+
+	public int toSQLTypes() {
+		if (Int == this) {
+			return Types.INTEGER;
+		}
+		else if (Double == this) {
+			return Types.NUMERIC;
+		}	
+		else if (Date == this) {
+			return Types.DATE;
+		}	
+		else if (Boolean == this) {
+			return Types.BIT;
+		}		
+		else {
+			return Types.VARCHAR;
+		}
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/VariantLink.java b/IMserver/medeasy/src/frame/variant/VariantLink.java
new file mode 100644
index 0000000..7a6ff2d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/VariantLink.java
@@ -0,0 +1,100 @@
+package frame.variant;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import frame.util.Util;
+
+public class VariantLink {
+
+	public static void moveOnConsumer(IVariantsConsumer consumer, IVariantsProvider... providers) throws Exception {
+		if (providers == null) {
+			return;
+		}
+		
+		List<String> nameList = consumer.getVariantNameList();
+		boolean multi = providers.length > 1;
+		boolean first = true;
+		
+		for (String name: nameList) {
+			first = true;
+			
+			for (IVariantsProvider provider: providers) {
+				if (provider.containsVariant(name)) {
+					if (first || (multi && consumer.isVariantNull(name))) {
+						Object value = provider.getVariantValue(name);
+						consumer.setVariant(name, value);
+					}
+				}
+				
+				first = false;
+			}
+		}
+	}
+	
+	public static boolean moveOnConsumer(IVariantsProvider provider, IVariantsConsumer consumer, Set<String> excludeNames) throws Exception {
+		boolean excluded = false;
+		
+		Set<String> lowerSet = new HashSet<String>();
+		for (String one: excludeNames) {
+			lowerSet.add(one.toLowerCase());
+		}
+		
+		List<String> nameList = consumer.getVariantNameList();
+		if (Util.isEmptyStr(nameList)) {
+			return excluded;
+		}
+		for (String name: nameList) {
+			if (lowerSet.contains(name)) {
+				excluded = true;
+				continue;
+			}
+			
+			if (provider.containsVariant(name)) {
+				Object value = provider.getVariantValue(name);
+				consumer.setVariant(name, value);
+			}
+		}		
+		
+		return excluded;
+	}
+	
+
+	public static void moveOnProvider(IVariantsProvider provider, IVariantsConsumer consumer) throws Exception {
+		List<String> nameList = provider.getVariantNameList();
+		
+		for (String name: nameList) {
+			if (consumer.containsVariant(name)) {
+				Object value = provider.getVariantValue(name);
+				consumer.setVariant(name, value);
+			}
+		}
+	}
+	
+	public static boolean moveOnProvider(IVariantsProvider provider, IVariantsConsumer consumer, Set<String> excludeNames) throws Exception {
+		boolean excluded = false;
+		
+		Set<String> lowerSet = new HashSet<String>();
+		for (String one: excludeNames) {
+			lowerSet.add(one.toLowerCase());
+		}
+		
+		List<String> nameList = provider.getVariantNameList();
+		
+		for (String name: nameList) {
+			if (lowerSet.contains(name)) {
+				excluded = true;
+				continue;
+			}
+			
+			if (consumer.containsVariant(name)) {
+				Object value = provider.getVariantValue(name);
+				consumer.setVariant(name, value);
+			}
+		}		
+		
+		return excluded;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/Expression.java b/IMserver/medeasy/src/frame/variant/expression/Expression.java
new file mode 100644
index 0000000..32489b7
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/Expression.java
@@ -0,0 +1,208 @@
+package frame.variant.expression;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import frame.util.Util;
+import frame.variant.IVariantsConsumer;
+import frame.variant.IVariantsProvider;
+
+public class Expression implements Iterable<VariantSegment>, IVariantParseListener, IExpression, IVariantsConsumer {
+	
+	protected static Logger logger;
+	protected List<Segment> segments;
+	protected VariantList variantList;
+	
+	static {
+		logger = Logger.getLogger(Expression.class);
+	}
+	
+	public Expression(String String) throws Exception {
+		this(String, 0);
+	}
+	
+	public Expression(String String, int size) throws Exception {
+		this(size);
+		
+		VariantParser parser = new VariantParser(this);
+		parser.parse(String);
+	}
+
+	private Expression(int size) throws Exception {
+		if (size <= 0) {
+			size = 4;
+		}
+		
+		segments = new ArrayList<Segment>(size);
+		variantList = new VariantList();
+	}
+	
+	public Expression newInstance() throws Exception {
+		int size = segments.size();
+		Expression instance = new Expression(size);
+		
+		Segment segment;
+		VariantSegment param;
+		
+		for (int i = 0; i < size; i++) {
+			segment = segments.get(i);
+			
+			if (segment instanceof VariantSegment) {
+				param = (VariantSegment) segment;
+				String name = param.getName();
+				
+				if (instance.variantList.contains(param.getName())) {
+					instance.segments.add(instance.variantList.get(name));
+				}
+				else {
+					segment = segment.newInstance();
+					instance.segments.add(segment);
+					instance.variantList.add(name, (VariantSegment) segment);
+				}
+			}
+			else {
+				segment = segment.newInstance();
+				instance.segments.add(segment);
+			}
+		}
+		
+		return instance;
+	}
+	
+	public String tryGetString() throws Exception {
+		for (VariantSegment variant : variantList) {
+			if (variant.isEmpty()) {
+				throw new Exception("empty sql param: " + variant.getName());
+			}
+		}
+		
+		return getString();
+	}
+	
+	public String getString() {
+		StringBuilder result = new StringBuilder();
+		
+		int n = segments.size();
+		Segment segment;
+		String value;
+		
+		for (int i = 0; i < n; i++) {
+			segment = segments.get(i);
+			value = segment.getValueString();
+			
+			result.append(value);
+		}
+		
+		return result.toString();
+	}
+	
+	@Override
+	public void onSegment(String value) {
+		if (Util.isEmptyStr(value)) {
+			return;
+		}
+		
+		Segment segment = new StringSegment(value);
+		segments.add(segment);
+	}
+
+	@Override
+	public void addVariant(String name) throws Exception {
+		if (Util.isEmptyStr(name)) {
+			return;
+		}
+		
+		if (variantList.contains(name)) {
+			VariantSegment segment = variantList.get(name);
+			segments.add(segment);
+		}
+		else {
+			VariantSegment segment = new VariantSegment(name);
+			segments.add(segment);
+			variantList.add(name, segment);
+		}	
+	}
+	
+	public VariantSegment getVariant(String name) {
+		if (Util.isEmptyStr(name)) {
+			return null;
+		}
+		
+		return variantList.get(name);
+	}
+
+	public Iterator<VariantSegment> iterator() {
+		return variantList.getItemList().iterator();
+	}
+
+	@Override
+	public VariantList getVariantList() {
+		return variantList;
+	}
+
+	public boolean isVariantListEmpty() {
+		return variantList.isEmpty();
+	}
+	
+	public void clearVariantValues() {
+		for (VariantSegment variant: variantList) {
+			variant.clearValue();
+		}		
+	}
+
+	public boolean containsVariant(String name) {
+		return variantList.contains(name);
+	}
+	
+	@Override
+	public boolean isVariantNull(String name) {
+		VariantSegment segment = getVariant(name);
+		return segment.isEmpty();
+	}
+	
+	public List<Segment> getSegments() {
+		return segments;
+	}
+
+	@Override
+	public List<String> getVariantNameList() {
+		List<String> result = new ArrayList<String>();
+		result.addAll(variantList.getKeySet());
+		
+		return result;
+	}
+
+	@Override
+	public void setVariants(IVariantsProvider... providers) throws Exception {
+		for (VariantSegment param: variantList) {
+			String name = param.getName();
+			
+			for (IVariantsProvider provider: providers) {
+				if (provider.containsVariant(name)) {
+					Object value = provider.getVariantValue(name);
+					param.setValue(String.valueOf(value));
+				}
+			}
+		}
+	}
+
+	@Override
+	public void setVariant(String name, Object value) throws Exception {
+		VariantSegment param = variantList.get(name);
+		
+		if (param == null) {
+			return;
+		}
+		
+		param.setValue(String.valueOf(value));
+	}
+
+	@Override
+	public String toString() {
+		return getString();
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/GlobalVariant.java b/IMserver/medeasy/src/frame/variant/expression/GlobalVariant.java
new file mode 100644
index 0000000..ab85fa1
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/GlobalVariant.java
@@ -0,0 +1,132 @@
+package frame.variant.expression;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import frame.util.Util;
+
+public class GlobalVariant {
+
+	private static Object lock = new Object();
+	private static GlobalVariant instance;
+	private Map<String, IVariantRequestListener> listenerMap;
+	
+	
+	private GlobalVariant() throws VariantExistsException {
+		listenerMap = new HashMap<String, IVariantRequestListener>();
+	}
+	
+	public static GlobalVariant getInstance() {
+		if (instance == null) {
+			synchronized(lock) {
+				try {
+					if (instance == null) {
+						instance = new GlobalVariant();
+						GlobalVariantProvider provider = new GlobalVariantProvider();
+						GlobalVariant.regist(provider);
+					}
+				}
+				catch(Exception e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		
+		return instance;
+	}
+	
+	public static void regist(IVariantRequestListener listener) throws VariantExistsException {
+		GlobalVariant service = getInstance();
+		
+		List<String> variantNames = listener.getVariantNames();
+		
+		if (variantNames == null) {
+			return;
+		}
+		
+		for (String name: variantNames) {
+			if (name == null) {
+				continue;
+			}
+			
+			String lower = name.toLowerCase();
+			
+			if (service.listenerMap.containsKey(lower)) {
+				throw new VariantExistsException(name);
+			}
+			
+			service.listenerMap.put(lower, listener);
+		}
+	}
+	
+	public static String getStringValue(String name) throws Exception {
+		return getStringValue(name, null);
+	}
+		
+	public static String getStringValue(String name, VariantRequestParams params) throws Exception {
+		GlobalVariant service = getInstance();
+		
+		if (name == null) {
+			return null;
+		}
+		
+		String lower = name.toLowerCase();
+		
+		IVariantRequestListener listener = service.listenerMap.get(lower);
+		
+		if (listener == null) {
+			return null;
+		}
+		
+		return listener.getStringValue(lower, params);
+	}
+	
+	public static class GlobalVariantProvider implements IVariantRequestListener {
+		
+		private List<String> variantNames;
+		
+		public GlobalVariantProvider() {
+			variantNames = new ArrayList<String>();
+			initVariantNames();
+		}
+		
+		@Override
+		public String getStringValue(String name, VariantRequestParams params) {
+			if ("guid".equals(name)) {
+				return Util.newShortGUID();
+			}
+			else if ("newDate".equals(name)) {
+				return Util.newDateStr();
+			}
+			else if ("newDateTime".equals(name)) {
+				return Util.newDateTimeStr();
+			}
+			else if ("current.year".equals(name)) {
+				Calendar calendar = Calendar.getInstance();
+				return String.valueOf(calendar.get(Calendar.YEAR));
+			}
+			else if ("current.month".equals(name)) {
+				Calendar calendar = Calendar.getInstance();
+				return String.valueOf(calendar.get(Calendar.MONTH) + 1);
+			}
+			
+			return null;			
+		}
+
+		@Override
+		public List<String> getVariantNames() {
+			return variantNames;
+		}
+		
+		public void initVariantNames() {
+			variantNames.add("guid");
+			variantNames.add("newDate");
+			variantNames.add("newDateTime");
+			variantNames.add("current.year");
+			variantNames.add("current.month");
+		}
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/IExpression.java b/IMserver/medeasy/src/frame/variant/expression/IExpression.java
new file mode 100644
index 0000000..3ef6613
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/IExpression.java
@@ -0,0 +1,8 @@
+package frame.variant.expression;
+
+
+public interface IExpression {
+
+	VariantList getVariantList();
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/IVariantParseListener.java b/IMserver/medeasy/src/frame/variant/expression/IVariantParseListener.java
new file mode 100644
index 0000000..e5b4505
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/IVariantParseListener.java
@@ -0,0 +1,9 @@
+package frame.variant.expression;
+
+public interface IVariantParseListener {
+
+	void onSegment(String segment);
+
+	void addVariant(String variant) throws Exception;
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/IVariantRequestListener.java b/IMserver/medeasy/src/frame/variant/expression/IVariantRequestListener.java
new file mode 100644
index 0000000..d823eb9
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/IVariantRequestListener.java
@@ -0,0 +1,11 @@
+package frame.variant.expression;
+
+import java.util.List;
+
+public interface IVariantRequestListener {
+
+	public List<String> getVariantNames();
+
+	public String getStringValue(String name, VariantRequestParams params) throws Exception;
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/Segment.java b/IMserver/medeasy/src/frame/variant/expression/Segment.java
new file mode 100644
index 0000000..2081da1
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/Segment.java
@@ -0,0 +1,20 @@
+package frame.variant.expression;
+
+import org.apache.log4j.Logger;
+
+import frame.object.data.DataException;
+
+
+public abstract class Segment {
+
+	protected static Logger logger;
+	
+	static {
+		logger = Logger.getLogger(Segment.class);
+	}
+	
+	abstract public String getValueString();
+	
+	abstract public Segment newInstance() throws DataException;
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/StringSegment.java b/IMserver/medeasy/src/frame/variant/expression/StringSegment.java
new file mode 100644
index 0000000..67282c2
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/StringSegment.java
@@ -0,0 +1,26 @@
+package frame.variant.expression;
+
+
+public class StringSegment extends Segment {
+
+	private String value;
+	
+	public StringSegment(String value) {
+		this.value = value;
+	}
+	
+	@Override
+	public String getValueString() {
+		return value;
+	}
+
+	public String toString() {
+		return value;
+	}
+
+	@Override
+	public Segment newInstance() {
+		return new StringSegment(value);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantContext.java b/IMserver/medeasy/src/frame/variant/expression/VariantContext.java
new file mode 100644
index 0000000..32b8e8d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantContext.java
@@ -0,0 +1,70 @@
+package frame.variant.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public abstract class VariantContext implements IVariantRequestListener {
+
+	private List<VariantContext> linkedContextList;
+	
+	public VariantContext() {
+		linkedContextList = new ArrayList<VariantContext>();
+	}
+	
+	public void setParametersTo(IExpression expression) throws Exception {
+		doSetParametersTo(expression, true);
+	}
+	
+	protected void doSetParametersTo(IExpression expression, boolean queryGlabal) throws Exception {
+		VariantList paramList = expression.getVariantList();
+		
+		//1. on local
+		for (VariantSegment variant: paramList) {
+			if (!variant.isEmpty()) {
+				continue;
+			}
+			
+			String name = variant.getName();
+			String value = getStringValue(name, null);
+
+			if (value != null) {
+				variant.setValue(value);
+			}
+		}
+		
+		//2. on linked
+		for (VariantContext linked: linkedContextList) {
+			linked.doSetParametersTo(expression, false);
+		}
+		
+		//3.
+		if (queryGlabal) {
+			for (VariantSegment variant: paramList) {
+				if (!variant.isEmpty()) {
+					continue;
+				}
+				
+				String name = variant.getName();
+				String value = GlobalVariant.getStringValue(name, null);
+
+				if (value != null) {
+					variant.setValue(value);
+				}
+			}			
+		}
+	}
+
+	@Override
+	public List<String> getVariantNames() {
+		return null;
+	}
+
+	@Override
+	public abstract String getStringValue(String name, VariantRequestParams params) throws Exception;
+	
+	public void linkContext(VariantContext context) {
+		linkedContextList.add(context);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantExistsException.java b/IMserver/medeasy/src/frame/variant/expression/VariantExistsException.java
new file mode 100644
index 0000000..34a9725
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantExistsException.java
@@ -0,0 +1,11 @@
+package frame.variant.expression;
+
+public class VariantExistsException extends Exception {
+
+	private static final long serialVersionUID = 6370169285699904127L;
+	
+	public VariantExistsException(String name) {
+		super("variant has exists: " + name);
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantList.java b/IMserver/medeasy/src/frame/variant/expression/VariantList.java
new file mode 100644
index 0000000..0126050
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantList.java
@@ -0,0 +1,12 @@
+package frame.variant.expression;
+
+import frame.util.MapList;
+
+public class VariantList extends MapList<VariantSegment>{
+	
+	public void clearValues() {
+		for (VariantSegment param: itemList) {
+			param.clearValue();
+		}
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantNotFoundException.java b/IMserver/medeasy/src/frame/variant/expression/VariantNotFoundException.java
new file mode 100644
index 0000000..058ae20
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantNotFoundException.java
@@ -0,0 +1,10 @@
+package frame.variant.expression;
+
+public class VariantNotFoundException extends Exception {
+
+	private static final long serialVersionUID = 5270739430116585535L;
+	
+	public VariantNotFoundException(String name) {
+		super("param not found : " + name);
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantParser.java b/IMserver/medeasy/src/frame/variant/expression/VariantParser.java
new file mode 100644
index 0000000..8f509d5
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantParser.java
@@ -0,0 +1,107 @@
+package frame.variant.expression;
+
+public class VariantParser {
+
+	private static char Flag_Variant = '@';
+	private static char Flag_LeftQuote = '{';	
+	private static char Flag_RightQuote = '}';	
+	private IVariantParseListener listener;
+
+	public VariantParser(IVariantParseListener listener) {
+		this.listener = listener;
+	}
+	
+	public void parse(String expression) throws Exception {
+		if (expression == null) {
+			return;
+		}
+		
+		int length = expression.length();
+		
+		String segmentString;
+		int variantLength = 0;		
+		int begin = 0;
+		char curr;
+		
+		for (int i = 0; i < length; i++) {
+			curr = expression.charAt(i);
+			
+			if (isKey(curr)) {
+				if (Flag_LeftQuote != expression.charAt(Math.min(i + 1, length - 1))) {
+					continue;
+				}
+				
+				segmentString = expression.substring(begin, i);
+				onFindSegment(segmentString);
+				
+				variantLength = getVariantLength(expression, i + 1, length);
+				segmentString = expression.substring(i + 2, i + 2 + variantLength);
+				
+				onFindVariant(curr, segmentString);
+				
+				i = i + 2 + variantLength + 1;
+				begin = i;
+			}
+		}
+		
+		if (begin <= length - 1) {
+			segmentString = expression.substring(begin, length);
+			onFindSegment(segmentString);
+		}
+	}
+	
+	public static String getVariantName(String value) {
+		if (value == null) {
+			return null;
+		}
+		
+		int begin = value.indexOf("@{") + 2;
+		int end = value.indexOf("}", begin);
+		
+		if (end <= begin) {
+			return null; 
+		}
+		
+		return value.substring(begin, end);
+	}
+	
+	public static String toSegmentString(String name) {
+		return "@{" + name + "}";
+	}
+	
+	protected boolean isKey(char value) {
+		return Flag_Variant == value;
+	}
+
+	protected void onFindSegment(String segment) throws Exception {
+		if (listener != null) {
+			listener.onSegment(segment);
+		}
+	}	
+	
+	protected void onFindVariant(char key, String variant) throws Exception {
+		if (listener != null) {
+			listener.addVariant(variant);
+		}		
+	}
+
+	private int getVariantLength(String expression, int pos, int max) throws Exception {
+		if (Flag_LeftQuote == expression.charAt(pos)) {
+			for (int i = pos + 1; i < max; i++) {
+				if (Flag_RightQuote == expression.charAt(i)) {
+					return i - pos - 1;
+				}
+			}
+		}
+		else {
+			throw new Exception("error parse param expression (" + pos + "):" + expression);
+		}
+		
+		throw new Exception("error parse param expression (" + pos + "):" + expression);
+	}
+	
+	public static void main(String[] args) {
+		System.out.println(getVariantName("123@{456}789"));
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantRequestParams.java b/IMserver/medeasy/src/frame/variant/expression/VariantRequestParams.java
new file mode 100644
index 0000000..759cd59
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantRequestParams.java
@@ -0,0 +1,21 @@
+package frame.variant.expression;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class VariantRequestParams {
+	
+	private HttpServletRequest request;
+	
+	public VariantRequestParams() {
+
+	}
+	
+	public VariantRequestParams(HttpServletRequest request) {
+		this.request = request;
+	}
+
+	public HttpServletRequest getRequest() {
+		return request;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/expression/VariantSegment.java b/IMserver/medeasy/src/frame/variant/expression/VariantSegment.java
new file mode 100644
index 0000000..6f2a80b
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/expression/VariantSegment.java
@@ -0,0 +1,51 @@
+package frame.variant.expression;
+
+import frame.object.data.DataException;
+import frame.util.Util;
+
+
+public class VariantSegment extends Segment {
+
+	protected String name;
+	protected String value;
+	
+	
+	public VariantSegment(String name) {
+		this.name = name;
+	}
+	
+	@Override
+	public Segment newInstance() throws DataException {
+		VariantSegment result = new VariantSegment(name);
+		result.value = value;
+		
+		return result;
+	}
+	
+	@Override
+	public String getValueString() {
+		return value;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+	@Override
+	public String toString() {
+		return "@{" + name + "}=" + value;
+	}
+
+	public void clearValue() {
+		value = null;
+	}
+	
+	public boolean isEmpty() {
+		return Util.isNull(value);
+	}
+	
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/BigDecimalTranslator.java b/IMserver/medeasy/src/frame/variant/translator/BigDecimalTranslator.java
new file mode 100644
index 0000000..368e966
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/BigDecimalTranslator.java
@@ -0,0 +1,132 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class BigDecimalTranslator extends ITranslator {
+
+	@Override
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+
+		return ((BigDecimal)value).intValue();
+	}
+	
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((BigDecimal)value).doubleValue();
+	}
+
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return (BigDecimal)value;
+	}
+	
+	public Boolean toBoolean(Object value) throws Exception {
+		if (value == null) {
+			return false;
+		}
+		
+		
+		return ((BigDecimal)value).compareTo(BigDecimal.ZERO) > 0;
+	}
+
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return new Date(((BigDecimal)value).longValue());
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return new BigDecimal(value.toString());
+	}
+
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return BigDecimal.valueOf(Double.valueOf(value));
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Decimal);
+		
+		return variant;
+	}
+
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Decimal);
+			return variant;
+		}
+	}
+
+	@Override
+	public Class<?> getDataClass() {
+		return BigDecimal.class;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/BooleanTranslator.java b/IMserver/medeasy/src/frame/variant/translator/BooleanTranslator.java
new file mode 100644
index 0000000..b85a35a
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/BooleanTranslator.java
@@ -0,0 +1,141 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class BooleanTranslator extends ITranslator {
+
+	@Override
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		Boolean bool = (Boolean) value;
+		return bool.toString();
+	}
+
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		Boolean bool = (Boolean) value;
+		
+		if (bool) {
+			return "T";
+		}
+		else {
+			return "F";
+		}
+	}
+	
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		Boolean bool = (Boolean) value;
+		return bool.toString();
+	}
+
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		Boolean bool = (Boolean) value;
+		return bool.toString();
+	}
+
+	@Override
+	public Integer toInteger(Object object) throws Exception {
+		throw new Exception("can not translate boolean (" + object + ") to Integer");
+	}
+
+	@Override
+	public Double toDouble(Object object) throws Exception {
+		throw new Exception("can not translate boolean (" + object + ") to Double");
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object object) throws Exception {
+		throw new Exception("can not translate boolean (" + object + ") to BigDecimal");
+	}
+	
+	public Boolean toBoolean(Object object) throws Exception {
+		return Boolean.valueOf(object.toString());
+	}
+
+	@Override
+	public Date toDate(Object object) throws Exception {
+		throw new Exception("can not translate boolean (" + object + ") to Date");
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return (Boolean)value;
+	}
+
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		value = value.toLowerCase();
+		
+		if ("t".equals(value)) {
+			return true;
+		}
+		
+		if ("true".equals(value)) {
+			return true;
+		}
+		
+		if ("y".equals(value)) {
+			return true;
+		}
+		
+		if ("yes".equals(value)) {
+			return true;
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Boolean);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Boolean);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return Boolean.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/DateTranslator.java b/IMserver/medeasy/src/frame/variant/translator/DateTranslator.java
new file mode 100644
index 0000000..b5fb79b
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/DateTranslator.java
@@ -0,0 +1,147 @@
+package frame.variant.translator;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+public class DateTranslator extends ITranslator {
+
+	private static String DefaultFormat = "yyyy-MM-dd HH:mm:ss";
+	private DateFormat dateFormat;
+			
+	public DateTranslator() {
+		dateFormat = new SimpleDateFormat(DefaultFormat);
+	}
+	
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		Date date = (Date)value;
+		return dateFormat.format(date);
+	}
+	
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		Date date = toDate(value);
+		return Util.quotedStr(dateFormat.format(date));
+	}
+	
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		Date date = (Date)value;
+		return "\"" + dateFormat.format(date) + "\"";
+	}
+	
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		Date date = (Date)value;
+		return "\"" + dateFormat.format(date) + "\"";
+	}
+
+	@Override
+	public Integer toInteger(Object object) throws Exception {
+		throw new Exception("can not translate date (" + object + ") to Integer");
+	}
+
+	@Override
+	public Double toDouble(Object object) throws Exception {
+		throw new Exception("can not translate date (" + object + ") to Double");
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object object) throws Exception {
+		throw new Exception("can not translate date (" + object + ") to BigDecimal");
+	}
+	
+	@Override
+	public Boolean toBoolean(Object object) throws Exception {
+		throw new Exception("can not translate date (" + object + ") to BigDecimal");
+	}
+
+	@Override
+	public Date toDate(Object object) throws Exception {
+		// 鍙兘鎺ュ彈 long(Timestamp)  date string  
+		if(object instanceof Long) {
+			return new Date((Long)object);
+		}
+		else if (object instanceof String) {
+			Date parsedDate = dateFormat.parse((String) object);
+			return parsedDate;
+		}
+		else if (object instanceof Date) {
+			return (Date) object;
+		}
+		else {
+			throw new Exception("can not parse to date");
+		}
+	
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return toDate(value);
+	}
+	
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return dateFormat.parse(value);
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Date);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Date);
+			return variant;
+		}
+	}
+	
+	@Override
+	public void setFormat(String format) {
+		if (Util.isEmptyStr(format)) {
+			format = DefaultFormat;
+		}
+		
+		this.format = format;
+		dateFormat = new SimpleDateFormat(format);
+	}
+
+	@Override
+	public Class<?> getDataClass() {
+		return Date.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/DoubleTranslator.java b/IMserver/medeasy/src/frame/variant/translator/DoubleTranslator.java
new file mode 100644
index 0000000..3f9a8fb
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/DoubleTranslator.java
@@ -0,0 +1,144 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class DoubleTranslator extends ITranslator {
+
+	@Override
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return String.valueOf(value);
+	}
+	
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((Double)value).intValue();
+	}
+
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return (Double)value;
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return BigDecimal.valueOf((Double)value);
+	}
+	
+	@Override
+	public Boolean toBoolean(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return (Double)value > 0;
+	}
+
+	@Override
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}		
+		
+		Long longValue = ((Double)value).longValue();
+		
+		if (longValue >= 19500101 && longValue <= 21000101) {
+			DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+			return dateFormat.parse(String.valueOf(longValue));
+		}
+		else {
+			return new Date(longValue);
+		}
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return (Double)value;
+	}
+	
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return Double.valueOf(value);
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Double);
+		
+		return variant;
+	}
+
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Double);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return Double.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/ITranslator.java b/IMserver/medeasy/src/frame/variant/translator/ITranslator.java
new file mode 100644
index 0000000..373109d
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/ITranslator.java
@@ -0,0 +1,141 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.variant.Value;
+
+public abstract class ITranslator {
+
+	protected String format;
+	
+	public ITranslator() {
+		
+	}
+	
+	public abstract String toString(Object value) throws Exception;
+	
+	public String toString(Object value, String defaultValue) {
+		try {
+			return toString(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public abstract String toSqlString(Object value) throws Exception;
+	
+	public String toSqlString(String prefix, Object value, String suffix) throws Exception	{
+		if (value == null) {
+			return "null";
+		}
+		
+		String result = toSqlString(value);
+		
+		if (prefix != null) {
+			result = result + prefix;
+		}
+		
+		if (suffix != null) {
+			result = result + suffix;
+		}
+		
+		return "'" + result + "'";
+	}
+
+	public abstract String toJSONString(Object value) throws Exception;
+	
+	public abstract String toSchemaString(Object value) throws Exception;
+	
+	public abstract Integer toInteger(Object value) throws Exception;
+
+	public Integer toInteger(Object value, Integer defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		try {
+			return toInteger(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public abstract Double toDouble(Object value)throws Exception;
+	
+	public Double toDouble(Object value, Double defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		try {
+			return toDouble(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public abstract BigDecimal toBigDecimal(Object value) throws Exception;
+
+	public BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
+		try {
+			return toBigDecimal(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public abstract Boolean toBoolean(Object value) throws Exception;
+	
+	public Boolean toBoolean(Object value, boolean defaultValue) {
+		try {
+			return toBoolean(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	public abstract Date toDate(Object value) throws Exception;
+	
+	public Date toDate(Object value, Date defaultValue) {
+		try {
+			return toDate(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+
+	public abstract Object toTranslatorTypeValue(Object value) throws Exception;;
+	
+	public abstract Object loadObjectFrom(String value) throws Exception;
+	
+	public Object loadObjectFrom(String value, Object defaultValue) {
+		try {
+			return loadObjectFrom(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public abstract Value loadVariantFrom(String value) throws Exception;
+	
+	public abstract Value loadVariantFrom(String value, Object defaultValue);
+	
+	public abstract Class<?> getDataClass();
+	
+	public void setFormat(String format) {
+		this.format = format;
+	}
+	
+	public String getFormat() {
+		return format;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/IntegerTranslator.java b/IMserver/medeasy/src/frame/variant/translator/IntegerTranslator.java
new file mode 100644
index 0000000..43cfeb6
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/IntegerTranslator.java
@@ -0,0 +1,147 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class IntegerTranslator extends ITranslator {
+
+	
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return value.toString();
+	}
+	
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+	
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return (Integer)value;
+		}
+		
+		return Integer.valueOf(String.valueOf(value));
+	}
+
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return Double.valueOf((Integer)value);
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return BigDecimal.valueOf((Integer)value);
+	}
+	
+	@Override
+	public Boolean toBoolean(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((Integer)value) > 0;
+	}
+
+	@Override
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		Integer intValue = (Integer)value;
+		
+		if (intValue >= 19500101 && intValue <= 21000101) {
+			DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
+			return dateFormat.parse(String.valueOf(intValue));
+		}
+		else {
+			return new Date(Long.valueOf((Integer)value));
+		}
+	}
+	
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return (Integer)value;
+	}
+
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return Integer.valueOf(value);
+	}
+
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Int);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Int);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return Integer.class;
+	}
+
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/LongTranslator.java b/IMserver/medeasy/src/frame/variant/translator/LongTranslator.java
new file mode 100644
index 0000000..bd4c268
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/LongTranslator.java
@@ -0,0 +1,133 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+public class LongTranslator extends ITranslator {
+
+	
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((Long)value).intValue();
+	}
+
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((Long)value).doubleValue();
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return BigDecimal.valueOf(((Long)value).doubleValue());
+	}
+
+	@Override
+	public Boolean toBoolean(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return ((Long)value) > 0;
+	}
+
+	@Override
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return new Date((Long)value);
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return (Long)value;
+	}
+	
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return Long.valueOf(value);
+	}
+
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Long);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Long);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return Long.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/ObjectTranslator.java b/IMserver/medeasy/src/frame/variant/translator/ObjectTranslator.java
new file mode 100644
index 0000000..837866f
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/ObjectTranslator.java
@@ -0,0 +1,281 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class ObjectTranslator extends ITranslator {
+	
+	private static IntegerTranslator integerTranslator;
+	private static LongTranslator longTranslator;
+	private static DoubleTranslator doubleTranslator;
+	private static BigDecimalTranslator bigDecimalTranslator;
+	private static StringTranslator stringTranslator;
+
+	static {
+		integerTranslator = new IntegerTranslator();
+		longTranslator = new LongTranslator();
+		doubleTranslator = new DoubleTranslator();
+		bigDecimalTranslator = new BigDecimalTranslator();
+		stringTranslator = new StringTranslator();
+	}
+	
+	@Override
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof String) {
+			return (String)value;
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		if (value instanceof String) {
+			return "'" + value + "'";
+		}
+		
+		if (value instanceof Date) {
+			return "'" + value + "'";
+		}		
+		
+		return value.toString();
+	}
+
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return "\"" + value.toString() + "\"";		
+	}
+	
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		return "\"" + value.toString() + "\"";
+	}
+
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return (Integer)value;
+		}
+		
+		if (value instanceof Double) {
+			return ((Double)value).intValue();
+		}
+		
+		if (value instanceof Float) {
+			return ((Float)value).intValue();
+		}
+		
+		if (value instanceof Long) {
+			return ((Long)value).intValue();
+		}
+		
+		if (value instanceof BigDecimal) {
+			return ((BigDecimal)value).intValue();
+		}
+		
+		if (value instanceof String) {
+			return Integer.valueOf((String)value);
+		}
+		
+		return Integer.valueOf(String.valueOf(value));
+	}
+	
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return (Double)value;
+		}
+		
+		if (value instanceof Double) {
+			return (Double)value;
+		}
+		
+		if (value instanceof Float) {
+			return (Double)value;
+		}
+		
+		if (value instanceof Long) {
+			return (Double)value;
+		}
+		
+		if (value instanceof BigDecimal) {
+			return ((BigDecimal)value).doubleValue();
+		}
+		
+		if (value instanceof String) {
+			return Double.valueOf((String)value);
+		}
+		
+		return Double.valueOf(String.valueOf(value));
+
+	}
+
+	@Override
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return  BigDecimal.valueOf((Double)value); 
+		}
+		
+		if (value instanceof Double) {
+			return BigDecimal.valueOf((Double)value); 
+		}
+		
+		if (value instanceof Float) {
+			return BigDecimal.valueOf((Double)value); 
+		}
+		
+		if (value instanceof Long) {
+			return BigDecimal.valueOf((Double)value); 
+		}
+		
+		if (value instanceof BigDecimal) {
+			return (BigDecimal)value;
+		}
+		
+		if (value instanceof String) {
+			return BigDecimal.valueOf(Double.valueOf((String)value));
+		}
+		
+		return BigDecimal.valueOf(Double.valueOf(String.valueOf(value)));
+	}
+
+	@Override
+	public Boolean toBoolean(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return integerTranslator.toBoolean((Integer)value);
+		}
+		
+		if (value instanceof Double) {
+			return doubleTranslator.toBoolean((Double)value);
+		}
+		
+		if (value instanceof Float) {
+			return doubleTranslator.toBoolean((Float)value);
+		}
+		
+		if (value instanceof Long) {
+			return longTranslator.toBoolean((Long)value);
+		}
+		
+		if (value instanceof BigDecimal) {
+			return bigDecimalTranslator.toBoolean((BigDecimal)value);
+		}
+		
+		if (value instanceof String) {
+			return stringTranslator.toBoolean((String)value);
+		}
+		
+		return stringTranslator.toBoolean(String.valueOf(value));
+	}
+	
+	@Override
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		if (value instanceof Integer) {
+			return integerTranslator.toDate((Integer)value);
+		}
+		
+		if (value instanceof Double) {
+			return doubleTranslator.toDate((Double)value);
+		}
+		
+		if (value instanceof Float) {
+			return doubleTranslator.toDate((Double)value);
+		}
+		
+		if (value instanceof Long) {
+			return longTranslator.toDate((Long)value);
+		}
+		
+		if (value instanceof BigDecimal) {
+			return bigDecimalTranslator.toDate((BigDecimal)value);
+		}
+		
+		if (value instanceof String) {
+			return stringTranslator.toDate((String)value);
+		}
+		
+		return stringTranslator.toDate(String.valueOf(value));
+	}
+	
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return value;
+	}
+
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return value;
+	}
+
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.Void);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.Void);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return Object.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/StringTranslator.java b/IMserver/medeasy/src/frame/variant/translator/StringTranslator.java
new file mode 100644
index 0000000..2dfda6e
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/StringTranslator.java
@@ -0,0 +1,195 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import frame.util.Util;
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+
+public class StringTranslator extends ITranslator {
+
+	
+	@Override
+	public String toString(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return value.toString();
+	}
+	
+	@Override
+	public String toSqlString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return "'" + value + "'";
+	}
+
+	@Override
+	public String toJSONString(Object value) throws Exception {
+		if (value == null) {
+			return "null";
+		}
+		
+		return "\"" + value.toString() + "\"";
+	}
+
+	@Override
+	public String toSchemaString(Object value) throws Exception {
+		if (value == null) {
+			return "";
+		}
+		
+		return "\"" + value.toString() + "\"";
+	}
+
+	@Override
+	public Integer toInteger(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return Integer.valueOf(String.valueOf(value));
+	}
+	
+	@Override
+	public Double toDouble(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		return Double.valueOf(String.valueOf(value));
+	}
+	
+	@Override
+	public BigDecimal toBigDecimal(Object value) throws Exception {
+		if (value == null) {
+			return BigDecimal.valueOf(0);
+		}
+		
+		return BigDecimal.valueOf(Double.valueOf(String.valueOf(value)));
+	}
+	
+	@Override
+	public Boolean toBoolean(Object object) throws Exception {
+		if (object == null) {
+			return false;
+		}
+		
+		String value = String.valueOf(object).toLowerCase();
+		
+		if ("t".equals(value)) {
+			return true;
+		}
+		
+		if ("true".equals(value)) {
+			return true;
+		}
+		
+		if ("y".equals(value)) {
+			return true;
+		}
+		
+		if ("yes".equals(value)) {
+			return true;
+		}
+		
+		if ("鏄�".equals(value)) {
+			return true;
+		}
+		
+		return false;		
+	}
+	
+	@Override
+	public Date toDate(Object value) throws Exception {
+		if (value == null) {
+			return null;
+		}
+		
+		String fomater = null;
+		String str = String.valueOf(value).replace('T', ' ');
+		
+		if (str.indexOf("/") == 4) {
+			fomater = "yyyy/MM/dd";
+		}
+		else if (str.indexOf("/") == 2 || str.indexOf("/") == 1) {
+			fomater = "MM/dd/yyyy";			
+		}
+		else if (str.indexOf("-") == 2 || str.indexOf("-") == 1) {
+			fomater = "MM-dd-yyyy";		
+		}
+		else if (str.indexOf("-") == 4 && str.indexOf(":")<0) {
+			fomater = "yyyy-MM-dd";				
+		}
+		else if (str.indexOf("-") == 4  && str.indexOf(":")>0) {
+			if(str.split(":").length == 3){
+			   fomater = "yyyy-MM-dd HH:mm:ss";
+			}
+			else{
+				str = str + ":00";
+				fomater = "yyyy-MM-dd HH:mm:00";
+			}
+						
+		}		
+		else if (str.indexOf(".") == 2 || str.indexOf(".") == 1) {
+			fomater = "MM.dd.yyyy";	
+		}
+		else if (str.indexOf(".") == 4) {
+			fomater = "yyyy.MM.dd";		
+		}
+		else if (str.indexOf("-") < 0 && str.indexOf("/") < 0) {
+			fomater = "yyyyMMdd";
+		}
+
+		DateFormat dateFormat = new SimpleDateFormat(fomater);
+		return dateFormat.parse(str);
+	}
+
+	@Override
+	public Object toTranslatorTypeValue(Object value) throws Exception {
+		return toString(value);
+	}
+	
+	@Override
+	public Object loadObjectFrom(String value) throws Exception {
+		if (Util.isEmptyStr(value)) {
+			return null;
+		}
+		
+		return value;
+	}
+
+	@Override
+	public Value loadVariantFrom(String value) throws Exception {
+		Object object = loadObjectFrom(value);
+		
+		Value variant = new Value();
+		variant.setData(object, ValueType.String);
+		
+		return variant;
+	}
+	
+	@Override
+	public Value loadVariantFrom(String value, Object defaultValue) {
+		try {
+			return loadVariantFrom(value);
+		}
+		catch (Exception e) {
+			Value variant = new Value();
+			variant.setData(defaultValue, ValueType.String);
+			return variant;
+		}
+	}
+	
+	@Override
+	public Class<?> getDataClass() {
+		return String.class;
+	}
+}
diff --git a/IMserver/medeasy/src/frame/variant/translator/Translator.java b/IMserver/medeasy/src/frame/variant/translator/Translator.java
new file mode 100644
index 0000000..be7edf9
--- /dev/null
+++ b/IMserver/medeasy/src/frame/variant/translator/Translator.java
@@ -0,0 +1,312 @@
+package frame.variant.translator;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import frame.variant.ValueType;
+import frame.variant.Value;
+
+public abstract class Translator {
+	
+	private static Map<Class<?>, Class<? extends ITranslator>> classTranslatorTypeMap;
+	private static Map<ValueType, Class<? extends ITranslator>> dataTypeTranslatorTypeMap;
+	private static Map<Class<?>, ITranslator> classTranslatorMap;
+	
+	
+	static {
+		initClassTranslatorTypeMap();
+		initDataTypeTranslatorTypeMap();
+		intiClassTranslatorMap();
+	}
+	
+	public static ITranslator getInstance(Class<?> type) {
+		return getInstance(type, null);
+	}
+	
+	public static ITranslator getInstance(ValueType type) {
+		return getInstance(type, null);
+	}
+	
+	public static ITranslator getInstance(Class<?> type, String format) {
+		ITranslator result = null;
+		
+		Class<? extends ITranslator> translatorClass = classTranslatorTypeMap.get(type);
+		
+		if (translatorClass == null) {
+			return null;
+		}
+
+		try {
+			result = translatorClass.newInstance();
+			result.setFormat(format);
+		}
+		catch (Exception e) {
+			return null;
+		}
+		
+		return result;
+	}
+	
+	public static ITranslator getInstance(ValueType type, String format) {
+		ITranslator result = null;
+		
+		Class<? extends ITranslator> translatorClass = dataTypeTranslatorTypeMap.get(type);
+		
+		if (translatorClass == null) {
+			return null;
+		}
+
+		try {
+			result = translatorClass.newInstance();
+			result.setFormat(format);
+		}
+		catch (Exception e) {
+			return null;
+		}			
+		
+		return result;
+	}
+	
+	public static String toString(Object value) {
+		return toString(value, null);
+	}
+	
+	public static String toString(Object value, String defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toString(value, defaultValue);
+	}
+	
+	public static String toSqlString(Object value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toSqlString(value);
+	}
+	
+	public static String toSqlString(String prefix, Object value, String suffix)throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toSqlString(prefix, value, suffix);
+	}
+
+	public static String toJSONString(Object value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toJSONString(value);
+	}
+	
+	public static String toJSONString(Object value, String defaultValue) {
+		try {
+			ITranslator simpleTranslator = getInstance(value.getClass());
+			return simpleTranslator.toJSONString(value);
+		}
+		catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public static String toSchemaString(Object value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toSchemaString(value);
+	}
+
+	public static Integer toInteger(Object value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toInteger(value);
+	}
+
+	public static Integer toInteger(Object value, Integer defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toInteger(value, defaultValue);
+	}
+	
+	public static Double toDouble(Object value)throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toDouble(value);
+	}
+
+	public static BigDecimal toBigDecimal(Object value) throws Exception {
+		return toBigDecimal(value, null);
+	}
+	
+	public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) throws Exception {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toBigDecimal(value, defaultValue);
+	}
+	
+	public static Boolean toBoolean(Object value) throws Exception {
+		return toBoolean(value, null);
+	}
+	
+	public static Boolean toBoolean(Object value, Boolean defaultValue) {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toBoolean(value, defaultValue);
+	}
+
+	public static Date toDate(Object value) throws Exception {
+		return toDate(value, null);
+	}
+	
+	public static Date toDate(Object value, Date defaultValue) throws Exception {
+		if (value == null) {
+			return defaultValue;
+		}
+		
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toDate(value, defaultValue);
+	}
+	
+	public static String toSQLTypeCode(Object typeValue, Object lengthValue) {
+		String result = toString(typeValue, null);
+		
+		if (result == null) {
+			result = "varchar";
+		}
+		
+		if (result.indexOf("char") >= 0) {
+			String length = toString(lengthValue, null);
+			
+			if (length == null) {
+				length = "32";
+			}
+			
+			result = result + "(" + length + ")"; 
+		}
+		
+		return result;
+	}
+	
+	public static String toSQLNullCode(Object object) {
+		boolean nullable = toBoolean(object, true);
+		
+		if (nullable) {
+			return "NULL";
+		}
+		else {
+			return "NOT NULL";
+		}
+	}
+	
+	public static Object toTranslatorTypeValue(Object value, Class<?> clazz) {
+		ITranslator iTranslator = classTranslatorMap.get(value.getClass());
+		
+		classTranslatorMap.put(Long.class, new LongTranslator());	
+		
+		if (String.class.equals(clazz)) {
+			iTranslator.toString();
+		}
+		else if (Integer.class.equals(clazz)) {
+			iTranslator.toInteger(value, 0);
+		}
+		else if (BigInteger.class.equals(clazz)) {
+			iTranslator.toInteger(value, 0);
+		}
+		else if (Double.class.equals(clazz)) {
+			iTranslator.toDouble(value, 0.0);
+		}
+		else if (Float.class.equals(clazz)) {
+			iTranslator.toDouble(value, 0.0);
+		}
+		else if (Long.class.equals(clazz)) {
+			iTranslator.toInteger(value, 0);
+		}
+		else if (BigDecimal.class.equals(clazz)) {
+			iTranslator.toBigDecimal(value, BigDecimal.ZERO);
+		}
+		else if (Date.class.equals(clazz)) {
+			iTranslator.toDate(value, null);
+		}		
+		else if (Boolean.class.equals(clazz)) {
+			iTranslator.toBoolean(value, false);
+		}			
+		else if (Object.class.equals(clazz)) {
+			return value;
+		}
+		
+		return value;
+	}
+
+	public static Object toTranslatorTypeValue(Object value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.toTranslatorTypeValue(value);
+	}
+	
+	public static Object loadToObject(String value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.loadObjectFrom(value);
+	}
+	
+	public static Value loadToVariant(String value) throws Exception {
+		ITranslator simpleTranslator = getInstance(value.getClass());
+		return simpleTranslator.loadVariantFrom(value);		
+	}
+	
+	private static void initClassTranslatorTypeMap() {
+		classTranslatorTypeMap = new HashMap<Class<?>, Class<? extends ITranslator>>();
+		
+		classTranslatorTypeMap.put(String.class, StringTranslator.class);
+		classTranslatorTypeMap.put(Integer.class, IntegerTranslator.class);
+		classTranslatorTypeMap.put(int.class, IntegerTranslator.class);
+		classTranslatorTypeMap.put(BigInteger.class, IntegerTranslator.class);
+		classTranslatorTypeMap.put(Double.class, DoubleTranslator.class);
+		classTranslatorTypeMap.put(double.class, DoubleTranslator.class);
+		classTranslatorTypeMap.put(Float.class, DoubleTranslator.class);
+		classTranslatorTypeMap.put(float.class, DoubleTranslator.class);
+		classTranslatorTypeMap.put(BigDecimal.class, BigDecimalTranslator.class);
+		classTranslatorTypeMap.put(Date.class, DateTranslator.class);
+		classTranslatorTypeMap.put(Boolean.class, BooleanTranslator.class);
+		classTranslatorTypeMap.put(boolean.class, BooleanTranslator.class);
+		classTranslatorTypeMap.put(Object.class, ObjectTranslator.class);
+		classTranslatorTypeMap.put(Long.class, LongTranslator.class);
+	}
+	
+	private static void intiClassTranslatorMap() {
+		classTranslatorMap = new HashMap<Class<?>, ITranslator>();
+		
+		classTranslatorMap.put(String.class, new StringTranslator());
+		classTranslatorMap.put(Integer.class, new IntegerTranslator());
+		classTranslatorMap.put(int.class, new IntegerTranslator());
+		classTranslatorMap.put(BigInteger.class, new IntegerTranslator());
+		classTranslatorMap.put(Double.class, new DoubleTranslator());
+		classTranslatorMap.put(double.class, new DoubleTranslator());
+		classTranslatorMap.put(Float.class, new DoubleTranslator());
+		classTranslatorMap.put(float.class, new DoubleTranslator());
+		classTranslatorMap.put(BigDecimal.class, new BigDecimalTranslator());
+		classTranslatorMap.put(Date.class, new DateTranslator());
+		classTranslatorMap.put(Boolean.class, new BooleanTranslator());
+		classTranslatorMap.put(boolean.class, new BooleanTranslator());
+		classTranslatorMap.put(Object.class, new ObjectTranslator());
+		classTranslatorMap.put(Long.class, new LongTranslator());		
+	}
+
+	private static void initDataTypeTranslatorTypeMap() {
+		dataTypeTranslatorTypeMap = new HashMap<ValueType, Class<? extends ITranslator>>();
+		
+		dataTypeTranslatorTypeMap.put(ValueType.String, StringTranslator.class);
+		dataTypeTranslatorTypeMap.put(ValueType.Int, IntegerTranslator.class);
+		dataTypeTranslatorTypeMap.put(ValueType.Double, DoubleTranslator.class);
+		dataTypeTranslatorTypeMap.put(ValueType.Decimal, BigDecimalTranslator.class);
+		dataTypeTranslatorTypeMap.put(ValueType.Date, DateTranslator.class);
+		dataTypeTranslatorTypeMap.put(ValueType.Boolean, BooleanTranslator.class);
+	}
+
+	public static boolean containsType(Class<?> type) {
+		return classTranslatorTypeMap.containsKey(type);
+	}
+
+}

--
Gitblit v1.8.0